Passenger::ApplicationPoolServer Class Reference
[Apache-independent support classes and function]

Multi-process usage support for ApplicationPool. More...

#include <ApplicationPoolServer.h>

List of all members.

Public Member Functions

 ApplicationPoolServer (const string &serverExecutable, const string &spawnServerCommand, const string &logFile="", const string &rubyCommand="ruby", const string &user="")
 Create a new ApplicationPoolServer object.
ApplicationPoolPtr connect ()
 Connects to the server and returns a usable ApplicationPool object.
void detach ()
 Detach the server, thereby telling it that we don't want to connect to it anymore.


Detailed Description

Multi-process usage support for ApplicationPool.

ApplicationPoolServer implements a client/server architecture for ApplicationPool. This allows one to use ApplicationPool in a multi-process environment (unlike StandardApplicationPool). The cache/pool data is stored in the server. Different processes can then access the pool through the server.

ApplicationPoolServer itself does not inherit ApplicationPool. Instead, it returns an ApplicationPool object via the connect() call. For example:

   // Create an ApplicationPoolServer.
   ApplicationPoolServer server(...);
   
   // Now fork a child process, like Apache's prefork MPM eventually will.
   pid_t pid = fork();
   if (pid == 0) {
       // Child process
       
       // Connect to the server. After connection, we have an ApplicationPool
       // object!
       ApplicationPoolPtr pool(server.connect());

       // We don't need to connect to the server anymore, so we detach from it.
       // This frees up some resources, such as file descriptors.
       server.detach();

       ApplicationPool::SessionPtr session(pool->get("/home/webapps/foo"));
       do_something_with(session);

       _exit(0);
   } else {
       // Parent process
       waitpid(pid, NULL, 0);
   }

Implementation notes

Separate server executable

The actual server is implemented in ApplicationPoolServerExecutable.cpp, this class is just a convenience class for starting/stopping the server executable and connecting to it.

In the past, the server logic itself was implemented in this class. This implies that the ApplicationPool server ran inside the Apache process. This presented us with several problems:

Because of these problems, it was decided to split the ApplicationPool server to a separate executable. This comes with no performance hit.

Anonymous server socket

Notice that ApplicationPoolServer does do not use TCP sockets at all, or even named Unix sockets, despite being a server that can handle multiple clients! So ApplicationPoolServer will expose no open ports or temporary Unix socket files. Only child processes are able to use the ApplicationPoolServer.

This is implemented through anonymous Unix sockets (socketpair()) and file descriptor passing. It allows one to emulate accept(). ApplicationPoolServer is connected to the server executable through a Unix socket pair. connect() sends a connect request to the server through that socket. The server will then create a new socket pair, and pass one of them back. This new socket pair represents the newly established connection.


Constructor & Destructor Documentation

Passenger::ApplicationPoolServer::ApplicationPoolServer ( const string &  serverExecutable,
const string &  spawnServerCommand,
const string &  logFile = "",
const string &  rubyCommand = "ruby",
const string &  user = "" 
) [inline]

Create a new ApplicationPoolServer object.

Parameters:
serverExecutable The filename of the ApplicationPool server executable to use.
spawnServerCommand The filename of the spawn server to use.
logFile Specify a log file that the spawn server should use. Messages on its standard output and standard error channels will be written to this log file. If an empty string is specified, no log file will be used, and the spawn server will use the same standard output/error channels as the current process.
rubyCommand The Ruby interpreter's command.
user The user that the spawn manager should run as. This parameter only has effect if the current process is running as root. If the empty string is given, or if the user is not a valid username, then the spawn manager will be run as the current user.
Exceptions:
SystemException An error occured while trying to setup the spawn server or the server socket.
IOException The specified log file could not be opened.


Member Function Documentation

ApplicationPoolPtr Passenger::ApplicationPoolServer::connect (  )  [inline]

Connects to the server and returns a usable ApplicationPool object.

All cache/pool data of this ApplicationPool is actually stored on the server and shared with other clients, but that is totally transparent to the user of the ApplicationPool object.

Note:
All methods of the returned ApplicationPool object may throw SystemException, IOException or boost::thread_interrupted.
Warning:
One may only use the returned ApplicationPool object for handling one session at a time. For example, don't do stuff like this:
   ApplicationPoolPtr pool = server.connect();
   Application::SessionPtr session1 = pool->get(...);
   Application::SessionPtr session2 = pool->get(...);
Otherwise, a deadlock can occur under certain circumstances.

Instead, one should call connect() multiple times:

   ApplicationPoolPtr pool1 = server.connect();
   Application::SessionPtr session1 = pool1->get(...);
   
   ApplicationPoolPtr pool2 = server.connect();
   Application::SessionPtr session2 = pool2->get(...);
Exceptions:
SystemException Something went wrong.
IOException Something went wrong.

void Passenger::ApplicationPoolServer::detach (  )  [inline]

Detach the server, thereby telling it that we don't want to connect to it anymore.

This frees up some resources in the current process, such as file descriptors.

This method is particularily useful to Apache worker processes that have just established a connection with the ApplicationPool server. Any sessions that are opened prior to calling detach(), will keep working even after a detach().

This method may only be called once. The ApplicationPoolServer object will become unusable once detach() has been called, so call connect() before calling detach().


The documentation for this class was generated from the following file:

Generated on Wed Apr 8 22:35:12 2009 for Passenger by  doxygen 1.5.8