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()));
}