AppserverIo\Appserver\Core\AbstractContainerThread::main PHP Method

main() public method

Run the containers logic
public main ( ) : void
return void
    public function main()
    {
        // register the default autoloader
        require SERVER_AUTOLOADER;
        // initialize the container state
        $this->containerState = ContainerStateKeys::get(ContainerStateKeys::WAITING_FOR_INITIALIZATION);
        // create a new API app service instance
        $this->service = $this->newService('AppserverIo\\Appserver\\Core\\Api\\AppService');
        // initialize the container for the configured class laoders
        $classLoaders = new GenericStackable();
        // register the configured class loaders
        $this->registerClassLoaders($classLoaders);
        // register shutdown handler
        register_shutdown_function(array(&$this, "shutdown"));
        // query whether the container's directories exists and are readable
        $this->validateDirectories();
        // initialize the naming directory with the environment data
        $this->namingDirectory->createSubdirectory(sprintf('php:env/%s', $this->getName()));
        $this->namingDirectory->createSubdirectory(sprintf('php:global/%s', $this->getName()));
        $this->namingDirectory->createSubdirectory(sprintf('php:global/log/%s', $this->getName()));
        $this->namingDirectory->bind(sprintf('php:env/%s/appBase', $this->getName()), $this->getAppBase());
        $this->namingDirectory->bind(sprintf('php:global/%s/runlevel', $this->getName()), $this->getRunlevel());
        // initialize the container state
        $this->containerState = ContainerStateKeys::get(ContainerStateKeys::INITIALIZATION_SUCCESSFUL);
        // initialize instance that contains the applications
        $this->applications = new GenericStackable();
        // initialize the profile logger and the thread context
        if ($profileLogger = $this->getInitialContext()->getLogger(LoggerUtils::PROFILE)) {
            $profileLogger->appendThreadContext($this->getContainerNode()->getName());
        }
        // initialize the array for the server configurations
        $serverConfigurations = array();
        // load the server configurations and query whether a server signatures has been set
        /** @var \AppserverIo\Appserver\Core\Api\Node\ServerNodeInterface $serverNode */
        foreach ($this->getContainerNode()->getServers() as $serverNode) {
            $serverConfigurations[] = $this->getServerNodeConfiguration($serverNode);
        }
        // init upstreams
        $upstreams = array();
        if ($this->getContainerNode()->getUpstreams()) {
            $upstreams = $this->getContainerNode()->getUpstreams();
            foreach ($this->getContainerNode()->getUpstreams() as $upstreamNode) {
                // get upstream type
                $upstreamType = $upstreamNode->getType();
                // init upstream instance
                $upstream = new $upstreamType();
                // init upstream servers
                $servers = array();
                // get upstream servers from upstream
                foreach ($upstreamNode->getUpstreamServers() as $upstreamServerNode) {
                    $upstreamServerType = $upstreamServerNode->getType();
                    $upstreamServerParams = $upstreamServerNode->getParamsAsArray();
                    $servers[$upstreamServerNode->getName()] = new $upstreamServerType($upstreamServerParams);
                }
                // inject server instances to upstream
                $upstream->injectServers($servers);
                // set upstream by name
                $upstreams[$upstreamNode->getName()] = $upstream;
            }
        }
        // init server array
        $this->servers = new GenericStackable();
        // start servers by given configurations
        /** @var \AppserverIo\Server\Interfaces\ServerConfigurationInterface $serverConfig */
        foreach ($serverConfigurations as $serverConfig) {
            // get type definitions
            $serverType = $serverConfig->getType();
            $serverContextType = $serverConfig->getServerContextType();
            // create a new instance server context
            /** @var \AppserverIo\Server\Interfaces\ServerContextInterface $serverContext */
            $serverContext = new $serverContextType();
            // inject container to be available in specific mods etc. and initialize the module
            $serverContext->injectContainer($this);
            // init server context by config
            $serverContext->init($serverConfig);
            // inject upstreams
            $serverContext->injectUpstreams($upstreams);
            // inject loggers
            $serverContext->injectLoggers($this->getInitialContext()->getLoggers());
            // create the server (which should start it automatically)
            /** @var \AppserverIo\Server\Interfaces\ServerInterface $server */
            $server = new $serverType($serverContext);
            // collect the servers we started
            $this->servers[$serverConfig->getName()] = $server;
        }
        // wait for all servers to be started
        $waitForServers = true;
        while ($waitForServers === true) {
            // iterate over all servers to check the state
            foreach ($this->servers as $server) {
                if ($server->serverState === ServerStateKeys::WORKERS_INITIALIZED) {
                    $waitForServers = false;
                } else {
                    $waitForServers = true;
                }
            }
            usleep(10000);
        }
        // the container has successfully been initialized
        $this->synchronized(function ($self) {
            $self->containerState = ContainerStateKeys::get(ContainerStateKeys::SERVERS_STARTED_SUCCESSFUL);
        }, $this);
        // initialize the flag to keep the application running
        $keepRunning = true;
        // wait till container will be shutdown
        while ($keepRunning) {
            // query whether we've a profile logger, log resource usage
            if ($profileLogger) {
                $profileLogger->debug(sprintf('Container %s still waiting for shutdown', $this->getContainerNode()->getName()));
            }
            // wait a second to lower system load
            $keepRunning = $this->synchronized(function ($self) {
                $self->wait(1000000 * AbstractContainerThread::TIME_TO_LIVE);
                return $self->containerState->equals(ContainerStateKeys::get(ContainerStateKeys::SERVERS_STARTED_SUCCESSFUL));
            }, $this);
        }
        // we need to stop all servers before we can shutdown the container
        /** @var \AppserverIo\Server\Interfaces\ServerInterface $server */
        foreach ($this->servers as $server) {
            $server->stop();
        }
        // mark the container as successfully shutdown
        $this->synchronized(function ($self) {
            $self->containerState = ContainerStateKeys::get(ContainerStateKeys::SHUTDOWN);
        }, $this);
        // send log message that the container has been shutdown
        $this->getInitialContext()->getSystemLogger()->info(sprintf('Successfully shutdown container %s', $this->getContainerNode()->getName()));
    }