ApplyRule::RuleMap: reduce complexity, save unnecessary lookups

This commit is contained in:
Alexander A. Klimov 2022-10-28 12:41:21 +02:00 committed by Julian Brost
parent 0bf093af14
commit cc67510063
7 changed files with 47 additions and 55 deletions

View File

@ -11,19 +11,15 @@ using namespace icinga;
/**
* @returns All ApplyRules targeting only specific parent objects including the given host. (See AddTargetedRule().)
*/
const std::vector<ApplyRule::Ptr>& ApplyRule::GetTargetedHostRules(const Type::Ptr& sourceType, const Type::Ptr& targetType, const String& host)
const std::vector<ApplyRule::Ptr>& ApplyRule::GetTargetedHostRules(const Type::Ptr& sourceType, const String& host)
{
auto perSourceType (m_Rules.find(sourceType.get()));
if (perSourceType != m_Rules.end()) {
auto perTargetType (perSourceType->second.find(targetType.get()));
auto perHost (perSourceType->second.Targeted.find(host));
if (perTargetType != perSourceType->second.end()) {
auto perHost (perTargetType->second.Targeted.find(host));
if (perHost != perTargetType->second.Targeted.end()) {
return perHost->second.ForHost;
}
if (perHost != perSourceType->second.Targeted.end()) {
return perHost->second.ForHost;
}
}
@ -34,22 +30,18 @@ const std::vector<ApplyRule::Ptr>& ApplyRule::GetTargetedHostRules(const Type::P
/**
* @returns All ApplyRules targeting only specific parent objects including the given service. (See AddTargetedRule().)
*/
const std::vector<ApplyRule::Ptr>& ApplyRule::GetTargetedServiceRules(const Type::Ptr& sourceType, const Type::Ptr& targetType, const String& host, const String& service)
const std::vector<ApplyRule::Ptr>& ApplyRule::GetTargetedServiceRules(const Type::Ptr& sourceType, const String& host, const String& service)
{
auto perSourceType (m_Rules.find(sourceType.get()));
if (perSourceType != m_Rules.end()) {
auto perTargetType (perSourceType->second.find(targetType.get()));
auto perHost (perSourceType->second.Targeted.find(host));
if (perTargetType != perSourceType->second.end()) {
auto perHost (perTargetType->second.Targeted.find(host));
if (perHost != perSourceType->second.Targeted.end()) {
auto perService (perHost->second.ForServices.find(service));
if (perHost != perTargetType->second.Targeted.end()) {
auto perService (perHost->second.ForServices.find(service));
if (perService != perHost->second.ForServices.end()) {
return perService->second;
}
if (perService != perHost->second.ForServices.end()) {
return perService->second;
}
}
}
@ -68,7 +60,7 @@ const std::vector<ApplyRule::Ptr>& ApplyRule::GetTargetedServiceRules(const Type
*
* @returns Whether the rule has been added to the "index".
*/
bool ApplyRule::AddTargetedRule(const ApplyRule::Ptr& rule, const String& sourceType, const String& targetType, ApplyRule::PerTypes& rules)
bool ApplyRule::AddTargetedRule(const ApplyRule::Ptr& rule, const String& targetType, ApplyRule::PerSourceType& rules)
{
if (targetType == "Host") {
std::vector<const String *> hosts;

View File

@ -82,10 +82,10 @@ void ApplyRule::AddRule(const String& sourceType, const String& targetType, cons
}
ApplyRule::Ptr rule = new ApplyRule(name, expression, filter, package, fkvar, fvvar, fterm, ignoreOnError, di, scope);
auto& rules (m_Rules[Type::GetByName(sourceType).get()][Type::GetByName(*actualTargetType).get()]);
auto& rules (m_Rules[Type::GetByName(sourceType).get()]);
if (!AddTargetedRule(rule, sourceType, *actualTargetType, rules)) {
rules.Regular.emplace_back(std::move(rule));
if (!AddTargetedRule(rule, *actualTargetType, rules)) {
rules.Regular[Type::GetByName(*actualTargetType).get()].emplace_back(std::move(rule));
}
}
@ -149,10 +149,10 @@ const std::vector<ApplyRule::Ptr>& ApplyRule::GetRules(const Type::Ptr& sourceTy
auto perSourceType (m_Rules.find(sourceType.get()));
if (perSourceType != m_Rules.end()) {
auto perTargetType (perSourceType->second.find(targetType.get()));
auto perTargetType (perSourceType->second.Regular.find(targetType.get()));
if (perTargetType != perSourceType->second.end()) {
return perTargetType->second.Regular;
if (perTargetType != perSourceType->second.Regular.end()) {
return perTargetType->second;
}
}
@ -163,28 +163,28 @@ const std::vector<ApplyRule::Ptr>& ApplyRule::GetRules(const Type::Ptr& sourceTy
void ApplyRule::CheckMatches(bool silent)
{
for (auto& perSourceType : m_Rules) {
for (auto& perTargetType : perSourceType.second) {
for (auto& rule : perTargetType.second.Regular) {
for (auto& perTargetType : perSourceType.second.Regular) {
for (auto& rule : perTargetType.second) {
CheckMatches(rule, perSourceType.first, silent);
}
}
std::unordered_set<ApplyRule*> targeted;
std::unordered_set<ApplyRule*> targeted;
for (auto& perHost : perTargetType.second.Targeted) {
for (auto& rule : perHost.second.ForHost) {
for (auto& perHost : perSourceType.second.Targeted) {
for (auto& rule : perHost.second.ForHost) {
targeted.emplace(rule.get());
}
for (auto& perService : perHost.second.ForServices) {
for (auto& rule : perService.second) {
targeted.emplace(rule.get());
}
for (auto& perService : perHost.second.ForServices) {
for (auto& rule : perService.second) {
targeted.emplace(rule.get());
}
}
}
}
for (auto rule : targeted) {
CheckMatches(rule, perSourceType.first, silent);
}
for (auto rule : targeted) {
CheckMatches(rule, perSourceType.first, silent);
}
}
}

View File

@ -27,27 +27,27 @@ public:
std::unordered_map<String /* service */, std::vector<ApplyRule::Ptr>> ForServices;
};
struct PerTypes
struct PerSourceType
{
std::vector<ApplyRule::Ptr> Regular;
std::unordered_map<Type* /* target type */, std::vector<ApplyRule::Ptr>> Regular;
std::unordered_map<String /* host */, PerHost> Targeted;
};
/*
* m_Rules[T::TypeInstance.get()][Host::TypeInstance.get()].Targeted["H"].ForHost
* m_Rules[T::TypeInstance.get()].Targeted["H"].ForHost
* contains all apply rules like apply T "x" to Host { ... }
* which target only specific hosts incl. "H", e. g. via
* assign where host.name == "H" || host.name == "h".
*
* m_Rules[T::TypeInstance.get()][Service::TypeInstance.get()].Targeted["H"].ForServices["S"]
* m_Rules[T::TypeInstance.get()].Targeted["H"].ForServices["S"]
* contains all apply rules like apply T "x" to Service { ... }
* which target only specific services on specific hosts incl. "H!S",
* e. g. via assign where host.name == "H" && service.name == "S".
*
* m_Rules[T::TypeInstance.get()][C::TypeInstance.get()].Regular
* m_Rules[T::TypeInstance.get()].Regular[C::TypeInstance.get()]
* contains all other apply rules like apply T "x" to C { ... }.
*/
typedef std::unordered_map<Type* /* source type */, std::unordered_map<Type* /* target type */, PerTypes>> RuleMap;
typedef std::unordered_map<Type* /* source type */, PerSourceType> RuleMap;
typedef std::map<String, std::vector<String> > TypeMap;
@ -70,8 +70,8 @@ public:
const Expression::Ptr& filter, const String& package, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm,
bool ignoreOnError, const DebugInfo& di, const Dictionary::Ptr& scope);
static const std::vector<ApplyRule::Ptr>& GetRules(const Type::Ptr& sourceType, const Type::Ptr& targetType);
static const std::vector<ApplyRule::Ptr>& GetTargetedHostRules(const Type::Ptr& sourceType, const Type::Ptr& targetType, const String& host);
static const std::vector<ApplyRule::Ptr>& GetTargetedServiceRules(const Type::Ptr& sourceType, const Type::Ptr& targetType, const String& host, const String& service);
static const std::vector<ApplyRule::Ptr>& GetTargetedHostRules(const Type::Ptr& sourceType, const String& host);
static const std::vector<ApplyRule::Ptr>& GetTargetedServiceRules(const Type::Ptr& sourceType, const String& host, const String& service);
static void RegisterType(const String& sourceType, const std::vector<String>& targetTypes);
static bool IsValidSourceType(const String& sourceType);
@ -97,7 +97,7 @@ private:
static TypeMap m_Types;
static RuleMap m_Rules;
static bool AddTargetedRule(const ApplyRule::Ptr& rule, const String& sourceType, const String& targetType, ApplyRule::PerTypes& rules);
static bool AddTargetedRule(const ApplyRule::Ptr& rule, const String& targetType, PerSourceType& rules);
static bool GetTargetHosts(Expression* assignFilter, std::vector<const String *>& hosts);
static bool GetTargetServices(Expression* assignFilter, std::vector<std::pair<const String *, const String *>>& services);
static std::pair<const String *, const String *> GetTargetService(Expression* assignFilter);

View File

@ -141,7 +141,7 @@ void Dependency::EvaluateApplyRules(const Host::Ptr& host)
rule->AddMatch();
}
for (auto& rule : ApplyRule::GetTargetedHostRules(Dependency::TypeInstance, Host::TypeInstance, host->GetName())) {
for (auto& rule : ApplyRule::GetTargetedHostRules(Dependency::TypeInstance, host->GetName())) {
if (EvaluateApplyRule(host, *rule, true))
rule->AddMatch();
}
@ -156,7 +156,7 @@ void Dependency::EvaluateApplyRules(const Service::Ptr& service)
rule->AddMatch();
}
for (auto& rule : ApplyRule::GetTargetedServiceRules(Dependency::TypeInstance, Service::TypeInstance, service->GetHost()->GetName(), service->GetName())) {
for (auto& rule : ApplyRule::GetTargetedServiceRules(Dependency::TypeInstance, service->GetHost()->GetName(), service->GetName())) {
if (EvaluateApplyRule(service, *rule, true))
rule->AddMatch();
}

View File

@ -141,7 +141,7 @@ void Notification::EvaluateApplyRules(const Host::Ptr& host)
rule->AddMatch();
}
for (auto& rule : ApplyRule::GetTargetedHostRules(Notification::TypeInstance, Host::TypeInstance, host->GetName())) {
for (auto& rule : ApplyRule::GetTargetedHostRules(Notification::TypeInstance, host->GetName())) {
if (EvaluateApplyRule(host, *rule, true))
rule->AddMatch();
}
@ -156,7 +156,7 @@ void Notification::EvaluateApplyRules(const Service::Ptr& service)
rule->AddMatch();
}
for (auto& rule : ApplyRule::GetTargetedServiceRules(Notification::TypeInstance, Service::TypeInstance, service->GetHost()->GetName(), service->GetName())) {
for (auto& rule : ApplyRule::GetTargetedServiceRules(Notification::TypeInstance, service->GetHost()->GetName(), service->GetName())) {
if (EvaluateApplyRule(service, *rule, true))
rule->AddMatch();
}

View File

@ -139,7 +139,7 @@ void ScheduledDowntime::EvaluateApplyRules(const Host::Ptr& host)
rule->AddMatch();
}
for (auto& rule : ApplyRule::GetTargetedHostRules(ScheduledDowntime::TypeInstance, Host::TypeInstance, host->GetName())) {
for (auto& rule : ApplyRule::GetTargetedHostRules(ScheduledDowntime::TypeInstance, host->GetName())) {
if (EvaluateApplyRule(host, *rule, true))
rule->AddMatch();
}
@ -154,7 +154,7 @@ void ScheduledDowntime::EvaluateApplyRules(const Service::Ptr& service)
rule->AddMatch();
}
for (auto& rule : ApplyRule::GetTargetedServiceRules(ScheduledDowntime::TypeInstance, Service::TypeInstance, service->GetHost()->GetName(), service->GetName())) {
for (auto& rule : ApplyRule::GetTargetedServiceRules(ScheduledDowntime::TypeInstance, service->GetHost()->GetName(), service->GetName())) {
if (EvaluateApplyRule(service, *rule, true))
rule->AddMatch();
}

View File

@ -128,7 +128,7 @@ void Service::EvaluateApplyRules(const Host::Ptr& host)
rule->AddMatch();
}
for (auto& rule : ApplyRule::GetTargetedHostRules(Service::TypeInstance, Host::TypeInstance, host->GetName())) {
for (auto& rule : ApplyRule::GetTargetedHostRules(Service::TypeInstance, host->GetName())) {
if (EvaluateApplyRule(host, *rule, true))
rule->AddMatch();
}