BpNode: free loop detection from side-effects

This commit is contained in:
Thomas Gelf 2016-11-29 11:11:43 +01:00
parent 370558f740
commit cbf8db3073
2 changed files with 39 additions and 31 deletions

View file

@ -45,8 +45,6 @@ class BpNode extends Node
0 => 4
);
protected static $loopDetection = array();
protected $className = 'process';
public function __construct(BusinessProcess $bp, $object)
@ -349,32 +347,15 @@ class BpNode extends Node
return $this;
}
protected function beginLoopDetection()
{
$name = $this->name;
if (array_key_exists($name, self::$loopDetection)) {
$loop = array_keys(self::$loopDetection);
$loop[] = $name;
self::$loopDetection = array();
throw new NestingError('Loop detected: %s', implode(' -> ', $loop));
}
self::$loopDetection[$name] = true;
}
protected function endLoopDetection()
{
unset(self::$loopDetection[$this->name]);
}
public function checkForLoops()
{
$bp = $this->bp;
foreach ($this->getChildren() as $child) {
$this->beginLoopDetection();
$bp->beginLoopDetection($this->name);
if ($child instanceof BpNode) {
$child->checkForLoops();
}
$this->endLoopDetection();
$bp->endLoopDetection($this->name);
}
return $this;

View file

@ -3,7 +3,9 @@
namespace Icinga\Module\Businessprocess;
use Icinga\Application\Benchmark;
use Icinga\Exception\IcingaException;
use Icinga\Exception\ProgrammingError;
use Icinga\Module\Businessprocess\Exception\NestingError;
use Icinga\Module\Businessprocess\Modification\ProcessChanges;
use Icinga\Module\Monitoring\Backend\MonitoringBackend;
use Icinga\Data\Filter\Filter;
@ -92,6 +94,11 @@ class BusinessProcess
*/
protected $hosts = array();
/** @var bool Whether catchable errors should be thrown nonetheless */
protected $throwErrors = false;
protected $loopDetection = array();
/**
* Applied state simulation
*
@ -309,7 +316,7 @@ class BusinessProcess
try {
$this->reallyRetrieveStatesFromBackend();
} catch (Exception $e) {
$this->error(
$this->addError(
$this->translate('Could not retrieve process state: %s'),
$e->getMessage()
);
@ -664,18 +671,19 @@ class BusinessProcess
{
$args = func_get_args();
array_shift($args);
$this->errors[] = vsprintf($msg, $args);
$msg = vsprintf($msg, $args);
if ($this->throwErrors) {
throw new IcingaException($msg);
}
$this->errors[] = $msg;
return $this;
}
/**
* @deprecated
*/
protected function error($msg)
public function throwErrors($throw = true)
{
$args = func_get_args();
array_shift($args);
$this->errors[] = vsprintf($msg, $args);
$this->throwErrors = $throw;
return $this;
}
public function toLegacyConfigString()
@ -713,6 +721,25 @@ class BusinessProcess
return $conf . "\n";
}
public function beginLoopDetection($name)
{
// echo "Begin loop $name\n";
if (array_key_exists($name, $this->loopDetection)) {
$loop = array_keys($this->loopDetection);
$loop[] = $name;
$this->loopDetection = array();
throw new NestingError('Loop detected: %s', implode(' -> ', $loop));
}
$this->loopDetection[$name] = true;
}
public function endLoopDetection($name)
{
// echo "End loop $this->name\n";
unset($this->loopDetection[$name]);
}
public function isEmpty()
{
return $this->countChildren() === 0;