From 4da3b1c5b3ef4afdecae714eb941d6ac7f279efe Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 25 Feb 2015 12:43:03 +0100 Subject: [PATCH] Make sure that Notification objects are activated after Host/Service objects fixes #8517 --- lib/base/type.cpp | 5 +++++ lib/base/type.hpp | 2 ++ lib/config/configitem.cpp | 36 +++++++++++++++++++++++++++++++-- lib/icinga/dependency.ti | 3 +++ lib/icinga/notification.ti | 3 +++ lib/icinga/scheduleddowntime.ti | 3 +++ lib/icinga/service.ti | 2 ++ tools/mkclass/class_lexer.ll | 1 + tools/mkclass/class_parser.yy | 17 +++++++++++++++- tools/mkclass/classcompiler.cpp | 11 ++++++++++ tools/mkclass/classcompiler.hpp | 4 +++- 11 files changed, 83 insertions(+), 4 deletions(-) diff --git a/lib/base/type.cpp b/lib/base/type.cpp index d330e52aa..95bc97412 100644 --- a/lib/base/type.cpp +++ b/lib/base/type.cpp @@ -106,6 +106,11 @@ Value Type::GetField(int id) const return Object::GetField(id); } +std::vector Type::GetLoadDependencies(void) const +{ + return std::vector(); +} + String TypeType::GetName(void) const { return "Type"; diff --git a/lib/base/type.hpp b/lib/base/type.hpp index fb25d05ce..e8ae7e87d 100644 --- a/lib/base/type.hpp +++ b/lib/base/type.hpp @@ -84,6 +84,8 @@ public: virtual void SetField(int id, const Value& value); virtual Value GetField(int id) const; + virtual std::vector GetLoadDependencies(void) const; + protected: virtual ObjectFactory GetFactory(void) const = 0; diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 69e7e2d1b..6cb4c8ae8 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -326,11 +326,43 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq) new_items.swap(m_CommittedItems); } + std::set types; + BOOST_FOREACH(const ConfigItem::Ptr& item, new_items) { - upq.Enqueue(boost::bind(&DynamicObject::OnAllConfigLoaded, item->m_Object)); + types.insert(item->m_Type); } - upq.Join(); + std::set completed_types; + + while (types.size() != completed_types.size()) { + std::set current_types; + + 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); + } + } + + upq.Join(); + } } while (!items.empty()); return true; diff --git a/lib/icinga/dependency.ti b/lib/icinga/dependency.ti index 244877c34..d89e046f1 100644 --- a/lib/icinga/dependency.ti +++ b/lib/icinga/dependency.ti @@ -33,6 +33,9 @@ public: class Dependency : CustomVarObject < DependencyNameComposer { + load_after Host; + load_after Service; + [config] String child_host_name; [config] String child_service_name; diff --git a/lib/icinga/notification.ti b/lib/icinga/notification.ti index ba40b8422..dbb19a1d0 100644 --- a/lib/icinga/notification.ti +++ b/lib/icinga/notification.ti @@ -32,6 +32,9 @@ public: class Notification : CustomVarObject < NotificationNameComposer { + load_after Host; + load_after Service; + [config, protected] String command (CommandRaw); [config] double interval { default {{{ return 1800; }}} diff --git a/lib/icinga/scheduleddowntime.ti b/lib/icinga/scheduleddowntime.ti index 27a75b65c..e2a68c579 100644 --- a/lib/icinga/scheduleddowntime.ti +++ b/lib/icinga/scheduleddowntime.ti @@ -32,6 +32,9 @@ public: class ScheduledDowntime : CustomVarObject < ScheduledDowntimeNameComposer { + load_after Host; + load_after Service; + [config, protected] String host_name; [config, protected] String service_name; diff --git a/lib/icinga/service.ti b/lib/icinga/service.ti index 4533403f5..8f524006d 100644 --- a/lib/icinga/service.ti +++ b/lib/icinga/service.ti @@ -35,6 +35,8 @@ public: class Service : Checkable < ServiceNameComposer { + load_after Host; + [config] String display_name { get {{{ if (m_DisplayName.IsEmpty()) diff --git a/tools/mkclass/class_lexer.ll b/tools/mkclass/class_lexer.ll index 2d74276c3..7c59cf62c 100644 --- a/tools/mkclass/class_lexer.ll +++ b/tools/mkclass/class_lexer.ll @@ -133,6 +133,7 @@ static char *lb_steal(lex_buf *lb) class { return T_CLASS; } namespace { return T_NAMESPACE; } code { return T_CODE; } +load_after { return T_LOAD_AFTER; } abstract { yylval->num = TAAbstract; return T_CLASS_ATTRIBUTE; } config { yylval->num = FAConfig; return T_FIELD_ATTRIBUTE; } state { yylval->num = FAState; return T_FIELD_ATTRIBUTE; } diff --git a/tools/mkclass/class_parser.yy b/tools/mkclass/class_parser.yy index 5f60d92b3..59e9147d3 100644 --- a/tools/mkclass/class_parser.yy +++ b/tools/mkclass/class_parser.yy @@ -55,6 +55,7 @@ using namespace icinga; %token T_INCLUDE "include (T_INCLUDE)" %token T_CLASS "class (T_CLASS)" %token T_CODE "code (T_CODE)" +%token T_LOAD_AFTER "load_after (T_LOAD_AFTER)" %token T_NAMESPACE "namespace (T_NAMESPACE)" %token T_STRING "string (T_STRING)" %token T_ANGLE_STRING "angle_string (T_ANGLE_STRING)" @@ -192,7 +193,13 @@ class: class_attribute_list T_CLASS T_IDENTIFIER inherits_specifier type_base_sp $$->Attributes = $1; - $$->Fields = *$7; + for (std::vector::iterator it = $7->begin(); it != $7->end(); it++) { + if (it->Attributes & FALoadDependency) { + $$->LoadDependencies.push_back(it->Name); + } else + $$->Fields.push_back(*it); + } + delete $7; ClassCompiler::OptimizeStructLayout($$->Fields); @@ -281,6 +288,14 @@ class_field: field_attribute_list identifier identifier alternative_name_specifi $$ = field; } + | T_LOAD_AFTER identifier ';' + { + Field *field = new Field(); + field->Attributes = FALoadDependency; + field->Name = $2; + std::free($2); + $$ = field; + } ; alternative_name_specifier: /* empty */ diff --git a/tools/mkclass/classcompiler.cpp b/tools/mkclass/classcompiler.cpp index 7dc7b1580..fa0c8d395 100644 --- a/tools/mkclass/classcompiler.cpp +++ b/tools/mkclass/classcompiler.cpp @@ -349,6 +349,17 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) << "\t\t" << "return TypeHelper<" << klass.Name << ">::GetFactory();" << std::endl << "\t" << "}" << std::endl << std::endl; + /* GetLoadDependencies */ + std::cout << "\t" << "virtual std::vector GetLoadDependencies(void) const" << std::endl + << "\t" << "{" << std::endl + << "\t\t" << "std::vector deps;" << std::endl; + + for (std::vector::const_iterator itd = klass.LoadDependencies.begin(); itd != klass.LoadDependencies.end(); itd++) + std::cout << "\t\t" << "deps.push_back(\"" << *itd << "\");" << std::endl; + + std::cout << "\t\t" << "return deps;" << std::endl + << "\t" << "}" << std::endl; + std::cout << "};" << std::endl << std::endl; /* ObjectImpl */ diff --git a/tools/mkclass/classcompiler.hpp b/tools/mkclass/classcompiler.hpp index 3b9844853..28df74c00 100644 --- a/tools/mkclass/classcompiler.hpp +++ b/tools/mkclass/classcompiler.hpp @@ -63,7 +63,8 @@ enum FieldAttribute FAGetProtected = 8, FASetProtected = 16, FAInternal = 32, - FANoStorage = 64 + FANoStorage = 64, + FALoadDependency = 128 }; struct Field @@ -124,6 +125,7 @@ struct Klass std::string TypeBase; int Attributes; std::vector Fields; + std::vector LoadDependencies; }; class ClassCompiler -- 2.40.0