]> granicus.if.org Git - icinga2/commitdiff
Make load order for objects more reliable
authorGunnar Beutner <gunnar@beutner.name>
Thu, 19 Mar 2015 14:47:46 +0000 (15:47 +0100)
committerGunnar Beutner <gunnar@beutner.name>
Thu, 19 Mar 2015 14:58:38 +0000 (15:58 +0100)
fixes #8770

lib/base/dynamicobject.cpp
lib/base/dynamicobject.hpp
lib/config/configitem.cpp
lib/icinga/dependency-apply.cpp
lib/icinga/host.cpp
lib/icinga/host.hpp
lib/icinga/notification-apply.cpp
lib/icinga/scheduleddowntime-apply.cpp
lib/icinga/service-apply.cpp
lib/icinga/service.cpp
lib/icinga/service.hpp

index 917f123f12021d50ae7ca6a4b5bcaad2109d800f..7176cab980f54c5f3a3df9db1f3815c083c2f5c7 100644 (file)
@@ -187,6 +187,11 @@ void DynamicObject::OnAllConfigLoaded(void)
        /* Nothing to do here. */
 }
 
+void DynamicObject::CreateChildObjects(const Type::Ptr& childType)
+{
+       /* Nothing to do here. */
+}
+
 void DynamicObject::OnStateLoaded(void)
 {
        /* Nothing to do here. */
index 8ec069861b8eeb1a5602b26d9d6069b3f31858b7..c7d3649bf901a9acda4a1f0fcd3af4622a0ff318 100644 (file)
@@ -75,6 +75,7 @@ public:
        virtual void Resume(void);
 
        virtual void OnConfigLoaded(void);
+       virtual void CreateChildObjects(const Type::Ptr& childType);
        virtual void OnAllConfigLoaded(void);
        virtual void OnStateLoaded(void);
 
index 437e34412dac32f547362e89417d5582068314fa..aa49644258b16624724e15e26e15c49d82f17148 100644 (file)
@@ -284,74 +284,100 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq)
        typedef std::pair<ConfigItem::Ptr, bool> ItemPair;
        std::vector<ItemPair> items;
 
-       do {
-               items.clear();
-
-               {
-                       boost::mutex::scoped_lock lock(m_Mutex);
-
-                       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::mutex::scoped_lock lock(m_Mutex);
 
-                       BOOST_FOREACH(const ConfigItem::Ptr& item, m_UnnamedItems) {
-                               if (!item->m_Abstract && !item->m_Object)
-                                       items.push_back(std::make_pair(item, true));
+               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));
                        }
-
-                       m_UnnamedItems.clear();
                }
 
-               BOOST_FOREACH(const ItemPair& ip, items) {
-                       upq.Enqueue(boost::bind(&ConfigItem::Commit, ip.first, ip.second));
+               BOOST_FOREACH(const ConfigItem::Ptr& item, m_UnnamedItems) {
+                       if (!item->m_Abstract && !item->m_Object)
+                               items.push_back(std::make_pair(item, true));
                }
 
-               upq.Join();
+               m_UnnamedItems.clear();
+       }
 
-               if (upq.HasExceptions())
-                       return false;
+       if (items.empty())
+               return true;
 
-               std::vector<ConfigItem::Ptr> new_items;
+       BOOST_FOREACH(const ItemPair& ip, items) {
+               upq.Enqueue(boost::bind(&ConfigItem::Commit, ip.first, ip.second));
+       }
 
-               {
-                       boost::mutex::scoped_lock lock(m_Mutex);
-                       new_items.swap(m_CommittedItems);
-               }
+       upq.Join();
+
+       if (upq.HasExceptions())
+               return false;
+
+       std::vector<ConfigItem::Ptr> new_items;
+
+       {
+               boost::mutex::scoped_lock lock(m_Mutex);
+               new_items.swap(m_CommittedItems);
+       }
 
-               std::set<String> types;
+       std::set<String> types;
 
-               BOOST_FOREACH(const ConfigItem::Ptr& item, new_items) {
-                       types.insert(item->m_Type);
+       std::vector<Type::Ptr> all_types;
+       Dictionary::Ptr globals = ScriptGlobal::GetGlobals();
+
+       {
+               ObjectLock olock(globals);
+               BOOST_FOREACH(const Dictionary::Pair& kv, globals) {
+                       if (kv.second.IsObjectType<Type>())
+                               all_types.push_back(kv.second);
                }
+       }
+
+       Type::Ptr dotype = Type::GetByName("DynamicObject");
+       BOOST_FOREACH(const Type::Ptr& type, all_types) {
+               if (dotype->IsAssignableFrom(type))
+                       types.insert(type->GetName());
+       }
 
-               std::set<String> completed_types;
+       std::set<String> completed_types;
 
-               while (types.size() != completed_types.size()) {
-                       BOOST_FOREACH(const String& type, types) {
-                               if (completed_types.find(type) != completed_types.end())
-                                       continue;
+       while (types.size() != completed_types.size()) {
+               BOOST_FOREACH(const String& type, types) {
+                       if (completed_types.find(type) != completed_types.end())
+                               continue;
 
-                               Type::Ptr ptype = Type::GetByName(type);
-                               bool unresolved_dep = false;
+                       Type::Ptr ptype = Type::GetByName(type);
+                       bool unresolved_dep = false;
 
-                               BOOST_FOREACH(const String& loadDep, ptype->GetLoadDependencies()) {
-                                       if (types.find(loadDep) != types.end() && completed_types.find(loadDep) == completed_types.end()) {
-                                               unresolved_dep = true;
-                                               break;
-                                       }
+                       /* skip this type (for now) if there are unresolved load dependencies */
+                       BOOST_FOREACH(const String& loadDep, ptype->GetLoadDependencies()) {
+                               if (types.find(loadDep) != types.end() && completed_types.find(loadDep) == completed_types.end()) {
+                                       unresolved_dep = true;
+                                       break;
                                }
+                       }
 
-                               if (!unresolved_dep) {
-                                       BOOST_FOREACH(const ConfigItem::Ptr& item, new_items) {
-                                               if (item->m_Type == type)
-                                                       upq.Enqueue(boost::bind(&DynamicObject::OnAllConfigLoaded, item->m_Object));
-                                       }
+                       if (unresolved_dep)
+                               continue;
+
+                       BOOST_FOREACH(const ConfigItem::Ptr& item, new_items) {
+                               if (item->m_Type == type)
+                                       upq.Enqueue(boost::bind(&DynamicObject::OnAllConfigLoaded, item->m_Object));
+                       }
 
-                                       completed_types.insert(type);
+                       completed_types.insert(type);
+
+                       upq.Join();
+
+                       if (upq.HasExceptions())
+                               return false;
+
+                       BOOST_FOREACH(const String& loadDep, ptype->GetLoadDependencies()) {
+                               BOOST_FOREACH(const ConfigItem::Ptr& item, new_items) {
+                                       if (item->m_Type == loadDep)
+                                               upq.Enqueue(boost::bind(&DynamicObject::CreateChildObjects, item->m_Object, ptype));
                                }
                        }
 
@@ -359,8 +385,11 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq)
 
                        if (upq.HasExceptions())
                                return false;
+
+                       if (!CommitNewItems(upq))
+                               return false;
                }
-       } while (!items.empty());
+       }
 
        return true;
 }
index 119a7cd912bd2aeb199cd78eb163394415cb9e7a..be761bd1b09da8e3ad883e7c34832c0142801380 100644 (file)
@@ -74,7 +74,7 @@ bool Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, cons
        builder->AddExpression(new OwnedExpression(rule.GetExpression()));
 
        ConfigItem::Ptr dependencyItem = builder->Compile();
-       dependencyItem->Commit();
+       dependencyItem->Register();
 
        return true;
 }
index 5d56d8ab8046c462add3e2f4cd7b29f6e89cafdb..8f6caec568323a756456fb0ded2cc286c6e77aa0 100644 (file)
@@ -54,11 +54,21 @@ void Host::OnAllConfigLoaded(void)
                                hg->ResolveGroupMembership(this, true);
                }
        }
+}
+
+void Host::CreateChildObjects(const Type::Ptr& childType)
+{
+       if (childType->GetName() == "ScheduledDowntime")
+               ScheduledDowntime::EvaluateApplyRules(this);
+
+       if (childType->GetName() == "Notification")
+               Notification::EvaluateApplyRules(this);
+
+       if (childType->GetName() == "Dependency")
+               Dependency::EvaluateApplyRules(this);
 
-       ScheduledDowntime::EvaluateApplyRules(this);
-       Notification::EvaluateApplyRules(this);
-       Dependency::EvaluateApplyRules(this);
-       Service::EvaluateApplyRules(this);
+       if (childType->GetName() == "Service")
+               Service::EvaluateApplyRules(this);
 }
 
 void Host::Stop(void)
index 7ff78f6fd7ef44bf527329146b652f47f5d31927..18adeddad18fe089a45727c51f6876912d4eb0c4 100644 (file)
@@ -69,6 +69,7 @@ protected:
        virtual void Stop(void);
 
        virtual void OnAllConfigLoaded(void);
+       virtual void CreateChildObjects(const Type::Ptr& childType);
 
 private:
        mutable boost::mutex m_ServicesMutex;
index 8112aa31044758591bf6360dd2c259b3c610851c..d52ec85002d699f996267876b7aa86064e2277f5 100644 (file)
@@ -73,7 +73,7 @@ bool Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, co
        builder->AddExpression(new OwnedExpression(rule.GetExpression()));
 
        ConfigItem::Ptr notificationItem = builder->Compile();
-       notificationItem->Commit();
+       notificationItem->Register();
 
        return true;
 }
index 452f75b0807e75841bb93294e1066735a172aa80..32f86c4490681ff0906cf4d420a69156c430f433 100644 (file)
@@ -72,7 +72,7 @@ bool ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkabl
        builder->AddExpression(new OwnedExpression(rule.GetExpression()));
 
        ConfigItem::Ptr downtimeItem = builder->Compile();
-       downtimeItem->Commit();
+       downtimeItem->Register();
 
        return true;
 }
index 167abd0a0e8ba0f2ad44df685639e106c83ae8e9..065dd5f93215601c8b9e51f70c7a7090da856ae4 100644 (file)
@@ -66,7 +66,7 @@ bool Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& nam
        builder->AddExpression(new OwnedExpression(rule.GetExpression()));
 
        ConfigItem::Ptr serviceItem = builder->Compile();
-       serviceItem->Commit();
+       serviceItem->Register();
 
        return true;
 }
index fde4edae4d7b122c425c8d82300da9e11f00b628..b1cc8e36b8ac9fc97426489894bc5acf21710300 100644 (file)
@@ -66,10 +66,18 @@ void Service::OnAllConfigLoaded(void)
                                sg->ResolveGroupMembership(this, true);
                }
        }
+}
+
+void Service::CreateChildObjects(const Type::Ptr& childType)
+{
+       if (childType->GetName() == "ScheduledDowntime")
+               ScheduledDowntime::EvaluateApplyRules(this);
+
+       if (childType->GetName() == "Notification")
+               Notification::EvaluateApplyRules(this);
 
-       ScheduledDowntime::EvaluateApplyRules(this);
-       Notification::EvaluateApplyRules(this);
-       Dependency::EvaluateApplyRules(this);
+       if (childType->GetName() == "Dependency")
+               Dependency::EvaluateApplyRules(this);
 }
 
 Service::Ptr Service::GetByNamePair(const String& hostName, const String& serviceName)
index 548b6474622ca9935050ce4cc6dbed4914757d1c..b682e8a2c9e2978aaf9883097858cdff69345610 100644 (file)
@@ -57,6 +57,7 @@ public:
 
 protected:
        virtual void OnAllConfigLoaded(void);
+       virtual void CreateChildObjects(const Type::Ptr& childType);
 
 private:
        Host::Ptr m_Host;