/**
  * Set start or finish time in metadata of the socket
  *
  * @param RequestDescriptor $requestDescriptor Socket meta data
  * @param string            $key Metadata key to set
  *
  * @return void
  * @throws \InvalidArgumentException
  */
 protected function setSocketOperationTime(RequestDescriptor $requestDescriptor, $key)
 {
     $meta = $requestDescriptor->getMetadata();
     $table = [RequestExecutorInterface::META_CONNECTION_START_TIME => $meta[RequestExecutorInterface::META_CONNECTION_START_TIME] === null, RequestExecutorInterface::META_CONNECTION_FINISH_TIME => $meta[RequestExecutorInterface::META_CONNECTION_FINISH_TIME] === null, RequestExecutorInterface::META_LAST_IO_START_TIME => $meta[RequestExecutorInterface::META_CONNECTION_FINISH_TIME] !== null];
     if (isset($table[$key]) && $table[$key]) {
         $requestDescriptor->setMetadata($key, microtime(true));
     }
 }
Пример #2
0
 /**
  * Disconnects given socket descriptor
  *
  * @param RequestDescriptor $descriptor Socket descriptor
  *
  * @return void
  */
 public function disconnect(RequestDescriptor $descriptor)
 {
     $meta = $descriptor->getMetadata();
     $socket = $descriptor->getSocket();
     $descriptor->setMetadata(RequestExecutorInterface::META_REQUEST_COMPLETE, true);
     try {
         $socket->close();
         if ($meta[RequestExecutorInterface::META_CONNECTION_FINISH_TIME] !== null) {
             $this->callSocketSubscribers($descriptor, $this->createEvent($descriptor, EventType::DISCONNECTED));
         }
     } catch (SocketException $e) {
         $this->callExceptionSubscribers($descriptor, $e);
     }
     $this->callSocketSubscribers($descriptor, $this->createEvent($descriptor, EventType::FINALIZE));
     $this->removeOperationsFromSelector($descriptor);
 }
Пример #3
0
 /**
  * Fire timeout event and processes user response
  *
  * @param RequestDescriptor $descriptor
  *
  * @return bool True if we may do one more attempt, false otherwise
  */
 public function handleTimeoutOnDescriptor(RequestDescriptor $descriptor)
 {
     $meta = $descriptor->getMetadata();
     $event = new TimeoutEvent($this->executor, $descriptor->getSocket(), $meta[RequestExecutorInterface::META_USER_CONTEXT], $meta[RequestExecutorInterface::META_CONNECTION_FINISH_TIME] !== null && !$descriptor->getSocket() instanceof ServerSocket ? TimeoutEvent::DURING_IO : TimeoutEvent::DURING_CONNECTION);
     try {
         $this->callSocketSubscribers($descriptor, $event);
         $result = $event->isNextAttemptEnabled();
     } catch (SocketException $e) {
         $this->callExceptionSubscribers($descriptor, $e);
         $result = false;
     }
     if ($result) {
         $this->updateMetadataForAttempt($descriptor, $event->when());
     }
     return $result;
 }
Пример #4
0
 /**
  * Decide how to process given operation
  *
  * @param RequestDescriptor $requestDescriptor Operation to decide
  * @param int               $totalItems Total amount of pending requestDescriptors
  *
  * @return int One of LimitationSolverInterface::DECISION_* consts
  */
 private function decide(RequestDescriptor $requestDescriptor, $totalItems)
 {
     $meta = $requestDescriptor->getMetadata();
     if ($requestDescriptor->isRunning()) {
         return LimitationSolverInterface::DECISION_SKIP_CURRENT;
     }
     $isSkippingThis = $meta[RequestExecutorInterface::META_CONNECTION_START_TIME] !== null;
     if ($isSkippingThis) {
         return LimitationSolverInterface::DECISION_SKIP_CURRENT;
     }
     $decision = $this->decider->decide($this->executor, $requestDescriptor->getSocket(), $totalItems);
     if ($decision !== LimitationSolverInterface::DECISION_OK) {
         return $decision;
     }
     return LimitationSolverInterface::DECISION_OK;
 }
Пример #5
0
 /**
  * Handle OOB data
  *
  * @param RequestDescriptor        $descriptor Request descriptor
  * @param RequestExecutorInterface $executor Executor, processing operation
  * @param EventHandlerInterface    $eventHandler Event handler for this operation
  *
  * @return OperationInterface|null Operation to return to user or null to continue normal processing
  */
 private function handleOobData(RequestDescriptor $descriptor, RequestExecutorInterface $executor, EventHandlerInterface $eventHandler)
 {
     if (!$descriptor->hasState(RequestDescriptor::RDS_OOB)) {
         return null;
     }
     $descriptor->clearState(RequestDescriptor::RDS_OOB);
     $picker = new RawFramePicker();
     $socket = $descriptor->getSocket();
     $meta = $descriptor->getMetadata();
     $frame = $socket->read($picker, true);
     $event = new ReadEvent($executor, $socket, $meta[RequestExecutorInterface::META_USER_CONTEXT], $frame, true);
     $eventHandler->invokeEvent($event);
     return $event->getNextOperation();
 }
 /**
  * Resolves timeout for setting up event
  *
  * @param RequestDescriptor $descriptor Descriptor object
  *
  * @return int
  */
 private function resolveTimeout(RequestDescriptor $descriptor)
 {
     $meta = $descriptor->getMetadata();
     $key = spl_object_hash($descriptor);
     $result = $meta[RequestExecutorInterface::META_IO_TIMEOUT];
     if (!isset($this->connectedDescriptors[$key])) {
         $result = $meta[RequestExecutorInterface::META_CONNECTION_TIMEOUT];
         $this->connectedDescriptors[$key] = true;
     }
     return $result;
 }
Пример #7
0
 /**
  * Notify handlers about exception
  *
  * @param RequestDescriptor $requestDescriptor Socket operation object
  * @param SocketException   $exception Thrown exception
  *
  * @return void
  */
 public function callExceptionSubscribers(RequestDescriptor $requestDescriptor, SocketException $exception)
 {
     if ($exception instanceof StopSocketOperationException) {
         return;
     }
     $meta = $requestDescriptor->getMetadata();
     $exceptionEvent = new SocketExceptionEvent($exception, $this->executor, $requestDescriptor->getSocket(), $meta[RequestExecutorInterface::META_USER_CONTEXT]);
     $this->callSocketSubscribers($requestDescriptor, $exceptionEvent);
 }
Пример #8
0
 /**
  * Set connection finish time and fire socket if it was not connected
  *
  * @param RequestDescriptor $requestDescriptor
  *
  * @return bool True, if there was no error, false if operation should be stopped
  */
 private function setConnectionFinishTime(RequestDescriptor $requestDescriptor)
 {
     $meta = $requestDescriptor->getMetadata();
     $wasConnected = $meta[RequestExecutorInterface::META_CONNECTION_FINISH_TIME] !== null;
     $this->setSocketOperationTime($requestDescriptor, RequestExecutorInterface::META_CONNECTION_FINISH_TIME);
     if (!$wasConnected) {
         $event = $this->createEvent($requestDescriptor, EventType::CONNECTED);
         try {
             $this->callSocketSubscribers($requestDescriptor, $event);
         } catch (SocketException $e) {
             $this->callExceptionSubscribers($requestDescriptor, $e);
             return false;
         }
     }
     return true;
 }
Пример #9
0
 /**
  * Check if this socket can be a zombie
  *
  * @param RequestDescriptor $descriptor Descriptor object
  *
  * @return bool
  */
 private function isZombieCandidate(RequestDescriptor $descriptor)
 {
     $metadata = $descriptor->getMetadata();
     if ($metadata[RequestExecutorInterface::META_REQUEST_COMPLETE]) {
         return false;
     }
     $operation = $descriptor->getOperation();
     return $operation instanceof NullOperation || $operation instanceof ReadOperation && $operation->getFramePicker() instanceof EmptyFramePicker;
 }
 /**
  * Check whether given descriptor is active
  *
  * @param RequestDescriptor $descriptor
  *
  * @return bool
  */
 private function isDescriptorActive(RequestDescriptor $descriptor)
 {
     $meta = $descriptor->getMetadata();
     return !$meta[RequestExecutorInterface::META_REQUEST_COMPLETE] && $descriptor->isRunning() && !$descriptor->isPostponed();
 }
Пример #11
0
 /**
  * Create simple event
  *
  * @param RequestDescriptor $operation Operation item
  * @param string            $eventName Event name for object
  *
  * @return Event
  */
 protected function createEvent(RequestDescriptor $operation, $eventName)
 {
     $meta = $operation->getMetadata();
     return new Event($this->executor, $operation->getSocket(), $meta[RequestExecutorInterface::META_USER_CONTEXT], $eventName);
 }