mirror of https://github.com/Icinga/icinga2.git
Fix: The order in which config items are defined should not matter
Fixes #3733
This commit is contained in:
parent
734f76af96
commit
6df051fad3
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,10 +359,7 @@ void ConfigItem::UnregisterFromParents(void)
|
|||
{
|
||||
ASSERT(OwnsLock());
|
||||
|
||||
BOOST_FOREACH(const String& parentName, m_Parents) {
|
||||
ConfigItem::Ptr parent = GetObject(GetType(), parentName);
|
||||
|
||||
if (parent)
|
||||
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
|
||||
|
|
|
@ -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,7 +73,7 @@ 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);
|
||||
|
||||
|
@ -83,13 +85,15 @@ 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 */
|
||||
* of this configuration item */
|
||||
std::set<ConfigItem::WeakPtr> m_ChildObjects; /**< Instantiated items
|
||||
* that inherit from this item */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() + "')");
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue