public function sieve($start, $end) { $primes = array(); // The sieve is designed to work from 3 and above. // We know that "2" is a Prime. So if $start is less than "3", we will prepend the array with "2". // But in some cases, "1" is considered prime, and in others not. For our purposes, we've put a setting in the ini file to resolve this issue. // The daemon() method on the mediator allows us to import objects/properties from the daemon by name if ($start < 3) { $settings = $this->mediator->daemon('settings'); if ($start < 1 && $settings['default']['is_one_prime']) { $primes = array(1, 2); } else { $primes = array(2); } $start = 3; } // This is an example of how you can add in custom breakpoints that will be active when you run // your daemon with the --debugworkers flag set. $this->mediator->breakpoint("Something Is Happeneing in sieve! Oh Noes!"); for ($i = $start; $i <= $end; $i++) { if ($i % 2 != 1) { continue; } $d = 3; $x = sqrt($i); while ($i % $d != 0 && $d < $x) { $d += 2; } if (($i % $d == 0 && $i != $d) * 1 == 0) { $primes[] = $i; } } return $primes; }
/** * Poll the API for updated information -- Simulate an API call of varying duration. * @param Credential $credential * @return void * @throws \ConnectionException */ public function poll(Credential $credential) { $client = new Client($credential, Pdo::createInstance(), new CoreWorkerMediator($this->mediator)); try { while (true) { $client->pollMessages(); $client->sendMessages(); } } catch (\Exception $e) { $this->mediator->log("error: " . $e->getMessage() . "\n" . $e->getTraceAsString()); } }
public function check_environment(array $errors = array()) { $errors = array(); if (!is_object($this->object) || !$this->object instanceof Core_IWorker) { $errors[] = 'Invalid worker object. Workers must implement Core_IWorker'; } $object_errors = $this->object->check_environment(); if (is_array($object_errors)) { $errors = array_merge($errors, $object_errors); } return parent::check_environment($errors); }
/** * Poll the API for updated information -- Simulate an API call of varying duration. * @return Array Return associative array of results */ public function poll(array $existing_results) { static $calls = 0; $calls++; $this->results = $existing_results; $this->mediator->log('Calling API...'); // Simulate an API call of varying length $rand = mt_rand(1, 10); switch ($rand) { case 1: $ttl = 4; break; case 2: case 3: $ttl = 8; break; case 8: case 9: $ttl = 16; break; case 10: $ttl = 20; break; default: $ttl = 12; } // Sleep for $ttl seconds to simulate API request time sleep($ttl); // If this is our first call, create initial results if ($calls == 1) { $this->results['customers'] = mt_rand(100, 1000); $this->results['sales'] = $this->results['customers'] * mt_rand(20, 100); return $this->results; } // Increase the stats in our results array accordingly $multiplier = mt_rand(100, 125) / 100; $this->results['customers'] = intval($this->results['customers'] * $multiplier); $this->results['sales'] = intval($this->results['sales'] * $multiplier); return $this->results; }
/** * Handle IPC Errors * @param $error * @param int $try Inform error() of repeated failures of the same $error_code * @return boolean Returns true if the operation should be retried. */ public function error($error, $try = 1) { // Create an array of random, moderate size and verify it can be written to shared memory // Return boolean $that = $this; $test = function () use($that) { $arr = array_fill(0, mt_rand(10, 100), mt_rand(1000, 1000 * 1000)); $key = mt_rand(1000 * 1000, 2000 * 1000); @shm_put_var($that->shm, $key, $arr); usleep(5000); return @shm_get_var($that->shm, $key) == $arr; }; switch ($error) { case 0: // Success // Success case 4: // System Interrupt // System Interrupt case MSG_ENOMSG: // No message of desired type // Ignored Errors return true; break; case MSG_EAGAIN: // Temporary Problem, Try Again usleep($this->mediator->backoff(20000, $try)); return true; break; case 13: // Permission Denied $this->mediator->count_error('communication'); $this->mediator->log('Permission Denied: Cannot connect to message queue'); $this->purge_mq(); if (Core_Daemon::is('parent')) { usleep($this->mediator->backoff(100000, $try)); } else { sleep($this->mediator->backoff(3, $try)); } $this->setup_ipc(); return true; break; case 22: // Invalid Argument // Probably because the queue was removed in another process. // Invalid Argument // Probably because the queue was removed in another process. case 43: // Identifier Removed // A message queue was re-created at this address but the resource identifier we have needs to be re-created $this->mediator->count_error('communication'); if (Core_Daemon::is('parent')) { usleep($this->mediator->backoff(20000, $try)); } else { sleep($this->mediator->backoff(2, $try)); } $this->setup_ipc(); return true; break; case self::ERROR_UNKNOWN: // Almost certainly an issue with shared memory $this->mediator->log("Shared Memory I/O Error at Address {$this->mediator->guid}."); $this->mediator->count_error('corruption'); // If this is a worker, all we can do is try to re-attach the shared memory. // Any corruption or OOM errors will be handled by the parent exclusively. if (!Core_Daemon::is('parent')) { sleep($this->mediator->backoff(3, $try)); $this->setup_ipc(); return true; } // If this is the parent, do some diagnostic checks and attempt correction. usleep($this->mediator->backoff(20000, $try)); // Test writing to shared memory using an array that should come to a few kilobytes. for ($i = 0; $i < 2; $i++) { if ($test()) { return true; } // Re-attach the shared memory and try the diagnostic again $this->setup_ipc(); } $this->mediator->log("IPC DIAG: Re-Connect failed to solve the problem."); if (!$this->mediator->daemon->is('parent')) { break; } // Attempt to re-connect the shared memory // See if we can read what's in shared memory and re-write it later $items_to_copy = array(); $items_to_call = array(); for ($i = 0; $i < $this->mediator->call_count; $i++) { $call = @shm_get_var($this->shm, $i); if (!is_object($call)) { continue; } $cached = $this->mediator->get_struct($i); if (!is_object($cached)) { continue; } if ($cached->status == Core_Worker_Mediator::TIMEOUT) { continue; } if ($cached->status == Core_Worker_Mediator::UNCALLED) { $items_to_call[$i] = $call; continue; } $items_to_copy[$i] = $call; } $this->mediator->log("IPC DIAG: Preparing to clean SHM and Reconnect..."); for ($i = 0; $i < 2; $i++) { $this->purge_shm(); $this->setup_ipc(); if (!empty($items_to_copy)) { foreach ($items_to_copy as $key => $value) { @shm_put_var($this->shm, $key, $value); } } if (!$test()) { if (empty($items_to_copy)) { $this->mediator->fatal_error("Shared Memory Failure: Unable to proceed."); } else { $this->mediator->log('IPC DIAG: Purging items from shared memory: ' . implode(', ', array_keys($items_to_copy))); unset($items_to_copy); } } } foreach ($items_to_call as $call) { $this->mediator->retry($call); } return true; default: if ($error) { $this->mediator->log("Message Queue Error {$error}: " . posix_strerror($error)); } if (Core_Daemon::is('parent')) { usleep($this->mediator->backoff(100000, $try)); } else { sleep($this->mediator->backoff(3, $try)); } $this->mediator->count_error('catchall'); $this->setup_ipc(); return false; } }