diff --git a/lib/base/array.cpp b/lib/base/array.cpp index 9d236954b..d9e8ea06c 100644 --- a/lib/base/array.cpp +++ b/lib/base/array.cpp @@ -108,6 +108,20 @@ size_t Array::GetLength(void) const return m_Data.size(); } +/** + * Checks whether the array contains the specified value. + * + * @param value The value. + * @returns true if the array contains the value, false otherwise. + */ +bool Array::Contains(const String& value) const +{ + ASSERT(!OwnsLock()); + ObjectLock olock(this); + + return (std::find(m_Data.begin(), m_Data.end(), value) != m_Data.end()); +} + /** * Insert the given value at the specified index * diff --git a/lib/base/array.h b/lib/base/array.h index 0e53fbf78..b7e39b0ef 100644 --- a/lib/base/array.h +++ b/lib/base/array.h @@ -50,6 +50,7 @@ public: Iterator End(void); size_t GetLength(void) const; + bool Contains(const String& value) const; void Insert(unsigned int index, const Value& value); void Remove(unsigned int index); diff --git a/lib/config/applyrule.cpp b/lib/config/applyrule.cpp index a9eba3026..cb73ba229 100644 --- a/lib/config/applyrule.cpp +++ b/lib/config/applyrule.cpp @@ -75,7 +75,7 @@ bool ApplyRule::EvaluateFilter(const Dictionary::Ptr& scope) const return result; } -void ApplyRule::EvaluateRules(void) +void ApplyRule::EvaluateRules(bool clear) { std::set completedTypes; @@ -113,7 +113,8 @@ void ApplyRule::EvaluateRules(void) } } - m_Rules.clear(); + if (clear) + m_Rules.clear(); } void ApplyRule::RegisterType(const String& sourceType, const std::vector& targetTypes, const ApplyRule::Callback& callback) diff --git a/lib/config/applyrule.h b/lib/config/applyrule.h index cdbe4bb3b..8692f718b 100644 --- a/lib/config/applyrule.h +++ b/lib/config/applyrule.h @@ -49,7 +49,7 @@ public: static void AddRule(const String& sourceType, const String& targetType, const String& name, const AExpression::Ptr& expression, const AExpression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope); - static void EvaluateRules(void); + static void EvaluateRules(bool clear); static void RegisterType(const String& sourceType, const std::vector& targetTypes, const ApplyRule::Callback& callback); static bool IsValidSourceType(const String& sourceType); diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 28bf248c9..194fa9c27 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -316,11 +316,14 @@ bool ConfigItem::ValidateItems(void) upq.Join(); - Log(LogInformation, "config", "Evaluating 'apply' rules..."); - ApplyRule::EvaluateRules(); + Log(LogInformation, "config", "Evaluating 'object' rules (step 1)..."); + ObjectRule::EvaluateRules(false); - Log(LogInformation, "config", "Evaluating 'object' rules..."); - ObjectRule::EvaluateRules(); + Log(LogInformation, "config", "Evaluating 'apply' rules..."); + ApplyRule::EvaluateRules(true); + + Log(LogInformation, "config", "Evaluating 'object' rules (step 2)..."); + ObjectRule::EvaluateRules(true); Log(LogInformation, "config", "Validating config items (step 2)..."); diff --git a/lib/config/objectrule.cpp b/lib/config/objectrule.cpp index a6cc0ab2e..c0c7bc0a7 100644 --- a/lib/config/objectrule.cpp +++ b/lib/config/objectrule.cpp @@ -70,7 +70,7 @@ bool ObjectRule::EvaluateFilter(const Dictionary::Ptr& scope) const return result; } -void ObjectRule::EvaluateRules(void) +void ObjectRule::EvaluateRules(bool clear) { std::pair kv; BOOST_FOREACH(kv, m_Callbacks) { @@ -84,7 +84,8 @@ void ObjectRule::EvaluateRules(void) callback(it->second); } - m_Rules.clear(); + if (clear) + m_Rules.clear(); } void ObjectRule::RegisterType(const String& sourceType, const ObjectRule::Callback& callback) diff --git a/lib/config/objectrule.h b/lib/config/objectrule.h index 3f3cbe0b9..530fd35bf 100644 --- a/lib/config/objectrule.h +++ b/lib/config/objectrule.h @@ -48,7 +48,7 @@ public: static void AddRule(const String& sourceType, const String& name, const AExpression::Ptr& expression, const AExpression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope); - static void EvaluateRules(void); + static void EvaluateRules(bool clear); static void RegisterType(const String& sourceType, const ObjectRule::Callback& callback); static bool IsValidSourceType(const String& sourceType); diff --git a/lib/icinga/checkable.cpp b/lib/icinga/checkable.cpp index 6bb251eef..d60ffaf44 100644 --- a/lib/icinga/checkable.cpp +++ b/lib/icinga/checkable.cpp @@ -88,6 +88,21 @@ void Checkable::OnStateLoaded(void) } } +void Checkable::AddGroup(const String& name) +{ + boost::mutex::scoped_lock lock(m_CheckableMutex); + + Array::Ptr groups = GetGroups(); + + if (groups && groups->Contains(name)) + return; + + if (!groups) + groups = make_shared(); + + groups->Add(name); +} + AcknowledgementType Checkable::GetAcknowledgement(void) { ASSERT(OwnsLock()); diff --git a/lib/icinga/checkable.h b/lib/icinga/checkable.h index 8d4f1c673..e068d2477 100644 --- a/lib/icinga/checkable.h +++ b/lib/icinga/checkable.h @@ -89,6 +89,8 @@ public: std::set GetParents(void) const; std::set GetChildren(void) const; + void AddGroup(const String& name); + //bool IsHostCheck(void) const; bool IsReachable(DependencyType dt = DependencyState, shared_ptr *failedDependency = NULL, int rstack = 0) const; @@ -270,6 +272,7 @@ protected: virtual void OnStateLoaded(void); private: + mutable boost::mutex m_CheckableMutex; bool m_CheckRunning; long m_SchedulingOffset; diff --git a/lib/icinga/checkable.ti b/lib/icinga/checkable.ti index dd2fade39..380ff9ff2 100644 --- a/lib/icinga/checkable.ti +++ b/lib/icinga/checkable.ti @@ -1,5 +1,6 @@ #include "icinga/icingaapplication.h" #include "base/dynamicobject.h" +#include "base/array.h" namespace icinga { @@ -20,7 +21,9 @@ enum AcknowledgementType abstract class Checkable : DynamicObject { - [config] Array::Ptr groups; + [config] Array::Ptr groups { + default {{{ return make_shared(); }}} + }; [config, protected] String check_command (CheckCommandRaw); [config] int max_check_attempts (MaxCheckAttemptsRaw) { default {{{ return 3; }}} diff --git a/lib/icinga/host.ti b/lib/icinga/host.ti index a45493258..1a8c3ed83 100644 --- a/lib/icinga/host.ti +++ b/lib/icinga/host.ti @@ -14,7 +14,6 @@ class Host : Checkable return m_DisplayName; }}} }; - [config] Array::Ptr groups; [config] String address; [config] String address6; diff --git a/lib/icinga/hostgroup.cpp b/lib/icinga/hostgroup.cpp index cc6d2ac6e..d57de68cb 100644 --- a/lib/icinga/hostgroup.cpp +++ b/lib/icinga/hostgroup.cpp @@ -66,6 +66,9 @@ bool HostGroup::EvaluateObjectRule(const Host::Ptr host, const ObjectRule& rule) /* assign host group membership */ group->ResolveGroupMembership(host, true); + /* update groups attribute for apply */ + host->AddGroup(group_name); + return true; } diff --git a/lib/icinga/servicegroup.cpp b/lib/icinga/servicegroup.cpp index 09f82cc43..9a2d0bcb5 100644 --- a/lib/icinga/servicegroup.cpp +++ b/lib/icinga/servicegroup.cpp @@ -70,6 +70,9 @@ bool ServiceGroup::EvaluateObjectRule(const Service::Ptr service, const ObjectRu /* assign service group membership */ group->ResolveGroupMembership(service, true); + /* update groups attribute for apply */ + service->AddGroup(group_name); + return true; } diff --git a/lib/icinga/user.cpp b/lib/icinga/user.cpp index 6834574bf..71ab946b8 100644 --- a/lib/icinga/user.cpp +++ b/lib/icinga/user.cpp @@ -69,6 +69,21 @@ void User::Stop(void) } } +void User::AddGroup(const String& name) +{ + boost::mutex::scoped_lock lock(m_UserMutex); + + Array::Ptr groups = GetGroups(); + + if (groups && groups->Contains(name)) + return; + + if (!groups) + groups = make_shared(); + + groups->Add(name); +} + TimePeriod::Ptr User::GetPeriod(void) const { return TimePeriod::GetByName(GetPeriodRaw()); diff --git a/lib/icinga/user.h b/lib/icinga/user.h index d5b441ca6..780cd979f 100644 --- a/lib/icinga/user.h +++ b/lib/icinga/user.h @@ -40,6 +40,8 @@ public: DECLARE_PTR_TYPEDEFS(User); DECLARE_TYPENAME(User); + void AddGroup(const String& name); + /* Notifications */ TimePeriod::Ptr GetPeriod(void) const; @@ -52,6 +54,8 @@ protected: virtual void Stop(void); virtual void OnConfigLoaded(void); +private: + mutable boost::mutex m_UserMutex; }; } diff --git a/lib/icinga/user.ti b/lib/icinga/user.ti index 2c25a7631..052c16151 100644 --- a/lib/icinga/user.ti +++ b/lib/icinga/user.ti @@ -1,4 +1,5 @@ #include "base/dynamicobject.h" +#include "base/array.h" namespace icinga { @@ -13,7 +14,9 @@ class User : DynamicObject return m_DisplayName; }}} }; - [config] Array::Ptr groups; + [config] Array::Ptr groups { + default {{{ return make_shared(); }}} + }; [config] String period (PeriodRaw); [config] Array::Ptr types; int type_filter_real (TypeFilter); diff --git a/lib/icinga/usergroup.cpp b/lib/icinga/usergroup.cpp index 2ee963709..1735d24a6 100644 --- a/lib/icinga/usergroup.cpp +++ b/lib/icinga/usergroup.cpp @@ -66,6 +66,9 @@ bool UserGroup::EvaluateObjectRule(const User::Ptr user, const ObjectRule& rule) /* assign user group membership */ group->ResolveGroupMembership(user, true); + /* update groups attribute for apply */ + user->AddGroup(group_name); + return true; }