/** * Add sync process and associated locks to database */ private static function addUploadProcess($userID, $libraryIDs, $syncQueueID = null, $syncProcessID = null) { Zotero_DB::beginTransaction(); $syncProcessID = $syncProcessID ? $syncProcessID : Zotero_ID::getBigInt(); $sql = "INSERT INTO syncProcesses (syncProcessID, userID) VALUES (?, ?)"; try { Zotero_DB::query($sql, array($syncProcessID, $userID)); } catch (Exception $e) { $sql = "SELECT CONCAT(syncProcessID,' ',userID,' ',started) FROM syncProcesses WHERE userID=?"; $val = Zotero_DB::valueQuery($sql, $userID); Z_Core::logError($val); } if ($libraryIDs) { $sql = "INSERT INTO syncProcessLocks VALUES "; $sql .= implode(', ', array_fill(0, sizeOf($libraryIDs), '(?,?)')); $params = array(); foreach ($libraryIDs as $libraryID) { $params[] = $syncProcessID; $params[] = $libraryID; } Zotero_DB::query($sql, $params); } // Record the process id in the queue entry, if given if ($syncQueueID) { $sql = "UPDATE syncUploadQueue SET syncProcessID=? WHERE syncUploadQueueID=?"; Zotero_DB::query($sql, array($syncProcessID, $syncQueueID)); } Zotero_DB::commit(); return $syncProcessID; }
public function run() { // Catch TERM and unregister from the database //pcntl_signal(SIGTERM, array($this, 'handleSignal')); //pcntl_signal(SIGINT, array($this, 'handleSignal')); $this->log("Starting " . $this->mode . " processor daemon"); $this->register(); // Bind $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); $success = socket_bind($socket, $this->addr, $this->port); if (!$success) { $code = socket_last_error($socket); $this->unregister(); die(socket_strerror($code)); } $buffer = 'GO'; $mode = null; $first = true; $lastPurge = 0; do { if ($first) { $first = false; } else { //$this->log("Waiting for command"); $from = ''; $port = 0; socket_recvfrom($socket, $buffer, 32, MSG_WAITALL, $from, $port); } //pcntl_signal_dispatch(); // Processor return value if (preg_match('/^(DONE|NONE|LOCK|ERROR) ([0-9]+)/', $buffer, $return)) { $signal = $return[1]; $id = $return[2]; $this->removeProcessor($id); if ($signal == "DONE" || $signal == "ERROR") { } else { if ($signal == "NONE") { continue; } else { if ($signal == "LOCK") { $this->log("LOCK received — waiting " . $this->lockWait . " second" . $this->pluralize($this->lockWait)); sleep($this->lockWait); } } } $buffer = "GO"; } if ($buffer == "NEXT" || $buffer == "GO") { if ($lastPurge == 0) { $lastPurge = microtime(true); } else { if (microtime(true) - $lastPurge >= $this->minPurgeInterval) { $purged = $this->purgeProcessors(); $this->log("Purged {$purged} lost processor" . $this->pluralize($purged)); $purged = $this->purgeOldProcesses(); $this->log("Purged {$purged} old process" . $this->pluralize($purged, "es")); $lastPurge = microtime(true); } } $numProcessors = $this->countProcessors(); if ($numProcessors >= $this->maxProcessors) { //$this->log("Already at max " . $this->maxProcessors . " processors"); continue; } try { $queuedProcesses = $this->countQueuedProcesses(); $this->log($numProcessors . " processor" . $this->pluralize($numProcessors) . ", " . $queuedProcesses . " queued process" . $this->pluralize($queuedProcesses, "es")); // Nothing queued, so go back and wait if (!$queuedProcesses) { continue; } // Wanna be startin' somethin' $maxToStart = $this->maxProcessors - $numProcessors; if ($queuedProcesses > $maxToStart) { $toStart = $maxToStart; } else { $toStart = 1; } if ($toStart <= 0) { $this->log("No processors to start"); continue; } $this->log("Starting {$toStart} new processor" . $this->pluralize($toStart)); // Start new processors for ($i = 0; $i < $toStart; $i++) { $id = Zotero_ID::getBigInt(); $pid = shell_exec(Z_CONFIG::$CLI_PHP_PATH . " " . Z_ENV_BASE_PATH . "processor/" . $this->mode . "/processor.php {$id} > /dev/null & echo \$!"); $this->processors[$id] = $pid; } } catch (Exception $e) { // If lost connection to MySQL, exit so we can be restarted if (strpos($e->getMessage(), "MySQL error: MySQL server has gone away") === 0) { $this->log($e); $this->log("Lost connection to DB — exiting"); exit; } $this->log($e); } } } while ($buffer != 'QUIT'); $this->log("QUIT received — exiting"); $this->unregister(); }