Improve config compiler's memory usage

This commit is contained in:
Gunnar Beutner 2014-11-06 19:35:47 +01:00 committed by Gunnar Beutner
parent 85a380c443
commit e1c95d4fa0
33 changed files with 442 additions and 396 deletions

View File

@ -29,12 +29,14 @@ enum HAMode
class NameComposer { class NameComposer {
public: public:
virtual String MakeName(const String& shortName, const Dictionary::Ptr& props) const = 0; virtual String MakeName(const String& shortName, const Object::Ptr& context) const = 0;
}; };
}}} }}}
abstract class DynamicObject abstract class DynamicObject
{ {
[protected] Object::Ptr __parent (ParentScope);
[config, internal] String __name (Name); [config, internal] String __name (Name);
[config] String name (ShortName) { [config] String name (ShortName) {
get {{{ get {{{

View File

@ -123,19 +123,6 @@ DynamicObject::Ptr DynamicType::GetObject(const String& name) const
return nt->second; return nt->second;
} }
DynamicObject::Ptr DynamicType::CreateObject(const Dictionary::Ptr& serializedUpdate)
{
ASSERT(!OwnsLock());
Type::Ptr type = Type::GetByName(m_Name);
Object::Ptr object = type->Instantiate();
Deserialize(object, serializedUpdate, true, FAConfig);
return static_pointer_cast<DynamicObject>(object);
}
boost::mutex& DynamicType::GetStaticMutex(void) boost::mutex& DynamicType::GetStaticMutex(void)
{ {
static boost::mutex mutex; static boost::mutex mutex;

View File

@ -44,7 +44,6 @@ public:
static DynamicType::Ptr GetByName(const String& name); static DynamicType::Ptr GetByName(const String& name);
DynamicObject::Ptr CreateObject(const Dictionary::Ptr& serializedUpdate);
DynamicObject::Ptr GetObject(const String& name) const; DynamicObject::Ptr GetObject(const String& name) const;
void RegisterObject(const DynamicObject::Ptr& object); void RegisterObject(const DynamicObject::Ptr& object);

View File

@ -97,6 +97,9 @@ public:
if (IsEmpty()) if (IsEmpty())
return shared_ptr<T>(); return shared_ptr<T>();
if (!IsObject())
BOOST_THROW_EXCEPTION(std::runtime_error("Cannot convert value to object."));
Object::Ptr object = boost::get<Object::Ptr>(m_Value); Object::Ptr object = boost::get<Object::Ptr>(m_Value);
ASSERT(object); ASSERT(object);

View File

@ -81,6 +81,9 @@ static bool LoadConfigFiles(const boost::program_options::variables_map& vm, con
{ {
ConfigCompilerContext::GetInstance()->Reset(); ConfigCompilerContext::GetInstance()->Reset();
if (!objectsFile.IsEmpty())
ConfigCompilerContext::GetInstance()->OpenObjectsFile(objectsFile);
if (vm.count("config") > 0) { if (vm.count("config") > 0) {
BOOST_FOREACH(const String& configPath, vm["config"].as<std::vector<std::string> >()) { BOOST_FOREACH(const String& configPath, vm["config"].as<std::vector<std::string> >()) {
ConfigCompiler::CompileFile(configPath); ConfigCompiler::CompileFile(configPath);
@ -109,7 +112,7 @@ static bool LoadConfigFiles(const boost::program_options::variables_map& vm, con
ConfigItem::Ptr item = builder->Compile(); ConfigItem::Ptr item = builder->Compile();
item->Register(); item->Register();
bool result = ConfigItem::ValidateItems(objectsFile); bool result = ConfigItem::ValidateItems();
int warnings = 0, errors = 0; int warnings = 0, errors = 0;
@ -149,6 +152,8 @@ static bool LoadConfigFiles(const boost::program_options::variables_map& vm, con
if (!result) if (!result)
return false; return false;
ConfigCompilerContext::GetInstance()->FinishObjectsFile();
ScriptVariable::WriteVariablesFile(varsfile); ScriptVariable::WriteVariablesFile(varsfile);
return true; return true;

View File

@ -29,7 +29,7 @@ ApplyRule::CallbackMap ApplyRule::m_Callbacks;
ApplyRule::ApplyRule(const String& targetType, const String& name, const Expression::Ptr& expression, ApplyRule::ApplyRule(const String& targetType, const String& name, const Expression::Ptr& expression,
const Expression::Ptr& filter, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm, const Expression::Ptr& filter, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm,
const DebugInfo& di, const Dictionary::Ptr& scope) const DebugInfo& di, const Object::Ptr& scope)
: m_TargetType(targetType), m_Name(name), m_Expression(expression), m_Filter(filter), m_FKVar(fkvar), : m_TargetType(targetType), m_Name(name), m_Expression(expression), m_Filter(filter), m_FKVar(fkvar),
m_FVVar(fvvar), m_FTerm(fterm), m_DebugInfo(di), m_Scope(scope) m_FVVar(fvvar), m_FTerm(fterm), m_DebugInfo(di), m_Scope(scope)
{ } { }
@ -74,19 +74,19 @@ DebugInfo ApplyRule::GetDebugInfo(void) const
return m_DebugInfo; return m_DebugInfo;
} }
Dictionary::Ptr ApplyRule::GetScope(void) const Object::Ptr ApplyRule::GetScope(void) const
{ {
return m_Scope; return m_Scope;
} }
void ApplyRule::AddRule(const String& sourceType, const String& targetType, const String& name, void ApplyRule::AddRule(const String& sourceType, const String& targetType, const String& name,
const Expression::Ptr& expression, const Expression::Ptr& filter, const String& fkvar, const Expression::Ptr& expression, const Expression::Ptr& filter, const String& fkvar,
const String& fvvar, const Expression::Ptr& fterm, const DebugInfo& di, const Dictionary::Ptr& scope) const String& fvvar, const Expression::Ptr& fterm, const DebugInfo& di, const Object::Ptr& scope)
{ {
m_Rules[sourceType].push_back(ApplyRule(targetType, name, expression, filter, fkvar, fvvar, fterm, di, scope)); m_Rules[sourceType].push_back(ApplyRule(targetType, name, expression, filter, fkvar, fvvar, fterm, di, scope));
} }
bool ApplyRule::EvaluateFilter(const Dictionary::Ptr& scope) const bool ApplyRule::EvaluateFilter(const Object::Ptr& scope) const
{ {
return m_Filter->Evaluate(scope); return m_Filter->Evaluate(scope);
} }

View File

@ -46,12 +46,12 @@ public:
String GetFVVar(void) const; String GetFVVar(void) const;
Expression::Ptr GetFTerm(void) const; Expression::Ptr GetFTerm(void) const;
DebugInfo GetDebugInfo(void) const; DebugInfo GetDebugInfo(void) const;
Dictionary::Ptr GetScope(void) const; Object::Ptr GetScope(void) const;
bool EvaluateFilter(const Dictionary::Ptr& scope) const; bool EvaluateFilter(const Object::Ptr& scope) const;
static void AddRule(const String& sourceType, const String& targetType, const String& name, const Expression::Ptr& expression, static void AddRule(const String& sourceType, const String& targetType, const String& name, const Expression::Ptr& expression,
const Expression::Ptr& filter, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm, const DebugInfo& di, const Dictionary::Ptr& scope); const Expression::Ptr& filter, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm, const DebugInfo& di, const Object::Ptr& scope);
static void EvaluateRules(bool clear); static void EvaluateRules(bool clear);
static void RegisterType(const String& sourceType, const std::vector<String>& targetTypes, const ApplyRule::Callback& callback); static void RegisterType(const String& sourceType, const std::vector<String>& targetTypes, const ApplyRule::Callback& callback);
@ -68,14 +68,14 @@ private:
String m_FVVar; String m_FVVar;
Expression::Ptr m_FTerm; Expression::Ptr m_FTerm;
DebugInfo m_DebugInfo; DebugInfo m_DebugInfo;
Dictionary::Ptr m_Scope; Object::Ptr m_Scope;
static CallbackMap m_Callbacks; static CallbackMap m_Callbacks;
static RuleMap m_Rules; static RuleMap m_Rules;
ApplyRule(const String& targetType, const String& name, const Expression::Ptr& expression, ApplyRule(const String& targetType, const String& name, const Expression::Ptr& expression,
const Expression::Ptr& filter, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm, const Expression::Ptr& filter, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm,
const DebugInfo& di, const Dictionary::Ptr& scope); const DebugInfo& di, const Object::Ptr& scope);
}; };
} }

View File

@ -19,7 +19,10 @@
#include "config/configcompilercontext.hpp" #include "config/configcompilercontext.hpp"
#include "base/singleton.hpp" #include "base/singleton.hpp"
#include "base/json.hpp"
#include "base/netstring.hpp"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <fstream>
using namespace icinga; using namespace icinga;
@ -61,3 +64,50 @@ ConfigCompilerContext *ConfigCompilerContext::GetInstance(void)
return Singleton<ConfigCompilerContext>::GetInstance(); return Singleton<ConfigCompilerContext>::GetInstance();
} }
void ConfigCompilerContext::OpenObjectsFile(const String& filename)
{
m_ObjectsPath = filename;
String tempFilename = m_ObjectsPath + ".tmp";
std::fstream *fp = new std::fstream();
fp->open(tempFilename.CStr(), std::ios_base::out);
if (!*fp)
BOOST_THROW_EXCEPTION(std::runtime_error("Could not open '" + tempFilename + "' file"));
m_ObjectsFP = make_shared<StdioStream>(fp, true);
}
void ConfigCompilerContext::WriteObject(const Dictionary::Ptr& object)
{
if (!m_ObjectsFP)
return;
String json = JsonEncode(object);
{
boost::mutex::scoped_lock lock(m_Mutex);
NetString::WriteStringToStream(m_ObjectsFP, json);
}
}
void ConfigCompilerContext::FinishObjectsFile(void)
{
m_ObjectsFP->Close();
String tempFilename = m_ObjectsPath + ".tmp";
#ifdef _WIN32
_unlink(m_ObjectsPath.CStr());
#endif /* _WIN32 */
if (rename(tempFilename.CStr(), m_ObjectsPath.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempFilename));
}
}

View File

@ -22,6 +22,8 @@
#include "config/i2-config.hpp" #include "config/i2-config.hpp"
#include "base/debuginfo.hpp" #include "base/debuginfo.hpp"
#include "base/stdiostream.hpp"
#include "base/dictionary.hpp"
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <vector> #include <vector>
@ -51,10 +53,16 @@ public:
void Reset(void); void Reset(void);
void OpenObjectsFile(const String& filename);
void WriteObject(const Dictionary::Ptr& object);
void FinishObjectsFile(void);
static ConfigCompilerContext *GetInstance(void); static ConfigCompilerContext *GetInstance(void);
private: private:
std::vector<ConfigCompilerMessage> m_Messages; std::vector<ConfigCompilerMessage> m_Messages;
String m_ObjectsPath;
StdioStream::Ptr m_ObjectsFP;
mutable boost::mutex m_Mutex; mutable boost::mutex m_Mutex;
}; };

View File

@ -32,6 +32,7 @@
#include "base/exception.hpp" #include "base/exception.hpp"
#include "base/stdiostream.hpp" #include "base/stdiostream.hpp"
#include "base/netstring.hpp" #include "base/netstring.hpp"
#include "base/serializer.hpp"
#include "base/json.hpp" #include "base/json.hpp"
#include "base/configerror.hpp" #include "base/configerror.hpp"
#include <sstream> #include <sstream>
@ -55,9 +56,9 @@ ConfigItem::ItemMap ConfigItem::m_Items;
*/ */
ConfigItem::ConfigItem(const String& type, const String& name, ConfigItem::ConfigItem(const String& type, const String& name,
bool abstract, const Expression::Ptr& exprl, bool abstract, const Expression::Ptr& exprl,
const DebugInfo& debuginfo, const Dictionary::Ptr& scope, const DebugInfo& debuginfo, const Object::Ptr& scope,
const String& zone) const String& zone)
: m_Type(type), m_Name(name), m_Abstract(abstract), m_Validated(false), : m_Type(type), m_Name(name), m_Abstract(abstract),
m_ExpressionList(exprl), m_DebugInfo(debuginfo), m_ExpressionList(exprl), m_DebugInfo(debuginfo),
m_Scope(scope), m_Zone(zone) m_Scope(scope), m_Zone(zone)
{ {
@ -103,7 +104,7 @@ DebugInfo ConfigItem::GetDebugInfo(void) const
return m_DebugInfo; return m_DebugInfo;
} }
Dictionary::Ptr ConfigItem::GetScope(void) const Object::Ptr ConfigItem::GetScope(void) const
{ {
return m_Scope; return m_Scope;
} }
@ -118,62 +119,13 @@ Expression::Ptr ConfigItem::GetExpressionList(void) const
return m_ExpressionList; return m_ExpressionList;
} }
Dictionary::Ptr ConfigItem::GetProperties(void)
{
ASSERT(!OwnsLock());
VERIFY(!IsAbstract());
ObjectLock olock(this);
if (!m_Properties) {
Dictionary::Ptr locals = make_shared<Dictionary>();
locals->Set("__parent", m_Scope);
locals->Set("name", m_Name);
m_Properties = make_shared<Dictionary>();
m_Properties->Set("type", m_Type);
if (!m_Zone.IsEmpty())
m_Properties->Set("zone", m_Zone);
m_Properties->Set("__parent", locals);
GetExpressionList()->Evaluate(m_Properties, &m_DebugHints);
m_Properties->Remove("__parent");
String name = m_Name;
if (!m_Abstract) {
shared_ptr<NameComposer> nc = dynamic_pointer_cast<NameComposer>(Type::GetByName(m_Type));
if (nc) {
name = nc->MakeName(m_Name, m_Properties);
if (name.IsEmpty())
BOOST_THROW_EXCEPTION(std::runtime_error("Could not determine name for object"));
}
}
if (name != m_Name)
m_Properties->Set("name", m_Name);
m_Properties->Set("__name", name);
VERIFY(m_Properties->Get("type") == GetType());
}
return m_Properties;
}
const DebugHint& ConfigItem::GetDebugHints(void) const
{
return m_DebugHints;
}
/** /**
* Commits the configuration item by creating a DynamicObject * Commits the configuration item by creating a DynamicObject
* object. * object.
* *
* @returns The DynamicObject that was created/updated. * @returns The DynamicObject that was created/updated.
*/ */
DynamicObject::Ptr ConfigItem::Commit(void) DynamicObject::Ptr ConfigItem::Commit(bool discard)
{ {
ASSERT(!OwnsLock()); ASSERT(!OwnsLock());
@ -183,16 +135,88 @@ DynamicObject::Ptr ConfigItem::Commit(void)
#endif /* _DEBUG */ #endif /* _DEBUG */
/* Make sure the type is valid. */ /* Make sure the type is valid. */
DynamicType::Ptr dtype = DynamicType::GetByName(GetType()); Type::Ptr type = Type::GetByName(GetType());
if (!dtype) if (!type || !Type::GetByName("DynamicObject")->IsAssignableFrom(type))
BOOST_THROW_EXCEPTION(std::runtime_error("Type '" + GetType() + "' does not exist.")); BOOST_THROW_EXCEPTION(ConfigError("Type '" + GetType() + "' does not exist."));
if (IsAbstract()) if (IsAbstract())
return DynamicObject::Ptr(); return DynamicObject::Ptr();
DynamicObject::Ptr dobj = dtype->CreateObject(GetProperties()); DynamicObject::Ptr dobj = static_pointer_cast<DynamicObject>(type->Instantiate());
dobj->SetDebugInfo(m_DebugInfo); dobj->SetDebugInfo(m_DebugInfo);
dobj->SetTypeName(m_Type);
dobj->SetZone(m_Zone);
Dictionary::Ptr locals = make_shared<Dictionary>();
locals->Set("__parent", m_Scope);
m_Scope.reset();
locals->Set("name", m_Name);
dobj->SetParentScope(locals);
DebugHint debugHints;
try {
m_ExpressionList->Evaluate(dobj, &debugHints);
} catch (const ConfigError& ex) {
const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
} catch (const std::exception& ex) {
ConfigCompilerContext::GetInstance()->AddMessage(true, DiagnosticInformation(ex));
}
if (discard)
m_ExpressionList.reset();
dobj->SetParentScope(Dictionary::Ptr());
String name = m_Name;
shared_ptr<NameComposer> nc = dynamic_pointer_cast<NameComposer>(type);
if (nc) {
name = nc->MakeName(m_Name, dobj);
if (name.IsEmpty())
BOOST_THROW_EXCEPTION(std::runtime_error("Could not determine name for object"));
}
if (name != m_Name)
dobj->SetShortName(m_Name);
dobj->SetName(name);
Dictionary::Ptr attrs = Serialize(dobj, FAConfig);
Dictionary::Ptr persistentItem = make_shared<Dictionary>();
persistentItem->Set("type", GetType());
persistentItem->Set("name", GetName());
persistentItem->Set("properties", attrs);
persistentItem->Set("debug_hints", debugHints.ToDictionary());
ConfigCompilerContext::GetInstance()->WriteObject(persistentItem);
ConfigType::Ptr ctype = ConfigType::GetByName(GetType());
if (!ctype)
ConfigCompilerContext::GetInstance()->AddMessage(false, "No validation type found for object '" + GetName() + "' of type '" + GetType() + "'");
else {
TypeRuleUtilities utils;
try {
attrs->Remove("name");
ctype->ValidateItem(GetName(), attrs, GetDebugInfo(), &utils);
} catch (const ConfigError& ex) {
const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
} catch (const std::exception& ex) {
ConfigCompilerContext::GetInstance()->AddMessage(true, DiagnosticInformation(ex));
}
}
dobj->Register(); dobj->Register();
m_Object = dobj; m_Object = dobj;
@ -207,20 +231,11 @@ void ConfigItem::Register(void)
{ {
String name = m_Name; String name = m_Name;
/* If this is a non-abstract object we need to figure out
* its real name now - or assign it a temporary name. */
if (!m_Abstract) {
shared_ptr<NameComposer> nc = dynamic_pointer_cast<NameComposer>(Type::GetByName(m_Type)); shared_ptr<NameComposer> nc = dynamic_pointer_cast<NameComposer>(Type::GetByName(m_Type));
if (nc) { /* If this is a non-abstract object with a composite name we don't register it. */
name = nc->MakeName(m_Name, Dictionary::Ptr()); if (!m_Abstract && nc)
return;
ASSERT(name.IsEmpty() || name == m_Name);
if (name.IsEmpty())
name = Utility::NewUniqueID();
}
}
std::pair<String, String> key = std::make_pair(m_Type, name); std::pair<String, String> key = std::make_pair(m_Type, name);
ConfigItem::Ptr self = GetSelf(); ConfigItem::Ptr self = GetSelf();
@ -254,104 +269,17 @@ ConfigItem::Ptr ConfigItem::GetObject(const String& type, const String& name)
return ConfigItem::Ptr(); return ConfigItem::Ptr();
} }
void ConfigItem::ValidateItem(void) bool ConfigItem::ValidateItems(void)
{
if (m_Validated || IsAbstract())
return;
ConfigType::Ptr ctype = ConfigType::GetByName(GetType());
if (!ctype) {
ConfigCompilerContext::GetInstance()->AddMessage(false, "No validation type found for object '" + GetName() + "' of type '" + GetType() + "'");
return;
}
TypeRuleUtilities utils;
try {
ctype->ValidateItem(GetName(), GetProperties(), GetDebugInfo(), &utils);
} catch (const ConfigError& ex) {
const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
} catch (const std::exception& ex) {
ConfigCompilerContext::GetInstance()->AddMessage(true, DiagnosticInformation(ex));
}
m_Validated = true;
}
void ConfigItem::WriteObjectsFile(const String& filename)
{
Log(LogInformation, "ConfigItem")
<< "Dumping config items to file '" << filename << "'";
String tempFilename = filename + ".tmp";
std::fstream fp;
fp.open(tempFilename.CStr(), std::ios_base::out);
if (!fp)
BOOST_THROW_EXCEPTION(std::runtime_error("Could not open '" + tempFilename + "' file"));
StdioStream::Ptr sfp = make_shared<StdioStream>(&fp, false);
BOOST_FOREACH(const ItemMap::value_type& kv, m_Items) {
ConfigItem::Ptr item = kv.second;
if (item->IsAbstract())
continue;
Dictionary::Ptr persistentItem = make_shared<Dictionary>();
persistentItem->Set("type", item->GetType());
persistentItem->Set("name", item->GetName());
persistentItem->Set("properties", item->GetProperties());
persistentItem->Set("debug_hints", item->GetDebugHints().ToDictionary());
String json = JsonEncode(persistentItem);
NetString::WriteStringToStream(sfp, json);
}
sfp->Close();
fp.close();
#ifdef _WIN32
_unlink(filename.CStr());
#endif /* _WIN32 */
if (rename(tempFilename.CStr(), filename.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(tempFilename));
}
}
bool ConfigItem::ValidateItems(const String& objectsFile)
{ {
if (ConfigCompilerContext::GetInstance()->HasErrors()) if (ConfigCompilerContext::GetInstance()->HasErrors())
return false; return false;
ParallelWorkQueue upq; ParallelWorkQueue upq;
Log(LogInformation, "ConfigItem", "Validating config items (step 1)...");
BOOST_FOREACH(const ItemMap::value_type& kv, m_Items) {
upq.Enqueue(boost::bind(&ConfigItem::ValidateItem, kv.second));
}
upq.Join();
if (ConfigCompilerContext::GetInstance()->HasErrors())
return false;
Log(LogInformation, "ConfigItem", "Committing config items"); Log(LogInformation, "ConfigItem", "Committing config items");
BOOST_FOREACH(const ItemMap::value_type& kv, m_Items) { BOOST_FOREACH(const ItemMap::value_type& kv, m_Items) {
upq.Enqueue(boost::bind(&ConfigItem::Commit, kv.second)); upq.Enqueue(boost::bind(&ConfigItem::Commit, kv.second, false));
} }
upq.Join(); upq.Join();
@ -381,17 +309,8 @@ bool ConfigItem::ValidateItems(const String& objectsFile)
Log(LogInformation, "ConfigItem", "Evaluating 'object' rules (step 2)..."); Log(LogInformation, "ConfigItem", "Evaluating 'object' rules (step 2)...");
ObjectRule::EvaluateRules(true); ObjectRule::EvaluateRules(true);
Log(LogInformation, "ConfigItem", "Validating config items (step 2)...");
BOOST_FOREACH(const ItemMap::value_type& kv, m_Items) {
upq.Enqueue(boost::bind(&ConfigItem::ValidateItem, kv.second));
}
upq.Join(); upq.Join();
if (!objectsFile.IsEmpty())
ConfigItem::WriteObjectsFile(objectsFile);
ConfigItem::DiscardItems(); ConfigItem::DiscardItems();
ConfigType::DiscardTypes(); ConfigType::DiscardTypes();

View File

@ -39,7 +39,7 @@ public:
ConfigItem(const String& type, const String& name, bool abstract, ConfigItem(const String& type, const String& name, bool abstract,
const Expression::Ptr& exprl, const DebugInfo& debuginfo, const Expression::Ptr& exprl, const DebugInfo& debuginfo,
const Dictionary::Ptr& scope, const String& zone); const Object::Ptr& scope, const String& zone);
String GetType(void) const; String GetType(void) const;
String GetName(void) const; String GetName(void) const;
@ -48,42 +48,33 @@ public:
std::vector<ConfigItem::Ptr> GetParents(void) const; std::vector<ConfigItem::Ptr> GetParents(void) const;
Expression::Ptr GetExpressionList(void) const; Expression::Ptr GetExpressionList(void) const;
Dictionary::Ptr GetProperties(void);
const DebugHint& GetDebugHints(void) const;
DynamicObject::Ptr Commit(void); DynamicObject::Ptr Commit(bool discard = true);
void Register(void); void Register(void);
DebugInfo GetDebugInfo(void) const; DebugInfo GetDebugInfo(void) const;
Dictionary::Ptr GetScope(void) const; Object::Ptr GetScope(void) const;
String GetZone(void) const; String GetZone(void) const;
static ConfigItem::Ptr GetObject(const String& type, static ConfigItem::Ptr GetObject(const String& type,
const String& name); const String& name);
void ValidateItem(void); static bool ValidateItems(void);
static bool ValidateItems(const String& objectsFile = String());
static bool ActivateItems(void); static bool ActivateItems(void);
static void DiscardItems(void); static void DiscardItems(void);
static void WriteObjectsFile(const String& filename);
private: private:
String m_Type; /**< The object type. */ String m_Type; /**< The object type. */
String m_Name; /**< The name. */ String m_Name; /**< The name. */
bool m_Abstract; /**< Whether this is a template. */ bool m_Abstract; /**< Whether this is a template. */
bool m_Validated; /** Whether this object has been validated. */
Expression::Ptr m_ExpressionList; Expression::Ptr m_ExpressionList;
Dictionary::Ptr m_Properties;
DebugHint m_DebugHints;
std::vector<String> m_ParentNames; /**< The names of parent configuration std::vector<String> m_ParentNames; /**< The names of parent configuration
items. */ items. */
DebugInfo m_DebugInfo; /**< Debug information. */ DebugInfo m_DebugInfo; /**< Debug information. */
Dictionary::Ptr m_Scope; /**< variable scope. */ Object::Ptr m_Scope; /**< variable scope. */
String m_Zone; /**< The zone. */ String m_Zone; /**< The zone. */
DynamicObject::Ptr m_Object; DynamicObject::Ptr m_Object;

View File

@ -54,7 +54,7 @@ void ConfigItemBuilder::SetAbstract(bool abstract)
m_Abstract = abstract; m_Abstract = abstract;
} }
void ConfigItemBuilder::SetScope(const Dictionary::Ptr& scope) void ConfigItemBuilder::SetScope(const Object::Ptr& scope)
{ {
m_Scope = scope; m_Scope = scope;
} }

View File

@ -45,7 +45,7 @@ public:
void SetType(const String& type); void SetType(const String& type);
void SetName(const String& name); void SetName(const String& name);
void SetAbstract(bool abstract); void SetAbstract(bool abstract);
void SetScope(const Dictionary::Ptr& scope); void SetScope(const Object::Ptr& scope);
void SetZone(const String& zone); void SetZone(const String& zone);
void AddExpression(const Expression::Ptr& expr); void AddExpression(const Expression::Ptr& expr);
@ -58,7 +58,7 @@ private:
bool m_Abstract; /**< Whether the item is abstract. */ bool m_Abstract; /**< Whether the item is abstract. */
Array::Ptr m_Expressions; /**< Expressions for this item. */ Array::Ptr m_Expressions; /**< Expressions for this item. */
DebugInfo m_DebugInfo; /**< Debug information. */ DebugInfo m_DebugInfo; /**< Debug information. */
Dictionary::Ptr m_Scope; /**< variable scope. */ Object::Ptr m_Scope; /**< variable scope. */
String m_Zone; /**< The zone. */ String m_Zone; /**< The zone. */
}; };

View File

@ -33,6 +33,7 @@
#include "base/configerror.hpp" #include "base/configerror.hpp"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/exception_ptr.hpp> #include <boost/exception_ptr.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/exception/errinfo_nested_exception.hpp> #include <boost/exception/errinfo_nested_exception.hpp>
using namespace icinga; using namespace icinga;
@ -45,7 +46,7 @@ Expression::Expression(OpCallback op, const Value& operand1, const Value& operan
: m_Operator(op), m_Operand1(operand1), m_Operand2(operand2), m_DebugInfo(di) : m_Operator(op), m_Operand1(operand1), m_Operand2(operand2), m_DebugInfo(di)
{ } { }
Value Expression::Evaluate(const Dictionary::Ptr& locals, DebugHint *dhint) const Value Expression::Evaluate(const Object::Ptr& context, DebugHint *dhint) const
{ {
try { try {
#ifdef _DEBUG #ifdef _DEBUG
@ -57,7 +58,7 @@ Value Expression::Evaluate(const Dictionary::Ptr& locals, DebugHint *dhint) cons
} }
#endif /* _DEBUG */ #endif /* _DEBUG */
return m_Operator(this, locals, dhint); return m_Operator(this, context, dhint);
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
if (boost::get_error_info<boost::errinfo_nested_exception>(ex)) if (boost::get_error_info<boost::errinfo_nested_exception>(ex))
throw; throw;
@ -99,125 +100,125 @@ void Expression::Dump(std::ostream& stream, int indent) const
DumpOperand(stream, m_Operand2, indent + 1); DumpOperand(stream, m_Operand2, indent + 1);
} }
Value Expression::EvaluateOperand1(const Dictionary::Ptr& locals, DebugHint *dhint) const Value Expression::EvaluateOperand1(const Object::Ptr& context, DebugHint *dhint) const
{ {
return static_cast<Expression::Ptr>(m_Operand1)->Evaluate(locals, dhint); return static_cast<Expression::Ptr>(m_Operand1)->Evaluate(context, dhint);
} }
Value Expression::EvaluateOperand2(const Dictionary::Ptr& locals, DebugHint *dhint) const Value Expression::EvaluateOperand2(const Object::Ptr& context, DebugHint *dhint) const
{ {
return static_cast<Expression::Ptr>(m_Operand2)->Evaluate(locals, dhint); return static_cast<Expression::Ptr>(m_Operand2)->Evaluate(context, dhint);
} }
Value Expression::OpLiteral(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpLiteral(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->m_Operand1; return expr->m_Operand1;
} }
Value Expression::OpVariable(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpVariable(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
Dictionary::Ptr scope = locals; Object::Ptr scope = context;
while (scope) { while (scope) {
if (scope->Contains(expr->m_Operand1)) if (HasField(scope, expr->m_Operand1))
return scope->Get(expr->m_Operand1); return GetField(scope, expr->m_Operand1);
scope = scope->Get("__parent"); scope = GetField(scope, "__parent");
} }
return ScriptVariable::Get(expr->m_Operand1); return ScriptVariable::Get(expr->m_Operand1);
} }
Value Expression::OpNegate(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpNegate(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return ~(long)expr->EvaluateOperand1(locals); return ~(long)expr->EvaluateOperand1(context);
} }
Value Expression::OpLogicalNegate(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpLogicalNegate(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return !expr->EvaluateOperand1(locals).ToBool(); return !expr->EvaluateOperand1(context).ToBool();
} }
Value Expression::OpAdd(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpAdd(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals) + expr->EvaluateOperand2(locals); return expr->EvaluateOperand1(context) + expr->EvaluateOperand2(context);
} }
Value Expression::OpSubtract(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpSubtract(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals) - expr->EvaluateOperand2(locals); return expr->EvaluateOperand1(context) - expr->EvaluateOperand2(context);
} }
Value Expression::OpMultiply(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpMultiply(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals) * expr->EvaluateOperand2(locals); return expr->EvaluateOperand1(context) * expr->EvaluateOperand2(context);
} }
Value Expression::OpDivide(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpDivide(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals) / expr->EvaluateOperand2(locals); return expr->EvaluateOperand1(context) / expr->EvaluateOperand2(context);
} }
Value Expression::OpBinaryAnd(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpBinaryAnd(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals) & expr->EvaluateOperand2(locals); return expr->EvaluateOperand1(context) & expr->EvaluateOperand2(context);
} }
Value Expression::OpBinaryOr(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpBinaryOr(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals) | expr->EvaluateOperand2(locals); return expr->EvaluateOperand1(context) | expr->EvaluateOperand2(context);
} }
Value Expression::OpShiftLeft(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpShiftLeft(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals) << expr->EvaluateOperand2(locals); return expr->EvaluateOperand1(context) << expr->EvaluateOperand2(context);
} }
Value Expression::OpShiftRight(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpShiftRight(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals) >> expr->EvaluateOperand2(locals); return expr->EvaluateOperand1(context) >> expr->EvaluateOperand2(context);
} }
Value Expression::OpEqual(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals) == expr->EvaluateOperand2(locals); return expr->EvaluateOperand1(context) == expr->EvaluateOperand2(context);
} }
Value Expression::OpNotEqual(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpNotEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals) != expr->EvaluateOperand2(locals); return expr->EvaluateOperand1(context) != expr->EvaluateOperand2(context);
} }
Value Expression::OpLessThan(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpLessThan(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals) < expr->EvaluateOperand2(locals); return expr->EvaluateOperand1(context) < expr->EvaluateOperand2(context);
} }
Value Expression::OpGreaterThan(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpGreaterThan(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals) > expr->EvaluateOperand2(locals); return expr->EvaluateOperand1(context) > expr->EvaluateOperand2(context);
} }
Value Expression::OpLessThanOrEqual(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpLessThanOrEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals) <= expr->EvaluateOperand2(locals); return expr->EvaluateOperand1(context) <= expr->EvaluateOperand2(context);
} }
Value Expression::OpGreaterThanOrEqual(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpGreaterThanOrEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals) >= expr->EvaluateOperand2(locals); return expr->EvaluateOperand1(context) >= expr->EvaluateOperand2(context);
} }
Value Expression::OpIn(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpIn(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
Value right = expr->EvaluateOperand2(locals); Value right = expr->EvaluateOperand2(context);
if (right.IsEmpty()) if (right.IsEmpty())
return false; return false;
else if (!right.IsObjectType<Array>()) else if (!right.IsObjectType<Array>())
BOOST_THROW_EXCEPTION(ConfigError("Invalid right side argument for 'in' operator: " + JsonEncode(right))); BOOST_THROW_EXCEPTION(ConfigError("Invalid right side argument for 'in' operator: " + JsonEncode(right)));
Value left = expr->EvaluateOperand1(locals); Value left = expr->EvaluateOperand1(context);
Array::Ptr arr = right; Array::Ptr arr = right;
bool found = false; bool found = false;
@ -232,24 +233,24 @@ Value Expression::OpIn(const Expression *expr, const Dictionary::Ptr& locals, De
return found; return found;
} }
Value Expression::OpNotIn(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpNotIn(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return !OpIn(expr, locals, dhint); return !OpIn(expr, context, dhint);
} }
Value Expression::OpLogicalAnd(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpLogicalAnd(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals).ToBool() && expr->EvaluateOperand2(locals).ToBool(); return expr->EvaluateOperand1(context).ToBool() && expr->EvaluateOperand2(context).ToBool();
} }
Value Expression::OpLogicalOr(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpLogicalOr(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
return expr->EvaluateOperand1(locals).ToBool() || expr->EvaluateOperand2(locals).ToBool(); return expr->EvaluateOperand1(context).ToBool() || expr->EvaluateOperand2(context).ToBool();
} }
Value Expression::OpFunctionCall(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpFunctionCall(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
Value funcName = expr->EvaluateOperand1(locals); Value funcName = expr->EvaluateOperand1(context);
ScriptFunction::Ptr func; ScriptFunction::Ptr func;
@ -261,17 +262,17 @@ Value Expression::OpFunctionCall(const Expression *expr, const Dictionary::Ptr&
if (!func) if (!func)
BOOST_THROW_EXCEPTION(ConfigError("Function '" + funcName + "' does not exist.")); BOOST_THROW_EXCEPTION(ConfigError("Function '" + funcName + "' does not exist."));
Array::Ptr arr = expr->EvaluateOperand2(locals); Array::Ptr arr = expr->EvaluateOperand2(context);
std::vector<Value> arguments; std::vector<Value> arguments;
for (Array::SizeType index = 0; index < arr->GetLength(); index++) { for (Array::SizeType index = 0; index < arr->GetLength(); index++) {
const Expression::Ptr& aexpr = arr->Get(index); const Expression::Ptr& aexpr = arr->Get(index);
arguments.push_back(aexpr->Evaluate(locals)); arguments.push_back(aexpr->Evaluate(context));
} }
return func->Invoke(arguments); return func->Invoke(arguments);
} }
Value Expression::OpArray(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpArray(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
Array::Ptr arr = expr->m_Operand1; Array::Ptr arr = expr->m_Operand1;
Array::Ptr result = make_shared<Array>(); Array::Ptr result = make_shared<Array>();
@ -279,28 +280,28 @@ Value Expression::OpArray(const Expression *expr, const Dictionary::Ptr& locals,
if (arr) { if (arr) {
for (Array::SizeType index = 0; index < arr->GetLength(); index++) { for (Array::SizeType index = 0; index < arr->GetLength(); index++) {
const Expression::Ptr& aexpr = arr->Get(index); const Expression::Ptr& aexpr = arr->Get(index);
result->Add(aexpr->Evaluate(locals)); result->Add(aexpr->Evaluate(context));
} }
} }
return result; return result;
} }
Value Expression::OpDict(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpDict(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
Array::Ptr arr = expr->m_Operand1; Array::Ptr arr = expr->m_Operand1;
bool in_place = expr->m_Operand2; bool in_place = expr->m_Operand2;
Dictionary::Ptr result = make_shared<Dictionary>(); Dictionary::Ptr result = make_shared<Dictionary>();
result->Set("__parent", locals); result->Set("__parent", context);
if (arr) { if (arr) {
for (Array::SizeType index = 0; index < arr->GetLength(); index++) { for (Array::SizeType index = 0; index < arr->GetLength(); index++) {
const Expression::Ptr& aexpr = arr->Get(index); const Expression::Ptr& aexpr = arr->Get(index);
Dictionary::Ptr alocals = in_place ? locals : result; Object::Ptr acontext = in_place ? context : result;
aexpr->Evaluate(alocals, dhint); aexpr->Evaluate(acontext, dhint);
if (alocals->Contains("__result")) if (HasField(acontext, "__result"))
break; break;
} }
} }
@ -310,7 +311,7 @@ Value Expression::OpDict(const Expression *expr, const Dictionary::Ptr& locals,
return xresult; return xresult;
} }
Value Expression::OpSet(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpSet(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
Array::Ptr left = expr->m_Operand1; Array::Ptr left = expr->m_Operand1;
Array::Ptr indexer = left->Get(0); Array::Ptr indexer = left->Get(0);
@ -323,14 +324,14 @@ Value Expression::OpSet(const Expression *expr, const Dictionary::Ptr& locals, D
for (Array::SizeType i = 0; i < indexer->GetLength(); i++) { for (Array::SizeType i = 0; i < indexer->GetLength(); i++) {
Expression::Ptr indexExpr = indexer->Get(i); Expression::Ptr indexExpr = indexer->Get(i);
String tempindex = indexExpr->Evaluate(locals, dhint); String tempindex = indexExpr->Evaluate(context, dhint);
if (i == indexer->GetLength() - 1) if (i == indexer->GetLength() - 1)
index = tempindex; index = tempindex;
if (i == 0) { if (i == 0) {
parent = locals; parent = context;
object = locals->Get(tempindex); object = GetField(context, tempindex);
} else { } else {
parent = object; parent = object;
@ -338,7 +339,7 @@ Value Expression::OpSet(const Expression *expr, const Dictionary::Ptr& locals, D
Expression::Ptr eindex = make_shared<Expression>(&Expression::OpLiteral, tempindex, expr->m_DebugInfo); Expression::Ptr eindex = make_shared<Expression>(&Expression::OpLiteral, tempindex, expr->m_DebugInfo);
Expression::Ptr eip = make_shared<Expression>(&Expression::OpIndexer, eparent, eindex, expr->m_DebugInfo); Expression::Ptr eip = make_shared<Expression>(&Expression::OpIndexer, eparent, eindex, expr->m_DebugInfo);
object = eip->Evaluate(locals, dhint); object = eip->Evaluate(context, dhint);
} }
if (sdhint) if (sdhint)
@ -347,12 +348,11 @@ Value Expression::OpSet(const Expression *expr, const Dictionary::Ptr& locals, D
if (i != indexer->GetLength() - 1 && object.IsEmpty()) { if (i != indexer->GetLength() - 1 && object.IsEmpty()) {
object = make_shared<Dictionary>(); object = make_shared<Dictionary>();
Dictionary::Ptr pdict = parent; SetField(parent, tempindex, object);
pdict->Set(tempindex, object);
} }
} }
Value right = expr->EvaluateOperand2(locals, dhint); Value right = expr->EvaluateOperand2(context, dhint);
if (csop != OpSetLiteral) { if (csop != OpSetLiteral) {
Expression::OpCallback op; Expression::OpCallback op;
@ -379,11 +379,10 @@ Value Expression::OpSet(const Expression *expr, const Dictionary::Ptr& locals, D
make_shared<Expression>(&Expression::OpLiteral, right, expr->m_DebugInfo), make_shared<Expression>(&Expression::OpLiteral, right, expr->m_DebugInfo),
expr->m_DebugInfo); expr->m_DebugInfo);
right = ecp->Evaluate(locals, dhint); right = ecp->Evaluate(context, dhint);
} }
Dictionary::Ptr pdict = parent; SetField(parent, index, right);
pdict->Set(index, right);
if (sdhint) if (sdhint)
sdhint->AddMessage("=", expr->m_DebugInfo); sdhint->AddMessage("=", expr->m_DebugInfo);
@ -391,10 +390,10 @@ Value Expression::OpSet(const Expression *expr, const Dictionary::Ptr& locals, D
return right; return right;
} }
Value Expression::OpIndexer(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpIndexer(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
Value value = expr->EvaluateOperand1(locals); Value value = expr->EvaluateOperand1(context);
Value index = expr->EvaluateOperand2(locals); Value index = expr->EvaluateOperand2(context);
if (value.IsObjectType<Dictionary>()) { if (value.IsObjectType<Dictionary>()) {
Dictionary::Ptr dict = value; Dictionary::Ptr dict = value;
@ -422,44 +421,44 @@ Value Expression::OpIndexer(const Expression *expr, const Dictionary::Ptr& local
} }
} }
Value Expression::OpImport(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpImport(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
{ {
Value type = expr->EvaluateOperand1(locals); Value type = expr->EvaluateOperand1(context);
Value name = expr->EvaluateOperand2(locals); Value name = expr->EvaluateOperand2(context);
ConfigItem::Ptr item = ConfigItem::GetObject(type, name); ConfigItem::Ptr item = ConfigItem::GetObject(type, name);
if (!item) if (!item)
BOOST_THROW_EXCEPTION(ConfigError("Import references unknown template: '" + name + "'")); BOOST_THROW_EXCEPTION(ConfigError("Import references unknown template: '" + name + "'"));
item->GetExpressionList()->Evaluate(locals, dhint); item->GetExpressionList()->Evaluate(context, dhint);
return Empty; return Empty;
} }
Value Expression::FunctionWrapper(const std::vector<Value>& arguments, const Array::Ptr& funcargs, const Expression::Ptr& expr, const Dictionary::Ptr& scope) Value Expression::FunctionWrapper(const std::vector<Value>& arguments, const Array::Ptr& funcargs, const Expression::Ptr& expr, const Object::Ptr& scope)
{ {
if (arguments.size() < funcargs->GetLength()) if (arguments.size() < funcargs->GetLength())
BOOST_THROW_EXCEPTION(ConfigError("Too few arguments for function")); BOOST_THROW_EXCEPTION(ConfigError("Too few arguments for function"));
Dictionary::Ptr locals = make_shared<Dictionary>(); Dictionary::Ptr context = make_shared<Dictionary>();
locals->Set("__parent", scope); context->Set("__parent", scope);
for (std::vector<Value>::size_type i = 0; i < std::min(arguments.size(), funcargs->GetLength()); i++) for (std::vector<Value>::size_type i = 0; i < std::min(arguments.size(), funcargs->GetLength()); i++)
locals->Set(funcargs->Get(i), arguments[i]); context->Set(funcargs->Get(i), arguments[i]);
expr->Evaluate(locals); expr->Evaluate(context);
return locals->Get("__result"); return context->Get("__result");
} }
Value Expression::OpFunction(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpFunction(const Expression* expr, const Object::Ptr& context, DebugHint *dhint)
{ {
Array::Ptr left = expr->m_Operand1; Array::Ptr left = expr->m_Operand1;
Expression::Ptr aexpr = left->Get(1); Expression::Ptr aexpr = left->Get(1);
String name = left->Get(0); String name = left->Get(0);
Array::Ptr funcargs = expr->m_Operand2; Array::Ptr funcargs = expr->m_Operand2;
ScriptFunction::Ptr func = make_shared<ScriptFunction>(boost::bind(&Expression::FunctionWrapper, _1, funcargs, aexpr, locals)); ScriptFunction::Ptr func = make_shared<ScriptFunction>(boost::bind(&Expression::FunctionWrapper, _1, funcargs, aexpr, context));
if (!name.IsEmpty()) if (!name.IsEmpty())
ScriptFunction::Register(name, func); ScriptFunction::Register(name, func);
@ -467,7 +466,7 @@ Value Expression::OpFunction(const Expression* expr, const Dictionary::Ptr& loca
return func; return func;
} }
Value Expression::OpApply(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpApply(const Expression* expr, const Object::Ptr& context, DebugHint *dhint)
{ {
Array::Ptr left = expr->m_Operand1; Array::Ptr left = expr->m_Operand1;
Expression::Ptr exprl = expr->m_Operand2; Expression::Ptr exprl = expr->m_Operand2;
@ -479,14 +478,14 @@ Value Expression::OpApply(const Expression* expr, const Dictionary::Ptr& locals,
String fvvar = left->Get(5); String fvvar = left->Get(5);
Expression::Ptr fterm = left->Get(6); Expression::Ptr fterm = left->Get(6);
String name = aname->Evaluate(locals, dhint); String name = aname->Evaluate(context, dhint);
ApplyRule::AddRule(type, target, name, exprl, filter, fkvar, fvvar, fterm, expr->m_DebugInfo, locals); ApplyRule::AddRule(type, target, name, exprl, filter, fkvar, fvvar, fterm, expr->m_DebugInfo, context);
return Empty; return Empty;
} }
Value Expression::OpObject(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpObject(const Expression* expr, const Object::Ptr& context, DebugHint *dhint)
{ {
Array::Ptr left = expr->m_Operand1; Array::Ptr left = expr->m_Operand1;
Expression::Ptr exprl = expr->m_Operand2; Expression::Ptr exprl = expr->m_Operand2;
@ -496,7 +495,7 @@ Value Expression::OpObject(const Expression* expr, const Dictionary::Ptr& locals
Expression::Ptr filter = left->Get(3); Expression::Ptr filter = left->Get(3);
String zone = left->Get(4); String zone = left->Get(4);
String name = aname->Evaluate(locals, dhint); String name = aname->Evaluate(context, dhint);
ConfigItemBuilder::Ptr item = make_shared<ConfigItemBuilder>(expr->m_DebugInfo); ConfigItemBuilder::Ptr item = make_shared<ConfigItemBuilder>(expr->m_DebugInfo);
@ -531,16 +530,16 @@ Value Expression::OpObject(const Expression* expr, const Dictionary::Ptr& locals
item->AddExpression(exprl); item->AddExpression(exprl);
item->SetAbstract(abstract); item->SetAbstract(abstract);
item->SetScope(locals); item->SetScope(context);
item->SetZone(zone); item->SetZone(zone);
item->Compile()->Register(); item->Compile()->Register();
ObjectRule::AddRule(type, name, exprl, filter, expr->m_DebugInfo, locals); ObjectRule::AddRule(type, name, exprl, filter, expr->m_DebugInfo, context);
return Empty; return Empty;
} }
Value Expression::OpFor(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpFor(const Expression* expr, const Object::Ptr& context, DebugHint *dhint)
{ {
Array::Ptr left = expr->m_Operand1; Array::Ptr left = expr->m_Operand1;
String kvar = left->Get(0); String kvar = left->Get(0);
@ -548,7 +547,7 @@ Value Expression::OpFor(const Expression* expr, const Dictionary::Ptr& locals, D
Expression::Ptr aexpr = left->Get(2); Expression::Ptr aexpr = left->Get(2);
Expression::Ptr ascope = expr->m_Operand2; Expression::Ptr ascope = expr->m_Operand2;
Value value = aexpr->Evaluate(locals, dhint); Value value = aexpr->Evaluate(context, dhint);
if (value.IsObjectType<Array>()) { if (value.IsObjectType<Array>()) {
if (!vvar.IsEmpty()) if (!vvar.IsEmpty())
@ -558,11 +557,11 @@ Value Expression::OpFor(const Expression* expr, const Dictionary::Ptr& locals, D
ObjectLock olock(arr); ObjectLock olock(arr);
BOOST_FOREACH(const Value& value, arr) { BOOST_FOREACH(const Value& value, arr) {
Dictionary::Ptr xlocals = make_shared<Dictionary>(); Dictionary::Ptr xcontext = make_shared<Dictionary>();
xlocals->Set("__parent", locals); xcontext->Set("__parent", context);
xlocals->Set(kvar, value); xcontext->Set(kvar, value);
ascope->Evaluate(xlocals, dhint); ascope->Evaluate(xcontext, dhint);
} }
} else if (value.IsObjectType<Dictionary>()) { } else if (value.IsObjectType<Dictionary>()) {
if (vvar.IsEmpty()) if (vvar.IsEmpty())
@ -572,12 +571,12 @@ Value Expression::OpFor(const Expression* expr, const Dictionary::Ptr& locals, D
ObjectLock olock(dict); ObjectLock olock(dict);
BOOST_FOREACH(const Dictionary::Pair& kv, dict) { BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
Dictionary::Ptr xlocals = make_shared<Dictionary>(); Dictionary::Ptr xcontext = make_shared<Dictionary>();
xlocals->Set("__parent", locals); xcontext->Set("__parent", context);
xlocals->Set(kvar, kv.first); xcontext->Set(kvar, kv.first);
xlocals->Set(vvar, kv.second); xcontext->Set(vvar, kv.second);
ascope->Evaluate(xlocals, dhint); ascope->Evaluate(xcontext, dhint);
} }
} else } else
BOOST_THROW_EXCEPTION(ConfigError("Invalid type in __for expression: " + value.GetTypeName()) << errinfo_debuginfo(expr->m_DebugInfo)); BOOST_THROW_EXCEPTION(ConfigError("Invalid type in __for expression: " + value.GetTypeName()) << errinfo_debuginfo(expr->m_DebugInfo));
@ -620,3 +619,68 @@ Expression::Ptr icinga::MakeLiteral(const Value& lit)
{ {
return make_shared<Expression>(&Expression::OpLiteral, lit, DebugInfo()); return make_shared<Expression>(&Expression::OpLiteral, lit, DebugInfo());
} }
bool Expression::HasField(const Object::Ptr& context, const String& field)
{
Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(context);
if (dict)
return dict->Contains(field);
else {
Type::Ptr type = context->GetReflectionType();
if (!type)
return false;
return type->GetFieldId(field) != -1;
}
}
Value Expression::GetField(const Object::Ptr& context, const String& field)
{
Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(context);
if (dict)
return dict->Get(field);
else {
Type::Ptr type = context->GetReflectionType();
if (!type)
return Empty;
int fid = type->GetFieldId(field);
if (fid == -1)
return Empty;
return context->GetField(fid);
}
}
void Expression::SetField(const Object::Ptr& context, const String& field, const Value& value)
{
Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(context);
if (dict)
dict->Set(field, value);
else {
Type::Ptr type = context->GetReflectionType();
if (!type)
BOOST_THROW_EXCEPTION(ConfigError("Cannot set field on object."));
int fid = type->GetFieldId(field);
if (fid == -1)
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' does not exist."));
try {
context->SetField(fid, value);
} catch (const boost::bad_lexical_cast&) {
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "'"));
} catch (const std::bad_cast&) {
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "'"));
}
}
}

View File

@ -63,49 +63,49 @@ class I2_CONFIG_API Expression : public Object
public: public:
DECLARE_PTR_TYPEDEFS(Expression); DECLARE_PTR_TYPEDEFS(Expression);
typedef Value (*OpCallback)(const Expression *, const Dictionary::Ptr&, DebugHint *dhint); typedef Value (*OpCallback)(const Expression *, const Object::Ptr&, DebugHint *dhint);
Expression(OpCallback op, const Value& operand1, const DebugInfo& di); Expression(OpCallback op, const Value& operand1, const DebugInfo& di);
Expression(OpCallback op, const Value& operand1, const Value& operand2, const DebugInfo& di); Expression(OpCallback op, const Value& operand1, const Value& operand2, const DebugInfo& di);
Value Evaluate(const Dictionary::Ptr& locals, DebugHint *dhint = NULL) const; Value Evaluate(const Object::Ptr& context, DebugHint *dhint = NULL) const;
void MakeInline(void); void MakeInline(void);
void Dump(std::ostream& stream, int indent = 0) const; void Dump(std::ostream& stream, int indent = 0) const;
static Value OpLiteral(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpLiteral(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpVariable(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpVariable(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpNegate(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpNegate(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpLogicalNegate(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpLogicalNegate(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpAdd(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpAdd(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpSubtract(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpSubtract(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpMultiply(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpMultiply(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpDivide(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpDivide(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpBinaryAnd(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpBinaryAnd(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpBinaryOr(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpBinaryOr(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpShiftLeft(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpShiftLeft(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpShiftRight(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpShiftRight(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpEqual(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpNotEqual(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpNotEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpLessThan(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpLessThan(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpGreaterThan(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpGreaterThan(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpLessThanOrEqual(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpLessThanOrEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpGreaterThanOrEqual(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpGreaterThanOrEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpIn(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpIn(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpNotIn(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpNotIn(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpLogicalAnd(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpLogicalAnd(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpLogicalOr(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpLogicalOr(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpFunctionCall(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpFunctionCall(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpArray(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpArray(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpDict(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpDict(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpSet(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpSet(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpIndexer(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpIndexer(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpImport(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpImport(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpFunction(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpFunction(const Expression* expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpApply(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpApply(const Expression* expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpObject(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpObject(const Expression* expr, const Object::Ptr& context, DebugHint *dhint);
static Value OpFor(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpFor(const Expression* expr, const Object::Ptr& context, DebugHint *dhint);
private: private:
OpCallback m_Operator; OpCallback m_Operator;
@ -113,13 +113,17 @@ private:
Value m_Operand2; Value m_Operand2;
DebugInfo m_DebugInfo; DebugInfo m_DebugInfo;
Value EvaluateOperand1(const Dictionary::Ptr& locals, DebugHint *dhint = NULL) const; Value EvaluateOperand1(const Object::Ptr& context, DebugHint *dhint = NULL) const;
Value EvaluateOperand2(const Dictionary::Ptr& locals, DebugHint *dhint = NULL) const; Value EvaluateOperand2(const Object::Ptr& context, DebugHint *dhint = NULL) const;
static void DumpOperand(std::ostream& stream, const Value& operand, int indent); static void DumpOperand(std::ostream& stream, const Value& operand, int indent);
static Value FunctionWrapper(const std::vector<Value>& arguments, const Array::Ptr& funcargs, static Value FunctionWrapper(const std::vector<Value>& arguments, const Array::Ptr& funcargs,
const Expression::Ptr& expr, const Dictionary::Ptr& scope); const Expression::Ptr& expr, const Object::Ptr& scope);
static bool HasField(const Object::Ptr& context, const String& field);
static Value GetField(const Object::Ptr& context, const String& field);
static void SetField(const Object::Ptr& context, const String& field, const Value& value);
}; };
I2_CONFIG_API Expression::Ptr MakeLiteral(const Value& lit = Value()); I2_CONFIG_API Expression::Ptr MakeLiteral(const Value& lit = Value());

View File

@ -27,7 +27,7 @@ ObjectRule::RuleMap ObjectRule::m_Rules;
ObjectRule::CallbackMap ObjectRule::m_Callbacks; ObjectRule::CallbackMap ObjectRule::m_Callbacks;
ObjectRule::ObjectRule(const String& name, const Expression::Ptr& expression, ObjectRule::ObjectRule(const String& name, const Expression::Ptr& expression,
const Expression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope) const Expression::Ptr& filter, const DebugInfo& di, const Object::Ptr& scope)
: m_Name(name), m_Expression(expression), m_Filter(filter), m_DebugInfo(di), m_Scope(scope) : m_Name(name), m_Expression(expression), m_Filter(filter), m_DebugInfo(di), m_Scope(scope)
{ } { }
@ -51,19 +51,19 @@ DebugInfo ObjectRule::GetDebugInfo(void) const
return m_DebugInfo; return m_DebugInfo;
} }
Dictionary::Ptr ObjectRule::GetScope(void) const Object::Ptr ObjectRule::GetScope(void) const
{ {
return m_Scope; return m_Scope;
} }
void ObjectRule::AddRule(const String& sourceType, const String& name, void ObjectRule::AddRule(const String& sourceType, const String& name,
const Expression::Ptr& expression, const Expression::Ptr& filter, const Expression::Ptr& expression, const Expression::Ptr& filter,
const DebugInfo& di, const Dictionary::Ptr& scope) const DebugInfo& di, const Object::Ptr& scope)
{ {
m_Rules[sourceType].push_back(ObjectRule(name, expression, filter, di, scope)); m_Rules[sourceType].push_back(ObjectRule(name, expression, filter, di, scope));
} }
bool ObjectRule::EvaluateFilter(const Dictionary::Ptr& scope) const bool ObjectRule::EvaluateFilter(const Object::Ptr& scope) const
{ {
return m_Filter->Evaluate(scope); return m_Filter->Evaluate(scope);
} }

View File

@ -42,12 +42,12 @@ public:
Expression::Ptr GetExpression(void) const; Expression::Ptr GetExpression(void) const;
Expression::Ptr GetFilter(void) const; Expression::Ptr GetFilter(void) const;
DebugInfo GetDebugInfo(void) const; DebugInfo GetDebugInfo(void) const;
Dictionary::Ptr GetScope(void) const; Object::Ptr GetScope(void) const;
bool EvaluateFilter(const Dictionary::Ptr& scope) const; bool EvaluateFilter(const Object::Ptr& scope) const;
static void AddRule(const String& sourceType, const String& name, const Expression::Ptr& expression, static void AddRule(const String& sourceType, const String& name, const Expression::Ptr& expression,
const Expression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope); const Expression::Ptr& filter, const DebugInfo& di, const Object::Ptr& scope);
static void EvaluateRules(bool clear); static void EvaluateRules(bool clear);
static void RegisterType(const String& sourceType, const ObjectRule::Callback& callback); static void RegisterType(const String& sourceType, const ObjectRule::Callback& callback);
@ -58,13 +58,13 @@ private:
Expression::Ptr m_Expression; Expression::Ptr m_Expression;
Expression::Ptr m_Filter; Expression::Ptr m_Filter;
DebugInfo m_DebugInfo; DebugInfo m_DebugInfo;
Dictionary::Ptr m_Scope; Object::Ptr m_Scope;
static CallbackMap m_Callbacks; static CallbackMap m_Callbacks;
static RuleMap m_Rules; static RuleMap m_Rules;
ObjectRule(const String& name, const Expression::Ptr& expression, ObjectRule(const String& name, const Expression::Ptr& expression,
const Expression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope); const Expression::Ptr& filter, const DebugInfo& di, const Object::Ptr& scope);
}; };
} }

View File

@ -86,6 +86,9 @@ bool TypeRule::MatchValue(const Value& value, String *hint, const TypeRuleUtilit
bool TypeRuleUtilities::ValidateName(const String& type, const String& name, String *hint) const bool TypeRuleUtilities::ValidateName(const String& type, const String& name, String *hint) const
{ {
if (name.IsEmpty())
return true;
ConfigItem::Ptr item = ConfigItem::GetObject(type, name); ConfigItem::Ptr item = ConfigItem::GetObject(type, name);
if (!item) { if (!item) {

View File

@ -46,7 +46,7 @@ void Command::SetModifiedAttributes(int flags, const MessageOrigin& origin)
void Command::ValidateAttributes(const String& location, const Dictionary::Ptr& attrs) void Command::ValidateAttributes(const String& location, const Dictionary::Ptr& attrs)
{ {
if (attrs->Contains("arguments") && !attrs->Get("command").IsObjectType<Array>()) { if (attrs->Get("arguments") != Empty && !attrs->Get("command").IsObjectType<Array>()) {
ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " + ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
location + ": Attribute 'command' must be an array if the 'arguments' attribute is set."); location + ": Attribute 'command' must be an array if the 'arguments' attribute is set.");
} }

View File

@ -87,7 +87,6 @@ void Dependency::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, c
builder->AddExpression(rule.GetExpression()); builder->AddExpression(rule.GetExpression());
ConfigItem::Ptr dependencyItem = builder->Compile(); ConfigItem::Ptr dependencyItem = builder->Compile();
dependencyItem->Register();
DynamicObject::Ptr dobj = dependencyItem->Commit(); DynamicObject::Ptr dobj = dependencyItem->Commit();
dobj->OnConfigLoaded(); dobj->OnConfigLoaded();

View File

@ -29,15 +29,17 @@ using namespace icinga;
REGISTER_TYPE(Dependency); REGISTER_TYPE(Dependency);
REGISTER_SCRIPTFUNCTION(ValidateDependencyFilters, &Dependency::ValidateFilters); REGISTER_SCRIPTFUNCTION(ValidateDependencyFilters, &Dependency::ValidateFilters);
String DependencyNameComposer::MakeName(const String& shortName, const Dictionary::Ptr& props) const String DependencyNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const
{ {
if (!props) Dependency::Ptr dependency = dynamic_pointer_cast<Dependency>(context);
if (!dependency)
return ""; return "";
String name = props->Get("child_host_name"); String name = dependency->GetChildHostName();
if (props->Contains("child_service_name")) if (!dependency->GetChildServiceName().IsEmpty())
name += "!" + props->Get("child_service_name"); name += "!" + dependency->GetChildServiceName();
name += "!" + shortName; name += "!" + shortName;
@ -205,12 +207,12 @@ void Dependency::ValidateFilters(const String& location, const Dictionary::Ptr&
{ {
int sfilter = FilterArrayToInt(attrs->Get("state_filter"), 0); int sfilter = FilterArrayToInt(attrs->Get("state_filter"), 0);
if (!attrs->Contains("parent_service_name") && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) { if (attrs->Get("parent_service_name") == Empty && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) {
ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " + ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
location + ": State filter is invalid for host dependency."); location + ": State filter is invalid for host dependency.");
} }
if (attrs->Contains("parent_service_name") && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) { if (attrs->Get("parent_service_name") != Empty && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) {
ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " + ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
location + ": State filter is invalid for service dependency."); location + ": State filter is invalid for service dependency.");
} }

View File

@ -27,7 +27,7 @@ code {{{
class I2_ICINGA_API DependencyNameComposer : public NameComposer class I2_ICINGA_API DependencyNameComposer : public NameComposer
{ {
public: public:
virtual String MakeName(const String& shortName, const Dictionary::Ptr& props) const; virtual String MakeName(const String& shortName, const Object::Ptr& context) const;
}; };
}}} }}}

View File

@ -82,7 +82,6 @@ void Notification::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable,
builder->AddExpression(rule.GetExpression()); builder->AddExpression(rule.GetExpression());
ConfigItem::Ptr notificationItem = builder->Compile(); ConfigItem::Ptr notificationItem = builder->Compile();
notificationItem->Register();
DynamicObject::Ptr dobj = notificationItem->Commit(); DynamicObject::Ptr dobj = notificationItem->Commit();
dobj->OnConfigLoaded(); dobj->OnConfigLoaded();

View File

@ -39,15 +39,17 @@ INITIALIZE_ONCE(&Notification::StaticInitialize);
boost::signals2::signal<void (const Notification::Ptr&, double, const MessageOrigin&)> Notification::OnNextNotificationChanged; boost::signals2::signal<void (const Notification::Ptr&, double, const MessageOrigin&)> Notification::OnNextNotificationChanged;
String NotificationNameComposer::MakeName(const String& shortName, const Dictionary::Ptr& props) const String NotificationNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const
{ {
if (!props) Notification::Ptr notification = dynamic_pointer_cast<Notification>(context);
if (!notification)
return ""; return "";
String name = props->Get("host_name"); String name = notification->GetHostName();
if (props->Contains("service_name")) if (!notification->GetServiceName().IsEmpty())
name += "!" + props->Get("service_name"); name += "!" + notification->GetServiceName();
name += "!" + shortName; name += "!" + shortName;
@ -450,12 +452,12 @@ void Notification::ValidateFilters(const String& location, const Dictionary::Ptr
{ {
int sfilter = FilterArrayToInt(attrs->Get("states"), 0); int sfilter = FilterArrayToInt(attrs->Get("states"), 0);
if (!attrs->Contains("service_name") && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) { if (attrs->Get("service_name") == Empty && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) {
ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " + ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
location + ": State filter is invalid."); location + ": State filter is invalid.");
} }
if (attrs->Contains("service_name") && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) { if (attrs->Get("service_name") != Empty && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) {
ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " + ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
location + ": State filter is invalid."); location + ": State filter is invalid.");
} }

View File

@ -26,7 +26,7 @@ code {{{
class I2_ICINGA_API NotificationNameComposer : public NameComposer class I2_ICINGA_API NotificationNameComposer : public NameComposer
{ {
public: public:
virtual String MakeName(const String& shortName, const Dictionary::Ptr& props) const; virtual String MakeName(const String& shortName, const Object::Ptr& context) const;
}; };
}}} }}}

View File

@ -81,7 +81,6 @@ void ScheduledDowntime::EvaluateApplyRuleOneInstance(const Checkable::Ptr& check
builder->AddExpression(rule.GetExpression()); builder->AddExpression(rule.GetExpression());
ConfigItem::Ptr downtimeItem = builder->Compile(); ConfigItem::Ptr downtimeItem = builder->Compile();
downtimeItem->Register();
DynamicObject::Ptr dobj = downtimeItem->Commit(); DynamicObject::Ptr dobj = downtimeItem->Commit();
dobj->OnConfigLoaded(); dobj->OnConfigLoaded();
} }

View File

@ -39,15 +39,17 @@ INITIALIZE_ONCE(&ScheduledDowntime::StaticInitialize);
static Timer::Ptr l_Timer; static Timer::Ptr l_Timer;
String ScheduledDowntimeNameComposer::MakeName(const String& shortName, const Dictionary::Ptr& props) const String ScheduledDowntimeNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const
{ {
if (!props) ScheduledDowntime::Ptr downtime = dynamic_pointer_cast<ScheduledDowntime>(context);
if (!downtime)
return ""; return "";
String name = props->Get("host_name"); String name = downtime->GetHostName();
if (props->Contains("service_name")) if (!downtime->GetServiceName().IsEmpty())
name += "!" + props->Get("service_name"); name += "!" + downtime->GetServiceName();
name += "!" + shortName; name += "!" + shortName;

View File

@ -26,7 +26,7 @@ code {{{
class I2_ICINGA_API ScheduledDowntimeNameComposer : public NameComposer class I2_ICINGA_API ScheduledDowntimeNameComposer : public NameComposer
{ {
public: public:
virtual String MakeName(const String& shortName, const Dictionary::Ptr& props) const; virtual String MakeName(const String& shortName, const Object::Ptr& context) const;
}; };
}}} }}}

View File

@ -74,7 +74,6 @@ void Service::EvaluateApplyRuleOneInstance(const Host::Ptr& host, const String&
builder->AddExpression(rule.GetExpression()); builder->AddExpression(rule.GetExpression());
ConfigItem::Ptr serviceItem = builder->Compile(); ConfigItem::Ptr serviceItem = builder->Compile();
serviceItem->Register();
DynamicObject::Ptr dobj = serviceItem->Commit(); DynamicObject::Ptr dobj = serviceItem->Commit();
dobj->OnConfigLoaded(); dobj->OnConfigLoaded();
} }

View File

@ -30,11 +30,14 @@ using namespace icinga;
REGISTER_TYPE(Service); REGISTER_TYPE(Service);
String ServiceNameComposer::MakeName(const String& shortName, const Dictionary::Ptr& props) const { String ServiceNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const
if (!props) {
Service::Ptr service = dynamic_pointer_cast<Service>(context);
if (!service)
return ""; return "";
return props->Get("host_name") + "!" + shortName; return service->GetHostName() + "!" + shortName;
} }
void Service::OnConfigLoaded(void) void Service::OnConfigLoaded(void)

View File

@ -29,7 +29,7 @@ code {{{
class I2_ICINGA_API ServiceNameComposer : public NameComposer class I2_ICINGA_API ServiceNameComposer : public NameComposer
{ {
public: public:
virtual String MakeName(const String& shortName, const Dictionary::Ptr& props) const; virtual String MakeName(const String& shortName, const Object::Ptr& context) const;
}; };
}}} }}}

View File

@ -514,6 +514,12 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
} }
} }
if (klass.Name == "DynamicObject")
std::cout << "\t" << "friend class ConfigItem;" << std::endl;
if (!klass.TypeBase.empty())
std::cout << "\t" << "friend class " << klass.TypeBase << ";" << std::endl;
std::cout << "};" << std::endl << std::endl; std::cout << "};" << std::endl << std::endl;
} }