DESCRIPTION
    POE::Class::Server::PreFork - Class for preforking and monitoring server
    sessions.

SYNOPSIS
        use POE qw(Class::Server::PreFork);

        my $server = new POE::Class::Server::PreFork::Something;

        my $preforked = new POE::Class::Server::PreFork(
            server            => $server,
            # optional and default
            shutdown_on_error => 1,
            min_spare_servers => 1,
            max_spare_servers => 2,
            start_servers     => 5,
            max_clients       => 50,
            timeout           => 0,
        );
        printf "Created prefork server with ID %d\n", $preforker->ID;

        # Create the session
        my $session = $preforked->start;
        printf "Created prefork session with ID %d\n", $session->ID;

        # don't forget this
        $poe_kernel->run;

DESCRIPTION
    POE::Class::Server::PreFork is more or less a monitor. It tracks forked
    sessions, reforkes them when they timeout and preforks them to the given
    specifications. POE::Class::Server::PreFork isa POE::Class.

ACCESSOR METHODS
    All accessors have three methods ala POE::Class::Attribs. set_ATTRIB,
    get_ATTRIB and ATTRIB. Set and get are obvious. ATTRIB is simply a
    set/get method. See POE::Class::Attribs for more details.

    server
        This is the object used for the server session.
        POE::Class::Server::PreFork comes with two such classes.
        POE::Class::Server::PreFork::TCP and
        POE::Class::Server::PreFork::UNIX.

    shutdown_on_error
        shutdown_on_error says whether the server should yield shutdown if
        an error occurs with the child server. See POE::Wheel::Run for
        possible errors.

    min_spare_servers
    max_spare_servers
        These are the maximum and minimum spare (non-busy) servers PreFork
        should keep around.

    start_servers
        The number of servers PreFork should initially start with. This will
        be set to max_clients if it is greater than max_clients.

    max_clients
        This is the maximum number of child servers that will be launched.

    timeout
        This is the approximate time in seconds a child is allowed to block.

INTERNALS
    This section is for people who wish to subclass
    POE::Class::Server::PreFork. If you are not such a person you may stop
    reading now.

  The Server Object
    The "server" object's session is started from within this class so that
    it becomes a child of this class. It is started with the method
    "start()" which is probably inherited from POE::Class. When it is
    started it is expected to setup a socket of some kind. It should NOT
    start accepting connections yet, that comes later.

    When PreFork initially starts it calles the child server's method
    send_ack with the proper interval PreFork needs ACKs for set_timeouts.
    After that, PreFork calles the child server's "start()" method.

    An ACK is the constant COMM_ACK, defined in this class, printed to
    STDOUT by the child server.

    PreFork forks child servers using POE::Wheel::Run. When PreFork forks it
    detaches the child session so that the session used by PreFork can exit.
    The child server's session object is accessed with the "get_session()"
    method (also inherited from POE::Class). Then PreFork posts a
    "resume_accept" event to the child server's session. This is the event
    that tells the child server session to start accepting connections now.

    In addition to ACKs the server child is responsible for letting us know
    when it is busy and when it is free. It does this by printing the
    COMM_BUSY or COMM_NOT_BUSY constants, defined in this package, to
    STDOUT.

    This constants COMM_BUSY, COMM_NOT_BUSY and COMM_ACK can be exported
    from this class

        use POE::Class::Server::PreFork qw(COMM_BUSY COMM_NOT_BUSY COMM_ACK);
        # -or-
        use POE::Class::Server::PreFork qw(:all);

  Server Tracking
    Child Servers are tracked using three hash references which can be
    accessed by methods:

    busy_servers
    free_servers
        These methods store a hash that maps the PID of the child process to
        a hash containing

        wheel
            The POE::Wheel::Run object used to fork off the child. See
            POE::Wheel::Run for details on methods.

        last_ack
            The last time PreFork recieved an ACK. This is used to timeout
            the process. It is unix time returned by time().

        starttime
            This stores the time() this process started. PreFork uses this
            time to decide which process to kill off when it is going back
            down to "max_spare_servers". PreFork kill the oldest non-busy
            server.

        Both of these combined are all the child servers.

    wheel_id_to_pid
        This hash simply maps POE::Wheel::Run ID to PID. It is needed in
        places PreFork only has the Wheel ID.

  Handlers
    These are the handlers this session defines. Handlers are all object
    states defined in the method "create_states()" which is called from the
    base class POE::Class.

    The following show the name of the state on the left and the name of the
    method on the right.

    _start => handler_start
        This handler is called when the PreFork session starts. It does some
        normalization on the attributes that are not set and or set to
        things that do not make sense. PreFork then creates the server child
        session and yields to forkoff.

    _child => handler_child
        Used to know if the server child session has ended for some reason
        (possibly an error). If it has ended PreFork yields shutdown.

    _stop => handler_stop
        Used to cleanup internal data structures.

    run_error => handler_run_error
        "handler_run_error()" is called by POE::Wheel::Run when an error
        occurs with the processes PeFork forked. See the StderrEvent in
        POE::Wheel::Run for details on arguments.

        This handler warns the error and yields shutdown if
        "shutdown_on_error()" is true.

    shutdown => handler_shutdown
        Puts us in the shutdown state and removes all alarms.

        In the forked child deletes all internal references to wheels so the
        PreFork session ends. In the parent it sends a SIGINT to all of the
        children.

    server_closed => handler_server_closed
        Called by POE::Wheel::Run when a child closes all it's output
        channels (PreFork assumes this means it exited). See the CloseEvent
        in POE::Wheel::Run for details on arguments.

        PreFork uses this handler to remove tracked POE::Wheel::Run wheels
        and to yield forkoff unless it is in a "Shutdown()" state.

    server_stderr => handler_server_stderr
        Called from POE::Wheel::Run when a child produces STDERR. See
        POE::Wheel::Run for details on this handler's arguments. This
        handler looks up the child hash and calles the "server_stderr()"
        method with the child's hash reference as the first argument and the
        input as the second.

    server_ack => handler_server_ack
        StdoutEvent from POE::Wheel::Run. If the output is the constant
        COMM_ACK calles the method "server_ack()", if the output is the
        constant COMM_BUSY calles the method "server_busy()", if the output
        is the constant COMM_NOT_BUSY calles the method "server_not_busy()"
        else calles the method "server_stdout()".

    server_timeout_check => handler_server_timeout_check
        Called on a timer of "get_timeout()" * 1.5. Checks all children to
        see that they have sent an ACK within "get_timeout()" seconds. If a
        free server is timeing out calles the method
        "server_timeout_free()", if a busy server is timeing out calles
        "server_timeout_busy()". If any servers have timed out yield
        forkoff.

    forkoff => handler_forkoff
        This handler is the main code for handling child server monitoring.
        It kills off the oldest processes if PreFork is over
        "get_max_spare_servers()", starts the initial "get_start_servers()"
        if total servers is zero, or yields server_fork for every child
        server PreFork is under "get_min_spare_servers()".

    server_fork => handler_server_fork
        Uses POE::Wheel::Run to fork of a child process. Calles the method
        "server_start()" from within the child process. Stores the child
        hash in "free_servers()" and the wheel ID to PID in
        "wheel_id_to_pid()".

  Methods
    Many of these methods were created to provide a simpler subclass
    interface.

    create_states
        Creates the following states

            run_error            => handler_run_error
            server_closed        => handler_server_closed
            server_stderr        => handler_server_stderr
            server_ack           => handler_server_ack
            server_timeout_check => handler_server_timeout_check
            server_fork          => handler_server_fork
            forkoff              => handler_forkoff

        See "Handlers" for details.

    server_timeout
        This method is called when a server has timed out. It sends a SIGINT
        to the process.

    server_timeout_busy
    server_timeout_free
        Server objects send information back to the monitor via STDOUT. This
        information lets the monitor know if the server is busy or not.
        "server_timeout_busy()" or "server_timeout_free()" are called when a
        free or busy server times out respectivly. The only argument to
        these methods is the child's hash.

        Both of these methods do the same thing by default (with slightly
        different debug information in debug mode). They call
        "server_timeout()" and removes the references to the childs wheel.

    server_start
        Called from within the forked process. Does the following:

        Detaches the child session.

        Pauses all wheels to keep them from getting input before they are
        destroyed.

        Posts a resume_accept event to the server child session, set.

        Calles the shutdown state.

    server_ack
        Takes the child hash reference as the first argument. Sets the
        last_ack attribute in the child hash to the current time.

    server_not_busy
        Takes the child hash reference as the first arugment. Moves the
        reference for this child from the "busy_servers()" hash to the
        "free_servers()" hash.

    server_busy
        Takes the child hash reference as the first arugment. Moves the
        reference for this child from the "free_servers()" hash to the
        "busy_servers()" hash.

    server_stdout
        Called when the child server produces stdout that is not recognized.
        Takes the child hash reference as the first argument and the output
        as the second. Prints the output to STDOUT prefixed with "$pid
        STDOUT: ".

    server_stderr
        Called when the child server produces stderr that is not recognized.
        Takes the child hash reference as the first argument and the output
        as the second. Prints the output to STDERR prefixed with "$pid
        STDERR: ".

    busy_servers
        Returns the hash reference of busy server childs.

    free_servers
        Returns the hash reference of non-busy server childs.

    wheel_id_to_pid
        Returns the hash reference that maps server childs wheel ID to PID.

    server_check_ack
        The interval we check for timed out children.

    is_child
        Used to know if we are the forked child. This is set in
        "server_start()".

BUGS
    The documentation is not complete.

    Tests are far from complete.

AUTHOR
    Scott Beck <sbeck@gossamer-threads.com>

SEE ALSO
    POE

    POE::Class

    POE::Class::Server::PreFork::TCP

    POE::Class::Server::PreFork::UNIX

