diff --git a/library/Director/Import/Sync.php b/library/Director/Import/Sync.php index ae42789e..c29298a1 100644 --- a/library/Director/Import/Sync.php +++ b/library/Director/Import/Sync.php @@ -6,6 +6,9 @@ use Exception; use Icinga\Data\Filter\Filter; use Icinga\Module\Director\Db; use Icinga\Module\Director\Db\Cache\PrefetchCache; +use Icinga\Module\Director\Objects\HostGroupMembershipResolver; +use Icinga\Module\Director\Objects\IcingaHost; +use Icinga\Module\Director\Objects\IcingaHostGroup; use Icinga\Module\Director\Objects\IcingaObject; use Icinga\Module\Director\Objects\ImportSource; use Icinga\Module\Director\Objects\IcingaService; @@ -79,6 +82,9 @@ class Sync /** @var Filter[] */ protected $columnFilters = array(); + /** @var HostGroupMembershipResolver|bool */ + protected $hostGropMembershipResolver; + /** * Constructor. No direct initialization allowed right now. Please use one * of the available static factory methods @@ -480,6 +486,53 @@ class Sync return $newObjects; } + protected function deferResolvers() + { + if (in_array($this->rule->get('object_type'), array('host', 'hostgroup'))) { + $resolver = new HostGroupMembershipResolver($this->db); + $resolver->defer()->setUseTransactions(false); + } + + return $this; + } + + protected function setResolver(IcingaObject $object) + { + if ($resolver = $this->getHostGropMembershipResolver()) { + /** @var IcingaHost|IcingaHostGroup $object */ + $object->setHostGroupMembershipResolver($resolver); + } + + return $this; + } + + protected function notifyResolvers() + { + if ($resolver = $this->getHostGropMembershipResolver()) { + $resolver->defer(); + } + + return $this; + } + + protected function getHostGropMembershipResolver() + { + if ($this->hostGropMembershipResolver === null) { + if (in_array( + $this->rule->get('object_type'), + array('host', 'hostgroup') + )) { + $this->hostGropMembershipResolver = new HostGroupMembershipResolver( + $this->db + ); + } else { + $this->hostGropMembershipResolver = false; + } + } + + return $this->hostGropMembershipResolver; + } + /** * Evaluates a SyncRule and returns a list of modified objects * @@ -501,7 +554,8 @@ class Sync ->prepareRelatedImportSources() ->prepareSourceColumns() ->loadExistingObjects() - ->fetchImportedData(); + ->fetchImportedData() + ->deferResolvers(); // TODO: directly work on existing objects, remember imported keys, then purge $newObjects = $this->prepareNewObjects(); @@ -579,6 +633,7 @@ class Sync $modified = 0; $deleted = 0; foreach ($objects as $object) { + $this->setResolver($object); if ($object->shouldBeRemoved()) { $object->delete($db); $deleted++; diff --git a/library/Director/Objects/HostGroupMembershipResolver.php b/library/Director/Objects/HostGroupMembershipResolver.php index a3c6f456..0e98d9e0 100644 --- a/library/Director/Objects/HostGroupMembershipResolver.php +++ b/library/Director/Objects/HostGroupMembershipResolver.php @@ -32,12 +32,16 @@ class HostGroupMembershipResolver /** @var IcingaHost[] */ protected $hosts; - /** @var IcingaHostGroup */ + /** @var IcingaHostGroup[] */ protected $hostgroups = array(); protected $table = 'icinga_hostgroup_host_resolved'; - protected static $deferred; + /** @var bool */ + protected $deferred = false; + + /** @var bool */ + protected $useTransactions = false; public function __construct(Db $connection) { @@ -59,7 +63,7 @@ class HostGroupMembershipResolver */ public function refreshDb($force = false) { - if ($force || ! static::$deferred) { + if ($force || ! $this->isDeferred()) { Benchmark::measure('Going to refresh all hostgroup mappings'); $this->fetchStoredMappings(); Benchmark::measure('Got stored HG mappings, rechecking all hosts'); @@ -72,14 +76,32 @@ class HostGroupMembershipResolver return $this; } - public static function defer($defer = true) + /** + * @param bool $defer + * @return $this + */ + public function defer($defer = true) { - static::$deferred = $defer; + $this->deferred = $defer; + return $this; } - public static function isDeferred() + /** + * @param $use + * @return $this + */ + public function setUseTransactions($use) { - return static::$deferred; + $this->useTransactions = $use; + return $this; + } + + /** + * @return bool + */ + public function isDeferred() + { + return $this->deferred; } /** @@ -205,7 +227,7 @@ class HostGroupMembershipResolver } $db = $this->db; - $db->beginTransaction(); + $this->beginTransaction(); foreach ($diff as $row) { $db->insert( $this->table, @@ -213,7 +235,7 @@ class HostGroupMembershipResolver ); } - $db->commit(); + $this->commit(); Benchmark::measure( sprintf( 'Stored %d new resolved hostgroup memberships', @@ -231,7 +253,7 @@ class HostGroupMembershipResolver } $db = $this->db; - $db->beginTransaction(); + $this->beginTransaction(); foreach ($diff as $row) { $db->delete( $this->table, @@ -243,7 +265,7 @@ class HostGroupMembershipResolver ); } - $db->commit(); + $this->commit(); Benchmark::measure( sprintf( 'Removed %d outdated hostgroup memberships', @@ -306,6 +328,12 @@ class HostGroupMembershipResolver $this->existingMappings = $mappings; } + /** + * @param ZfSelect $query + * @param string $column + * @param IcingaObject[] $objects + * @return ZfSelect + */ protected function addMembershipWhere(ZfSelect $query, $column, & $objects) { if (empty($objects)) { @@ -379,6 +407,30 @@ class HostGroupMembershipResolver return $this->db->fetchPairs($query); } + /** + * @return $this + */ + protected function beginTransaction() + { + if ($this->useTransactions) { + $this->db->beginTransaction(); + } + + return $this; + } + + /** + * @return $this + */ + protected function commit() + { + if ($this->useTransactions) { + $this->db->commit(); + } + + return $this; + } + /** * @return IcingaHost[] */ @@ -393,7 +445,7 @@ class HostGroupMembershipResolver protected function assertBeenLoadedFromDb(IcingaObject $object) { - if (! $object->hasBeenLoadedFromDb()) { + if (! ctype_digit($object->get('id'))) { throw new ProgrammingError( 'Hostgroup resolver does not support unstored objects' ); diff --git a/library/Director/Objects/IcingaHost.php b/library/Director/Objects/IcingaHost.php index 532a3480..2e43ab20 100644 --- a/library/Director/Objects/IcingaHost.php +++ b/library/Director/Objects/IcingaHost.php @@ -315,6 +315,12 @@ class IcingaHost extends IcingaObject return $this->hostgroupMembershipResolver; } + public function setHostGroupMembershipResolver(HostGroupMembershipResolver $resolver) + { + $this->hostgroupMembershipResolver = $resolver; + return $this; + } + protected function getServiceOverrivesVarname() { return $this->connection->settings()->override_services_varname; diff --git a/library/Director/Objects/IcingaHostGroup.php b/library/Director/Objects/IcingaHostGroup.php index 026ff966..0d1ec0e0 100644 --- a/library/Director/Objects/IcingaHostGroup.php +++ b/library/Director/Objects/IcingaHostGroup.php @@ -39,6 +39,12 @@ class IcingaHostGroup extends IcingaObjectGroup return $this->hostgroupMembershipResolver; } + public function setHostGroupMembershipResolver(HostGroupMembershipResolver $resolver) + { + $this->hostgroupMembershipResolver = $resolver; + return $this; + } + protected function notifyResolvers() { $resolver = $this->getHostGroupMembershipResolver(); diff --git a/library/Director/Objects/IcingaObject.php b/library/Director/Objects/IcingaObject.php index b645ad08..067ea92a 100644 --- a/library/Director/Objects/IcingaObject.php +++ b/library/Director/Objects/IcingaObject.php @@ -1278,8 +1278,7 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer ->storeImports() ->storeRanges() ->storeRelatedSets() - ->storeArguments() - ->notifyResolvers(); + ->storeArguments(); } protected function beforeStore() @@ -1299,6 +1298,11 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer $this->storeRelatedObjects(); } + public function onStore() + { + $this->notifyResolvers(); + } + /** * @return self */