/** * * @param Conjunct[] $conjuncts * @param boolean $cacheConjuncts * @return boolean */ public static function checkInvariantRules($conjuncts, $cacheConjuncts = true) { $logger = Logger::getLogger('FW'); $invariantRulesHold = true; // check invariant rules $logger->debug("Checking invariant rules for provided conjuncts: " . implode(', ', array_column($conjuncts, 'id'))); foreach ($conjuncts as $conjunct) { if ($conjunct->isInvConj()) { foreach ($conjunct->evaluateConjunct($cacheConjuncts) as $violation) { // If a conjunct is broken (i.e. returns 1 or more violation pairs) mark that invariant rules do not hold $invariantRulesHold = false; foreach ($conjunct->invRuleNames as $ruleName) { Notifications::addInvariant(new Violation(Rule::getRule($ruleName), $violation['src'], $violation['tgt'])); } } } else { $logger->error("Conjunct '{$conjunct->id}' provided to be checked for invariant violations, but this is not an invariant conjunct"); } } return $invariantRulesHold; }
// run all conjuncts (from - to) for ($i = $from; $i <= $to; $i++) { $conjunct = Conjunct::getConjunct('conj_' . $i); $startTimeStamp = microtime(true); // true means get as float instead of string $conjunct->evaluateConjunct(false); $endTimeStamp = microtime(true); $performanceArr[$conjunct->id] = array('id' => $conjunct->id, 'start' => round($startTimeStamp, 6), 'end' => round($endTimeStamp, 6), 'duration' => round($endTimeStamp - $startTimeStamp, 6), 'invariantRules' => implode(';', $conjunct->invRuleNames), 'signalRules' => implode(';', $conjunct->sigRuleNames)); } switch ($groupBy) { case 'conjuncts': $content = array_values($performanceArr); break; case 'rules': $ruleArr = array(); foreach (Rule::getAllRules() as $rule) { $duration = 0; $conjunctIds = array(); foreach ($rule->conjuncts as $conjunct) { $duration += $performanceArr[$conjunct->id]['duration']; $conjunctIds[] = $conjunct->id; } $ruleArr[] = array('ruleName' => $rule->id, 'duration' => $duration, 'conjuncts' => implode(';', $conjunctIds)); } $content = $ruleArr; break; case 'relations': $relArr = array(); $conjunctIds = array(); foreach (Relation::getAllRelations() as $relation) { $duration = 0;
public static function run($allRules = false) { $database = Database::singleton(); $logger = Logger::getLogger('EXECENGINE'); $logger->info("ExecEngine run started"); // Load the execEngine functions (security hazard :P) $files = getDirectoryList(__DIR__ . '/functions'); foreach ($files as $file) { if (substr($file, -3) !== 'php') { continue; } require_once $path = __DIR__ . '/functions/' . $file; $logger->debug("Included file: {$path}"); } self::$roleName = Config::get('execEngineRoleName', 'execEngine'); try { $role = Role::getRoleByName(self::$roleName); } catch (Exception $e) { $logger->warning("ExecEngine extension included but role '" . self::$roleName . "' not used/defined in &-script."); self::$doRun = false; // prevent exec engine execution } $maxRunCount = Config::get('maxRunCount', 'execEngine'); self::$runCount = 0; self::$autoRerun = Config::get('autoRerun', 'execEngine'); // Get all rules that are maintained by the ExecEngine $rulesThatHaveViolations = array(); while (self::$doRun) { self::$doRun = false; self::$runCount++; // Prevent infinite loop in ExecEngine reruns if (self::$runCount > $maxRunCount) { Logger::getUserLogger()->error('Maximum reruns exceeded for ExecEngine (rules with violations:' . implode(', ', $rulesThatHaveViolations) . ')'); break; } $logger->notice("ExecEngine run #" . self::$runCount . " (auto rerun: " . var_export(self::$autoRerun, true) . ") for role '{$role->label}'"); // Determine affected rules that must be checked by the exec engine $affectedConjuncts = RuleEngine::getAffectedConjuncts($database->getAffectedConcepts(), $database->getAffectedRelations(), 'sig'); $affectedRules = array(); foreach ($affectedConjuncts as $conjunct) { $affectedRules = array_merge($affectedRules, $conjunct->sigRuleNames); } // Check rules $rulesThatHaveViolations = array(); foreach ($role->maintains() as $ruleName) { if (!in_array($ruleName, $affectedRules) && !$allRules) { continue; } // skip this rule $rule = Rule::getRule($ruleName); $violations = $rule->getViolations(false); if (count($violations)) { $rulesThatHaveViolations[] = $rule->id; // Fix violations for every rule $logger->notice("ExecEngine fixing " . count($violations) . " violations for rule '{$rule->id}'"); self::fixViolations($violations); // Conjunct violations are not cached, because they are fixed by the ExecEngine $logger->debug("Fixed " . count($violations) . " violations for rule '{$rule->__toString()}'"); // If $autoRerun, set $doRun to true because violations have been fixed (this may fire other execEngine rules) if (self::$autoRerun) { self::$doRun = true; } } } } $logger->info("ExecEngine run completed"); }
/** * Activate provided role * @param Role $role * @return void */ private function activateRole(&$role) { $role->active = true; $this->accessibleInterfaces = array_merge($this->accessibleInterfaces, $role->interfaces()); foreach ($role->maintains() as $ruleName) { $this->rulesToMaintain[] = Rule::getRule($ruleName); } $this->logger->info("Role '{$role->id}' is activated"); }