Author: Vasily Zorin (maintainer@daemon.io)
Inheritance: use trait PHPDaemon\Traits\ClassWatchdog, use trait PHPDaemon\Traits\StaticObjectWatchdog
Example #1
0
 /**
  * Magic __call
  * Example:
  * $redis->lpush('mylist', microtime(true));
  * @param  string $name Command name
  * @param  array  $args Arguments
  * @return void
  */
 public function __call($cmd, $args)
 {
     $cb = null;
     for ($i = sizeof($args) - 1; $i >= 0; --$i) {
         $a = $args[$i];
         if ((is_array($a) || is_object($a)) && is_callable($a)) {
             $cb = CallbackWrapper::wrap($a);
             $args = array_slice($args, 0, $i);
             break;
         } elseif ($a !== null) {
             break;
         }
     }
     reset($args);
     $cmd = strtoupper($cmd);
     if ($this->sendSubCommand($cmd, $args, $cb)) {
         return;
     }
     if ($cmd === 'SENTINEL' || !isset($this->config->sentinelmaster->value)) {
         $this->sendCommand(null, $cmd, $args, $cb);
         return;
     }
     if ($this->currentMasterAddr !== null) {
         $this->sendCommand($this->currentMasterAddr, $cmd, $args, $cb);
         return;
     }
     $this->sentinel('get-master-addr-by-name', $this->config->sentinelmaster->value, function ($redis) use($cmd, $args, $cb) {
         $this->currentMasterAddr = 'tcp://' . $redis->result[0] . ':' . $redis->result[1];
         $this->sendCommand($this->currentMasterAddr, $cmd, $args, $cb);
     });
 }
Example #2
0
 public function status($phone, $id, $cb, $all = 0)
 {
     $cb = CallbackWrapper::wrap($cb);
     $this->appInstance->httpclient->get(['http://smsc.ru/sys/status.php', 'login' => $this->config->login->value, 'psw' => $this->config->password->value, 'phone' => $phone, 'id' => $id, 'fmt' => 3, 'all' => $all], function ($conn, $success) use($cb) {
         call_user_func($cb, json_decode($conn->body, true));
     });
 }
Example #3
0
 /**
  * @param $cb
  * @param $type
  * @param $args
  */
 public function enqueue($cb, $type, $args, $add = [], $pushcb = null)
 {
     $ts = microtime(true);
     return $this->appInstance->jobqueue->push($type, $args, $ts, $add, function ($job) use($cb, $pushcb) {
         if ($cb !== NULL) {
             $this->callbacks[(string) MongoId::import($job->getId())] = CallbackWrapper::wrap($cb);
         }
         if ($pushcb !== null) {
             call_user_func($pushcb);
         }
     });
 }
 /**
  * Lookup a hash
  * @param $hash
  * @param $cb
  * @return $this
  */
 public function lookup($hash, $cb)
 {
     $cb = CallbackWrapper::wrap($cb);
     $cj = new ComplexJob(function ($cj) use($cb) {
         $cb(array_merge(...$cj->results));
     });
     foreach ($this->indexes as $name => $index) {
         $cj($name, function ($name, $cj) use($hash, $index) {
             $index->lookup($hash, function ($res) use($cj, $name) {
                 $cj[$name] = $res;
             });
         });
     }
     $cj();
     return $this;
 }
Example #5
0
 /**
  * Constructor
  * @param  Pool    $pool   Redis pool or connection
  * @param  string  $cmd    Command
  * @param  array   $args   Arguments
  * @param  cllable $cbEnd  Callback
  * @param  integer $limit  Limit
  */
 public function __construct($pool, $cmd, $args = [], $cbEnd = null, $limit = false)
 {
     $this->conn = $pool;
     $this->cmd = $cmd;
     $this->args = empty($args) ? [] : $args;
     $this->limit = $limit;
     if (is_numeric($this->args[0])) {
         array_shift($this->args);
     }
     for ($i = sizeof($this->args) - 1; $i >= 0; --$i) {
         $a = $this->args[$i];
         if ((is_array($a) || is_object($a)) && is_callable($a)) {
             $this->cb = CallbackWrapper::wrap($a);
             $this->args = array_slice($this->args, 0, $i);
             break;
         } elseif ($a !== null) {
             break;
         }
     }
     if ($cbEnd !== null) {
         $this->cbEnd = CallbackWrapper::wrap($cbEnd);
     }
     $this->doIteration();
 }
Example #6
0
 /**
  * Commmit session data
  * @param  callable $cb Callback
  * @return void
  */
 public function sessionCommit($cb = null)
 {
     if (!$this->sessionFp || $this->sessionFlushing) {
         if ($cb) {
             call_user_func($cb, false);
         }
         return;
     }
     $this->sessionFlushing = true;
     $data = $this->sessionEncode();
     $l = strlen($data);
     $cb = CallbackWrapper::wrap($cb);
     $this->sessionFp->write($data, function ($file, $result) use($l, $cb) {
         $file->truncate($l, function ($file, $result) use($cb) {
             $this->sessionFlushing = false;
             if ($cb) {
                 call_user_func($cb, true);
             }
         });
     });
 }
Example #7
0
 /**
  * Push callback to the top of stack
  * @param  callable $cb Callback
  * @return void
  */
 public function unshift($cb)
 {
     parent::unshift(CallbackWrapper::wrap($cb));
 }
Example #8
0
 /**
  * @TODO
  * @param  string   $name
  * @param  array    $args
  * @param  callable $cb
  * @callback $cb ( )
  * @return void
  */
 public function command($name, $args, $cb = null)
 {
     if ($name === 'MULTI') {
         $this->acquire();
     } elseif (substr($name, -9) === 'SUBSCRIBE') {
         if (!$this->subscribed) {
             $this->subscribed = true;
             $this->pool->servConnSub[$this->url] = $this;
             $this->acquire();
             $this->setTimeouts(86400, 86400);
             // @TODO: remove timeout
         }
         $opcb = null;
         for ($i = sizeof($args) - 1; $i >= 0; --$i) {
             $a = $args[$i];
             if ((is_array($a) || is_object($a)) && is_callable($a)) {
                 $opcb = $cb;
                 $cb = CallbackWrapper::wrap($a);
                 $args = array_slice($args, 0, $i);
                 break;
             } elseif ($a !== null) {
                 break;
             }
         }
     }
     if ($name === 'SUBSCRIBE') {
         $this->subscribed();
         $channels = [];
         foreach ($args as $arg) {
             if (!is_array($arg)) {
                 $arg = [$arg];
             }
             foreach ($arg as $chan) {
                 $b = !isset($this->subscribeCb[$chan]);
                 CallbackWrapper::addToArray($this->subscribeCb[$chan], $cb);
                 if ($b) {
                     $channels[] = $chan;
                 } else {
                     if ($opcb !== null) {
                         call_user_func($opcb, $this);
                     }
                 }
             }
         }
         if (sizeof($channels)) {
             $this->sendCommand($name, $channels, $opcb);
         }
     } elseif ($name === 'PSUBSCRIBE') {
         $this->subscribed();
         $channels = [];
         foreach ($args as $arg) {
             if (!is_array($arg)) {
                 $arg = [$arg];
             }
             foreach ($arg as $chan) {
                 $b = !isset($this->psubscribeCb[$chan]);
                 CallbackWrapper::addToArray($this->psubscribeCb[$chan], $cb);
                 if ($b) {
                     $channels[] = $chan;
                 } else {
                     if ($opcb !== null) {
                         call_user_func($opcb, $this);
                     }
                 }
             }
         }
         if (sizeof($channels)) {
             $this->sendCommand($name, $channels, $opcb);
         }
     } elseif ($name === 'UNSUBSCRIBE') {
         $channels = [];
         foreach ($args as $arg) {
             if (!is_array($arg)) {
                 $arg = [$arg];
             }
             foreach ($arg as $chan) {
                 if (!isset($this->subscribeCb[$chan])) {
                     if ($opcb !== null) {
                         call_user_func($opcb, $this);
                     }
                     return;
                 }
                 CallbackWrapper::removeFromArray($this->subscribeCb[$chan], $cb);
                 if (sizeof($this->subscribeCb[$chan]) === 0) {
                     $channels[] = $chan;
                     unset($this->subscribeCb[$chan]);
                 } else {
                     if ($opcb !== null) {
                         call_user_func($opcb, $this);
                     }
                 }
             }
         }
         if (sizeof($channels)) {
             $this->sendCommand($name, $channels, $opcb);
         }
     } elseif ($name === 'UNSUBSCRIBEREAL') {
         /* Race-condition-free UNSUBSCRIBE */
         $old = $this->subscribeCb;
         $this->sendCommand('UNSUBSCRIBE', $args, function ($redis) use($cb, $args, $old) {
             if (!$redis) {
                 call_user_func($cb, $redis);
                 return;
             }
             foreach ($args as $arg) {
                 if (!isset($this->subscribeCb[$arg])) {
                     continue;
                 }
                 foreach ($old[$arg] as $oldcb) {
                     CallbackWrapper::removeFromArray($this->subscribeCb[$arg], $oldcb);
                 }
                 if (!sizeof($this->subscribeCb[$arg])) {
                     unset($this->subscribeCb[$arg]);
                 }
             }
             if ($cb !== null) {
                 call_user_func($cb, $this);
             }
         });
     } elseif ($name === 'PUNSUBSCRIBE') {
         $channels = [];
         foreach ($args as $arg) {
             if (!is_array($arg)) {
                 $arg = [$arg];
             }
             foreach ($arg as $chan) {
                 CallbackWrapper::removeFromArray($this->psubscribeCb[$chan], $cb);
                 if (sizeof($this->psubscribeCb[$chan]) === 0) {
                     $channels[] = $chan;
                     unset($this->psubscribeCb[$chan]);
                 } else {
                     if ($opcb !== null) {
                         call_user_func($opcb, $this);
                     }
                 }
             }
         }
         if (sizeof($channels)) {
             $this->sendCommand($name, $channels, $opcb);
         }
     } elseif ($name === 'PUNSUBSCRIBEREAL') {
         /* Race-condition-free PUNSUBSCRIBE */
         $old = $this->psubscribeCb;
         $this->sendCommand('PUNSUBSCRIBE', $args, function ($redis) use($cb, $args, $old) {
             if (!$redis) {
                 call_user_func($cb, $redis);
                 return;
             }
             foreach ($args as $arg) {
                 if (!isset($this->psubscribeCb[$arg])) {
                     continue;
                 }
                 foreach ($old[$arg] as $oldcb) {
                     CallbackWrapper::removeFromArray($this->psubscribeCb[$arg], $oldcb);
                 }
                 if (!sizeof($this->psubscribeCb[$arg])) {
                     unset($this->psubscribeCb[$arg]);
                 }
             }
             if ($cb !== null) {
                 call_user_func($cb, $this);
             }
         });
     } else {
         if ($name === 'MGET') {
             $this->resultTypeStack->push(static::RESULT_TYPE_ARGSVALS);
             $this->argsStack->push($args);
         } elseif ($name === 'HMGET') {
             $this->resultTypeStack->push(static::RESULT_TYPE_ARGSVALS);
             $a = $args;
             array_shift($a);
             $this->argsStack->push($a);
         } elseif ($name === 'HGETALL') {
             $this->resultTypeStack->push(static::RESULT_TYPE_ASSOC);
         } elseif (($name === 'ZRANGE' || $name === 'ZRANGEBYSCORE' || $name === 'ZREVRANGE' || $name === 'ZREVRANGEBYSCORE') && preg_grep('/WITHSCORES/i', $args)) {
             $this->resultTypeStack->push(static::RESULT_TYPE_ASSOC);
         } else {
             $this->resultTypeStack->push(static::RESULT_TYPE_DEFAULT);
         }
         $this->sendCommand($name, $args, $cb);
         if ($name === 'EXEC' || $name === 'DISCARD') {
             $this->release();
         }
     }
 }
Example #9
0
 /**
  * Open file
  * @param  string   $path  Path
  * @param  string   $flags Flags
  * @param  callable $cb    Callback (File)
  * @param  integer  $mode  Mode (see EIO_S_I* constants)
  * @param  integer  $pri   Priority
  * @return resource
  */
 public static function open($path, $flags, $cb, $mode = null, $pri = EIO_PRI_DEFAULT)
 {
     $cb = CallbackWrapper::forceWrap($cb);
     if (!FileSystem::$supported) {
         $mode = File::convertFlags($flags, true);
         $fd = fopen($path, $mode);
         if (!$fd) {
             call_user_func($cb, false);
             return false;
         }
         $file = new File($fd, $path);
         call_user_func($cb, $file);
         return true;
     }
     $fdCacheKey = $path . "" . $flags;
     $noncache = strpos($flags, '!') !== false;
     $flags = File::convertFlags($flags);
     if (!$noncache && ($item = FileSystem::$fdCache->get($fdCacheKey))) {
         // cache hit
         $file = $item->getValue();
         if ($file === null) {
             // operation in progress
             $item->addListener($cb);
         } else {
             // hit
             call_user_func($cb, $file);
         }
         return null;
     } elseif (!$noncache) {
         $item = FileSystem::$fdCache->put($fdCacheKey, null);
         $item->addListener($cb);
     }
     return eio_open($path, $flags, $mode, $pri, function ($path, $fd) use($cb, $flags, $fdCacheKey, $noncache) {
         if ($fd === -1) {
             if ($noncache) {
                 call_user_func($cb, false);
             } else {
                 FileSystem::$fdCache->put($fdCacheKey, false, self::$badFDttl);
             }
             return;
         }
         $file = new File($fd, $path);
         $file->append = ($flags | EIO_O_APPEND) === $flags;
         if ($file->append) {
             $file->stat(function ($file, $stat) use($cb, $noncache, $fdCacheKey) {
                 $file->offset = $stat['size'];
                 if (!$noncache) {
                     $file->fdCacheKey = $fdCacheKey;
                     FileSystem::$fdCache->put($fdCacheKey, $file);
                 } else {
                     call_user_func($cb, $file);
                 }
             });
         } else {
             if (!$noncache) {
                 $file->fdCacheKey = $fdCacheKey;
                 FileSystem::$fdCache->put($fdCacheKey, $file);
             } else {
                 call_user_func($cb, $file);
             }
         }
     }, $path);
 }
Example #10
0
 /**
  * Move pointer to arbitrary position
  * @param  integer $offset Offset
  * @param  callable $cb Callback
  * @param  integer $pri Priority
  * @return resource|false
  */
 public function seek($offset, $cb, $pri = EIO_PRI_DEFAULT)
 {
     $cb = CallbackWrapper::forceWrap($cb);
     if (!\EIO::$supported) {
         fseek($this->fd, $offset);
         return false;
     }
     return eio_seek($this->fd, $offset, $pri, $cb, $this);
 }
Example #11
0
 /**
  * Sets callback which will be called once when got EOF
  * @param  callable $cb
  * @return this
  */
 public function onEOF($cb = NULL)
 {
     $this->onEOF = CallbackWrapper::wrap($cb);
     return $this;
 }
Example #12
0
 /**
  * Aggregate function
  * @param  array $p Hash of properties (offset, limit, opts, key, col)
  * @param  callable $cb Callback called when response received
  * @callback $cb ( )
  * @return void
  */
 public function aggregate($p, $cb)
 {
     $this->_params($p);
     $e = explode('.', $p['col'], 2);
     $query = ['aggregate' => $e[1]];
     if (isset($p['rp'])) {
         $query['$readPreference'] = $p['rp'];
         unset($p['rp']);
     }
     foreach ($p as $k => $v) {
         if (substr($k, 0, 1) === '$' || $k === 'pipeline') {
             $query[$k] = $v;
         }
     }
     $cb = CallbackWrapper::wrap($cb);
     try {
         $this->request(self::OP_QUERY, pack('V', $p['opts']) . $e[0] . '.$cmd' . "" . pack('VV', $p['offset'], $p['limit']) . bson_encode($query) . (isset($p['fields']) ? bson_encode($p['fields']) : ''), true, null, function ($conn, $reqId = null) use($p, $cb) {
             if (!$conn) {
                 !$cb || $cb(['$err' => 'Connection error.']);
                 return;
             }
             $conn->requests[$reqId] = [$p['col'], $cb, false];
         });
     } catch (\MongoException $e) {
         Daemon::log('MongoClient exception: ' . $e->getMessage() . ': ' . $e->getTraceAsString());
         if ($cb !== null) {
             $cb(['$err' => $e->getMessage(), '$query' => $query, '$fields' => isset($p['fields']) ? $p['fields'] : null]);
         }
     }
 }
Example #13
0
 /**
  * Adds listener
  * @param  callable $cb Callback
  * @return void
  */
 public function addListener($cb)
 {
     if ($this->state === self::STATE_DONE) {
         call_user_func($cb, $this);
         return;
     }
     $this->listeners[] = CallbackWrapper::wrap($cb);
 }
Example #14
0
 public function setCallback($cb)
 {
     $this->callback = CallbackWrapper::wrap($cb);
 }
Example #15
0
 /**
  * Sends arbitrary command
  * @param string   $packet    A packet for sending by the connected client to Asterisk
  * @param callable $cb        Callback called when response received
  * @param array    $assertion If more events may follow as response this is a main part or full an action complete event indicating that all data has been sent
  */
 protected function command($packet, $cb, $assertion = null)
 {
     if ($this->finished) {
         throw new ConnectionFinished();
     }
     if ($this->state !== self::CONN_STATE_HANDSHAKED_OK) {
         return;
     }
     $actionId = Daemon::uniqid();
     if (!is_callable($cb, true)) {
         $cb = false;
     }
     $this->callbacks[$actionId] = CallbackWrapper::wrap($cb);
     if ($assertion !== null) {
         $this->assertions[$actionId] = $assertion;
     }
     $this->write($packet);
     $this->write('ActionID: ' . $actionId . "\r\n\r\n");
 }
Example #16
0
 /**
  * Unbind event(s) or callback from event(s)
  * @param string|array $event Event name
  * @param callable     $cb    Callback, optional
  * @return this
  */
 public function unbind($event, $cb = null)
 {
     if ($cb !== null) {
         $cb = CallbackWrapper::wrap($cb);
     }
     is_array($event) or $event = [$event];
     $success = true;
     foreach ($event as $e) {
         if (!isset($this->eventHandlers[$e])) {
             $success = false;
             continue;
         }
         if ($cb === null) {
             unset($this->eventHandlers[$e]);
             continue;
         }
         CallbackWrapper::removeFromArray($this->eventHandlers[$e], $cb);
     }
     return $this;
 }
 /**
  * Enqueue callback
  * @param  callable $cb Callback
  * @param  integer $pri Priority
  * @return void
  */
 public function enqueue($cb, $pri = 0)
 {
     parent::insert(CallbackWrapper::wrap($cb), $pri);
 }
Example #18
0
 /**
  * Returns string of pseudo random bytes
  * @param  integer $len Length of desired string
  * @param  callable $cb Callback
  * @param  integer $pri Priority of EIO operation
  * @param  boolean $hang If true, we shall use /dev/random instead of /dev/urandom and it may cause a delay
  * @return integer
  */
 public static function randomBytes($len, $cb, $pri = 0, $hang = false)
 {
     $cb = CallbackWrapper::wrap($cb);
     FileSystem::open('/dev/' . ($hang ? '' : 'u') . 'random', 'r', function ($file) use($len, $cb, $pri) {
         if (!$file) {
             $cb(false);
             return;
         }
         $file->read($len, 0, function ($file, $data) use($cb) {
             $cb($data);
         }, $pri);
     }, null, $pri);
 }
Example #19
0
 /**
  * Adds listener
  * @param callable $cb
  */
 public function addListener($cb)
 {
     $this->listeners[] = CallbackWrapper::wrap($cb);
 }
Example #20
0
 /**
  * Lookup a hash
  * @param $hash
  * @param $cb
  * @return $this
  */
 public function lookup($hash, $cb)
 {
     $cb = CallbackWrapper::wrap($cb);
     if (!$this->count()) {
         $this->queue->push(function () use($hash, $cb) {
             $this->lookup($hash, $cb);
         });
         return;
     }
     if (!$this->valid()) {
         $this->rewind();
     }
     $process = $this->current();
     $process->lookup($hash, $cb);
     $this->next();
     return $this;
 }