Author: Vasily Zorin (maintainer@daemon.io)
Inheritance: use trait PHPDaemon\Traits\ClassWatchdog, use trait PHPDaemon\Traits\StaticObjectWatchdog, use trait PHPDaemon\Traits\EventLoopContainer
Example #1
4
 /**
  * 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);
         }
     }));
 }
Example #2
0
 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;
 }
Example #3
0
 /**
  * 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;
 }
Example #4
0
 /**
  * @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']);
         }
     }
 }
Example #5
0
 /**
  * @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);
 }
Example #6
0
 /**
  * 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;
 }
Example #7
0
 /**
  * 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.
 }
Example #8
0
File: UDP.php Project: zenus/phpinx
 /**
  * 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;
 }
Example #9
0
 function clearTimeout($id)
 {
     \PHPDaemon\Core\Timer::remove($id);
 }
Example #10
0
 /**
  * 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();
     }
 }
Example #11
0
 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);
     };
 }
Example #12
0
 /**
  * Called when new data received
  * @return void
  */
 public function onRead()
 {
     Timer::setTimeout($this->keepaliveTimer);
     if (isset($this->xml)) {
         $this->xml->feed($this->readUnlimited());
     }
 }
Example #13
0
 /**
  * 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;
     }
 }
Example #15
0
 /**
  * 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);
 }