if (!$forked) { exit(1); } // Avoid forking connection crash, renew the connection. Database::disconnect(); // Get maximum allowed connections before table lock. $capLimit = (int) @conf::get('system::crontab.process_limit'); if (!$capLimit) { $capLimit = Process::MAXIMUM_CAPACITY; } // Start transaction before lock tables. Database::beginTransaction(); // Pick next awaiting process Database::locKTables([FRAMEWORK_COLLECTION_PROCESS . ' READ']); $res = (int) Database::fetchField('SELECT IFNULL(SUM(`capacity`), 0) as occupation FROM `' . FRAMEWORK_COLLECTION_PROCESS . '` WHERE `pid` IS NOT NULL AND `pid` > 0'); Database::unlockTables(true); if ($res >= $capLimit) { Log::debug('Active processes has occupied maximum server capacity, daemon exits.'); Database::rollback(); die; } unset($res, $capLimit); Database::lockTables(array(FRAMEWORK_COLLECTION_PROCESS . ' LOW_PRIORITY WRITE', FRAMEWORK_COLLECTION_PROCESS . ' as `active` LOW_PRIORITY WRITE', FRAMEWORK_COLLECTION_PROCESS . ' as `inactive` LOW_PRIORITY WRITE')); $process = Database::fetchRow('SELECT `inactive`.* FROM `' . FRAMEWORK_COLLECTION_PROCESS . '` as `inactive` LEFT JOIN ( SELECT `type`, SUM(`capacity`) as `occupation` FROM `' . FRAMEWORK_COLLECTION_PROCESS . '` WHERE `pid` IS NOT NULL GROUP BY `type` ) as `active` ON `active`.`type` = `inactive`.`type` WHERE `timestamp` <= CURRENT_TIMESTAMP AND `start_time` <= CURRENT_TIMESTAMP
/** * @protected * * A TaskInstance can only be saved when, * 1. WorkInstance is mutable, or * 2. WorkInstance exists and this is creating, or * 3. WorkInstance is Open, and nextTask is empty or equals to this one. */ function beforeSave(array &$errors = array()) { $workInstance = $this->workInstance(); if ($workInstance->immutable()) { throw new FrameworkException('Task instance cannot be modified.'); } if (!$workInstance || $workInstance->state == $workInstance::STATE_CLOSE) { throw new FrameworkException('Work instance does not exist.'); } if ($this->isCreate()) { // note; loop until we find a unique uuid do { $this->identity(Database::fetchField("SELECT UNHEX(REPLACE(UUID(), '-', ''))")); } while ($this->find(array($this->primaryKey() => $this->identity()))); } else { if ($workInstance->nextTask != $this->identity()) { throw new FrameworkException('Task is not active.'); } } return parent::beforeSave($errors); }
/** * @protected * * Takes care of tasks and settings. */ function beforeSave(array &$errors = array()) { // packUuid if ($this->isCreate()) { // note; loop until we find a unique uuid do { $this->identity(Database::fetchField("SELECT UNHEX(REPLACE(UUID(), '-', ''))")); } while ($this->find(array($this->primaryKey() => $this->identity()))); } else { if (isset($this->uuid)) { $this->uuid = util::packUuid($this->uuid); } } parent::beforeSave($errors); if (!$errors) { if (empty($this->tasks)) { unset($this->tasks); } else { // Only take task identity and settings $this->tasks = array_reduce($this->tasks, function ($result, $task) { $taskModel = new Task($task); $taskModel->load($taskModel->identity()); if ($taskModel->identity()) { $result[] = array_filter(array('name' => $taskModel->name, 'version' => $taskModel->version, 'settings' => @$task['settings'])); } return $result; }, array()); \core\Log::info('Tasks', $this->tasks); } } return $this; }
/** * Generate a one-time authentication token string for additional * security for AJAX service calls. * * Each additional call to this function overwrites the token generated last time. * * @return One-time token string, or null on invalid session. */ static function generateToken($sid = null) { $res = static::ensure($sid); if ($res !== true) { return $res; } $res =& static::$currentSession; $res['token'] = Database::fetchField("SELECT UNHEX(REPLACE(UUID(),'-',''));"); unset($res['timestamp']); if (Node::set($res) === false) { return null; } return util::unpackUuid($res['token']); }
/** * Process POST data with current step. */ function beforeSave(array &$errors = array()) { // note; WorkInstance is locked from modification, except when staging and processing. if (!$this->isCreate() && $this->_immutable) { // todo; Validation messages is not yet put into play. $errors[] = 'Cannot modify work instance.'; throw new FrameworkException('Cannot modify work instance.'); } if ($this->state == static::STATE_CLOSE) { $this->nextTask = null; } // binary encode task uuid if (!empty($this->nextTask)) { $this->nextTask = util::packUuid($this->nextTask); } if (isset($this->uuid)) { $this->uuid = util::packUuid($this->uuid); } // reset empty data store if (empty($this->dataStore)) { unset($this->dataStore); } // note; task instances will not be created after work instance creation. if ($this->isCreate()) { // note; loop until we find a unique uuid do { $this->identity(Database::fetchField("SELECT UNHEX(REPLACE(UUID(), '-', ''))")); } while ($this->find(array($this->primaryKey() => $this->identity()))); // note; Only users with permission to first task can create. // note;security; Copy tasks from parent work again. if (empty($this->state)) { $this->state = static::STATE_OPEN; } $this->__tasks = array_reduce($this->work()->tasks, function ($result, $task) { $task = new TaskInstance($task); $task->workInstance($this); $task->order = count($result); $result[] = $task; return $result; }, array()); $task = reset($this->__tasks); if (!$task) { throw new FrameworkException('Unable to load work tasks.'); } if (!$this->__isInternal && !array_intersect((array) @$this->__request->user->groups, $task->userGroups())) { throw new FrameworkException('User has no permission to work on this.'); } } unset($this->tasks); return parent::beforeSave($errors); }