From e22386e63fb05b95fbddb40c1f0beea85471187e Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 19 Mar 2015 15:47:46 +0100 Subject: [PATCH] Make load order for objects more reliable fixes #8770 --- lib/base/dynamicobject.cpp | 5 + lib/base/dynamicobject.hpp | 1 + lib/config/configitem.cpp | 147 +++++++++++++++---------- lib/icinga/dependency-apply.cpp | 2 +- lib/icinga/host.cpp | 18 ++- lib/icinga/host.hpp | 1 + lib/icinga/notification-apply.cpp | 2 +- lib/icinga/scheduleddowntime-apply.cpp | 2 +- lib/icinga/service-apply.cpp | 2 +- lib/icinga/service.cpp | 14 ++- lib/icinga/service.hpp | 1 + 11 files changed, 125 insertions(+), 70 deletions(-) diff --git a/lib/base/dynamicobject.cpp b/lib/base/dynamicobject.cpp index 917f123f1..7176cab98 100644 --- a/lib/base/dynamicobject.cpp +++ b/lib/base/dynamicobject.cpp @@ -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. */ diff --git a/lib/base/dynamicobject.hpp b/lib/base/dynamicobject.hpp index 8ec069861..c7d3649bf 100644 --- a/lib/base/dynamicobject.hpp +++ b/lib/base/dynamicobject.hpp @@ -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); diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 437e34412..aa4964425 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -284,74 +284,100 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq) typedef std::pair ItemPair; std::vector items; - do { - items.clear(); + { + boost::mutex::scoped_lock lock(m_Mutex); - { - 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_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) + items.push_back(std::make_pair(item, true)); + } + + m_UnnamedItems.clear(); + } + + if (items.empty()) + return true; + + BOOST_FOREACH(const ItemPair& ip, items) { + upq.Enqueue(boost::bind(&ConfigItem::Commit, ip.first, ip.second)); + } + + upq.Join(); + + if (upq.HasExceptions()) + return false; + + std::vector new_items; + + { + boost::mutex::scoped_lock lock(m_Mutex); + new_items.swap(m_CommittedItems); + } + + std::set types; + + std::vector all_types; + Dictionary::Ptr globals = ScriptGlobal::GetGlobals(); + + { + ObjectLock olock(globals); + BOOST_FOREACH(const Dictionary::Pair& kv, globals) { + if (kv.second.IsObjectType()) + 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 completed_types; + + 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; + + /* 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; } } - BOOST_FOREACH(const ConfigItem::Ptr& item, m_UnnamedItems) { - if (!item->m_Abstract && !item->m_Object) - items.push_back(std::make_pair(item, true)); + 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)); } - m_UnnamedItems.clear(); - } + completed_types.insert(type); - BOOST_FOREACH(const ItemPair& ip, items) { - upq.Enqueue(boost::bind(&ConfigItem::Commit, ip.first, ip.second)); - } + upq.Join(); - upq.Join(); + if (upq.HasExceptions()) + return false; - if (upq.HasExceptions()) - return false; - - std::vector new_items; - - { - boost::mutex::scoped_lock lock(m_Mutex); - new_items.swap(m_CommittedItems); - } - - std::set types; - - BOOST_FOREACH(const ConfigItem::Ptr& item, new_items) { - types.insert(item->m_Type); - } - - std::set completed_types; - - 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; - - 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)); - } - - completed_types.insert(type); + 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; } diff --git a/lib/icinga/dependency-apply.cpp b/lib/icinga/dependency-apply.cpp index 119a7cd91..be761bd1b 100644 --- a/lib/icinga/dependency-apply.cpp +++ b/lib/icinga/dependency-apply.cpp @@ -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; } diff --git a/lib/icinga/host.cpp b/lib/icinga/host.cpp index 5d56d8ab8..8f6caec56 100644 --- a/lib/icinga/host.cpp +++ b/lib/icinga/host.cpp @@ -54,11 +54,21 @@ void Host::OnAllConfigLoaded(void) hg->ResolveGroupMembership(this, true); } } +} - ScheduledDowntime::EvaluateApplyRules(this); - Notification::EvaluateApplyRules(this); - Dependency::EvaluateApplyRules(this); - Service::EvaluateApplyRules(this); +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); + + if (childType->GetName() == "Service") + Service::EvaluateApplyRules(this); } void Host::Stop(void) diff --git a/lib/icinga/host.hpp b/lib/icinga/host.hpp index 7ff78f6fd..18adeddad 100644 --- a/lib/icinga/host.hpp +++ b/lib/icinga/host.hpp @@ -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; diff --git a/lib/icinga/notification-apply.cpp b/lib/icinga/notification-apply.cpp index 8112aa310..d52ec8500 100644 --- a/lib/icinga/notification-apply.cpp +++ b/lib/icinga/notification-apply.cpp @@ -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; } diff --git a/lib/icinga/scheduleddowntime-apply.cpp b/lib/icinga/scheduleddowntime-apply.cpp index 452f75b08..32f86c449 100644 --- a/lib/icinga/scheduleddowntime-apply.cpp +++ b/lib/icinga/scheduleddowntime-apply.cpp @@ -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; } diff --git a/lib/icinga/service-apply.cpp b/lib/icinga/service-apply.cpp index 167abd0a0..065dd5f93 100644 --- a/lib/icinga/service-apply.cpp +++ b/lib/icinga/service-apply.cpp @@ -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; } diff --git a/lib/icinga/service.cpp b/lib/icinga/service.cpp index fde4edae4..b1cc8e36b 100644 --- a/lib/icinga/service.cpp +++ b/lib/icinga/service.cpp @@ -66,10 +66,18 @@ void Service::OnAllConfigLoaded(void) sg->ResolveGroupMembership(this, true); } } +} - ScheduledDowntime::EvaluateApplyRules(this); - Notification::EvaluateApplyRules(this); - Dependency::EvaluateApplyRules(this); +void Service::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); } Service::Ptr Service::GetByNamePair(const String& hostName, const String& serviceName) diff --git a/lib/icinga/service.hpp b/lib/icinga/service.hpp index 548b64746..b682e8a2c 100644 --- a/lib/icinga/service.hpp +++ b/lib/icinga/service.hpp @@ -57,6 +57,7 @@ public: protected: virtual void OnAllConfigLoaded(void); + virtual void CreateChildObjects(const Type::Ptr& childType); private: Host::Ptr m_Host;