- Main Page
- Modules
- Classes
- Files

# ApplicationPool.h

    00001 /*
    00002  *  Phusion Passenger - http://www.modrails.com/
    00003  *  Copyright (C) 2008  Phusion
    00004  *
    00005  *  Phusion Passenger is a trademark of Hongli Lai & Ninh Bui.
    00006  *
    00007  *  This program is free software; you can redistribute it and/or modify
    00008  *  it under the terms of the GNU General Public License as published by
    00009  *  the Free Software Foundation; version 2 of the License.
    00010  *
    00011  *  This program is distributed in the hope that it will be useful,
    00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00014  *  GNU General Public License for more details.
    00015  *
    00016  *  You should have received a copy of the GNU General Public License along
    00017  *  with this program; if not, write to the Free Software Foundation, Inc.,
    00018  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    00019  */
    00020 #ifndef _PASSENGER_APPLICATION_POOL_H_
    00021 #define _PASSENGER_APPLICATION_POOL_H_
    00022
    00023 #include <boost/shared_ptr.hpp>
    00024 #include <sys/types.h>
    00025
    00026 #include "Application.h"
    00027 #include "PoolOptions.h"
    00028
    00029 namespace Passenger {
    00030
    00031 using namespace std;
    00032 using namespace boost;
    00033
    00034 /**
    00035  * A persistent pool of Applications.
    00036  *
    00037  * Spawning application instances, especially Ruby on Rails ones, is a very expensive operation.
    00038  * Despite best efforts to make the operation less expensive (see SpawnManager),
    00039  * it remains expensive compared to the cost of processing an HTTP request/response.
    00040  * So, in order to solve this, some sort of caching/pooling mechanism will be required.
    00041  * ApplicationPool provides this.
    00042  *
    00043  * Normally, one would use SpawnManager to spawn a new RoR/Rack application instance,
    00044  * then use Application::connect() to create a new session with that application
    00045  * instance, and then use the returned Session object to send the request and
    00046  * to read the HTTP response. ApplicationPool replaces the first step with
    00047  * a call to Application::get(). For example:
    00048  * @code
    00049  *   ApplicationPool pool = some_function_which_creates_an_application_pool();
    00050  *
    00051  *   // Connect to the application and get the newly opened session.
    00052  *   Application::SessionPtr session(pool->get("/home/webapps/foo"));
    00053  *
    00054  *   // Send the request headers and request body data.
    00055  *   session->sendHeaders(...);
    00056  *   session->sendBodyBlock(...);
    00057  *   // Done sending data, so we shutdown the writer stream.
    00058  *   session->shutdownWriter();
    00059  *
    00060  *   // Now read the HTTP response.
    00061  *   string responseData = readAllDataFromSocket(session->getStream());
    00062  *   // Done reading data, so we shutdown the reader stream.
    00063  *   session->shutdownReader();
    00064  *
    00065  *   // This session has now finished, so we close the session by resetting
    00066  *   // the smart pointer to NULL (thereby destroying the Session object).
    00067  *   session.reset();
    00068  *
    00069  *   // We can connect to an Application multiple times. Just make sure
    00070  *   // the previous session is closed.
    00071  *   session = app->connect("/home/webapps/bar")
    00072  * @endcode
    00073  *
    00074  * Internally, ApplicationPool::get() will keep spawned applications instances in
    00075  * memory, and reuse them if possible. It wil* @throw l try to keep spawning to a minimum.
    00076  * Furthermore, if an application instance hasn't been used for a while, it
    00077  * will be automatically shutdown in order to save memory. Restart requests are
    00078  * honored: if an application has the file 'restart.txt' in its 'tmp' folder,
    00079  * then get() will shutdown existing instances of that application and spawn
    00080  * a new instance (this is useful when a new version of an application has been
    00081  * deployed). And finally, one can set a hard limit on the maximum number of
    00082  * applications instances that may be spawned (see ApplicationPool::setMax()).
    00083  *
    00084  * Note that ApplicationPool is just an interface (i.e. a pure virtual class).
    00085  * For concrete classes, see StandardApplicationPool and ApplicationPoolServer.
    00086  * The exact pooling algorithm depends on the implementation class.
    00087  *
    00088  * @ingroup Support
    00089  */
    00090 class ApplicationPool {
    00091 public:
    00092         virtual ~ApplicationPool() {};
    00093
    00094         /**
    00095          * Checks whether this ApplicationPool object is still connected to the
    00096          * ApplicationPool server.
    00097          *
    00098          * If that's not the case, then one should reconnect to the ApplicationPool server.
    00099          *
    00100          * This method is only meaningful for instances of type ApplicationPoolServer::Client.
    00101          * The default implementation always returns true.
    00102          */
    00103         virtual bool connected() const {
    00104                 return true;
    00105         }
    00106
    00107         /**
    00108          * Open a new session with the application specified by <tt>PoolOptions.appRoot</tt>.
    00109          * See the class description for ApplicationPool, as well as Application::connect(),
    00110          * on how to use the returned session object.
    00111          *
    00112          * Internally, this method may either spawn a new application instance, or use
    00113          * an existing one.
    00114          *
    00115          * @param options An object containing information on which application to open
    00116          *             a session with, as well as spawning details. Spawning details will be used
    00117          *             if the pool decides that spawning a new application instance is necessary.
    00118          *             See SpawnManager and PoolOptions for details.
    00119          * @return A session object.
    00120          * @throw SpawnException An attempt was made to spawn a new application instance, but that attempt failed.
    00121          * @throw BusyException The application pool is too busy right now, and cannot
    00122          *       satisfy the request. One should either abort, or try again later.
    00123          * @throw IOException Something else went wrong.
    00124          * @throw thread_interrupted
    00125          * @note Applications are uniquely identified with the application root
    00126          *       string. So although <tt>appRoot</tt> does not have to be absolute, it
    00127          *       should be. If one calls <tt>get("/home/foo")</tt> and
    00128          *       <tt>get("/home/../home/foo")</tt>, then ApplicationPool will think
    00129          *       they're 2 different applications, and thus will spawn 2 application instances.
    00130          */
    00131         virtual Application::SessionPtr get(const PoolOptions &options) = 0;
    00132
    00133         /**
    00134          * Convenience shortcut for calling get() with default spawn options.
    00135          */
    00136         virtual Application::SessionPtr get(const string &appRoot) {
    00137                 return get(PoolOptions(appRoot));
    00138         }
    00139
    00140         /**
    00141          * Clear all application instances that are currently in the pool.
    00142          *
    00143          * This method is used by unit tests to verify that the implementation is correct,
    00144          * and thus should not be called directly.
    00145          */
    00146         virtual void clear() = 0;
    00147
    00148         virtual void setMaxIdleTime(unsigned int seconds) = 0;
    00149
    00150         /**
    00151          * Set a hard limit on the number of application instances that this ApplicationPool
    00152          * may spawn. The exact behavior depends on the used algorithm, and is not specified by
    00153          * these API docs.
    00154          *
    00155          * It is allowed to set a limit lower than the current number of spawned applications.
    00156          */
    00157         virtual void setMax(unsigned int max) = 0;
    00158
    00159         /**
    00160          * Get the number of active applications in the pool.
    00161          *
    00162          * This method exposes an implementation detail of the underlying pooling algorithm.
    00163          * It is used by unit tests to verify that the implementation is correct,
    00164          * and thus should not be called directly.
    00165          */
    00166         virtual unsigned int getActive() const = 0;
    00167
    00168         /**
    00169          * Get the number of active applications in the pool.
    00170          *
    00171          * This method exposes an implementation detail of the underlying pooling algorithm.
    00172          * It is used by unit tests to verify that the implementation is correct,
    00173          * and thus should not be called directly.
    00174          */
    00175         virtual unsigned int getCount() const = 0;
    00176
    00177         /**
    00178          * Set a hard limit on the number of application instances that a single application
    00179          * may spawn in this ApplicationPool. The exact behavior depends on the used algorithm,
    00180          * and is not specified by these API docs.
    00181          *
    00182          * It is allowed to set a limit lower than the current number of spawned applications.
    00183          */
    00184         virtual void setMaxPerApp(unsigned int max) = 0;
    00185
    00186         /**
    00187          * Get the process ID of the spawn server that is used.
    00188          *
    00189          * This method exposes an implementation detail. It is used by unit tests to verify
    00190          * that the implementation is correct, and thus should not be used directly.
    00191          */
    00192         virtual pid_t getSpawnServerPid() const = 0;
    00193 };
    00194
    00195 typedef shared_ptr<ApplicationPool> ApplicationPoolPtr;
    00196
    00197 }; // namespace Passenger
    00198
    00199 #endif /* _PASSENGER_APPLICATION_POOL_H_ */