From b18bc644404e02b57635bfcc8258e85abb141146 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 13:44:46 +0200 Subject: Adding upstream version 1.1.1. Signed-off-by: Daniel Baumann --- library/Icingadb/Redis/VolatileStateResults.php | 170 ++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 library/Icingadb/Redis/VolatileStateResults.php (limited to 'library/Icingadb/Redis/VolatileStateResults.php') diff --git a/library/Icingadb/Redis/VolatileStateResults.php b/library/Icingadb/Redis/VolatileStateResults.php new file mode 100644 index 0000000..9418398 --- /dev/null +++ b/library/Icingadb/Redis/VolatileStateResults.php @@ -0,0 +1,170 @@ +resolver = $query->getResolver(); + $self->redisUnavailable = IcingaRedis::isUnavailable(); + + return $self; + } + + /** + * Get whether Redis is unavailable + * + * @return bool + */ + public function isRedisUnavailable(): bool + { + return $this->redisUnavailable; + } + + #[\ReturnTypeWillChange] + public function current() + { + if (! $this->redisUnavailable && ! $this->updatesApplied && ! $this->isCacheDisabled) { + $this->rewind(); + } + + return parent::current(); + } + + public function next(): void + { + parent::next(); + + if (! $this->redisUnavailable && $this->isCacheDisabled && $this->valid()) { + $this->applyRedisUpdates([parent::current()]); + } + } + + public function key(): int + { + if (! $this->redisUnavailable && ! $this->updatesApplied && ! $this->isCacheDisabled) { + $this->rewind(); + } + + return parent::key(); + } + + public function rewind(): void + { + if (! $this->redisUnavailable && ! $this->updatesApplied && ! $this->isCacheDisabled) { + $this->updatesApplied = true; + $this->advance(); + + Benchmark::measure('Applying Redis updates'); + $this->applyRedisUpdates($this); + Benchmark::measure('Redis updates applied'); + } + + parent::rewind(); + } + + /** + * Apply redis state details to the given results + * + * @param self|array $rows + * + * @return void + */ + protected function applyRedisUpdates($rows) + { + $type = null; + $behaviors = null; + + $keys = []; + $hostStateKeys = []; + + $showSourceGranted = $this->getAuth()->hasPermission('icingadb/object/show-source'); + + $states = []; + $hostStates = []; + foreach ($rows as $row) { + if ($type === null) { + $behaviors = $this->resolver->getBehaviors($row->state); + + switch (true) { + case $row instanceof Host: + $type = 'host'; + break; + case $row instanceof Service: + $type = 'service'; + break; + default: + throw new RuntimeException('Volatile states can only be fetched for hosts and services'); + } + } + + $states[bin2hex($row->id)] = $row->state; + if (empty($keys)) { + $keys = $row->state->getColumns(); + if (! $showSourceGranted) { + $keys = array_diff($keys, ['check_commandline']); + } + } + + if ($type === 'service' && $row->host instanceof Host) { + $hostStates[bin2hex($row->host->id)] = $row->host->state; + if (empty($hostStateKeys)) { + $hostStateKeys = $row->host->state->getColumns(); + } + } + } + + if (empty($states)) { + return; + } + + if ($type === 'service') { + $results = IcingaRedis::fetchServiceState(array_keys($states), $keys); + } else { + $results = IcingaRedis::fetchHostState(array_keys($states), $keys); + } + + foreach ($results as $id => $data) { + foreach ($data as $key => $value) { + $data[$key] = $behaviors->retrieveProperty($value, $key); + } + + $states[$id]->setProperties($data); + } + + if ($type === 'service' && ! empty($hostStates)) { + foreach (IcingaRedis::fetchHostState(array_keys($hostStates), $hostStateKeys) as $id => $data) { + foreach ($data as $key => $value) { + $data[$key] = $behaviors->retrieveProperty($value, $key); + } + + $hostStates[$id]->setProperties($data); + } + } + } +} -- cgit v1.2.3