From: Gunnar Beutner Date: Tue, 19 Mar 2013 06:09:06 +0000 (+0100) Subject: Fix: The order in which config items are defined should not matter X-Git-Tag: v0.0.2~213 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6df051fad30fb32b50775f1a3f5ce613f5fc0aa5;p=icinga2 Fix: The order in which config items are defined should not matter Fixes #3733 --- diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index 6610925f0..e4fe39e39 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -71,9 +71,11 @@ static bool LoadConfigFiles(bool validateOnly) } } + context.LinkItems(); + /* Don't validate if we have already encountered at least one error. */ if (!hasError) - context.Validate(); + context.ValidateItems(); hasError = false; diff --git a/lib/config/configcompilercontext.cpp b/lib/config/configcompilercontext.cpp index eda8674f4..0f38cb33c 100644 --- a/lib/config/configcompilercontext.cpp +++ b/lib/config/configcompilercontext.cpp @@ -109,7 +109,18 @@ String ConfigCompilerContext::GetUnit(void) const return m_Unit; } -void ConfigCompilerContext::Validate(void) +void ConfigCompilerContext::LinkItems(void) +{ + SetContext(this); + + BOOST_FOREACH(const ConfigItem::Ptr& item, m_Items) { + item->Link(); + } + + SetContext(NULL); +} + +void ConfigCompilerContext::ValidateItems(void) { SetContext(this); @@ -137,6 +148,10 @@ void ConfigCompilerContext::ActivateItems(void) ASSERT(m_Context == NULL); Log(LogInformation, "config", "Activating config items in compilation unit '" + m_Unit + "'"); + BOOST_FOREACH(const ConfigItem::Ptr& item, m_Items) { + item->Register(); + } + BOOST_FOREACH(const ConfigItem::Ptr& item, m_Items) { item->Commit(); } diff --git a/lib/config/configcompilercontext.h b/lib/config/configcompilercontext.h index bfd4b79bc..f34966eeb 100644 --- a/lib/config/configcompilercontext.h +++ b/lib/config/configcompilercontext.h @@ -69,7 +69,8 @@ public: String GetUnit(void) const; - void Validate(void); + void LinkItems(void); + void ValidateItems(void); void ActivateItems(void); static void SetContext(ConfigCompilerContext *context); diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index f8bea440c..a1ae17d5e 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -50,7 +50,7 @@ ConfigItem::ConfigItem(const String& type, const String& name, const String& unit, bool abstract, const ExpressionList::Ptr& exprl, const std::vector& parents, const DebugInfo& debuginfo) : m_Type(type), m_Name(name), m_Unit(unit), m_Abstract(abstract), - m_ExpressionList(exprl), m_Parents(parents), m_DebugInfo(debuginfo) + m_ExpressionList(exprl), m_ParentNames(parents), m_DebugInfo(debuginfo) { } @@ -119,30 +119,20 @@ ExpressionList::Ptr ConfigItem::GetExpressionList(void) const * * @returns The list of parents. */ -std::vector ConfigItem::GetParents(void) const +std::vector ConfigItem::GetParents(void) const { return m_Parents; } -Dictionary::Ptr ConfigItem::Link(void) const -{ - Dictionary::Ptr attrs = boost::make_shared(); - InternalLink(attrs); - return attrs; -} - -/** - * Calculates the object's properties based on parent objects and the object's - * expression list. - * - * @param dictionary The dictionary that should be used to store the - * properties. - */ -void ConfigItem::InternalLink(const Dictionary::Ptr& dictionary) const +void ConfigItem::Link(void) { ObjectLock olock(this); - BOOST_FOREACH(const String& name, m_Parents) { + m_LinkedExpressionList = boost::make_shared(); + + m_Parents.clear(); + + BOOST_FOREACH(const String& name, m_ParentNames) { ConfigItem::Ptr parent; ConfigCompilerContext *context = ConfigCompilerContext::GetContext(); @@ -162,10 +152,22 @@ void ConfigItem::InternalLink(const Dictionary::Ptr& dictionary) const BOOST_THROW_EXCEPTION(std::invalid_argument(message.str())); } - parent->InternalLink(dictionary); + parent->Link(); + + ExpressionList::Ptr pexprl = parent->GetLinkedExpressionList(); + m_LinkedExpressionList->AddExpression(Expression("", OperatorExecute, pexprl, m_DebugInfo)); + + m_Parents.push_back(parent); } - m_ExpressionList->Execute(dictionary); + m_LinkedExpressionList->AddExpression(Expression("", OperatorExecute, m_ExpressionList, m_DebugInfo)); +} + +ExpressionList::Ptr ConfigItem::GetLinkedExpressionList(void) const +{ + ObjectLock olock(this); + + return m_LinkedExpressionList; } /** @@ -233,8 +235,7 @@ DynamicObject::Ptr ConfigItem::Commit(void) dobj = dtype->GetObject(m_Name); /* Register this item with its parents. */ - BOOST_FOREACH(const String& parentName, m_Parents) { - ConfigItem::Ptr parent = GetObject(m_Type, parentName); + BOOST_FOREACH(const ConfigItem::Ptr& parent, m_Parents) { parent->m_ChildObjects.insert(self); } @@ -244,7 +245,10 @@ DynamicObject::Ptr ConfigItem::Commit(void) double tx = DynamicObject::GetCurrentTx(); - Dictionary::Ptr properties = Link(); + Link(); + + Dictionary::Ptr properties = boost::make_shared(); + GetLinkedExpressionList()->Execute(properties); { ObjectLock olock(properties); @@ -310,6 +314,20 @@ DynamicObject::Ptr ConfigItem::Commit(void) return dobj; } +/** + * Registers the configuration item. + */ +void ConfigItem::Register(void) +{ + ASSERT(!OwnsLock()); + + { + ObjectLock olock(this); + + m_Items[std::make_pair(m_Type, m_Name)] = GetSelf(); + } +} + /** * Unregisters the configuration item. */ @@ -341,11 +359,8 @@ void ConfigItem::UnregisterFromParents(void) { ASSERT(OwnsLock()); - BOOST_FOREACH(const String& parentName, m_Parents) { - ConfigItem::Ptr parent = GetObject(GetType(), parentName); - - if (parent) - parent->m_ChildObjects.erase(GetSelf()); + BOOST_FOREACH(const ConfigItem::Ptr& parent, m_Parents) { + parent->m_ChildObjects.erase(GetSelf()); } } @@ -414,7 +429,7 @@ void ConfigItem::Dump(std::ostream& fp) const fp << " inherits"; bool first = true; - BOOST_FOREACH(const String& name, m_Parents) { + BOOST_FOREACH(const String& name, m_ParentNames) { if (!first) fp << ","; else diff --git a/lib/config/configitem.h b/lib/config/configitem.h index a7b46852a..f91aef108 100644 --- a/lib/config/configitem.h +++ b/lib/config/configitem.h @@ -47,11 +47,15 @@ public: String GetUnit(void) const; bool IsAbstract(void) const; - std::vector GetParents(void) const; + std::vector GetParents(void) const; - ExpressionList::Ptr GetExpressionList(void) const; + void Link(void); + ExpressionList::Ptr GetLinkedExpressionList(void) const; + + void GetProperties(void); DynamicObject::Ptr Commit(void); + void Register(void); void Unregister(void); void Dump(std::ostream& fp) const; @@ -60,8 +64,6 @@ public: DebugInfo GetDebugInfo(void) const; - Dictionary::Ptr Link(void) const; - static ConfigItem::Ptr GetObject(const String& type, const String& name); @@ -71,11 +73,11 @@ public: static boost::signals2::signal OnRemoved; private: - void InternalLink(const Dictionary::Ptr& dictionary) const; + ExpressionList::Ptr GetExpressionList(void) const; - void UnregisterFromParents(void); + void UnregisterFromParents(void); - void OnParentCommitted(void); + void OnParentCommitted(void); String m_Type; /**< The object type. */ String m_Name; /**< The name. */ @@ -83,14 +85,16 @@ private: bool m_Abstract; /**< Whether this is a template. */ ExpressionList::Ptr m_ExpressionList; - std::vector m_Parents; /**< The names of parent configuration + std::vector m_ParentNames; /**< The names of parent configuration items. */ + std::vector m_Parents; DebugInfo m_DebugInfo; /**< Debug information. */ + ExpressionList::Ptr m_LinkedExpressionList; + DynamicObject::WeakPtr m_DynamicObject; /**< The instantiated version - * of this configuration - * item */ - std::set m_ChildObjects; /**< Instantiated items + * of this configuration item */ + std::set m_ChildObjects; /**< Instantiated items * that inherit from this item */ static boost::mutex m_Mutex; diff --git a/lib/config/configitembuilder.cpp b/lib/config/configitembuilder.cpp index 0023c4d98..111f42b6a 100644 --- a/lib/config/configitembuilder.cpp +++ b/lib/config/configitembuilder.cpp @@ -110,26 +110,6 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void) BOOST_THROW_EXCEPTION(std::invalid_argument(msgbuf.str())); } - BOOST_FOREACH(const String& parent, m_Parents) { - ConfigItem::Ptr item; - - ConfigCompilerContext *context = ConfigCompilerContext::GetContext(); - - if (context) - item = context->GetItem(m_Type, parent); - - /* ignore already active objects while we're in the compiler - * context and linking to existing items is disabled. */ - if (!item && (!context || (context->GetFlags() & CompilerLinkExisting))) - item = ConfigItem::GetObject(m_Type, parent); - - if (!item) { - std::ostringstream msgbuf; - msgbuf << "The parent config item '" + parent + "' does not exist: " << m_DebugInfo; - BOOST_THROW_EXCEPTION(std::invalid_argument(msgbuf.str())); - } - } - ExpressionList::Ptr exprl = boost::make_shared(); Expression execExpr("", OperatorExecute, m_ExpressionList, m_DebugInfo); diff --git a/lib/config/configtype.cpp b/lib/config/configtype.cpp index 5f2c4bc3d..bc23aba07 100644 --- a/lib/config/configtype.cpp +++ b/lib/config/configtype.cpp @@ -59,12 +59,13 @@ DebugInfo ConfigType::GetDebugInfo(void) const void ConfigType::ValidateItem(const ConfigItem::Ptr& item) const { - Dictionary::Ptr attrs = item->Link(); - /* Don't validate abstract items. */ if (item->IsAbstract()) return; + Dictionary::Ptr attrs = boost::make_shared(); + item->GetLinkedExpressionList()->Execute(attrs); + std::vector locations; locations.push_back("Object '" + item->GetName() + "' (Type: '" + item->GetType() + "')"); diff --git a/lib/config/expression.cpp b/lib/config/expression.cpp index 2a86607f3..6276e242d 100644 --- a/lib/config/expression.cpp +++ b/lib/config/expression.cpp @@ -213,3 +213,18 @@ void Expression::Dump(std::ostream& fp, int indent) const fp << ", " << "\n"; } + +void Expression::Extract(const std::vector& path, const ExpressionList::Ptr& result) const +{ + ASSERT(!path.empty()); + + if (path[0] == m_Key) { + if (path.size() > 1) + BOOST_THROW_EXCEPTION(std::invalid_argument("Specified path does not exist.")); + else + result->AddExpression(*this); + } else if (m_Operator == OperatorExecute) { + ExpressionList::Ptr exprl = m_Value; + exprl->Extract(path, result); + } +} diff --git a/lib/config/expression.h b/lib/config/expression.h index c785290de..0bf2a1e83 100644 --- a/lib/config/expression.h +++ b/lib/config/expression.h @@ -43,6 +43,8 @@ enum ExpressionOperator OperatorDivide }; +class ExpressionList; + /** * A configuration expression. * @@ -57,6 +59,8 @@ public: void Execute(const Dictionary::Ptr& dictionary) const; void Dump(std::ostream& fp, int indent = 0) const; + void Extract(const std::vector& path, const shared_ptr& result) const; + private: String m_Key; ExpressionOperator m_Operator; diff --git a/lib/config/expressionlist.cpp b/lib/config/expressionlist.cpp index a359f4755..2f3aac234 100644 --- a/lib/config/expressionlist.cpp +++ b/lib/config/expressionlist.cpp @@ -67,3 +67,10 @@ void ExpressionList::Dump(std::ostream& fp, int indent) const expression.Dump(fp, indent); } } + +void ExpressionList::Extract(const std::vector& path, const ExpressionList::Ptr& result) const +{ + BOOST_FOREACH(const Expression& expression, m_Expressions) { + expression.Extract(path, result); + } +} diff --git a/lib/config/expressionlist.h b/lib/config/expressionlist.h index 73173a273..2365f2917 100644 --- a/lib/config/expressionlist.h +++ b/lib/config/expressionlist.h @@ -46,6 +46,8 @@ public: size_t GetLength(void) const; + void Extract(const std::vector& path, const ExpressionList::Ptr& result) const; + private: std::vector m_Expressions; };