Sync: tune membership resolver

Also fixes error on host creation

refs #832
This commit is contained in:
Thomas Gelf 2017-03-14 14:21:15 +01:00
parent 3cb38596c0
commit 5ae7997f9d
5 changed files with 138 additions and 15 deletions

View File

@ -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++;

View File

@ -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'
);

View File

@ -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;

View File

@ -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();

View File

@ -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
*/