Merge pull request #6568 from Icinga/feature/commit-order

Ensure that config object types are committed in dependent load order
This commit is contained in:
Michael Friedrich 2018-09-04 13:39:40 +02:00 committed by GitHub
commit 18bf1ef519
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 77 additions and 13 deletions

View File

@ -443,27 +443,22 @@ bool ConfigItem::CommitNewItems(const ActivationContext::Ptr& context, WorkQueue
// noticably in environments with lots of objects and available threads.
std::shuffle(std::begin(items), std::end(items), std::default_random_engine {});
#ifdef I2_DEBUG
Log(LogDebug, "configitem")
<< "Committing " << items.size() << " new items.";
#endif /* I2_DEBUG */
for (const auto& ip : items)
newItems.push_back(ip.first);
upq.ParallelFor(items, [](const ItemPair& ip) {
ip.first->Commit(ip.second);
});
upq.Join();
if (upq.HasExceptions())
return false;
std::set<Type::Ptr> types;
std::set<Type::Ptr> completed_types;
for (const Type::Ptr& type : Type::GetAllTypes()) {
if (ConfigObject::TypeInstance->IsAssignableFrom(type))
types.insert(type);
}
std::set<Type::Ptr> completed_types;
while (types.size() != completed_types.size()) {
for (const Type::Ptr& type : types) {
if (completed_types.find(type) != completed_types.end())
@ -483,7 +478,60 @@ bool ConfigItem::CommitNewItems(const ActivationContext::Ptr& context, WorkQueue
if (unresolved_dep)
continue;
upq.ParallelFor(items, [&type](const ItemPair& ip) {
int committed_items = 0;
upq.ParallelFor(items, [&type, &committed_items](const ItemPair& ip) {
const ConfigItem::Ptr& item = ip.first;
if (item->m_Type != type)
return;
ip.first->Commit(ip.second);
committed_items++;
});
upq.Join();
completed_types.insert(type);
#ifdef I2_DEBUG
if (committed_items > 0)
Log(LogDebug, "configitem")
<< "Committed " << committed_items << " items of type '" << type->GetName() << "'.";
#endif /* I2_DEBUG */
if (upq.HasExceptions())
return false;
}
}
#ifdef I2_DEBUG
Log(LogDebug, "configitem")
<< "Committed " << items.size() << " items.";
#endif /* I2_DEBUG */
completed_types.clear();
while (types.size() != completed_types.size()) {
for (const Type::Ptr& type : types) {
if (completed_types.find(type) != completed_types.end())
continue;
bool unresolved_dep = false;
/* skip this type (for now) if there are unresolved load dependencies */
for (const String& loadDep : type->GetLoadDependencies()) {
Type::Ptr pLoadDep = Type::GetByName(loadDep);
if (types.find(pLoadDep) != types.end() && completed_types.find(pLoadDep) == completed_types.end()) {
unresolved_dep = true;
break;
}
}
if (unresolved_dep)
continue;
int notified_items = 0;
upq.ParallelFor(items, [&type, &notified_items](const ItemPair& ip) {
const ConfigItem::Ptr& item = ip.first;
if (!item->m_Object || item->m_Type != type)
@ -491,6 +539,7 @@ bool ConfigItem::CommitNewItems(const ActivationContext::Ptr& context, WorkQueue
try {
item->m_Object->OnAllConfigLoaded();
notified_items++;
} catch (const std::exception& ex) {
if (!item->m_IgnoreOnError)
throw;
@ -511,11 +560,18 @@ bool ConfigItem::CommitNewItems(const ActivationContext::Ptr& context, WorkQueue
upq.Join();
#ifdef I2_DEBUG
if (notified_items > 0)
Log(LogDebug, "configitem")
<< "Sent OnAllConfigLoaded to " << notified_items << " items of type '" << type->GetName() << "'.";
#endif /* I2_DEBUG */
if (upq.HasExceptions())
return false;
notified_items = 0;
for (const String& loadDep : type->GetLoadDependencies()) {
upq.ParallelFor(items, [loadDep, &type](const ItemPair& ip) {
upq.ParallelFor(items, [loadDep, &type, &notified_items](const ItemPair& ip) {
const ConfigItem::Ptr& item = ip.first;
if (!item->m_Object || item->m_Type->GetName() != loadDep)
@ -523,14 +579,22 @@ bool ConfigItem::CommitNewItems(const ActivationContext::Ptr& context, WorkQueue
ActivationScope ascope(item->m_ActivationContext);
item->m_Object->CreateChildObjects(type);
notified_items++;
});
}
upq.Join();
#ifdef I2_DEBUG
if (notified_items > 0)
Log(LogDebug, "configitem")
<< "Sent CreateChildObjects to " << notified_items << " items of type '" << type->GetName() << "'.";
#endif /* I2_DEBUG */
if (upq.HasExceptions())
return false;
// Make sure to activate any additionally generated items
if (!CommitNewItems(context, upq, newItems))
return false;
}