beforeAgents = $data['EventManager.beforeRegularEvents']; $this->afterAgents = $data['EventManager.afterRegularEvents']; } /** * Gets object data for caching * * @return Array * @access public */ public function getToCache() { return Array ( 'EventManager.beforeRegularEvents' => $this->beforeAgents, 'EventManager.afterRegularEvents' => $this->afterAgents, ); } /** * Returns information about registered agents * * @param bool $from_cache * @return Array * @access public */ public function getAll($from_cache = false) { static $agents = null; if ($from_cache) { return Array ( reBEFORE => $this->beforeAgents, reAFTER => $this->afterAgents, ); } if ( !isset($agents) ) { $timeout_clause = 'LastRunStatus = ' . Agent::LAST_RUN_RUNNING . ' AND Timeout > 0 AND ' . adodb_mktime() . ' - LastRunOn > Timeout'; $sql = 'SELECT * FROM ' . $this->Application->getUnitOption('agent', 'TableName') . ' WHERE (Status = ' . STATUS_ACTIVE . ') AND ((LastRunStatus != ' . Agent::LAST_RUN_RUNNING . ') OR (' . $timeout_clause . '))'; $all_agents = $this->Conn->Query($sql); $agents = Array ( reBEFORE => Array (), reAFTER => Array (), ); foreach ($all_agents as $agent_data) { $agents[ $agent_data['RunMode'] ][ $agent_data['AgentName'] ] = Array ( 'EventName' => $agent_data['Event'], 'RunInterval' => (int)$agent_data['RunInterval'], 'LastRunOn' => (int)$agent_data['LastRunOn'], 'NextRunOn' => (int)$agent_data['NextRunOn'], 'Status' => $agent_data['Status'], 'LastRunStatus' => $agent_data['LastRunStatus'], 'SiteDomainLimitation' => $agent_data['SiteDomainLimitation'], ); } } return $agents; } /** * Returns agents by type * * @param int $type * @return Array * @access protected */ protected function &getAgentsByType($type) { if ($type == reBEFORE) { return $this->beforeAgents; } return $this->afterAgents; } /** * Add new agent * * @param string $short_name name to be used to store last maintenance run info * @param string $event_name * @param int $run_interval run interval in seconds * @param int $type before or after agent * @param int $status * @access public */ public function add($short_name, $event_name, $run_interval, $type = reBEFORE, $status = STATUS_ACTIVE) { $agents =& $this->getAgentsByType($type); $agents[$short_name] = Array ( 'EventName' => $event_name, 'RunInterval' => $run_interval, 'Status' => $status ); } /** * Run registered agents with specified event type * * @param int $event_type * @param bool $from_cron * @access public */ public function runAgents($event_type = reBEFORE, $from_cron = false) { if ( defined('IS_INSTALL') ) { return ; } if ( !$from_cron && $this->Application->ConfigValue('UseCronForRegularEvent') ) { // if RegularEvents are set to run from cron return ; } $agents = $this->getAll(); $events_source = $agents[$event_type]; $user_id = $this->Application->RecallVar('user_id'); $this->Application->StoreVar('user_id', USER_ROOT, true); // to prevent permission checking inside events, true for optional storage $site_helper =& $this->Application->recallObject('SiteHelper'); /* @var $site_helper SiteHelper */ $site_domain_id = $site_helper->getDomainByName('DomainName', DOMAIN); foreach ($events_source as $short_name => $event_data) { if ( $site_domain_id && $event_data['SiteDomainLimitation'] != '' ) { $site_domains = explode('|', substr($event_data['SiteDomainLimitation'], 1, -1)); if ( !in_array($site_domain_id, $site_domains) ) { // agent isn't allowed on this site domain continue; } } // remember LastTimeoutOn only for events that are still running and will be reset if ( $event_data['LastRunStatus'] == Agent::LAST_RUN_RUNNING ) { $this->updateAgent($short_name, Array ('LastTimeoutOn' => adodb_mktime())); } $next_run = $event_data['NextRunOn']; if ($next_run && ($next_run > adodb_mktime())) { continue; } $event_data['AgentName'] = $short_name; $this->runAgent($event_data); } $this->Application->StoreVar('user_id', $user_id, $user_id == USER_GUEST); } /** * Runs agent based on given data * * @param Array $agent_data * @return bool * @access public */ public function runAgent($agent_data) { $event = new kEvent($agent_data['EventName']); if ( !$this->Application->prefixRegistred($event->Prefix) ) { // don't process agents, left from disabled modules return false; } $start_time = adodb_mktime(); // remember, when agent execution started $fields_hash = Array ( 'LastRunOn' => $start_time, 'LastRunStatus' => Agent::LAST_RUN_RUNNING, 'NextRunOn' => $start_time + $agent_data['RunInterval'], ); $this->updateAgent($agent_data['AgentName'], $fields_hash); $event->redirect = false; $this->Application->HandleEvent($event); $now = adodb_mktime(); $next_run = $agent_data['RunInterval'] ? $start_time + $agent_data['RunInterval'] : $now; while ($next_run < $now) { // in case event execution took longer, then RunInterval (don't use <=, because RunInterval can be 0) $next_run += $agent_data['RunInterval']; } // remember, when agent execution ended $fields_hash = Array ( 'NextRunOn' => $next_run, 'RunTime' => round(($now - $start_time) / 60), 'LastRunStatus' => $event->status == kEvent::erSUCCESS ? Agent::LAST_RUN_SUCCEDED : Agent::LAST_RUN_FAILED, ); $this->updateAgent($agent_data['AgentName'], $fields_hash); return true; } /** * Updates agent record with latest changes about it's invocation progress * * @param string $agent_name * @param Array $fields_hash * @return void * @access protected */ protected function updateAgent($agent_name, $fields_hash) { $this->Conn->doUpdate( $fields_hash, $this->Application->getUnitOption('agent', 'TableName'), 'AgentName = ' . $this->Conn->qstr($agent_name) ); } }