protected function _run() { // Run in a loop until we run out of time, or breakflag is set $registry = AliceFactory::getConfiguration(); $timer = AliceFactory::getTimer(); // Let's check if I already have a stack coming from previous call $this->log = $registry->get('volatile.alice.logToAnalyze'); $this->checks = $registry->get('volatile.alice.' . $this->checksName . '.checks', array()); $this->totalChecks = $registry->get('volatile.alice.' . $this->checksName . '.totalChecks', 0); // No incoming stack, let's build it now if (!$this->checks) { $this->checks = AliceUtilScripting::getChecksStack($this->checksName); $this->totalChecks = count($this->checks); } while ($timer->getTimeLeft() > 0 && !$registry->get('volatile.breakflag', false) && count($this->checks)) { if ($this->getState() == 'postrun') { AliceUtilLogger::WriteLog(_AE_LOG_DEBUG, __CLASS__ . " :: Already finished"); $this->setStep("-"); $this->setSubstep(""); break; } else { // Did I finished every check? if (!$this->checks) { return; } $error = ''; $solution = ''; $className = array_shift($this->checks); $check = new $className($this->log); $this->setSubstep($check->getName()); $this->progress = ($this->totalChecks - count($this->checks)) / $this->totalChecks; // Well, check, do your job! try { $check->check(); } catch (Exception $e) { // Mhm... log didn't passed the check. Let's save the error and the suggested solution $error = $e->getMessage(); $solution = $check->getSolution(); } $result = $check->getResult(); $feedback = $registry->get('volatile.alice.feedback', array()); $feedback[] = array('check' => $check->getName(), 'result' => $result, 'error' => $error, 'solution' => $solution); $registry->set('volatile.alice.feedback', $feedback); unset($check); } } // Let's save everything $registry->set('volatile.alice.requirements.checks', $this->checks); $registry->set('volatile.alice.requirements.totalChecks', $this->totalChecks); $this->setState('postrun'); }
/** * The public interface to an engine part. This method takes care for * calling the correct method in order to perform the initialisation - * run - finalisation cycle of operation and return a proper reponse array. * * @param int $nesting * * @return array A Reponse Array */ public final function tick($nesting = 0) { $configuration = AliceFactory::getConfiguration(); $timer = AliceFactory::getTimer(); // Call the right action method, depending on engine part state switch ($this->getState()) { case "init": $this->_prepare(); $breakFlag = $configuration->set('volatile.breakflag', false); break; case "prepared": $this->_run(); break; case "running": $this->_run(); break; case "postrun": $this->_finalize(); $breakFlag = $configuration->set('volatile.breakflag', false); break; } // If there is still time, we are not finished and there is no break flag set, re-run the tick() // method. $breakFlag = $configuration->get('volatile.breakflag', false); if (!in_array($this->getState(), array('finished', 'error')) && $timer->getTimeLeft() > 0 && !$breakFlag && $nesting < 20 && $this->nest_logging) { // Nesting is only applied if $this->nest_logging == true (currently only Kettenrad has this) $nesting++; if ($this->nest_logging) { AliceUtilLogger::WriteLog(_AE_LOG_DEBUG, "*** Batching successive steps (nesting level {$nesting})"); } $out = $this->tick($nesting); } else { // Return the output array $out = $this->_makeReturnTable(); // Things to do for nest-logged parts (currently, only Kettenrad is) if ($this->nest_logging) { if ($breakFlag) { AliceUtilLogger::WriteLog(_AE_LOG_DEBUG, "*** Engine steps batching: Break flag detected."); } // Reset the break flag $configuration->set('volatile.breakflag', false); // Log that we're breaking the step AliceUtilLogger::WriteLog(_AE_LOG_DEBUG, "*** Batching of engine steps finished. I will now return control to the caller."); // Enforce minimum execution time $timer = AliceFactory::getTimer(); $timer->enforce_min_exec_time(true); } } // Send a Return Table back to the caller return $out; }
protected function _run() { AliceUtilLogger::openLog($this->tag); set_error_handler('aliceBackupErrorHandler'); // Maybe we're already done or in an error state? if ($this->getError() || $this->getState() == 'postrun') { return; } // Set running state $this->setState('running'); // Initialize operation counter $registry = AliceFactory::getConfiguration(); $registry->set('volatile.operation_counter', 0); // Advance step counter $stepCounter = $registry->get('volatile.step_counter', 0); $registry->set('volatile.step_counter', ++$stepCounter); // Log step start number AliceUtilLogger::WriteLog(_AE_LOG_DEBUG, '====== Starting Step number ' . $stepCounter . ' ======'); $timer = AliceFactory::getTimer(); $finished = false; $error = false; $breakFlag = false; // BREAKFLAG is optionally passed by domains to force-break current operation // Apply an infinite time limit if required if ($registry->get('akeeba.tuning.settimelimit', 0)) { if (function_exists('set_time_limit')) { set_time_limit(0); } } $this->array_cache = null; // Loop until time's up, we're done or an error occurred, or BREAKFLAG is set while ($timer->getTimeLeft() > 0 && !$finished && !$error && !$breakFlag) { // Reset the break flag $registry->set('volatile.breakflag', false); // Do we have to switch domains? This only happens if there is no active // domain, or the current domain has finished $have_to_switch = false; if ($this->class == '') { $have_to_switch = true; } else { $object = AliceFactory::getDomainObject($this->class); if (!is_object($object)) { $have_to_switch = true; } else { if (!in_array('getState', get_class_methods($object))) { $have_to_switch = true; } else { if ($object->getState() == 'finished') { $have_to_switch = true; } } } } // Switch domain if necessary if ($have_to_switch) { // TODO Check what's the most conservative value and use it if (!AliceFactory::getConfiguration()->get('akeeba.tuning.nobreak.domains', 0)) { AliceUtilLogger::WriteLog(_AE_LOG_DEBUG, "Kettenrad :: BREAKING STEP BEFORE SWITCHING DOMAIN"); $registry->set('volatile.breakflag', true); } $object = null; // Free last domain if (empty($this->domain_chain)) { // Aw, we're done! No more domains to run. $this->setState('postrun'); AliceUtilLogger::WriteLog(_AE_LOG_DEBUG, "Kettenrad :: No more domains to process"); $this->array_cache = null; //restore_error_handler(); return; } // Shift the next definition off the stack $this->array_cache = null; $new_definition = array_shift($this->domain_chain); if (array_key_exists('class', $new_definition)) { $this->domain = $new_definition['domain']; $this->class = $new_definition['class']; // Get a working object $object = AliceFactory::getDomainObject($this->class); $object->setup($this->_parametersArray); } else { AliceUtilLogger::WriteLog(_AE_LOG_WARNING, "Kettenrad :: No class defined trying to switch domains. The analysis will crash."); $this->domain = null; $this->class = null; } } else { if (!is_object($object)) { $object = AliceFactory::getDomainObject($this->class); } } // Tick the object $result = $object->tick(); // Propagate errors $this->propagateFromObject($object); // Advance operation counter $currentOperationNumber = $registry->get('volatile.operation_counter', 0); $currentOperationNumber++; $registry->set('volatile.operation_counter', $currentOperationNumber); // Process return array $this->setDomain($this->domain); $this->setStep($result['Step']); $this->setSubstep($result['Substep']); // Check for BREAKFLAG $breakFlag = $registry->get('volatile.breakflag', false); // Process errors $error = false; if ($this->getError()) { $error = true; } // Check if the backup procedure should finish now $finished = $error ? true : !$result['HasRun']; // Log operation end AliceUtilLogger::WriteLog(_AE_LOG_DEBUG, '----- Finished operation ' . $currentOperationNumber . ' ------'); } // while // Log the result if (!$error) { AliceUtilLogger::WriteLog(_AE_LOG_DEBUG, "Successful Smart algorithm on " . get_class($object)); } else { AliceUtilLogger::WriteLog(_AE_LOG_ERROR, "Failed Smart algorithm on " . get_class($object)); } // Log if we have to do more work or not if (!is_object($object)) { AliceUtilLogger::WriteLog(_AE_LOG_WARNING, "Kettenrad :: Empty object found when processing domain '" . $this->domain . "'. This should never happen."); } else { if ($object->getState() == 'running') { AliceUtilLogger::WriteLog(_AE_LOG_DEBUG, "Kettenrad :: More work required in domain '" . $this->domain . "'"); // We need to set the break flag for the part processing to not batch successive steps $registry->set('volatile.breakflag', true); } elseif ($object->getState() == 'finished') { AliceUtilLogger::WriteLog(_AE_LOG_DEBUG, "Kettenrad :: Domain '" . $this->domain . "' has finished."); $registry->set('volatile.breakflag', false); } } // Log step end AliceUtilLogger::WriteLog(_AE_LOG_DEBUG, '====== Finished Step number ' . $stepCounter . ' ======'); if (!$registry->get('akeeba.tuning.nobreak.domains', 0)) { // Force break between steps $registry->set('volatile.breakflag', true); } //restore_error_handler(); }