/** * Called when the worker is ready to go. * @return void */ public function onReady() { $appInstance = $this; // a reference to this application instance for ExampleWebSocketRoute \PHPDaemon\Servers\WebSocket\Pool::getInstance()->addRoute('ExamplePubSub', function ($client) use($appInstance) { return new ExamplePubSubWebSocketRoute($client, $appInstance); }); $this->sql = \PHPDaemon\Clients\MySQL\Pool::getInstance(); $this->pubsub = new \PHPDaemon\PubSub\PubSub(); $this->pubsub->addEvent('usersNum', \PHPDaemon\PubSub\PubSubEvent::init()->onActivation(function ($pubsub) use($appInstance) { \PHPDaemon\Core\Daemon::log('onActivation'); if (isset($pubsub->event)) { \PHPDaemon\Core\Timer::setTimeout($pubsub->event, 0); return; } $pubsub->event = setTimeout(function ($timer) use($pubsub, $appInstance) { $appInstance->sql->getConnection(function ($sql) use($pubsub) { if (!$sql->connected) { return; } $sql->query('SELECT COUNT(*) `num` FROM `dle_users`', function ($sql, $success) use($pubsub) { $pubsub->pub(sizeof($sql->resultRows) ? $sql->resultRows[0]['num'] : 'null'); }); }); $timer->timeout(5000000.0); // 5 seconds }, 0); })->onDeactivation(function ($pubsub) { if (isset($pubsub->event)) { \PHPDaemon\Core\Timer::cancelTimeout($pubsub->event); } })); }
protected function runAsync($method, $timeout = 3000000.0) { Timer::add(function () use($method) { self::assertSame(0, 1, 'Some callbacks didnt finished in ' . $method); }, $timeout); EventLoop::$instance->run(); //EventLoop::$instance->free(); //EventLoop::$instance = null; }
/** * Adds your subscription on object in FS * @param string $path Path * @param mixed $cb Callback * @param integer $flags Look inotify_add_watch() * @return true */ public function addWatch($path, $cb, $flags = null) { $path = realpath($path); if (!isset($this->files[$path])) { $this->files[$path] = []; if ($this->inotify) { $this->descriptors[inotify_add_watch($this->inotify, $path, $flags ?: IN_MODIFY)] = $path; } } $this->files[$path][] = $cb; Timer::setTimeout('fileWatcher'); return true; }
/** * @param $p */ protected function onPacket($p) { if ($p['op'] === 'spawnInstance') { $fullname = $p['appfullname']; $fullname = str_replace('-', ':', $fullname); if (mb_orig_strpos($fullname, ':') === false) { $fullname .= ':'; } list($app, $name) = explode(':', $fullname, 2); Daemon::$appResolver->getInstance($app, $name, true, true); } elseif ($p['op'] === 'importFile') { if (!Daemon::$config->autoreimport->value) { Daemon::$process->gracefulRestart(); return; } $path = $p['path']; Timer::add(function ($event) use($path) { if (Daemon::supported(Daemon::SUPPORT_RUNKIT_IMPORT)) { //Daemon::log('--start runkit_import('.$path.')'); runkit_import($path, RUNKIT_IMPORT_FUNCTIONS | RUNKIT_IMPORT_CLASSES | RUNKIT_IMPORT_OVERRIDE); //Daemon::log('--end runkit_import('.$path.')'); } else { $this->appInstance->log('Cannot import \'' . $path . '\': runkit_import is not callable.'); } $event->finish(); }, 5); } elseif ($p['op'] === 'call') { if (mb_orig_strpos($p['appfullname'], ':') === false) { $p['appfullname'] .= ':'; } list($app, $name) = explode(':', $p['appfullname'], 2); if ($app = Daemon::$appResolver->getInstance($app, $name)) { $app->RPCall($p['method'], $p['args']); } } }
/** * @TODO DESCR * @return void */ public function onFinish() { if ($this->onFinishedCalled) { return; } $this->onFinishedCalled = true; $this->appInstance->unsubscribe('c2s:' . $this->id, [$this, 'c2s']); $this->appInstance->unsubscribe('poll:' . $this->id, [$this, 'poll']); if (isset($this->route)) { $this->route->onFinish(); } $this->onWrite->reset(); $this->route = null; Timer::remove($this->finishTimer); $this->appInstance->endSession($this); }
/** * Called when connection is finished * @return void */ public function onFinish() { Timer::remove($this->keepaliveTimer); if ($this->req !== null && $this->req instanceof Generic) { if (!$this->req->isFinished()) { $this->req->abort(); } } $this->req = null; }
/** * Shutdown this worker * @param boolean Hard? If hard, we shouldn't wait for graceful shutdown of the running applications. * @return boolean|null Ready? */ protected function shutdown($hard = false) { $error = error_get_last(); if ($error) { if ($error['type'] === E_ERROR) { Daemon::log('W#' . $this->pid . ' crashed by error \'' . $error['message'] . '\' at ' . $error['file'] . ':' . $error['line']); } } if (Daemon::$config->logevents->value) { $this->log('event shutdown(' . ($hard ? 'HARD' : '') . ') invoked.'); } if (Daemon::$config->throwexceptiononshutdown->value) { throw new \Exception('event shutdown'); } @ob_flush(); if ($this->terminated === true) { if ($hard) { exit(0); } return; } $this->terminated = true; if ($hard) { $this->setState(Daemon::WSTATE_SHUTDOWN); exit(0); } $this->reloadReady = $this->appInstancesReloadReady(); if ($this->reload && $this->graceful) { $this->reloadReady = $this->reloadReady && microtime(TRUE) > $this->reloadTime; } if (Daemon::$config->logevents->value) { $this->log('reloadReady = ' . Debug::dump($this->reloadReady)); } Timer::remove('breakMainLoopCheck'); Timer::add(function ($event) { $self = Daemon::$process; $self->reloadReady = $self->appInstancesReloadReady(); if ($self->reload === TRUE) { $self->reloadReady = $self->reloadReady && microtime(TRUE) > $self->reloadTime; } if (!$self->reloadReady) { $event->timeout(); } else { $self->eventBase->exit(); } }, 1000000.0, 'checkReloadReady'); while (!$this->reloadReady) { $this->eventBase->loop(); } FileSystem::waitAllEvents(); // ensure that all I/O events completed before suicide exit(0); // R.I.P. }
/** * Called when we got UDP packet * @param resource $stream Descriptor * @param integer $events Events * @param mixed $arg Attached variable * @return boolean Success. */ public function onReadUdp($stream = null, $events = 0, $arg = null) { if (Daemon::$config->logevents->value) { Daemon::$process->log(get_class($this) . '::' . __METHOD__ . ' invoked.'); } if (Daemon::$process->reload) { return false; } if ($this->pool->maxConcurrency) { if ($this->pool->count() >= $this->pool->maxConcurrency) { $this->overload = true; return false; } } $host = null; do { $l = @socket_recvfrom($this->fd, $buf, 10240, MSG_DONTWAIT, $host, $port); if (!$l) { break; } $key = '[' . $host . ']:' . $port; if (!isset($this->portsMap[$key])) { if ($this->pool->allowedClients !== null) { if (!self::netMatch($conn->pool->allowedClients, $host)) { Daemon::log('Connection is not allowed (' . $host . ')'); } continue; } $class = $this->pool->connectionClass; $conn = new $class(null, $this->pool); $conn->setDgram(true); $conn->onWriteEv(null); $conn->setPeername($host, $port); $conn->setParentSocket($this); $this->portsMap[$key] = $conn; $conn->timeoutRef = setTimeout(function ($timer) use($conn) { $conn->finish(); $timer->finish(); }, $conn->timeout * 1000000.0); $conn->onUdpPacket($buf); } else { $conn = $this->portsMap[$key]; $conn->onUdpPacket($buf); Timer::setTimeout($conn->timeoutRef); } } while (true); return $host !== null; }
function clearTimeout($id) { \PHPDaemon\Core\Timer::remove($id); }
/** * Called when new data received * @return void */ public function onRead() { Timer::setTimeout($this->keepaliveTimer); while (($line = $this->readline()) !== null) { if ($line === '') { continue; } if (strlen($line) > 512) { Daemon::$process->log('IRCBouncerConnection error: buffer overflow.'); $this->finish(); return; } $line = binarySubstr($line, 0, -strlen($this->EOL)); $p = strpos($line, ':', 1); $max = $p ? substr_count($line, " ", 0, $p) + 1 : 18; $e = explode(" ", $line, $max); $i = 0; $cmd = $e[$i++]; $args = []; for ($s = min(sizeof($e), 14); $i < $s; ++$i) { if ($e[$i][0] === ':') { $args[] = binarySubstr($e[$i], 1); break; } $args[] = $e[$i]; } if (ctype_digit($cmd)) { $code = (int) $cmd; $cmd = isset(IRC::$codes[$code]) ? IRC::$codes[$code] : 'UNKNOWN-' . $code; } $this->onCommand($cmd, $args); } if (strlen($this->buf) > 512) { Daemon::$process->log('IRCClientConnection error: buffer overflow.'); $this->finish(); } }
public final function baz() { return function ($jobname, $job) { \PHPDaemon\Core\Timer::add(function ($event) use($jobname, $job) { // Job done $job->setResult($jobname, ['job' => 'baz', 'success' => false, 'line' => __LINE__]); $event->finish(); }, 1000.0 * 300); }; }
/** * Called when new data received * @return void */ public function onRead() { Timer::setTimeout($this->keepaliveTimer); if (isset($this->xml)) { $this->xml->feed($this->readUnlimited()); } }
/** * On finish * @return void */ public function onFinish() { $this->appInstance->unsubscribe('s2c:' . $this->sessId, [$this, 's2c']); $this->appInstance->unsubscribe('w8in:' . $this->sessId, [$this, 'w8in']); Timer::remove($this->heartbeatTimer); if ($this->heartbeatOnFinish) { $this->sendFrame('h'); } parent::onFinish(); }
/** * @TODO DESCR * @return void */ public function onFinish() { Timer::remove($this->heartbeatTimer); if ($this->realRoute) { $this->realRoute->onFinish(); $this->realRoute = null; } }
/** * Runtime of Master process * @return void */ protected function run() { Daemon::$process = $this; $this->prepareSystemEnv(); class_exists('Timer'); // ensure loading this class gc_enable(); /* This line must be commented according to current libevent binding implementation. May be uncommented in future. */ //$this->eventBase = new \EventBase; if ($this->eventBase) { $this->registerEventSignals(); } else { $this->registerSignals(); } $this->workers = new Collection(); $this->collections['workers'] = $this->workers; $this->ipcthreads = new Collection(); $this->collections['ipcthreads'] = $this->ipcthreads; Daemon::$appResolver->preload(true); $this->callbacks = new StackCallbacks(); $this->spawnIPCThread(); $this->spawnWorkers(min(Daemon::$config->startworkers->value, Daemon::$config->maxworkers->value)); $this->timerCb = function ($event) use(&$cbs) { static $c = 0; ++$c; if ($c > 0xfffff) { $c = 1; } if ($c % 10 == 0) { gc_collect_cycles(); } if (!$this->lastMpmActionTs || microtime(true) - $this->lastMpmActionTs > $this->minMpmActionInterval) { $this->callMPM(); } if ($event) { $event->timeout(); } }; if ($this->eventBase) { // we are using libevent in Master Timer::add($this->timerCb, 1000000.0 * Daemon::$config->mpmdelay->value, 'MPM'); while (!$this->breakMainLoop) { $this->callbacks->executeAll($this); if (!$this->eventBase->dispatch()) { break; } } } else { // we are NOT using libevent in Master $lastTimerCall = microtime(true); while (!$this->breakMainLoop) { $this->callbacks->executeAll($this); if (microtime(true) > $lastTimerCall + Daemon::$config->mpmdelay->value) { call_user_func($this->timerCb, null); $lastTimerCall = microtime(true); } $this->sigwait(); } } }
/** * @see \FutoIn\RI\Details\AsyncToolImpl::cancelCall */ public function cancelCall($ref) { \PHPDaemon\Core\Timer::remove($ref->id); }