From 8c6bb1f46c2025206bb270f1baa390a8981337d9 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 8 Nov 2022 13:26:27 +0100 Subject: [PATCH] T::EvaluateApplyRule(): don't squish non-for apply rules into apply-for logic to K. I. S. S. and avoid malloc(). --- lib/icinga/dependency-apply.cpp | 56 ++++++++++++------------ lib/icinga/notification-apply.cpp | 56 ++++++++++++------------ lib/icinga/scheduleddowntime-apply.cpp | 56 ++++++++++++------------ lib/icinga/service-apply.cpp | 60 +++++++++++++------------- 4 files changed, 111 insertions(+), 117 deletions(-) diff --git a/lib/icinga/dependency-apply.cpp b/lib/icinga/dependency-apply.cpp index 8681c4332..cd4aff3fc 100644 --- a/lib/icinga/dependency-apply.cpp +++ b/lib/icinga/dependency-apply.cpp @@ -79,52 +79,50 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR if (service) frame.Locals->Set("service", service); - Value vinstances; + bool match = false; if (rule.GetFTerm()) { + Value vinstances; + try { vinstances = rule.GetFTerm()->Evaluate(frame); } catch (const std::exception&) { /* Silently ignore errors here and assume there are no instances. */ return false; } - } else { - vinstances = new Array({ "" }); - } - bool match = false; + if (vinstances.IsObjectType()) { + if (!rule.GetFVVar().IsEmpty()) + BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); - if (vinstances.IsObjectType()) { - if (!rule.GetFVVar().IsEmpty()) - BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); + Array::Ptr arr = vinstances; - Array::Ptr arr = vinstances; + ObjectLock olock(arr); + for (const Value& instance : arr) { + String name = rule.GetName(); - ObjectLock olock(arr); - for (const Value& instance : arr) { - String name = rule.GetName(); - - if (!rule.GetFKVar().IsEmpty()) { frame.Locals->Set(rule.GetFKVar(), instance); name += instance; + + if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter)) + match = true; } + } else if (vinstances.IsObjectType()) { + if (rule.GetFVVar().IsEmpty()) + BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di)); - if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter)) - match = true; - } - } else if (vinstances.IsObjectType()) { - if (rule.GetFVVar().IsEmpty()) - BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di)); - - Dictionary::Ptr dict = vinstances; - - for (const String& key : dict->GetKeys()) { - frame.Locals->Set(rule.GetFKVar(), key); - frame.Locals->Set(rule.GetFVVar(), dict->Get(key)); - - if (EvaluateApplyRuleInstance(checkable, rule.GetName() + key, frame, rule, skipFilter)) - match = true; + Dictionary::Ptr dict = vinstances; + + for (const String& key : dict->GetKeys()) { + frame.Locals->Set(rule.GetFKVar(), key); + frame.Locals->Set(rule.GetFVVar(), dict->Get(key)); + + if (EvaluateApplyRuleInstance(checkable, rule.GetName() + key, frame, rule, skipFilter)) + match = true; + } } + } else if (EvaluateApplyRuleInstance(checkable, rule.GetName(), frame, rule, skipFilter)) { + match = true; } return match; diff --git a/lib/icinga/notification-apply.cpp b/lib/icinga/notification-apply.cpp index f5b37643b..51408fb24 100644 --- a/lib/icinga/notification-apply.cpp +++ b/lib/icinga/notification-apply.cpp @@ -78,52 +78,50 @@ bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const Appl if (service) frame.Locals->Set("service", service); - Value vinstances; + bool match = false; if (rule.GetFTerm()) { + Value vinstances; + try { vinstances = rule.GetFTerm()->Evaluate(frame); } catch (const std::exception&) { /* Silently ignore errors here and assume there are no instances. */ return false; } - } else { - vinstances = new Array({ "" }); - } - bool match = false; + if (vinstances.IsObjectType()) { + if (!rule.GetFVVar().IsEmpty()) + BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); - if (vinstances.IsObjectType()) { - if (!rule.GetFVVar().IsEmpty()) - BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); + Array::Ptr arr = vinstances; - Array::Ptr arr = vinstances; + ObjectLock olock(arr); + for (const Value& instance : arr) { + String name = rule.GetName(); - ObjectLock olock(arr); - for (const Value& instance : arr) { - String name = rule.GetName(); - - if (!rule.GetFKVar().IsEmpty()) { frame.Locals->Set(rule.GetFKVar(), instance); name += instance; + + if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter)) + match = true; } + } else if (vinstances.IsObjectType()) { + if (rule.GetFVVar().IsEmpty()) + BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di)); - if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter)) - match = true; - } - } else if (vinstances.IsObjectType()) { - if (rule.GetFVVar().IsEmpty()) - BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di)); - - Dictionary::Ptr dict = vinstances; - - for (const String& key : dict->GetKeys()) { - frame.Locals->Set(rule.GetFKVar(), key); - frame.Locals->Set(rule.GetFVVar(), dict->Get(key)); - - if (EvaluateApplyRuleInstance(checkable, rule.GetName() + key, frame, rule, skipFilter)) - match = true; + Dictionary::Ptr dict = vinstances; + + for (const String& key : dict->GetKeys()) { + frame.Locals->Set(rule.GetFKVar(), key); + frame.Locals->Set(rule.GetFVVar(), dict->Get(key)); + + if (EvaluateApplyRuleInstance(checkable, rule.GetName() + key, frame, rule, skipFilter)) + match = true; + } } + } else if (EvaluateApplyRuleInstance(checkable, rule.GetName(), frame, rule, skipFilter)) { + match = true; } return match; diff --git a/lib/icinga/scheduleddowntime-apply.cpp b/lib/icinga/scheduleddowntime-apply.cpp index 4f8aa471f..7aea69ebf 100644 --- a/lib/icinga/scheduleddowntime-apply.cpp +++ b/lib/icinga/scheduleddowntime-apply.cpp @@ -77,52 +77,50 @@ bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const if (service) frame.Locals->Set("service", service); - Value vinstances; + bool match = false; if (rule.GetFTerm()) { + Value vinstances; + try { vinstances = rule.GetFTerm()->Evaluate(frame); } catch (const std::exception&) { /* Silently ignore errors here and assume there are no instances. */ return false; } - } else { - vinstances = new Array({ "" }); - } - bool match = false; + if (vinstances.IsObjectType()) { + if (!rule.GetFVVar().IsEmpty()) + BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); - if (vinstances.IsObjectType()) { - if (!rule.GetFVVar().IsEmpty()) - BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); + Array::Ptr arr = vinstances; - Array::Ptr arr = vinstances; + ObjectLock olock(arr); + for (const Value& instance : arr) { + String name = rule.GetName(); - ObjectLock olock(arr); - for (const Value& instance : arr) { - String name = rule.GetName(); - - if (!rule.GetFKVar().IsEmpty()) { frame.Locals->Set(rule.GetFKVar(), instance); name += instance; + + if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter)) + match = true; } + } else if (vinstances.IsObjectType()) { + if (rule.GetFVVar().IsEmpty()) + BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di)); - if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter)) - match = true; - } - } else if (vinstances.IsObjectType()) { - if (rule.GetFVVar().IsEmpty()) - BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di)); - - Dictionary::Ptr dict = vinstances; - - for (const String& key : dict->GetKeys()) { - frame.Locals->Set(rule.GetFKVar(), key); - frame.Locals->Set(rule.GetFVVar(), dict->Get(key)); - - if (EvaluateApplyRuleInstance(checkable, rule.GetName() + key, frame, rule, skipFilter)) - match = true; + Dictionary::Ptr dict = vinstances; + + for (const String& key : dict->GetKeys()) { + frame.Locals->Set(rule.GetFKVar(), key); + frame.Locals->Set(rule.GetFVVar(), dict->Get(key)); + + if (EvaluateApplyRuleInstance(checkable, rule.GetName() + key, frame, rule, skipFilter)) + match = true; + } } + } else if (EvaluateApplyRuleInstance(checkable, rule.GetName(), frame, rule, skipFilter)) { + match = true; } return match; diff --git a/lib/icinga/service-apply.cpp b/lib/icinga/service-apply.cpp index 4419e0b34..d6d6c1b35 100644 --- a/lib/icinga/service-apply.cpp +++ b/lib/icinga/service-apply.cpp @@ -66,52 +66,52 @@ bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule, bo rule.GetScope()->CopyTo(frame.Locals); frame.Locals->Set("host", host); - Value vinstances; + bool match = false; if (rule.GetFTerm()) { + Value vinstances; + try { vinstances = rule.GetFTerm()->Evaluate(frame); } catch (const std::exception&) { /* Silently ignore errors here and assume there are no instances. */ return false; } - } else { - vinstances = new Array({ "" }); - } - bool match = false; + if (vinstances.IsObjectType()) { + if (!rule.GetFVVar().IsEmpty()) + BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); - if (vinstances.IsObjectType()) { - if (!rule.GetFVVar().IsEmpty()) - BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); + Array::Ptr arr = vinstances; - Array::Ptr arr = vinstances; + ObjectLock olock(arr); + for (const Value& instance : arr) { + String name = rule.GetName(); - ObjectLock olock(arr); - for (const Value& instance : arr) { - String name = rule.GetName(); + if (!rule.GetFKVar().IsEmpty()) { + frame.Locals->Set(rule.GetFKVar(), instance); + name += instance; + } - if (!rule.GetFKVar().IsEmpty()) { - frame.Locals->Set(rule.GetFKVar(), instance); - name += instance; + if (EvaluateApplyRuleInstance(host, name, frame, rule, skipFilter)) + match = true; } + } else if (vinstances.IsObjectType()) { + if (rule.GetFVVar().IsEmpty()) + BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di)); - if (EvaluateApplyRuleInstance(host, name, frame, rule, skipFilter)) - match = true; - } - } else if (vinstances.IsObjectType()) { - if (rule.GetFVVar().IsEmpty()) - BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di)); - - Dictionary::Ptr dict = vinstances; - - for (const String& key : dict->GetKeys()) { - frame.Locals->Set(rule.GetFKVar(), key); - frame.Locals->Set(rule.GetFVVar(), dict->Get(key)); - - if (EvaluateApplyRuleInstance(host, rule.GetName() + key, frame, rule, skipFilter)) - match = true; + Dictionary::Ptr dict = vinstances; + + for (const String& key : dict->GetKeys()) { + frame.Locals->Set(rule.GetFKVar(), key); + frame.Locals->Set(rule.GetFVVar(), dict->Get(key)); + + if (EvaluateApplyRuleInstance(host, rule.GetName() + key, frame, rule, skipFilter)) + match = true; + } } + } else if (EvaluateApplyRuleInstance(host, rule.GetName(), frame, rule, skipFilter)) { + match = true; } return match;