Make load order for objects more reliable

fixes #8770
This commit is contained in:
Gunnar Beutner 2015-03-19 15:47:46 +01:00
parent a99773b62d
commit 148a6c5bf3
11 changed files with 125 additions and 70 deletions

View File

@ -187,6 +187,11 @@ void DynamicObject::OnAllConfigLoaded(void)
/* Nothing to do here. */ /* Nothing to do here. */
} }
void DynamicObject::CreateChildObjects(const Type::Ptr& childType)
{
/* Nothing to do here. */
}
void DynamicObject::OnStateLoaded(void) void DynamicObject::OnStateLoaded(void)
{ {
/* Nothing to do here. */ /* Nothing to do here. */

View File

@ -75,6 +75,7 @@ public:
virtual void Resume(void); virtual void Resume(void);
virtual void OnConfigLoaded(void); virtual void OnConfigLoaded(void);
virtual void CreateChildObjects(const Type::Ptr& childType);
virtual void OnAllConfigLoaded(void); virtual void OnAllConfigLoaded(void);
virtual void OnStateLoaded(void); virtual void OnStateLoaded(void);

View File

@ -288,74 +288,100 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq)
typedef std::pair<ConfigItem::Ptr, bool> ItemPair; typedef std::pair<ConfigItem::Ptr, bool> ItemPair;
std::vector<ItemPair> items; std::vector<ItemPair> items;
do { {
items.clear(); boost::mutex::scoped_lock lock(m_Mutex);
{ BOOST_FOREACH(const TypeMap::value_type& kv, m_Items) {
boost::mutex::scoped_lock lock(m_Mutex); 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 ConfigItem::Ptr& item, m_UnnamedItems) {
BOOST_FOREACH(const ItemMap::value_type& kv2, kv.second) if (!item->m_Abstract && !item->m_Object)
{ items.push_back(std::make_pair(item, true));
if (!kv2.second->m_Abstract && !kv2.second->m_Object) }
items.push_back(std::make_pair(kv2.second, false));
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<ConfigItem::Ptr> new_items;
{
boost::mutex::scoped_lock lock(m_Mutex);
new_items.swap(m_CommittedItems);
}
std::set<String> types;
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;
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 (unresolved_dep)
if (!item->m_Abstract && !item->m_Object) continue;
items.push_back(std::make_pair(item, true));
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.Join();
upq.Enqueue(boost::bind(&ConfigItem::Commit, ip.first, ip.second));
}
upq.Join(); if (upq.HasExceptions())
return false;
if (upq.HasExceptions()) BOOST_FOREACH(const String& loadDep, ptype->GetLoadDependencies()) {
return false; BOOST_FOREACH(const ConfigItem::Ptr& item, new_items) {
if (item->m_Type == loadDep)
std::vector<ConfigItem::Ptr> new_items; upq.Enqueue(boost::bind(&DynamicObject::CreateChildObjects, item->m_Object, ptype));
{
boost::mutex::scoped_lock lock(m_Mutex);
new_items.swap(m_CommittedItems);
}
std::set<String> types;
BOOST_FOREACH(const ConfigItem::Ptr& item, new_items) {
types.insert(item->m_Type);
}
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;
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);
} }
} }
@ -363,8 +389,11 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq)
if (upq.HasExceptions()) if (upq.HasExceptions())
return false; return false;
if (!CommitNewItems(upq))
return false;
} }
} while (!items.empty()); }
return true; return true;
} }

View File

@ -74,7 +74,7 @@ bool Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, cons
builder->AddExpression(new OwnedExpression(rule.GetExpression())); builder->AddExpression(new OwnedExpression(rule.GetExpression()));
ConfigItem::Ptr dependencyItem = builder->Compile(); ConfigItem::Ptr dependencyItem = builder->Compile();
dependencyItem->Commit(); dependencyItem->Register();
return true; return true;
} }

View File

@ -54,11 +54,21 @@ void Host::OnAllConfigLoaded(void)
hg->ResolveGroupMembership(this, true); hg->ResolveGroupMembership(this, true);
} }
} }
}
ScheduledDowntime::EvaluateApplyRules(this); void Host::CreateChildObjects(const Type::Ptr& childType)
Notification::EvaluateApplyRules(this); {
Dependency::EvaluateApplyRules(this); if (childType->GetName() == "ScheduledDowntime")
Service::EvaluateApplyRules(this); 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) void Host::Stop(void)

View File

@ -69,6 +69,7 @@ protected:
virtual void Stop(void); virtual void Stop(void);
virtual void OnAllConfigLoaded(void); virtual void OnAllConfigLoaded(void);
virtual void CreateChildObjects(const Type::Ptr& childType);
private: private:
mutable boost::mutex m_ServicesMutex; mutable boost::mutex m_ServicesMutex;

View File

@ -73,7 +73,7 @@ bool Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, co
builder->AddExpression(new OwnedExpression(rule.GetExpression())); builder->AddExpression(new OwnedExpression(rule.GetExpression()));
ConfigItem::Ptr notificationItem = builder->Compile(); ConfigItem::Ptr notificationItem = builder->Compile();
notificationItem->Commit(); notificationItem->Register();
return true; return true;
} }

View File

@ -72,7 +72,7 @@ bool ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkabl
builder->AddExpression(new OwnedExpression(rule.GetExpression())); builder->AddExpression(new OwnedExpression(rule.GetExpression()));
ConfigItem::Ptr downtimeItem = builder->Compile(); ConfigItem::Ptr downtimeItem = builder->Compile();
downtimeItem->Commit(); downtimeItem->Register();
return true; return true;
} }

View File

@ -66,7 +66,7 @@ bool Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& nam
builder->AddExpression(new OwnedExpression(rule.GetExpression())); builder->AddExpression(new OwnedExpression(rule.GetExpression()));
ConfigItem::Ptr serviceItem = builder->Compile(); ConfigItem::Ptr serviceItem = builder->Compile();
serviceItem->Commit(); serviceItem->Register();
return true; return true;
} }

View File

@ -66,10 +66,18 @@ void Service::OnAllConfigLoaded(void)
sg->ResolveGroupMembership(this, true); sg->ResolveGroupMembership(this, true);
} }
} }
}
ScheduledDowntime::EvaluateApplyRules(this); void Service::CreateChildObjects(const Type::Ptr& childType)
Notification::EvaluateApplyRules(this); {
Dependency::EvaluateApplyRules(this); 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) Service::Ptr Service::GetByNamePair(const String& hostName, const String& serviceName)

View File

@ -57,6 +57,7 @@ public:
protected: protected:
virtual void OnAllConfigLoaded(void); virtual void OnAllConfigLoaded(void);
virtual void CreateChildObjects(const Type::Ptr& childType);
private: private:
Host::Ptr m_Host; Host::Ptr m_Host;