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. */
|
/* Don't validate if we have already encountered at least one error. */
|
||||||
if (!hasError)
|
if (!hasError)
|
||||||
context.Validate();
|
context.ValidateItems();
|
||||||
|
|
||||||
hasError = false;
|
hasError = false;
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,18 @@ String ConfigCompilerContext::GetUnit(void) const
|
||||||
return m_Unit;
|
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);
|
SetContext(this);
|
||||||
|
|
||||||
|
@ -137,6 +148,10 @@ void ConfigCompilerContext::ActivateItems(void)
|
||||||
ASSERT(m_Context == NULL);
|
ASSERT(m_Context == NULL);
|
||||||
|
|
||||||
Log(LogInformation, "config", "Activating config items in compilation unit '" + m_Unit + "'");
|
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) {
|
BOOST_FOREACH(const ConfigItem::Ptr& item, m_Items) {
|
||||||
item->Commit();
|
item->Commit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,8 @@ public:
|
||||||
|
|
||||||
String GetUnit(void) const;
|
String GetUnit(void) const;
|
||||||
|
|
||||||
void Validate(void);
|
void LinkItems(void);
|
||||||
|
void ValidateItems(void);
|
||||||
void ActivateItems(void);
|
void ActivateItems(void);
|
||||||
|
|
||||||
static void SetContext(ConfigCompilerContext *context);
|
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 String& unit, bool abstract, const ExpressionList::Ptr& exprl,
|
||||||
const std::vector<String>& parents, const DebugInfo& debuginfo)
|
const std::vector<String>& parents, const DebugInfo& debuginfo)
|
||||||
: m_Type(type), m_Name(name), m_Unit(unit), m_Abstract(abstract),
|
: 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.
|
* @returns The list of parents.
|
||||||
*/
|
*/
|
||||||
std::vector<String> ConfigItem::GetParents(void) const
|
std::vector<ConfigItem::Ptr> ConfigItem::GetParents(void) const
|
||||||
{
|
{
|
||||||
return m_Parents;
|
return m_Parents;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary::Ptr ConfigItem::Link(void) const
|
void ConfigItem::Link(void)
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
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;
|
ConfigItem::Ptr parent;
|
||||||
|
|
||||||
ConfigCompilerContext *context = ConfigCompilerContext::GetContext();
|
ConfigCompilerContext *context = ConfigCompilerContext::GetContext();
|
||||||
|
@ -162,10 +152,22 @@ void ConfigItem::InternalLink(const Dictionary::Ptr& dictionary) const
|
||||||
BOOST_THROW_EXCEPTION(std::invalid_argument(message.str()));
|
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);
|
dobj = dtype->GetObject(m_Name);
|
||||||
|
|
||||||
/* Register this item with its parents. */
|
/* Register this item with its parents. */
|
||||||
BOOST_FOREACH(const String& parentName, m_Parents) {
|
BOOST_FOREACH(const ConfigItem::Ptr& parent, m_Parents) {
|
||||||
ConfigItem::Ptr parent = GetObject(m_Type, parentName);
|
|
||||||
parent->m_ChildObjects.insert(self);
|
parent->m_ChildObjects.insert(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +245,10 @@ DynamicObject::Ptr ConfigItem::Commit(void)
|
||||||
|
|
||||||
double tx = DynamicObject::GetCurrentTx();
|
double tx = DynamicObject::GetCurrentTx();
|
||||||
|
|
||||||
Dictionary::Ptr properties = Link();
|
Link();
|
||||||
|
|
||||||
|
Dictionary::Ptr properties = boost::make_shared<Dictionary>();
|
||||||
|
GetLinkedExpressionList()->Execute(properties);
|
||||||
|
|
||||||
{
|
{
|
||||||
ObjectLock olock(properties);
|
ObjectLock olock(properties);
|
||||||
|
@ -310,6 +314,20 @@ DynamicObject::Ptr ConfigItem::Commit(void)
|
||||||
return dobj;
|
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.
|
* Unregisters the configuration item.
|
||||||
*/
|
*/
|
||||||
|
@ -341,11 +359,8 @@ void ConfigItem::UnregisterFromParents(void)
|
||||||
{
|
{
|
||||||
ASSERT(OwnsLock());
|
ASSERT(OwnsLock());
|
||||||
|
|
||||||
BOOST_FOREACH(const String& parentName, m_Parents) {
|
BOOST_FOREACH(const ConfigItem::Ptr& parent, m_Parents) {
|
||||||
ConfigItem::Ptr parent = GetObject(GetType(), parentName);
|
parent->m_ChildObjects.erase(GetSelf());
|
||||||
|
|
||||||
if (parent)
|
|
||||||
parent->m_ChildObjects.erase(GetSelf());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,7 +429,7 @@ void ConfigItem::Dump(std::ostream& fp) const
|
||||||
fp << " inherits";
|
fp << " inherits";
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
BOOST_FOREACH(const String& name, m_Parents) {
|
BOOST_FOREACH(const String& name, m_ParentNames) {
|
||||||
if (!first)
|
if (!first)
|
||||||
fp << ",";
|
fp << ",";
|
||||||
else
|
else
|
||||||
|
|
|
@ -47,11 +47,15 @@ public:
|
||||||
String GetUnit(void) const;
|
String GetUnit(void) const;
|
||||||
bool IsAbstract(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);
|
DynamicObject::Ptr Commit(void);
|
||||||
|
void Register(void);
|
||||||
void Unregister(void);
|
void Unregister(void);
|
||||||
|
|
||||||
void Dump(std::ostream& fp) const;
|
void Dump(std::ostream& fp) const;
|
||||||
|
@ -60,8 +64,6 @@ public:
|
||||||
|
|
||||||
DebugInfo GetDebugInfo(void) const;
|
DebugInfo GetDebugInfo(void) const;
|
||||||
|
|
||||||
Dictionary::Ptr Link(void) const;
|
|
||||||
|
|
||||||
static ConfigItem::Ptr GetObject(const String& type,
|
static ConfigItem::Ptr GetObject(const String& type,
|
||||||
const String& name);
|
const String& name);
|
||||||
|
|
||||||
|
@ -71,11 +73,11 @@ public:
|
||||||
static boost::signals2::signal<void (const ConfigItem::Ptr&)> OnRemoved;
|
static boost::signals2::signal<void (const ConfigItem::Ptr&)> OnRemoved;
|
||||||
|
|
||||||
private:
|
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_Type; /**< The object type. */
|
||||||
String m_Name; /**< The name. */
|
String m_Name; /**< The name. */
|
||||||
|
@ -83,14 +85,16 @@ private:
|
||||||
bool m_Abstract; /**< Whether this is a template. */
|
bool m_Abstract; /**< Whether this is a template. */
|
||||||
|
|
||||||
ExpressionList::Ptr m_ExpressionList;
|
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. */
|
items. */
|
||||||
|
std::vector<ConfigItem::Ptr> m_Parents;
|
||||||
DebugInfo m_DebugInfo; /**< Debug information. */
|
DebugInfo m_DebugInfo; /**< Debug information. */
|
||||||
|
|
||||||
|
ExpressionList::Ptr m_LinkedExpressionList;
|
||||||
|
|
||||||
DynamicObject::WeakPtr m_DynamicObject; /**< The instantiated version
|
DynamicObject::WeakPtr m_DynamicObject; /**< The instantiated version
|
||||||
* of this configuration
|
* of this configuration item */
|
||||||
* item */
|
std::set<ConfigItem::WeakPtr> m_ChildObjects; /**< Instantiated items
|
||||||
std::set<ConfigItem::WeakPtr> m_ChildObjects; /**< Instantiated items
|
|
||||||
* that inherit from this item */
|
* that inherit from this item */
|
||||||
|
|
||||||
static boost::mutex m_Mutex;
|
static boost::mutex m_Mutex;
|
||||||
|
|
|
@ -110,26 +110,6 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
|
||||||
BOOST_THROW_EXCEPTION(std::invalid_argument(msgbuf.str()));
|
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>();
|
ExpressionList::Ptr exprl = boost::make_shared<ExpressionList>();
|
||||||
|
|
||||||
Expression execExpr("", OperatorExecute, m_ExpressionList, m_DebugInfo);
|
Expression execExpr("", OperatorExecute, m_ExpressionList, m_DebugInfo);
|
||||||
|
|
|
@ -59,12 +59,13 @@ DebugInfo ConfigType::GetDebugInfo(void) const
|
||||||
|
|
||||||
void ConfigType::ValidateItem(const ConfigItem::Ptr& item) const
|
void ConfigType::ValidateItem(const ConfigItem::Ptr& item) const
|
||||||
{
|
{
|
||||||
Dictionary::Ptr attrs = item->Link();
|
|
||||||
|
|
||||||
/* Don't validate abstract items. */
|
/* Don't validate abstract items. */
|
||||||
if (item->IsAbstract())
|
if (item->IsAbstract())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Dictionary::Ptr attrs = boost::make_shared<Dictionary>();
|
||||||
|
item->GetLinkedExpressionList()->Execute(attrs);
|
||||||
|
|
||||||
std::vector<String> locations;
|
std::vector<String> locations;
|
||||||
locations.push_back("Object '" + item->GetName() + "' (Type: '" + item->GetType() + "')");
|
locations.push_back("Object '" + item->GetName() + "' (Type: '" + item->GetType() + "')");
|
||||||
|
|
||||||
|
|
|
@ -213,3 +213,18 @@ void Expression::Dump(std::ostream& fp, int indent) const
|
||||||
|
|
||||||
fp << ", " << "\n";
|
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
|
OperatorDivide
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ExpressionList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A configuration expression.
|
* A configuration expression.
|
||||||
*
|
*
|
||||||
|
@ -57,6 +59,8 @@ public:
|
||||||
void Execute(const Dictionary::Ptr& dictionary) const;
|
void Execute(const Dictionary::Ptr& dictionary) const;
|
||||||
void Dump(std::ostream& fp, int indent = 0) const;
|
void Dump(std::ostream& fp, int indent = 0) const;
|
||||||
|
|
||||||
|
void Extract(const std::vector<String>& path, const shared_ptr<ExpressionList>& result) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
String m_Key;
|
String m_Key;
|
||||||
ExpressionOperator m_Operator;
|
ExpressionOperator m_Operator;
|
||||||
|
|
|
@ -67,3 +67,10 @@ void ExpressionList::Dump(std::ostream& fp, int indent) const
|
||||||
expression.Dump(fp, indent);
|
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;
|
size_t GetLength(void) const;
|
||||||
|
|
||||||
|
void Extract(const std::vector<String>& path, const ExpressionList::Ptr& result) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Expression> m_Expressions;
|
std::vector<Expression> m_Expressions;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue