]> granicus.if.org Git - icinga2/commitdiff
Refactor apply/object rules
authorGunnar Beutner <gunnar@beutner.name>
Sun, 16 Nov 2014 15:20:39 +0000 (16:20 +0100)
committerGunnar Beutner <gunnar@beutner.name>
Thu, 20 Nov 2014 20:29:50 +0000 (21:29 +0100)
fixes #7700

26 files changed:
lib/config/applyrule.cpp
lib/config/applyrule.hpp
lib/config/configitem.cpp
lib/config/configitem.hpp
lib/config/configitembuilder.cpp
lib/config/configitembuilder.hpp
lib/config/expression.cpp
lib/config/objectrule.cpp
lib/config/objectrule.hpp
lib/icinga/dependency-apply.cpp
lib/icinga/dependency.hpp
lib/icinga/host.cpp
lib/icinga/hostgroup.cpp
lib/icinga/hostgroup.hpp
lib/icinga/notification-apply.cpp
lib/icinga/notification.hpp
lib/icinga/scheduleddowntime-apply.cpp
lib/icinga/scheduleddowntime.hpp
lib/icinga/service-apply.cpp
lib/icinga/service.cpp
lib/icinga/service.hpp
lib/icinga/servicegroup.cpp
lib/icinga/servicegroup.hpp
lib/icinga/user.cpp
lib/icinga/usergroup.cpp
lib/icinga/usergroup.hpp

index f542cb63a247f325b7ca79649471a942aebb8aa1..4e192cd57636eaef693f7f33dccf92788bd45d30 100644 (file)
 using namespace icinga;
 
 ApplyRule::RuleMap ApplyRule::m_Rules;
-ApplyRule::CallbackMap ApplyRule::m_Callbacks;
+ApplyRule::TypeMap ApplyRule::m_Types;
 
 ApplyRule::ApplyRule(const String& targetType, const String& name, const boost::shared_ptr<Expression>& expression,
     const boost::shared_ptr<Expression>& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm,
     const DebugInfo& di, const Object::Ptr& scope)
        : m_TargetType(targetType), m_Name(name), m_Expression(expression), m_Filter(filter), m_FKVar(fkvar),
-         m_FVVar(fvvar), m_FTerm(fterm), m_DebugInfo(di), m_Scope(scope)
+         m_FVVar(fvvar), m_FTerm(fterm), m_DebugInfo(di), m_Scope(scope), m_HasMatches(false)
 { }
 
 String ApplyRule::GetTargetType(void) const
@@ -91,69 +91,27 @@ bool ApplyRule::EvaluateFilter(const Object::Ptr& scope) const
        return m_Filter->Evaluate(scope).ToBool();
 }
 
-void ApplyRule::EvaluateRules(bool clear)
+void ApplyRule::RegisterType(const String& sourceType, const std::vector<String>& targetTypes)
 {
-       std::set<String> completedTypes;
-
-       while (completedTypes.size() < m_Callbacks.size()) {
-               std::pair<String, std::pair<Callback, std::vector<String> > > kv;
-               BOOST_FOREACH(kv, m_Callbacks) {
-                       const String& sourceType = kv.first;
-
-                       if (completedTypes.find(sourceType) != completedTypes.end())
-                               continue;
-
-                       const Callback& callback = kv.second.first;
-                       const std::vector<String>& targetTypes = kv.second.second;
-
-                       bool cont = false;
-
-                       BOOST_FOREACH(const String& targetType, targetTypes) {
-                               if (IsValidSourceType(targetType) && completedTypes.find(targetType) == completedTypes.end()) {
-                                       cont = true;
-                                       break;
-                               }
-                       }
-
-                       if (cont)
-                               continue;
-
-                       completedTypes.insert(sourceType);
-
-                       RuleMap::const_iterator it = m_Rules.find(kv.first);
-
-                       if (it == m_Rules.end())
-                               continue;
-
-                       callback(it->second);
-               }
-       }
-
-       if (clear)
-               m_Rules.clear();
-}
-
-void ApplyRule::RegisterType(const String& sourceType, const std::vector<String>& targetTypes, const ApplyRule::Callback& callback)
-{
-       m_Callbacks[sourceType] = make_pair(callback, targetTypes);
+       m_Types[sourceType] = targetTypes;
 }
 
 bool ApplyRule::IsValidSourceType(const String& sourceType)
 {
-       return m_Callbacks.find(sourceType) != m_Callbacks.end();
+       return m_Types.find(sourceType) != m_Types.end();
 }
 
 bool ApplyRule::IsValidTargetType(const String& sourceType, const String& targetType)
 {
-       CallbackMap::const_iterator it = m_Callbacks.find(sourceType);
+       TypeMap::const_iterator it = m_Types.find(sourceType);
 
-       if (it == m_Callbacks.end())
+       if (it == m_Types.end())
                return false;
 
-       if (it->second.second.size() == 1 && targetType == "")
+       if (it->second.size() == 1 && targetType == "")
                return true;
 
-       BOOST_FOREACH(const String& type, it->second.second) {
+       BOOST_FOREACH(const String& type, it->second) {
                if (type == targetType)
                        return true;
        }
@@ -163,11 +121,47 @@ bool ApplyRule::IsValidTargetType(const String& sourceType, const String& target
 
 std::vector<String> ApplyRule::GetTargetTypes(const String& sourceType)
 {
-       CallbackMap::const_iterator it = m_Callbacks.find(sourceType);
+       TypeMap::const_iterator it = m_Types.find(sourceType);
 
-       if (it == m_Callbacks.end())
+       if (it == m_Types.end())
                return std::vector<String>();
 
-       return it->second.second;
+       return it->second;
+}
+
+void ApplyRule::AddMatch(void)
+{
+       m_HasMatches = true;
+}
+
+bool ApplyRule::HasMatches(void) const
+{
+       return m_HasMatches;
+}
+
+std::vector<ApplyRule>& ApplyRule::GetRules(const String& type)
+{
+       RuleMap::iterator it = m_Rules.find(type);
+       if (it == m_Rules.end()) {
+               static std::vector<ApplyRule> emptyList;
+               return emptyList;
+       }
+       return it->second;
+}
+
+void ApplyRule::CheckMatches(void)
+{
+       BOOST_FOREACH(const RuleMap::value_type& kv, m_Rules) {
+               BOOST_FOREACH(const ApplyRule& rule, kv.second) {
+                       if (!rule.HasMatches())
+                               Log(LogWarning, "ApplyRule")
+                                   << "Apply rule '" + rule.GetName() + "' for type '" + kv.first + "' does not match anywhere!";
+               }
+       }
+}
+
+void ApplyRule::DiscardRules(void)
+{
+       m_Rules.clear();
 }
 
index 015556672e4fe7ca37cd439f3388085449c52902..b85357aa8232269f0f297c1ceec753fb9b9e1b5a 100644 (file)
@@ -34,8 +34,7 @@ namespace icinga
 class I2_CONFIG_API ApplyRule
 {
 public:
-       typedef boost::function<void (const std::vector<ApplyRule>& rules)> Callback;
-       typedef std::map<String, std::pair<Callback, std::vector<String> > > CallbackMap;
+       typedef std::map<String, std::vector<String> > TypeMap;
        typedef std::map<String, std::vector<ApplyRule> > RuleMap;
 
        String GetTargetType(void) const;
@@ -47,18 +46,23 @@ public:
        boost::shared_ptr<Expression> GetFTerm(void) const;
        DebugInfo GetDebugInfo(void) const;
        Object::Ptr GetScope(void) const;
+       void AddMatch(void);
+       bool HasMatches(void) const;
 
        bool EvaluateFilter(const Object::Ptr& scope) const;
 
        static void AddRule(const String& sourceType, const String& targetType, const String& name, const boost::shared_ptr<Expression>& expression,
            const boost::shared_ptr<Expression>& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm, const DebugInfo& di, const Object::Ptr& scope);
-       static void EvaluateRules(bool clear);
+       static std::vector<ApplyRule>& GetRules(const String& type);
 
-       static void RegisterType(const String& sourceType, const std::vector<String>& targetTypes, const ApplyRule::Callback& callback);
+       static void RegisterType(const String& sourceType, const std::vector<String>& targetTypes);
        static bool IsValidSourceType(const String& sourceType);
        static bool IsValidTargetType(const String& sourceType, const String& targetType);
        static std::vector<String> GetTargetTypes(const String& sourceType);
 
+       static void CheckMatches(void);
+       static void DiscardRules(void);
+
 private:
        String m_TargetType;
        String m_Name;
@@ -69,8 +73,9 @@ private:
        boost::shared_ptr<Expression> m_FTerm;
        DebugInfo m_DebugInfo;
        Object::Ptr m_Scope;
+       bool m_HasMatches;
 
-       static CallbackMap m_Callbacks;
+       static TypeMap m_Types;
        static RuleMap m_Rules;
 
        ApplyRule(const String& targetType, const String& name, const boost::shared_ptr<Expression>& expression,
index 00beca8bf8e551ae8a9132b7a87fb4a695646495..0d920eb1a41e75bef7a6d4c93605a578908f1d10 100644 (file)
@@ -42,7 +42,7 @@
 using namespace icinga;
 
 boost::mutex ConfigItem::m_Mutex;
-ConfigItem::ItemMap ConfigItem::m_Items;
+ConfigItem::TypeMap ConfigItem::m_Items;
 ConfigItem::ItemList ConfigItem::m_UnnamedItems;
 
 /**
@@ -57,11 +57,12 @@ ConfigItem::ItemList ConfigItem::m_UnnamedItems;
  */
 ConfigItem::ConfigItem(const String& type, const String& name,
     bool abstract, const boost::shared_ptr<Expression>& exprl,
+    const boost::shared_ptr<Expression>& filter,
     const DebugInfo& debuginfo, const Object::Ptr& scope,
     const String& zone)
        : m_Type(type), m_Name(name), m_Abstract(abstract),
-         m_Expression(exprl), m_DebugInfo(debuginfo),
-         m_Scope(scope), m_Zone(zone)
+         m_Expression(exprl), m_Filter(filter),
+         m_DebugInfo(debuginfo), m_Scope(scope), m_Zone(zone)
 {
 }
 
@@ -120,6 +121,16 @@ boost::shared_ptr<Expression> ConfigItem::GetExpression(void) const
        return m_Expression;
 }
 
+/**
+* Retrieves the object filter for the configuration item.
+*
+* @returns The filter expression.
+*/
+boost::shared_ptr<Expression> ConfigItem::GetFilter(void) const
+{
+       return m_Filter;
+}
+
 /**
  * Commits the configuration item by creating a DynamicObject
  * object.
@@ -150,7 +161,6 @@ DynamicObject::Ptr ConfigItem::Commit(bool discard)
 
        Dictionary::Ptr locals = new Dictionary();
        locals->Set("__parent", m_Scope);
-       m_Scope.reset();
 
        dobj->SetParentScope(locals);
        locals.reset();
@@ -238,10 +248,8 @@ void ConfigItem::Register(void)
                boost::mutex::scoped_lock lock(m_Mutex);
                m_UnnamedItems.push_back(this);
        } else {
-               std::pair<String, String> key = std::make_pair(m_Type, m_Name);
-
                boost::mutex::scoped_lock lock(m_Mutex);
-               m_Items[key] = this;
+               m_Items[m_Type][m_Name] = this;
        }
 }
 
@@ -254,57 +262,61 @@ void ConfigItem::Register(void)
  */
 ConfigItem::Ptr ConfigItem::GetObject(const String& type, const String& name)
 {
-       std::pair<String, String> key = std::make_pair(type, name);
-       ConfigItem::ItemMap::iterator it;
-
        {
                boost::mutex::scoped_lock lock(m_Mutex);
 
-               it = m_Items.find(key);
-       }
+               ConfigItem::TypeMap::const_iterator it = m_Items.find(type);
+
+               if (it == m_Items.end())
+                       return ConfigItem::Ptr();
+
+               ConfigItem::ItemMap::const_iterator it2 = it->second.find(name);
 
-       if (it != m_Items.end())
-               return it->second;
+               if (it2 == it->second.end())
+                       return ConfigItem::Ptr();
 
-       return ConfigItem::Ptr();
+               return it2->second;
+       }
 }
 
-bool ConfigItem::CommitNewItems(void)
+bool ConfigItem::CommitNewItems(ParallelWorkQueue& upq)
 {
-       std::vector<ConfigItem::Ptr> items;
+       typedef std::pair<ConfigItem::Ptr, bool> ItemPair;
+       std::vector<ItemPair> items;
 
        do {
-               ParallelWorkQueue upq;
-
                items.clear();
 
                {
                        boost::mutex::scoped_lock lock(m_Mutex);
 
-                       BOOST_FOREACH(const ItemMap::value_type& kv, m_Items) {
-                               if (!kv.second->m_Abstract && !kv.second->m_Object) {
-                                       upq.Enqueue(boost::bind(&ConfigItem::Commit, kv.second, false));
-                                       items.push_back(kv.second);
+                       BOOST_FOREACH(const TypeMap::value_type& kv, m_Items) {
+                               BOOST_FOREACH(const ItemMap::value_type& kv2, kv.second)
+                               {
+                                       if (!kv2.second->m_Abstract && !kv2.second->m_Object)
+                                               items.push_back(std::make_pair(kv2.second, false));
                                }
                        }
 
                        BOOST_FOREACH(const ConfigItem::Ptr& item, m_UnnamedItems) {
-                               if (!item->m_Abstract && !item->m_Object) {
-                                       upq.Enqueue(boost::bind(&ConfigItem::Commit, item, true));
-                                       items.push_back(item);
-                               }
+                               if (!item->m_Abstract && !item->m_Object)
+                                       items.push_back(std::make_pair(item, true));
                        }
 
                        m_UnnamedItems.clear();
                }
 
+               BOOST_FOREACH(const ItemPair& ip, items) {
+                       upq.Enqueue(boost::bind(&ConfigItem::Commit, ip.first, ip.second));
+               }
+
                upq.Join();
 
                if (ConfigCompilerContext::GetInstance()->HasErrors())
                        return false;
 
-               BOOST_FOREACH(const ConfigItem::Ptr& item, items) {
-                       upq.Enqueue(boost::bind(&DynamicObject::OnConfigLoaded, item->m_Object));
+               BOOST_FOREACH(const ItemPair& ip, items) {
+                       upq.Enqueue(boost::bind(&DynamicObject::OnConfigLoaded, ip.first->m_Object));
                }
 
                upq.Join();
@@ -315,25 +327,18 @@ bool ConfigItem::CommitNewItems(void)
 
 bool ConfigItem::ValidateItems(void)
 {
+       ParallelWorkQueue upq;
+
        if (ConfigCompilerContext::GetInstance()->HasErrors())
                return false;
 
        Log(LogInformation, "ConfigItem", "Committing config items");
 
-       if (!CommitNewItems())
+       if (!CommitNewItems(upq))
                return false;
 
-       Log(LogInformation, "ConfigItem", "Evaluating 'object' rules (step 1)...");
-       ObjectRule::EvaluateRules(false);
-
-       Log(LogInformation, "ConfigItem", "Evaluating 'apply' rules...");
-       ApplyRule::EvaluateRules(true);
-
-       if (!CommitNewItems())
-               return false;
-
-       Log(LogInformation, "ConfigItem", "Evaluating 'object' rules (step 2)...");
-       ObjectRule::EvaluateRules(true);
+       ApplyRule::CheckMatches();
+       ApplyRule::DiscardRules();
 
        ConfigItem::DiscardItems();
        ConfigType::DiscardTypes();
@@ -400,3 +405,22 @@ void ConfigItem::DiscardItems(void)
 
        m_Items.clear();
 }
+
+std::vector<ConfigItem::Ptr> ConfigItem::GetItems(const String& type)
+{
+       std::vector<ConfigItem::Ptr> items;
+
+       boost::mutex::scoped_lock lock(m_Mutex);
+
+       TypeMap::const_iterator it = m_Items.find(type);
+
+       if (it == m_Items.end())
+               return items;
+
+       BOOST_FOREACH(const ItemMap::value_type& kv, it->second)
+       {
+               items.push_back(kv.second);
+       }
+
+       return items;
+}
index 390f8ce72fb4d39a80d36a83c26de49bcb9a4220..f79c066bcfc98eb9b36c9793d324ef77c3889dee 100644 (file)
@@ -23,6 +23,7 @@
 #include "config/i2-config.hpp"
 #include "config/expression.hpp"
 #include "base/dynamicobject.hpp"
+#include "base/workqueue.hpp"
 
 namespace icinga
 {
@@ -38,7 +39,9 @@ public:
        DECLARE_PTR_TYPEDEFS(ConfigItem);
 
        ConfigItem(const String& type, const String& name, bool abstract,
-           const boost::shared_ptr<Expression>& exprl, const DebugInfo& debuginfo,
+           const boost::shared_ptr<Expression>& exprl,
+           const boost::shared_ptr<Expression>& filter,
+           const DebugInfo& debuginfo,
            const Object::Ptr& scope, const String& zone);
 
        String GetType(void) const;
@@ -48,12 +51,12 @@ public:
        std::vector<ConfigItem::Ptr> GetParents(void) const;
 
        boost::shared_ptr<Expression> GetExpression(void) const;
+       boost::shared_ptr<Expression> GetFilter(void) const;
 
        DynamicObject::Ptr Commit(bool discard = true);
        void Register(void);
 
        DebugInfo GetDebugInfo(void) const;
-
        Object::Ptr GetScope(void) const;
 
        String GetZone(void) const;
@@ -65,12 +68,15 @@ public:
        static bool ActivateItems(void);
        static void DiscardItems(void);
 
+       static std::vector<ConfigItem::Ptr> GetItems(const String& type);
+
 private:
        String m_Type; /**< The object type. */
        String m_Name; /**< The name. */
        bool m_Abstract; /**< Whether this is a template. */
 
        boost::shared_ptr<Expression> m_Expression;
+       boost::shared_ptr<Expression> m_Filter;
        DebugInfo m_DebugInfo; /**< Debug information. */
        Object::Ptr m_Scope; /**< variable scope. */
        String m_Zone; /**< The zone. */
@@ -79,8 +85,9 @@ private:
 
        static boost::mutex m_Mutex;
 
-       typedef std::map<std::pair<String, String>, ConfigItem::Ptr> ItemMap;
-       static ItemMap m_Items; /**< All registered configuration items. */
+       typedef std::map<String, ConfigItem::Ptr> ItemMap;
+       typedef std::map<String, ItemMap> TypeMap;
+       static TypeMap m_Items; /**< All registered configuration items. */
 
        typedef std::vector<ConfigItem::Ptr> ItemList;
        static ItemList m_UnnamedItems;
@@ -88,7 +95,7 @@ private:
        static ConfigItem::Ptr GetObjectUnlocked(const String& type,
            const String& name);
 
-       static bool CommitNewItems(void);
+       static bool CommitNewItems(ParallelWorkQueue& upq);
 };
 
 }
index 994a9dac2986102de9c9b7ecb52fa16917f78f75..89d016801cd0b9a629fabb2d59e32b27892a5762 100644 (file)
@@ -21,6 +21,7 @@
 #include "base/dynamictype.hpp"
 #include <sstream>
 #include <boost/foreach.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
 
 using namespace icinga;
 
@@ -69,6 +70,11 @@ void ConfigItemBuilder::AddExpression(Expression *expr)
        m_Expressions.push_back(expr);
 }
 
+void ConfigItemBuilder::SetFilter(const boost::shared_ptr<Expression>& filter)
+{
+       m_Filter = filter;
+}
+
 ConfigItem::Ptr ConfigItemBuilder::Compile(void)
 {
        if (m_Type.IsEmpty()) {
@@ -104,10 +110,10 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
        dexpr->MakeInline();
        exprs.push_back(dexpr);
 
-       DictExpression *exprl = new DictExpression(exprs, m_DebugInfo);
+       boost::shared_ptr<DictExpression> exprl = boost::make_shared<DictExpression>(exprs, m_DebugInfo);
        exprl->MakeInline();
 
-       return new ConfigItem(m_Type, m_Name, m_Abstract, boost::shared_ptr<Expression>(exprl),
+       return new ConfigItem(m_Type, m_Name, m_Abstract, exprl, m_Filter,
            m_DebugInfo, m_Scope, m_Zone);
 }
 
index b9795c6cc80d9a4baf868f14325063a8fe9e18ad..d44007ff87260dff47385136d6135c9a2fd898df 100644 (file)
@@ -49,6 +49,7 @@ public:
        void SetZone(const String& zone);
 
        void AddExpression(Expression *expr);
+       void SetFilter(const boost::shared_ptr<Expression>& filter);
 
        ConfigItem::Ptr Compile(void);
 
@@ -57,6 +58,7 @@ private:
        String m_Name; /**< The name. */
        bool m_Abstract; /**< Whether the item is abstract. */
        std::vector<Expression *> m_Expressions; /**< Expressions for this item. */
+       boost::shared_ptr<Expression> m_Filter; /**< Filter expression. */
        DebugInfo m_DebugInfo; /**< Debug information. */
        Object::Ptr m_Scope; /**< variable scope. */
        String m_Zone; /**< The zone. */
index f37e353f646579065ebba56e99a83cb07edf5e07..5bc4ecc396f5bdd9c883a276c2511386823cd271 100644 (file)
@@ -46,10 +46,10 @@ Value Expression::Evaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
        try {
 #ifdef _DEBUG
-               std::ostringstream msgbuf;
+/*             std::ostringstream msgbuf;
                ShowCodeFragment(msgbuf, GetDebugInfo(), false);
                Log(LogDebug, "Expression")
-                       << "Executing:\n" << msgbuf.str();
+                       << "Executing:\n" << msgbuf.str();*/
 #endif /* _DEBUG */
 
                return DoEvaluate(context, dhint);
@@ -508,10 +508,9 @@ Value ObjectExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint)
        item->SetAbstract(m_Abstract);
        item->SetScope(context);
        item->SetZone(m_Zone);
-       item->Compile()->Register();
+       item->SetFilter(m_Filter);
 
-       if (m_Filter)
-               ObjectRule::AddRule(m_Type, name, m_Filter, m_DebugInfo, context);
+       item->Compile()->Register();
 
        return Empty;
 }
index 37818cb41a3144d0e5da8d535632b4bacfb3d925..26975d19c4ae38ae978c41896e2d87af0bd9d66b 100644 (file)
 
 using namespace icinga;
 
-ObjectRule::RuleMap ObjectRule::m_Rules;
-ObjectRule::CallbackMap ObjectRule::m_Callbacks;
+ObjectRule::TypeSet ObjectRule::m_Types;
 
-ObjectRule::ObjectRule(const String& name, const boost::shared_ptr<Expression>& filter,
-    const DebugInfo& di, const Object::Ptr& scope)
-       : m_Name(name), m_Filter(filter), m_DebugInfo(di), m_Scope(scope)
-{ }
-
-String ObjectRule::GetName(void) const
-{
-       return m_Name;
-}
-
-boost::shared_ptr<Expression> ObjectRule::GetFilter(void) const
-{
-       return m_Filter;
-}
-
-DebugInfo ObjectRule::GetDebugInfo(void) const
+void ObjectRule::RegisterType(const String& sourceType)
 {
-       return m_DebugInfo;
-}
-
-Object::Ptr ObjectRule::GetScope(void) const
-{
-       return m_Scope;
-}
-
-void ObjectRule::AddRule(const String& sourceType, const String& name,
-    const boost::shared_ptr<Expression>& filter, const DebugInfo& di, const Object::Ptr& scope)
-{
-       m_Rules[sourceType].push_back(ObjectRule(name, filter, di, scope));
-}
-
-bool ObjectRule::EvaluateFilter(const Object::Ptr& scope) const
-{
-       return m_Filter->Evaluate(scope).ToBool();
-}
-
-void ObjectRule::EvaluateRules(bool clear)
-{
-       std::pair<String, Callback> kv;
-       BOOST_FOREACH(kv, m_Callbacks) {
-               const Callback& callback = kv.second;
-
-               RuleMap::const_iterator it = m_Rules.find(kv.first);
-
-               if (it == m_Rules.end())
-                       continue;
-
-               callback(it->second);
-       }
-
-       if (clear)
-               m_Rules.clear();
-}
-
-void ObjectRule::RegisterType(const String& sourceType, const ObjectRule::Callback& callback)
-{
-       m_Callbacks[sourceType] = callback;
+       m_Types.insert(sourceType);
 }
 
 bool ObjectRule::IsValidSourceType(const String& sourceType)
 {
-       return m_Callbacks.find(sourceType) != m_Callbacks.end();
+       return m_Types.find(sourceType) != m_Types.end();
 }
-
index 42bf19cb33b1edfe65bcfd0077b924ecd3e4ed3e..732aa48585a70f351e1475164f7aeb9aaf520c2f 100644 (file)
@@ -23,7 +23,7 @@
 #include "config/i2-config.hpp"
 #include "config/expression.hpp"
 #include "base/debuginfo.hpp"
-#include "base/dynamictype.hpp"
+#include <set>
 
 namespace icinga
 {
@@ -34,34 +34,15 @@ namespace icinga
 class I2_CONFIG_API ObjectRule
 {
 public:
-       typedef boost::function<void (const std::vector<ObjectRule>& rules)> Callback;
-       typedef std::map<String, Callback> CallbackMap;
-       typedef std::map<String, std::vector<ObjectRule> > RuleMap;
+       typedef std::set<String> TypeSet;
 
-       String GetName(void) const;
-       boost::shared_ptr<Expression> GetFilter(void) const;
-       DebugInfo GetDebugInfo(void) const;
-       Object::Ptr GetScope(void) const;
-
-       bool EvaluateFilter(const Object::Ptr& scope) const;
-
-       static void AddRule(const String& sourceType, const String& name,
-           const boost::shared_ptr<Expression>& filter, const DebugInfo& di, const Object::Ptr& scope);
-       static void EvaluateRules(bool clear);
-
-       static void RegisterType(const String& sourceType, const ObjectRule::Callback& callback);
+       static void RegisterType(const String& sourceType);
        static bool IsValidSourceType(const String& sourceType);
 
 private:
-       String m_Name;
-       boost::shared_ptr<Expression> m_Filter;
-       DebugInfo m_DebugInfo;
-       Object::Ptr m_Scope;
-
-       static CallbackMap m_Callbacks;
-       static RuleMap m_Rules;
+       ObjectRule(void);
 
-       ObjectRule(const String& name, const boost::shared_ptr<Expression>& filter, const DebugInfo& di, const Object::Ptr& scope);
+       static TypeSet m_Types;
 };
 
 }
index 3868615230cec5f8dbf5494a187500c52a547107..e7ffc327e34be1a257dcd27de469cbf6dc2e8c97 100644 (file)
@@ -39,10 +39,10 @@ void Dependency::RegisterApplyRuleHandler(void)
        std::vector<String> targets;
        targets.push_back("Host");
        targets.push_back("Service");
-       ApplyRule::RegisterType("Dependency", targets, &Dependency::EvaluateApplyRules);
+       ApplyRule::RegisterType("Dependency", targets);
 }
 
-void Dependency::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
+void Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
 {
        DebugInfo di = rule.GetDebugInfo();
 
@@ -77,7 +77,7 @@ void Dependency::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, c
 
 }
 
-bool Dependency::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule)
+bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule)
 {
        DebugInfo di = rule.GetDebugInfo();
 
@@ -123,7 +123,7 @@ bool Dependency::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const App
                                name += instance;
                        }
 
-                       EvaluateApplyRuleOneInstance(checkable, name, locals, rule);
+                       EvaluateApplyRuleInstance(checkable, name, locals, rule);
                }
        } else if (vinstances.IsObjectType<Dictionary>()) {
                if (rule.GetFVVar().IsEmpty())
@@ -136,68 +136,47 @@ bool Dependency::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const App
                        locals->Set(rule.GetFKVar(), kv.first);
                        locals->Set(rule.GetFVVar(), kv.second);
 
-                       EvaluateApplyRuleOneInstance(checkable, rule.GetName() + kv.first, locals, rule);
+                       EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, locals, rule);
                }
        }
 
        return true;
 }
 
-void Dependency::EvaluateApplyRule(const ApplyRule& rule)
+void Dependency::EvaluateApplyRules(const Host::Ptr& host)
 {
-       int apply_count = 0;
-
-       if (rule.GetTargetType() == "Host") {
-               apply_count = 0;
-
-               BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType<Host>()) {
-                       CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
-
-                       try {
-                               if (EvaluateApplyRuleOne(host, rule))
-                                       apply_count++;
-                       } catch (const ConfigError& ex) {
-                               const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
-                               ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
-                       }
-               }
-
-               if (apply_count == 0)
-                       Log(LogWarning, "Dependency")
-                           << "Apply rule '" << rule.GetName() << "' for host does not match anywhere!";
-
-       } else if (rule.GetTargetType() == "Service") {
-               apply_count = 0;
-
-               BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjectsByType<Service>()) {
-                       CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'");
-
-                       try {
-                               if (EvaluateApplyRuleOne(service, rule))
-                                       apply_count++;
-                       } catch (const ConfigError& ex) {
-                               const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
-                               ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
-                       }
+       CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
+
+       BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Dependency"))
+       {
+               if (rule.GetTargetType() != "Host")
+                       continue;
+
+               try {
+                       if (EvaluateApplyRule(host, rule))
+                               rule.AddMatch();
+               } catch (const ConfigError& ex) {
+                       const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
+                       ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
                }
-
-               if (apply_count == 0)
-                       Log(LogWarning, "Dependency")
-                           << "Apply rule '" << rule.GetName() << "' for service does not match anywhere!";
-
-       } else {
-               Log(LogWarning, "Dependency")
-                   << "Wrong target type for apply rule '" << rule.GetName() << "'!";
        }
 }
 
-void Dependency::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
+void Dependency::EvaluateApplyRules(const Service::Ptr& service)
 {
-       ParallelWorkQueue upq;
-
-       BOOST_FOREACH(const ApplyRule& rule, rules) {
-               upq.Enqueue(boost::bind(&Dependency::EvaluateApplyRule, boost::cref(rule)));
+       CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'");
+
+       BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Dependency"))
+       {
+               if (rule.GetTargetType() != "Service")
+                       continue;
+
+               try {
+                       if (EvaluateApplyRule(service, rule))
+                               rule.AddMatch();
+               } catch (const ConfigError& ex) {
+                       const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
+                       ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
+               }
        }
-
-       upq.Join();
 }
index a3d9b8a71db523d1073143185563edb1e8b2014f..f8aeeccc5b08c508cd85e61eb5de03cc0b39d4ff 100644 (file)
@@ -28,6 +28,8 @@ namespace icinga
 {
 
 class ApplyRule;
+class Host;
+class Service;
 
 /**
  * A service dependency..
@@ -51,6 +53,9 @@ public:
 
        static void ValidateFilters(const String& location, const Dependency::Ptr& object);
 
+       static void EvaluateApplyRules(const intrusive_ptr<Host>& host);
+       static void EvaluateApplyRules(const intrusive_ptr<Service>& service);
+
 protected:
        virtual void OnConfigLoaded(void);
        virtual void OnStateLoaded(void);
@@ -60,10 +65,8 @@ private:
        Checkable::Ptr m_Parent;
        Checkable::Ptr m_Child;
 
-       static void EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
-       static bool EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule);
-       static void EvaluateApplyRule(const ApplyRule& rule);
-       static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
+       static void EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
+       static bool EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule);
 };
 
 }
index 84a61a6b5f75c01ccd9a31fdc1df8da04c551e36..e612788d61bee5c670ad7fd0f5380ba9b491f2b5 100644 (file)
@@ -21,6 +21,9 @@
 #include "icinga/service.hpp"
 #include "icinga/hostgroup.hpp"
 #include "icinga/pluginutility.hpp"
+#include "icinga/scheduleddowntime.hpp"
+#include "config/configcompilercontext.hpp"
+#include "base/configerror.hpp"
 #include "base/objectlock.hpp"
 #include "base/convert.hpp"
 #include "base/utility.hpp"
@@ -52,6 +55,12 @@ void Host::OnConfigLoaded(void)
                                hg->ResolveGroupMembership(this, true);
                }
        }
+
+       HostGroup::EvaluateObjectRules(this);
+       ScheduledDowntime::EvaluateApplyRules(this);
+       Notification::EvaluateApplyRules(this);
+       Dependency::EvaluateApplyRules(this);
+       Service::EvaluateApplyRules(this);
 }
 
 void Host::Stop(void)
index 05c63275a8ff85e38d78bccacab35e06626a8149..ff84cde3168802389d2b62396997b125eec88b20 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "icinga/hostgroup.hpp"
 #include "config/objectrule.hpp"
+#include "config/configitem.hpp"
 #include "base/dynamictype.hpp"
 #include "base/logger.hpp"
 #include "base/objectlock.hpp"
@@ -34,60 +35,50 @@ INITIALIZE_ONCE(&HostGroup::RegisterObjectRuleHandler);
 
 void HostGroup::RegisterObjectRuleHandler(void)
 {
-       ObjectRule::RegisterType("HostGroup", &HostGroup::EvaluateObjectRules);
+       ObjectRule::RegisterType("HostGroup");
 }
 
-bool HostGroup::EvaluateObjectRuleOne(const Host::Ptr& host, const ObjectRule& rule)
+bool HostGroup::EvaluateObjectRule(const Host::Ptr& host, const ConfigItem::Ptr& group)
 {
-       DebugInfo di = rule.GetDebugInfo();
+       String group_name = group->GetName();
 
-       std::ostringstream msgbuf;
-       msgbuf << "Evaluating 'object' rule (" << di << ")";
-       CONTEXT(msgbuf.str());
+       CONTEXT("Evaluating rule for group '" + group_name + "'");
 
        Dictionary::Ptr locals = new Dictionary();
-       locals->Set("__parent", rule.GetScope());
+       locals->Set("__parent", group->GetScope());
        locals->Set("host", host);
 
-       if (!rule.EvaluateFilter(locals))
+       if (!group->GetFilter()->Evaluate(locals))
                return false;
 
        Log(LogDebug, "HostGroup")
-           << "Assigning membership for group '" << rule.GetName() << "' to host '" << host->GetName() << "' for rule " << di;
+           << "Assigning membership for group '" << group_name << "' to host '" << host->GetName() << "'";
 
-       String group_name = rule.GetName();
-       HostGroup::Ptr group = HostGroup::GetByName(group_name);
+       HostGroup::Ptr groupObject = HostGroup::GetByName(group_name);
 
-       if (!group) {
+       if (!groupObject) {
                Log(LogCritical, "HostGroup")
                    << "Invalid membership assignment. Group '" << group_name << "' does not exist.";
                return false;
        }
 
        /* assign host group membership */
-       group->ResolveGroupMembership(host, true);
+       groupObject->ResolveGroupMembership(host, true);
 
        return true;
 }
 
-void HostGroup::EvaluateObjectRule(const ObjectRule& rule)
+void HostGroup::EvaluateObjectRules(const Host::Ptr& host)
 {
-       BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType<Host>()) {
-               CONTEXT("Evaluating group membership in '" + rule.GetName() + "' for host '" + host->GetName() + "'");
+       CONTEXT("Evaluating group memberships for host '" + host->GetName() + "'");
 
-               EvaluateObjectRuleOne(host, rule);
-       }
-}
+       BOOST_FOREACH(const ConfigItem::Ptr& group, ConfigItem::GetItems("HostGroup"))
+       {
+               if (!group->GetFilter())
+                       continue;
 
-void HostGroup::EvaluateObjectRules(const std::vector<ObjectRule>& rules)
-{
-       ParallelWorkQueue upq;
-
-       BOOST_FOREACH(const ObjectRule& rule, rules) {
-               upq.Enqueue(boost::bind(HostGroup::EvaluateObjectRule, boost::cref(rule)));
+               EvaluateObjectRule(host, group);
        }
-
-       upq.Join();
 }
 
 std::set<Host::Ptr> HostGroup::GetMembers(void) const
index 1aa667a0e79f69e33af2ce953b3cd06dc02f040c..0c019464605936945be7e2c508ab3e242941cf6b 100644 (file)
@@ -27,7 +27,7 @@
 namespace icinga
 {
 
-class ObjectRule;
+class ConfigItem;
 
 /**
  * An Icinga host group.
@@ -48,13 +48,13 @@ public:
 
        static void RegisterObjectRuleHandler(void);
 
+       static void EvaluateObjectRules(const Host::Ptr& host);
+
 private:
        mutable boost::mutex m_HostGroupMutex;
        std::set<Host::Ptr> m_Members;
 
-       static bool EvaluateObjectRuleOne(const Host::Ptr& host, const ObjectRule& rule);
-       static void EvaluateObjectRule(const ObjectRule& rule);
-       static void EvaluateObjectRules(const std::vector<ObjectRule>& rules);
+       static bool EvaluateObjectRule(const Host::Ptr& host, const intrusive_ptr<ConfigItem>& item);
 };
 
 }
index 160933cc473ba25b5f79674218ba6d357f11c01f..7af35260ce0f7bf4fe0a1fbf5d2c6e0f905b10e0 100644 (file)
@@ -39,10 +39,10 @@ void Notification::RegisterApplyRuleHandler(void)
        std::vector<String> targets;
        targets.push_back("Host");
        targets.push_back("Service");
-       ApplyRule::RegisterType("Notification", targets, &Notification::EvaluateApplyRules);
+       ApplyRule::RegisterType("Notification", targets);
 }
 
-void Notification::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
+void Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
 {
        DebugInfo di = rule.GetDebugInfo();
 
@@ -76,7 +76,7 @@ void Notification::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable,
        
 }
 
-bool Notification::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule)
+bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule)
 {
        DebugInfo di = rule.GetDebugInfo();
 
@@ -122,7 +122,7 @@ bool Notification::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const A
                                name += instance;
                        }
 
-                       EvaluateApplyRuleOneInstance(checkable, name, locals, rule);
+                       EvaluateApplyRuleInstance(checkable, name, locals, rule);
                }
        } else if (vinstances.IsObjectType<Dictionary>()) {
                if (rule.GetFVVar().IsEmpty())
@@ -135,67 +135,47 @@ bool Notification::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const A
                        locals->Set(rule.GetFKVar(), kv.first);
                        locals->Set(rule.GetFVVar(), kv.second);
 
-                       EvaluateApplyRuleOneInstance(checkable, rule.GetName() + kv.first, locals, rule);
+                       EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, locals, rule);
                }
        }
 
        return true;
 }
 
-void Notification::EvaluateApplyRule(const ApplyRule& rule)
+void Notification::EvaluateApplyRules(const Host::Ptr& host)
 {
-       int apply_count = 0;
-
-       if (rule.GetTargetType() == "Host") {
-               apply_count = 0;
-
-               BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType<Host>()) {
-                       CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
-
-                       try {
-                               if (EvaluateApplyRuleOne(host, rule))
-                                       apply_count++;
-                       } catch (const ConfigError& ex) {
-                               const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
-                               ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
-                       }
+       CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
+
+       BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Notification"))
+       {
+               if (rule.GetTargetType() != "Host")
+                       continue;
+
+               try {
+                       if (EvaluateApplyRule(host, rule))
+                               rule.AddMatch();
+               } catch (const ConfigError& ex) {
+                       const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
+                       ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
                }
-
-               if (apply_count == 0)
-                       Log(LogWarning, "Notification")
-                           << "Apply rule '" << rule.GetName() << "' for host does not match anywhere!";
-
-       } else if (rule.GetTargetType() == "Service") {
-               apply_count = 0;
-
-               BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjectsByType<Service>()) {
-                       CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'");
-
-                       try {
-                               if (EvaluateApplyRuleOne(service, rule))
-                                       apply_count++;
-                       } catch (const ConfigError& ex) {
-                               const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
-                               ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
-                       }
-               }
-
-               if (apply_count == 0)
-                       Log(LogWarning, "Notification")
-                           << "Apply rule '" << rule.GetName() << "' for service does not match anywhere!";
-
-       } else {
-               Log(LogWarning, "Notification")
-                   << "Wrong target type for apply rule '" << rule.GetName() << "'!";
        }
 }
-void Notification::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
-{
-       ParallelWorkQueue upq;
 
-       BOOST_FOREACH(const ApplyRule& rule, rules) {
-               upq.Enqueue(boost::bind(&Notification::EvaluateApplyRule, boost::cref(rule)));
+void Notification::EvaluateApplyRules(const Service::Ptr& service)
+{
+       CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'");
+
+       BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Notification"))
+       {
+               if (rule.GetTargetType() != "Service")
+                       continue;
+
+               try {
+                       if (EvaluateApplyRule(service, rule))
+                               rule.AddMatch();
+               } catch (const ConfigError& ex) {
+                       const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
+                       ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
+               }
        }
-
-       upq.Join();
 }
index 6e27e8fd4cd8561e661f1f73dcda1467148cfcc5..80f2b05dd00f4822e048946a76fde094818ee3a2 100644 (file)
@@ -68,6 +68,8 @@ enum NotificationType
 class NotificationCommand;
 class Checkable;
 class ApplyRule;
+class Host;
+class Service;
 
 /**
  * An Icinga notification specification.
@@ -108,6 +110,9 @@ public:
 
        static void ValidateFilters(const String& location, const Notification::Ptr& object);
 
+       static void EvaluateApplyRules(const intrusive_ptr<Host>& host);
+       static void EvaluateApplyRules(const intrusive_ptr<Service>& service);
+
 protected:
        virtual void OnConfigLoaded(void);
        virtual void Start(void);
@@ -116,10 +121,8 @@ protected:
 private:
        void ExecuteNotificationHelper(NotificationType type, const User::Ptr& user, const CheckResult::Ptr& cr, bool force, const String& author = "", const String& text = "");
 
-       static void EvaluateApplyRuleOneInstance(const intrusive_ptr<Checkable>& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
-       static bool EvaluateApplyRuleOne(const intrusive_ptr<Checkable>& checkable, const ApplyRule& rule);
-       static void EvaluateApplyRule(const ApplyRule& rule);
-       static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
+       static void EvaluateApplyRuleInstance(const intrusive_ptr<Checkable>& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
+       static bool EvaluateApplyRule(const intrusive_ptr<Checkable>& checkable, const ApplyRule& rule);
 };
 
 I2_ICINGA_API int ServiceStateToFilter(ServiceState state);
index 27b3ba5ae7157defe7425e4360076e880e4e23a7..1e82677dd7b8bea668cc8a3ee5899f812feb09b4 100644 (file)
@@ -38,10 +38,10 @@ void ScheduledDowntime::RegisterApplyRuleHandler(void)
        std::vector<String> targets;
        targets.push_back("Host");
        targets.push_back("Service");
-       ApplyRule::RegisterType("ScheduledDowntime", targets, &ScheduledDowntime::EvaluateApplyRules);
+       ApplyRule::RegisterType("ScheduledDowntime", targets);
 }
 
-void ScheduledDowntime::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
+void ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
 {
        DebugInfo di = rule.GetDebugInfo();
 
@@ -75,7 +75,7 @@ void ScheduledDowntime::EvaluateApplyRuleOneInstance(const Checkable::Ptr& check
        dobj->OnConfigLoaded();
 }
 
-bool ScheduledDowntime::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule)
+bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule)
 {
        DebugInfo di = rule.GetDebugInfo();
 
@@ -121,7 +121,7 @@ bool ScheduledDowntime::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, co
                                name += instance;
                        }
 
-                       EvaluateApplyRuleOneInstance(checkable, name, locals, rule);
+                       EvaluateApplyRuleInstance(checkable, name, locals, rule);
                }
        } else if (vinstances.IsObjectType<Dictionary>()) {
                if (rule.GetFVVar().IsEmpty())
@@ -134,68 +134,47 @@ bool ScheduledDowntime::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, co
                        locals->Set(rule.GetFKVar(), kv.first);
                        locals->Set(rule.GetFVVar(), kv.second);
 
-                       EvaluateApplyRuleOneInstance(checkable, rule.GetName() + kv.first, locals, rule);
+                       EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, locals, rule);
                }
        }
 
        return true;
 }
 
-void ScheduledDowntime::EvaluateApplyRule(const ApplyRule& rule)
+void ScheduledDowntime::EvaluateApplyRules(const Host::Ptr& host)
 {
-       int apply_count = 0;
-
-       if (rule.GetTargetType() == "Host") {
-               apply_count = 0;
-
-               BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType<Host>()) {
-                       CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
-
-                       try {
-                               if (EvaluateApplyRuleOne(host, rule))
-                                       apply_count++;
-                       } catch (const ConfigError& ex) {
-                               const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
-                               ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
-                       }
-               }
-
-               if (apply_count == 0)
-                       Log(LogWarning, "ScheduledDowntime")
-                           << "Apply rule '" << rule.GetName() << "' for host does not match anywhere!";
-
-       } else if (rule.GetTargetType() == "Service") {
-               apply_count = 0;
-
-               BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjectsByType<Service>()) {
-                       CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'");
-
-                       try {
-                               if(EvaluateApplyRuleOne(service, rule))
-                                       apply_count++;
-                       } catch (const ConfigError& ex) {
-                               const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
-                               ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
-                       }
+       CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
+
+       BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("ScheduledDowntime"))
+       {
+               if (rule.GetTargetType() != "Host")
+                       continue;
+
+               try {
+                       if (EvaluateApplyRule(host, rule))
+                               rule.AddMatch();
+               } catch (const ConfigError& ex) {
+                       const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
+                       ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
                }
-
-               if (apply_count == 0)
-                       Log(LogWarning, "ScheduledDowntime")
-                           << "Apply rule '" << rule.GetName() << "' for service does not match anywhere!";
-
-       } else {
-               Log(LogWarning, "ScheduledDowntime")
-                   << "Wrong target type for apply rule '" << rule.GetName() << "'!";
        }
 }
 
-void ScheduledDowntime::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
+void ScheduledDowntime::EvaluateApplyRules(const Service::Ptr& service)
 {
-       ParallelWorkQueue upq;
-
-       BOOST_FOREACH(const ApplyRule& rule, rules) {
-               upq.Enqueue(boost::bind(&ScheduledDowntime::EvaluateApplyRule, boost::cref(rule)));
+       CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'");
+
+       BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("ScheduledDowntime"))
+       {
+               if (rule.GetTargetType() != "Service")
+                       continue;
+
+               try {
+                       if (EvaluateApplyRule(service, rule))
+                               rule.AddMatch();
+               } catch (const ConfigError& ex) {
+                       const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
+                       ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
+               }
        }
-
-       upq.Join();
 }
index 7683f445b8fa86438106871a628b84183f59cc9f..d0d15ea1357977d1eccdbca66c7458ade8e4ce0a 100644 (file)
@@ -29,6 +29,8 @@ namespace icinga
 {
 
 class ApplyRule;
+class Host;
+class Service;
 
 /**
  * An Icinga scheduled downtime specification.
@@ -47,6 +49,9 @@ public:
 
        static void RegisterApplyRuleHandler(void);
 
+       static void EvaluateApplyRules(const intrusive_ptr<Host>& host);
+       static void EvaluateApplyRules(const intrusive_ptr<Service>& service);
+
 protected:
        virtual void Start(void);
 
@@ -56,10 +61,8 @@ private:
        std::pair<double, double> FindNextSegment(void);
        void CreateNextDowntime(void);
 
-       static void EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
-       static bool EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule);
-       static void EvaluateApplyRule(const ApplyRule& rule);
-       static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
+       static void EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
+       static bool EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule);
 };
 
 }
index 7b24b58a85bbba2a076ce5b59541773968a4f650..35ca575f70580786cc624b1e68504de7134ab8ba 100644 (file)
@@ -37,10 +37,10 @@ void Service::RegisterApplyRuleHandler(void)
 {
        std::vector<String> targets;
        targets.push_back("Host");
-       ApplyRule::RegisterType("Service", targets, &Service::EvaluateApplyRules);
+       ApplyRule::RegisterType("Service", targets);
 }
 
-void Service::EvaluateApplyRuleOneInstance(const Host::Ptr& host, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
+void Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
 {
        DebugInfo di = rule.GetDebugInfo();
 
@@ -68,7 +68,7 @@ void Service::EvaluateApplyRuleOneInstance(const Host::Ptr& host, const String&
        dobj->OnConfigLoaded();
 }
 
-bool Service::EvaluateApplyRuleOne(const Host::Ptr& host, const ApplyRule& rule)
+bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule)
 {
        DebugInfo di = rule.GetDebugInfo();
 
@@ -108,7 +108,7 @@ bool Service::EvaluateApplyRuleOne(const Host::Ptr& host, const ApplyRule& rule)
                                name += instance;
                        }
 
-                       EvaluateApplyRuleOneInstance(host, name, locals, rule);
+                       EvaluateApplyRuleInstance(host, name, locals, rule);
                }
        } else if (vinstances.IsObjectType<Dictionary>()) {
                if (rule.GetFVVar().IsEmpty())
@@ -121,41 +121,24 @@ bool Service::EvaluateApplyRuleOne(const Host::Ptr& host, const ApplyRule& rule)
                        locals->Set(rule.GetFKVar(), kv.first);
                        locals->Set(rule.GetFVVar(), kv.second);
 
-                       EvaluateApplyRuleOneInstance(host, rule.GetName() + kv.first, locals, rule);
+                       EvaluateApplyRuleInstance(host, rule.GetName() + kv.first, locals, rule);
                }
        }
 
        return true;
 }
 
-void Service::EvaluateApplyRule(const ApplyRule& rule)
+void Service::EvaluateApplyRules(const Host::Ptr& host)
 {
-       int apply_count = 0;
-
-       BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType<Host>()) {
+       BOOST_FOREACH(ApplyRule& rule, ApplyRule::GetRules("Service")) {
                CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
 
                try {
-                       if (EvaluateApplyRuleOne(host, rule))
-                               apply_count++;
+                       if (EvaluateApplyRule(host, rule))
+                               rule.AddMatch();
                } catch (const ConfigError& ex) {
                        const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
                        ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
                }
        }
-
-       if (apply_count == 0)
-               Log(LogWarning, "Service")
-                   << "Apply rule '" << rule.GetName() << "' for host does not match anywhere!";
-}
-
-void Service::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
-{
-       ParallelWorkQueue upq;
-
-       BOOST_FOREACH(const ApplyRule& rule, rules) {
-               upq.Enqueue(boost::bind(&Service::EvaluateApplyRule, boost::cref(rule)));
-       }
-
-       upq.Join();
 }
index 9a27c1e1fc2c5e2aaaf3f3eaaaeae7d0ccf0cd7f..34fb67c521a5525bdc0e7bca90d2ac2d8621f6c2 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "icinga/service.hpp"
 #include "icinga/servicegroup.hpp"
+#include "icinga/scheduleddowntime.hpp"
 #include "icinga/pluginutility.hpp"
 #include "base/objectlock.hpp"
 #include "base/convert.hpp"
@@ -65,6 +66,11 @@ void Service::OnConfigLoaded(void)
        SetSchedulingOffset(Utility::Random());
 
        Checkable::OnConfigLoaded();
+
+       ServiceGroup::EvaluateObjectRules(this);
+       ScheduledDowntime::EvaluateApplyRules(this);
+       Notification::EvaluateApplyRules(this);
+       Dependency::EvaluateApplyRules(this);
 }
 
 Service::Ptr Service::GetByNamePair(const String& hostName, const String& serviceName)
index 36fb1ea6eb76bb0996a7846cae6deef93c3774e9..81f3b3ed865fd12b57546f573fe61310c677ef10 100644 (file)
@@ -53,16 +53,16 @@ public:
 
        static void RegisterApplyRuleHandler(void);
 
+       static void EvaluateApplyRules(const Host::Ptr& host);
+
 protected:
        virtual void OnConfigLoaded(void);
 
 private:
        Host::Ptr m_Host;
 
-       static void EvaluateApplyRuleOneInstance(const Host::Ptr& host, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
-       static bool EvaluateApplyRuleOne(const Host::Ptr& host, const ApplyRule& rule);
-       static void EvaluateApplyRule(const ApplyRule& rule);
-       static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
+       static void EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
+       static bool EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule);
 };
 
 I2_ICINGA_API boost::tuple<Host::Ptr, Service::Ptr> GetHostService(const Checkable::Ptr& checkable);
index af59b0d196c77d6179c6d820e9ecfdef7d3d6ab0..1feb23b0b0f8562387b7e09fb68f14fd32b3efc4 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "icinga/servicegroup.hpp"
 #include "config/objectrule.hpp"
+#include "config/configitem.hpp"
 #include "base/dynamictype.hpp"
 #include "base/objectlock.hpp"
 #include "base/logger.hpp"
@@ -34,63 +35,53 @@ INITIALIZE_ONCE(&ServiceGroup::RegisterObjectRuleHandler);
 
 void ServiceGroup::RegisterObjectRuleHandler(void)
 {
-       ObjectRule::RegisterType("ServiceGroup", &ServiceGroup::EvaluateObjectRules);
+       ObjectRule::RegisterType("ServiceGroup");
 }
 
-bool ServiceGroup::EvaluateObjectRuleOne(const Service::Ptr& service, const ObjectRule& rule)
+bool ServiceGroup::EvaluateObjectRule(const Service::Ptr& service, const ConfigItem::Ptr& group)
 {
-       DebugInfo di = rule.GetDebugInfo();
+       String group_name = group->GetName();
 
-       std::ostringstream msgbuf;
-       msgbuf << "Evaluating 'object' rule (" << di << ")";
-       CONTEXT(msgbuf.str());
+       CONTEXT("Evaluating rule for group '" + group_name + "'");
 
        Host::Ptr host = service->GetHost();
 
        Dictionary::Ptr locals = new Dictionary();
-       locals->Set("__parent", rule.GetScope());
+       locals->Set("__parent", group->GetScope());
        locals->Set("host", host);
        locals->Set("service", service);
 
-       if (!rule.EvaluateFilter(locals))
+       if (!group->GetFilter()->Evaluate(locals))
                return false;
 
        Log(LogDebug, "ServiceGroup")
-           << "Assigning membership for group '" << rule.GetName() << "' to service '" << service->GetName() << "' for rule " << di;
+           << "Assigning membership for group '" << group_name << "' to service '" << service->GetName() << "'";
 
-       String group_name = rule.GetName();
-       ServiceGroup::Ptr group = ServiceGroup::GetByName(group_name);
+       ServiceGroup::Ptr groupObject = ServiceGroup::GetByName(group_name);
 
-       if (!group) {
+       if (!groupObject) {
                Log(LogCritical, "ServiceGroup")
                    << "Invalid membership assignment. Group '" << group_name << "' does not exist.";
                return false;
        }
 
        /* assign service group membership */
-       group->ResolveGroupMembership(service, true);
+       groupObject->ResolveGroupMembership(service, true);
 
        return true;
 }
 
-void ServiceGroup::EvaluateObjectRule(const ObjectRule& rule)
+void ServiceGroup::EvaluateObjectRules(const Service::Ptr& service)
 {
-       BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjectsByType<Service>()) {
-               CONTEXT("Evaluating group membership in '" + rule.GetName() + "' for service '" + service->GetName() + "'");
+       CONTEXT("Evaluating group membership for service '" + service->GetName() + "'");
 
-               EvaluateObjectRuleOne(service, rule);
-       }
-}
+       BOOST_FOREACH(const ConfigItem::Ptr& group, ConfigItem::GetItems("ServiceGroup"))
+       {
+               if (!group->GetFilter())
+                       continue;
 
-void ServiceGroup::EvaluateObjectRules(const std::vector<ObjectRule>& rules)
-{
-       ParallelWorkQueue upq;
-
-       BOOST_FOREACH(const ObjectRule& rule, rules) {
-               upq.Enqueue(boost::bind(ServiceGroup::EvaluateObjectRule, boost::cref(rule)));
+               EvaluateObjectRule(service, group);
        }
-
-       upq.Join();
 }
 
 std::set<Service::Ptr> ServiceGroup::GetMembers(void) const
index 016dc38a36f7d9fbcc87d6b3fde9d072ae615d7e..e6a82bcba4ffd18bec5d180d2b0fd9ef847dd2d4 100644 (file)
@@ -27,7 +27,7 @@
 namespace icinga
 {
 
-class ObjectRule;
+class ConfigItem;
 
 /**
  * An Icinga service group.
@@ -48,13 +48,13 @@ public:
 
        static void RegisterObjectRuleHandler(void);
 
+       static void EvaluateObjectRules(const Service::Ptr& service);
+
 private:
        mutable boost::mutex m_ServiceGroupMutex;
        std::set<Service::Ptr> m_Members;
 
-       static bool EvaluateObjectRuleOne(const Service::Ptr& service, const ObjectRule& rule);
-       static void EvaluateObjectRule(const ObjectRule& rule);
-       static void EvaluateObjectRules(const std::vector<ObjectRule>& rules);
+       static bool EvaluateObjectRule(const Service::Ptr& service, const intrusive_ptr<ConfigItem>& group);
 };
 
 }
index 4691b7437bce289b3f942a19604696c4771a614e..40a7cddd14f2e6378f3762643939b134927d90fb 100644 (file)
@@ -18,6 +18,7 @@
  ******************************************************************************/
 
 #include "icinga/user.hpp"
+#include "icinga/usergroup.hpp"
 #include "icinga/notification.hpp"
 #include "icinga/usergroup.hpp"
 #include "config/configcompilercontext.hpp"
@@ -51,6 +52,8 @@ void User::OnConfigLoaded(void)
                                ug->ResolveGroupMembership(this, true);
                }
        }
+
+       UserGroup::EvaluateObjectRules(this);
 }
 
 void User::Stop(void)
index aaaf3df31933866b3cf3cf1bbe204eb411292eff..32e57e0b6170cace6630ceceef9313166f76eadc 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "icinga/usergroup.hpp"
 #include "config/objectrule.hpp"
+#include "config/configitem.hpp"
 #include "base/dynamictype.hpp"
 #include "base/objectlock.hpp"
 #include "base/logger.hpp"
@@ -34,60 +35,50 @@ INITIALIZE_ONCE(&UserGroup::RegisterObjectRuleHandler);
 
 void UserGroup::RegisterObjectRuleHandler(void)
 {
-       ObjectRule::RegisterType("UserGroup", &UserGroup::EvaluateObjectRules);
+       ObjectRule::RegisterType("UserGroup");
 }
 
-bool UserGroup::EvaluateObjectRuleOne(const User::Ptr& user, const ObjectRule& rule)
+bool UserGroup::EvaluateObjectRule(const User::Ptr& user, const ConfigItem::Ptr& group)
 {
-       DebugInfo di = rule.GetDebugInfo();
+       String group_name = group->GetName();
 
-       std::ostringstream msgbuf;
-       msgbuf << "Evaluating 'object' rule (" << di << ")";
-       CONTEXT(msgbuf.str());
+       CONTEXT("Evaluating rule for group '" + group_name + "'");
 
        Dictionary::Ptr locals = new Dictionary();
-       locals->Set("__parent", rule.GetScope());
+       locals->Set("__parent", group->GetScope());
        locals->Set("user", user);
 
-       if (!rule.EvaluateFilter(locals))
+       if (!group->GetFilter()->Evaluate(locals))
                return false;
 
        Log(LogDebug, "UserGroup")
-           << "Assigning membership for group '" << rule.GetName() << "' to user '" << user->GetName() << "' for rule " << di;
+           << "Assigning membership for group '" << group_name << "' to user '" << user->GetName() << "'";
 
-       String group_name = rule.GetName();
-       UserGroup::Ptr group = UserGroup::GetByName(group_name);
+       UserGroup::Ptr groupObject = UserGroup::GetByName(group_name);
 
-       if (!group) {
+       if (!groupObject) {
                Log(LogCritical, "UserGroup")
                    << "Invalid membership assignment. Group '" << group_name << "' does not exist.";
                return false;
        }
 
        /* assign user group membership */
-       group->ResolveGroupMembership(user, true);
+       groupObject->ResolveGroupMembership(user, true);
 
        return true;
 }
 
-void UserGroup::EvaluateObjectRule(const ObjectRule& rule)
+void UserGroup::EvaluateObjectRules(const User::Ptr& user)
 {
-       BOOST_FOREACH(const User::Ptr& user, DynamicType::GetObjectsByType<User>()) {
-               CONTEXT("Evaluating group membership in '" + rule.GetName() + "' for user '" + user->GetName() + "'");
+       CONTEXT("Evaluating group membership for user '" + user->GetName() + "'");
 
-               EvaluateObjectRuleOne(user, rule);
-       }
-}
+       BOOST_FOREACH(const ConfigItem::Ptr& group, ConfigItem::GetItems("UserGroup"))
+       {
+               if (!group->GetFilter())
+                       continue;
 
-void UserGroup::EvaluateObjectRules(const std::vector<ObjectRule>& rules)
-{
-       ParallelWorkQueue upq;
-
-       BOOST_FOREACH(const ObjectRule& rule, rules) {
-               upq.Enqueue(boost::bind(UserGroup::EvaluateObjectRule, boost::cref(rule)));
+               EvaluateObjectRule(user, group);
        }
-
-       upq.Join();
 }
 
 std::set<User::Ptr> UserGroup::GetMembers(void) const
index 981e385b2119b9e9b3e8348f79357df0c536aa4c..7f5c999c2550e6ccae86f885169ac7596ea04a1b 100644 (file)
@@ -27,7 +27,7 @@
 namespace icinga
 {
 
-class ObjectRule;
+class ConfigItem;
 
 /**
  * An Icinga user group.
@@ -48,13 +48,13 @@ public:
 
        static void RegisterObjectRuleHandler(void);
 
+       static void EvaluateObjectRules(const User::Ptr& user);
+
 private:
        mutable boost::mutex m_UserGroupMutex;
        std::set<User::Ptr> m_Members;
 
-       static bool EvaluateObjectRuleOne(const User::Ptr& user, const ObjectRule& rule);
-       static void EvaluateObjectRule(const ObjectRule& rule);
-       static void EvaluateObjectRules(const std::vector<ObjectRule>& rules);
+       static bool EvaluateObjectRule(const User::Ptr& user, const intrusive_ptr<ConfigItem>& group);
 };
 
 }