]> granicus.if.org Git - icinga2/commitdiff
Fix: The order in which config items are defined should not matter
authorGunnar Beutner <gunnar@beutner.name>
Tue, 19 Mar 2013 06:09:06 +0000 (07:09 +0100)
committerGunnar Beutner <gunnar@beutner.name>
Tue, 19 Mar 2013 06:09:06 +0000 (07:09 +0100)
Fixes #3733

icinga-app/icinga.cpp
lib/config/configcompilercontext.cpp
lib/config/configcompilercontext.h
lib/config/configitem.cpp
lib/config/configitem.h
lib/config/configitembuilder.cpp
lib/config/configtype.cpp
lib/config/expression.cpp
lib/config/expression.h
lib/config/expressionlist.cpp
lib/config/expressionlist.h

index 6610925f05e5dbe015d6d89d9b36d2cab045b5e0..e4fe39e395505514515108b703985d27bc114c08 100644 (file)
@@ -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;
 
index eda8674f4bdeed95fce67877b82ca84d888fc0d8..0f38cb33cab07145fd12d6615e04028ad9a0f3b3 100644 (file)
@@ -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();
        }
index bfd4b79bca03f782e3605726d617bdfd68a4a383..f34966eeb119f3dd003f781e54c69d97cb2f5082 100644 (file)
@@ -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);
index f8bea440ca8d7fb34c0a3d0ff1f674553a3a62e0..a1ae17d5e0e398c2a43166a9e145010ab074bfd1 100644 (file)
@@ -50,7 +50,7 @@ ConfigItem::ConfigItem(const String& type, const String& name,
     const String& unit, bool abstract, const ExpressionList::Ptr& exprl,
     const std::vector<String>& 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<String> ConfigItem::GetParents(void) const
+std::vector<ConfigItem::Ptr> ConfigItem::GetParents(void) const
 {
        return m_Parents;
 }
 
-Dictionary::Ptr ConfigItem::Link(void) const
-{
-       Dictionary::Ptr attrs = boost::make_shared<Dictionary>();
-       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<ExpressionList>();
+
+       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<Dictionary>();
+       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
index a7b46852a40cb944de5ec4c06676d812722a3613..f91aef1084742036da621b54a727cadbaefaf6f6 100644 (file)
@@ -47,11 +47,15 @@ public:
        String GetUnit(void) const;
        bool IsAbstract(void) const;
 
-       std::vector<String> GetParents(void) const;
+       std::vector<ConfigItem::Ptr> 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<void (const ConfigItem::Ptr&)> 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<String> m_Parents; /**< The names of parent configuration
+       std::vector<String> m_ParentNames; /**< The names of parent configuration
                                       items. */
+       std::vector<ConfigItem::Ptr> m_Parents;
        DebugInfo m_DebugInfo; /**< Debug information. */
 
+       ExpressionList::Ptr m_LinkedExpressionList;
+
        DynamicObject::WeakPtr m_DynamicObject; /**< The instantiated version
-                                                 * of this configuration
-                                                * item */
-        std::set<ConfigItem::WeakPtr> m_ChildObjects; /**< Instantiated items
+                                                 * of this configuration item */
+       std::set<ConfigItem::WeakPtr> m_ChildObjects; /**< Instantiated items
                                                      * that inherit from this item */
 
        static boost::mutex m_Mutex;
index 0023c4d9842203f7ce7c708455ab4f576f4b4a51..111f42b6a1f7510f38916c496665552d159cf30f 100644 (file)
@@ -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<ExpressionList>();
 
        Expression execExpr("", OperatorExecute, m_ExpressionList, m_DebugInfo);
index 5f2c4bc3d4cc87bb97426165be75faf1a76cff8b..bc23aba076e647b75628b8ee490a0582c37f4bde 100644 (file)
@@ -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<Dictionary>();
+       item->GetLinkedExpressionList()->Execute(attrs);
+
        std::vector<String> locations;
        locations.push_back("Object '" + item->GetName() + "' (Type: '" + item->GetType() + "')");
 
index 2a86607f3130281ce8f9652c7bd6162d61698f6c..6276e242dd790df1141a280d48c404975332a080 100644 (file)
@@ -213,3 +213,18 @@ void Expression::Dump(std::ostream& fp, int indent) const
 
        fp << ", " << "\n";
 }
+
+void Expression::Extract(const std::vector<String>& 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);
+       }
+}
index c785290def5534f62f7e663a72f1c3fe6d73af55..0bf2a1e832f36dd1b73f634c00da148ed4eb9a7c 100644 (file)
@@ -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<String>& path, const shared_ptr<ExpressionList>& result) const;
+
 private:
        String m_Key;
        ExpressionOperator m_Operator;
index a359f4755cde9c5de76b8b88fd2df07aba390c69..2f3aac23491b53fbaf6f5dfffd5365a27119f967 100644 (file)
@@ -67,3 +67,10 @@ void ExpressionList::Dump(std::ostream& fp, int indent) const
                expression.Dump(fp, indent);
        }
 }
+
+void ExpressionList::Extract(const std::vector<String>& path, const ExpressionList::Ptr& result) const
+{
+       BOOST_FOREACH(const Expression& expression, m_Expressions) {
+               expression.Extract(path, result);
+       }       
+}
index 73173a273bac22bec016983cf70c7fe58ddcbbe0..2365f2917c583826077cea5465f535d5f1aeeb03 100644 (file)
@@ -46,6 +46,8 @@ public:
 
        size_t GetLength(void) const;
 
+       void Extract(const std::vector<String>& path, const ExpressionList::Ptr& result) const;
+
 private:
        std::vector<Expression> m_Expressions;
 };