ApplyRule::CallbackMap ApplyRule::m_Callbacks;
ApplyRule::ApplyRule(const String& targetType, const String& name, const Expression::Ptr& expression,
- const Expression::Ptr& filter, const String& fvar, 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)
- : m_TargetType(targetType), m_Name(name), m_Expression(expression), m_Filter(filter), m_FVar(fvar),
- m_FTerm(fterm), m_DebugInfo(di), m_Scope(scope)
+ : 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)
{ }
String ApplyRule::GetTargetType(void) const
return m_Filter;
}
-String ApplyRule::GetFVar(void) const
+String ApplyRule::GetFKVar(void) const
{
- return m_FVar;
+ return m_FKVar;
+}
+
+String ApplyRule::GetFVVar(void) const
+{
+ return m_FVVar;
}
Expression::Ptr ApplyRule::GetFTerm(void) const
}
void ApplyRule::AddRule(const String& sourceType, const String& targetType, const String& name,
- const Expression::Ptr& expression, const Expression::Ptr& filter, const String& fvar,
- const Expression::Ptr& fterm, const DebugInfo& di, const Dictionary::Ptr& scope)
+ 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)
{
- m_Rules[sourceType].push_back(ApplyRule(targetType, name, expression, filter, fvar, 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
String GetName(void) const;
Expression::Ptr GetExpression(void) const;
Expression::Ptr GetFilter(void) const;
- String GetFVar(void) const;
+ String GetFKVar(void) const;
+ String GetFVVar(void) const;
Expression::Ptr GetFTerm(void) const;
DebugInfo GetDebugInfo(void) const;
Dictionary::Ptr GetScope(void) const;
bool EvaluateFilter(const Dictionary::Ptr& scope) const;
static void AddRule(const String& sourceType, const String& targetType, const String& name, const Expression::Ptr& expression,
- const Expression::Ptr& filter, const String& fvar, 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 Dictionary::Ptr& scope);
static void EvaluateRules(bool clear);
static void RegisterType(const String& sourceType, const std::vector<String>& targetTypes, const ApplyRule::Callback& callback);
String m_Name;
Expression::Ptr m_Expression;
Expression::Ptr m_Filter;
- String m_FVar;
+ String m_FKVar;
+ String m_FVVar;
Expression::Ptr m_FTerm;
DebugInfo m_DebugInfo;
Dictionary::Ptr m_Scope;
static RuleMap m_Rules;
ApplyRule(const String& targetType, const String& name, const Expression::Ptr& expression,
- const Expression::Ptr& filter, const String& fvar, 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);
};
%attribute %dictionary "methods",
- %attribute %dictionary "vars" {
- %attribute %string "*",
- %attribute %array "*" {
- %attribute %string "*"
- }
- },
+ %attribute %dictionary "vars"
}
%type Logger {
import return T_IMPORT;
assign return T_ASSIGN;
ignore return T_IGNORE;
+for return T_APPLY_FOR;
__function return T_FUNCTION;
__return return T_RETURN;
__for return T_FOR;
+=\> return T_FOLLOWS;
\<\< { yylval->op = &Expression::OpShiftLeft; return T_SHIFT_LEFT; }
\>\> { yylval->op = &Expression::OpShiftRight; return T_SHIFT_RIGHT; }
\<= { yylval->op = &Expression::OpLessThanOrEqual; return T_LESS_THAN_OR_EQUAL; }
%token T_IMPORT "import (T_IMPORT)"
%token T_ASSIGN "assign (T_ASSIGN)"
%token T_IGNORE "ignore (T_IGNORE)"
+%token T_APPLY_FOR "for (T_APPLY_FOR)"
%token T_FUNCTION "function (T_FUNCTION)"
%token T_RETURN "return (T_RETURN)"
%token T_FOR "for (T_FOR)"
+%token T_FOLLOWS "=> (T_FOLLOWS)"
%type <text> identifier
%type <array> rterm_items
%type <variant> lterm
%type <variant> object
%type <variant> apply
+%type <variant> optional_rterm
%type <text> target_type_specifier
%left T_LOGICAL_OR
static std::stack<bool> m_SeenAssign;
static std::stack<Expression::Ptr> m_Assign;
static std::stack<Expression::Ptr> m_Ignore;
-static std::stack<String> m_FVar;
+static std::stack<String> m_FKVar;
+static std::stack<String> m_FVVar;
static std::stack<Expression::Ptr> m_FTerm;
void ConfigCompiler::Compile(void)
m_SeenAssign = std::stack<bool>();
m_Assign = std::stack<Expression::Ptr>();
m_Ignore = std::stack<Expression::Ptr>();
- m_FVar = std::stack<String>();
+ m_FKVar = std::stack<String>();
+ m_FVVar = std::stack<String>();
m_FTerm = std::stack<Expression::Ptr>();
try {
$$ = new Value(make_shared<Expression>(&Expression::OpFunction, arr, Array::Ptr($3), DebugInfoRange(@1, @5)));
}
+ | T_FOR '(' identifier T_FOLLOWS identifier T_IN rterm ')' rterm_scope
+ {
+ Array::Ptr arr = make_shared<Array>();
+
+ arr->Add($3);
+ free($3);
+
+ arr->Add($5);
+ free($5);
+
+ Expression::Ptr aexpr = *$7;
+ delete $7;
+ arr->Add(aexpr);
+
+ Expression::Ptr ascope = *$9;
+ delete $9;
+
+ $$ = new Value(make_shared<Expression>(&Expression::OpFor, arr, ascope, DebugInfoRange(@1, @9)));
+ }
| T_FOR '(' identifier T_IN rterm ')' rterm_scope
{
Array::Ptr arr = make_shared<Array>();
arr->Add($3);
free($3);
+ arr->Add(Empty);
+
Expression::Ptr aexpr = *$5;
delete $5;
arr->Add(aexpr);
;
apply_for_specifier: /* empty */
- | T_FOR '(' identifier T_IN rterm ')'
+ | T_APPLY_FOR '(' identifier T_FOLLOWS identifier T_IN rterm ')'
+ {
+ m_FKVar.top() = $3;
+ free($3);
+
+ m_FVVar.top() = $5;
+ free($5);
+
+ m_FTerm.top() = *$7;
+ delete $7;
+ }
+ | T_APPLY_FOR '(' identifier T_IN rterm ')'
{
- m_FVar.top() = $3;
+ m_FKVar.top() = $3;
free($3);
+ m_FVVar.top() = "";
+
m_FTerm.top() = *$5;
delete $5;
}
;
+optional_rterm: /* empty */
+ {
+ $$ = new Value(make_shared<Expression>(&Expression::OpLiteral, Empty, DebugInfo()));
+ }
+ | rterm
+ {
+ $$ = $1;
+ }
+ ;
+
apply:
{
m_Apply.push(true);
m_SeenAssign.push(false);
m_Assign.push(make_shared<Expression>(&Expression::OpLiteral, false, DebugInfo()));
m_Ignore.push(make_shared<Expression>(&Expression::OpLiteral, false, DebugInfo()));
- m_FVar.push("");
+ m_FKVar.push("");
+ m_FVVar.push("");
m_FTerm.push(Expression::Ptr());
}
- T_APPLY identifier rterm apply_for_specifier target_type_specifier rterm
+ T_APPLY identifier optional_rterm apply_for_specifier target_type_specifier rterm
{
m_Apply.pop();
Expression::Ptr filter = make_shared<Expression>(&Expression::OpLogicalAnd, m_Assign.top(), rex, DebugInfoRange(@2, @5));
m_Assign.pop();
- String fvar = m_FVar.top();
- m_FVar.pop();
+ String fkvar = m_FKVar.top();
+ m_FKVar.pop();
+
+ String fvvar = m_FVVar.top();
+ m_FVVar.pop();
Expression::Ptr fterm = m_FTerm.top();
m_FTerm.pop();
args->Add(target);
args->Add(aname);
args->Add(filter);
- args->Add(fvar);
+ args->Add(fkvar);
+ args->Add(fvvar);
args->Add(fterm);
$$ = new Value(make_shared<Expression>(&Expression::OpApply, args, exprl, DebugInfoRange(@2, @5)));
String target = left->Get(1);
Expression::Ptr aname = left->Get(2);
Expression::Ptr filter = left->Get(3);
- String fvar = left->Get(4);
- Expression::Ptr fterm = left->Get(5);
+ String fkvar = left->Get(4);
+ String fvvar = left->Get(5);
+ Expression::Ptr fterm = left->Get(6);
String name = aname->Evaluate(locals, dhint);
- ApplyRule::AddRule(type, target, name, exprl, filter, fvar, fterm, expr->m_DebugInfo, locals);
+ ApplyRule::AddRule(type, target, name, exprl, filter, fkvar, fvvar, fterm, expr->m_DebugInfo, locals);
return Empty;
}
Value Expression::OpFor(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint)
{
Array::Ptr left = expr->m_Operand1;
- String varname = left->Get(0);
- Expression::Ptr aexpr = left->Get(1);
+ String kvar = left->Get(0);
+ String vvar = left->Get(1);
+ Expression::Ptr aexpr = left->Get(2);
Expression::Ptr ascope = expr->m_Operand2;
- Array::Ptr arr = aexpr->Evaluate(locals, dhint);
+ Value value = aexpr->Evaluate(locals, dhint);
- ObjectLock olock(arr);
- BOOST_FOREACH(const Value& value, arr) {
- Dictionary::Ptr xlocals = make_shared<Dictionary>();
- xlocals->Set("__parent", locals);
- xlocals->Set(varname, value);
+ if (value.IsObjectType<Array>()) {
+ if (!vvar.IsEmpty())
+ BOOST_THROW_EXCEPTION(ConfigError("Cannot use dictionary iterator for array.") << errinfo_debuginfo(expr->m_DebugInfo));
- ascope->Evaluate(xlocals, dhint);
- }
+ Array::Ptr arr = value;
+
+ ObjectLock olock(arr);
+ BOOST_FOREACH(const Value& value, arr) {
+ Dictionary::Ptr xlocals = make_shared<Dictionary>();
+ xlocals->Set("__parent", locals);
+ xlocals->Set(kvar, value);
+
+ ascope->Evaluate(xlocals, dhint);
+ }
+ } else if (value.IsObjectType<Dictionary>()) {
+ if (vvar.IsEmpty())
+ BOOST_THROW_EXCEPTION(ConfigError("Cannot use array iterator for dictionary.") << errinfo_debuginfo(expr->m_DebugInfo));
+
+ Dictionary::Ptr dict = value;
+
+ ObjectLock olock(dict);
+ BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
+ Dictionary::Ptr xlocals = make_shared<Dictionary>();
+ xlocals->Set("__parent", locals);
+ xlocals->Set(kvar, kv.first);
+ xlocals->Set(vvar, kv.second);
+
+ ascope->Evaluate(xlocals, dhint);
+ }
+ } else
+ BOOST_THROW_EXCEPTION(ConfigError("Invalid type in __for expression: " + value.GetTypeName()) << errinfo_debuginfo(expr->m_DebugInfo));
return Empty;
}
ApplyRule::RegisterType("Dependency", targets, &Dependency::EvaluateApplyRules);
}
+void Dependency::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
+{
+ DebugInfo di = rule.GetDebugInfo();
+
+ Log(LogDebug, "Dependency")
+ << "Applying dependency '" << name << "' to object '" << checkable->GetName() << "' for rule " << di;
+
+ ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
+ builder->SetType("Dependency");
+ builder->SetName(name);
+ builder->SetScope(locals);
+
+ Host::Ptr host;
+ Service::Ptr service;
+ tie(host, service) = GetHostService(checkable);
+
+ builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
+ make_shared<Expression>(&Expression::OpLiteral, "parent_host_name", di),
+ make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
+ di));
+
+ builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
+ make_shared<Expression>(&Expression::OpLiteral, "child_host_name", di),
+ make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
+ di));
+
+ if (service) {
+ builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
+ make_shared<Expression>(&Expression::OpLiteral, "child_service_name", di),
+ make_shared<Expression>(&Expression::OpLiteral, service->GetShortName(), di),
+ di));
+ }
+
+ String zone = checkable->GetZone();
+
+ if (!zone.IsEmpty()) {
+ builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
+ make_shared<Expression>(&Expression::OpLiteral, "zone", di),
+ make_shared<Expression>(&Expression::OpLiteral, zone, di),
+ di));
+ }
+
+ builder->AddExpression(rule.GetExpression());
+
+ ConfigItem::Ptr dependencyItem = builder->Compile();
+ dependencyItem->Register();
+ DynamicObject::Ptr dobj = dependencyItem->Commit();
+ dobj->OnConfigLoaded();
+
+}
+
bool Dependency::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule)
{
DebugInfo di = rule.GetDebugInfo();
if (!rule.EvaluateFilter(locals))
return false;
- Array::Ptr instances;
+ Value vinstances;
if (rule.GetFTerm()) {
- Value vinstances = rule.GetFTerm()->Evaluate(locals);
-
- if (!vinstances.IsObjectType<Array>())
- BOOST_THROW_EXCEPTION(std::invalid_argument("for expression must be an array"));
-
- instances = vinstances;
+ vinstances = rule.GetFTerm()->Evaluate(locals);
} else {
- instances = make_shared<Array>();
+ Array::Ptr instances = make_shared<Array>();
instances->Add("");
+ vinstances = instances;
}
- ObjectLock olock(instances);
- BOOST_FOREACH(const String& instance, instances) {
- String objName = rule.GetName();
+ if (vinstances.IsObjectType<Array>()) {
+ if (!rule.GetFVVar().IsEmpty())
+ BOOST_THROW_EXCEPTION(ConfigError("Array iterator requires value to be an array.") << errinfo_debuginfo(di));
- if (!rule.GetFVar().IsEmpty()) {
- locals->Set(rule.GetFVar(), instance);
- objName += "-" + instance;
- }
+ Array::Ptr arr = vinstances;
- Log(LogDebug, "Dependency")
- << "Applying dependency '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di;
+ ObjectLock olock(arr);
+ BOOST_FOREACH(const String& instance, arr) {
+ String name = rule.GetName();
- ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
- builder->SetType("Dependency");
- builder->SetName(objName);
- builder->SetScope(locals);
-
- builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
- make_shared<Expression>(&Expression::OpLiteral, "parent_host_name", di),
- make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
- di));
-
- builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
- make_shared<Expression>(&Expression::OpLiteral, "child_host_name", di),
- make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
- di));
+ if (!rule.GetFKVar().IsEmpty()) {
+ locals->Set(rule.GetFKVar(), instance);
+ name += instance;
+ }
- if (service) {
- builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
- make_shared<Expression>(&Expression::OpLiteral, "child_service_name", di),
- make_shared<Expression>(&Expression::OpLiteral, service->GetShortName(), di),
- di));
+ EvaluateApplyRuleOneInstance(checkable, name, locals, rule);
}
-
- String zone = checkable->GetZone();
-
- if (!zone.IsEmpty()) {
- builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
- make_shared<Expression>(&Expression::OpLiteral, "zone", di),
- make_shared<Expression>(&Expression::OpLiteral, zone, di),
- di));
+ } else if (vinstances.IsObjectType<Dictionary>()) {
+ if (rule.GetFVVar().IsEmpty())
+ BOOST_THROW_EXCEPTION(ConfigError("Dictionary iterator requires value to be a dictionary.") << errinfo_debuginfo(di));
+
+ Dictionary::Ptr dict = vinstances;
+
+ ObjectLock olock(dict);
+ BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
+ locals->Set(rule.GetFKVar(), kv.first);
+ locals->Set(rule.GetFVVar(), kv.second);
+
+ EvaluateApplyRuleOneInstance(checkable, rule.GetName() + kv.first, locals, rule);
}
-
- builder->AddExpression(rule.GetExpression());
-
- ConfigItem::Ptr dependencyItem = builder->Compile();
- dependencyItem->Register();
- DynamicObject::Ptr dobj = dependencyItem->Commit();
- dobj->OnConfigLoaded();
}
return true;
Checkable::Ptr m_Parent;
Checkable::Ptr m_Child;
+ static void EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
static bool EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule);
static void EvaluateApplyRule(const ApplyRule& rule);
static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
ApplyRule::RegisterType("Notification", targets, &Notification::EvaluateApplyRules);
}
+void Notification::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
+{
+ DebugInfo di = rule.GetDebugInfo();
+
+ Log(LogDebug, "Notification")
+ << "Applying notification '" << name << "' to object '" << checkable->GetName() << "' for rule " << di;
+
+ ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
+ builder->SetType("Notification");
+ builder->SetName(name);
+ builder->SetScope(locals);
+
+ Host::Ptr host;
+ Service::Ptr service;
+ tie(host, service) = GetHostService(checkable);
+
+ builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
+ make_shared<Expression>(&Expression::OpLiteral, "host_name", di),
+ make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
+ di));
+
+ if (service) {
+ builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
+ make_shared<Expression>(&Expression::OpLiteral, "service_name", di),
+ make_shared<Expression>(&Expression::OpLiteral, service->GetShortName(), di),
+ di));
+ }
+
+ String zone = checkable->GetZone();
+
+ if (!zone.IsEmpty()) {
+ builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
+ make_shared<Expression>(&Expression::OpLiteral, "zone", di),
+ make_shared<Expression>(&Expression::OpLiteral, zone, di),
+ di));
+ }
+
+ builder->AddExpression(rule.GetExpression());
+
+ ConfigItem::Ptr notificationItem = builder->Compile();
+ notificationItem->Register();
+ DynamicObject::Ptr dobj = notificationItem->Commit();
+ dobj->OnConfigLoaded();
+
+}
+
bool Notification::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule)
{
DebugInfo di = rule.GetDebugInfo();
if (!rule.EvaluateFilter(locals))
return false;
- Array::Ptr instances;
+ Value vinstances;
if (rule.GetFTerm()) {
- Value vinstances = rule.GetFTerm()->Evaluate(locals);
-
- if (!vinstances.IsObjectType<Array>())
- BOOST_THROW_EXCEPTION(std::invalid_argument("for expression must be an array"));
-
- instances = vinstances;
+ vinstances = rule.GetFTerm()->Evaluate(locals);
} else {
- instances = make_shared<Array>();
+ Array::Ptr instances = make_shared<Array>();
instances->Add("");
+ vinstances = instances;
}
- ObjectLock olock(instances);
- BOOST_FOREACH(const String& instance, instances) {
- String objName = rule.GetName();
-
- if (!rule.GetFVar().IsEmpty()) {
- locals->Set(rule.GetFVar(), instance);
- objName += "-" + instance;
- }
+ if (vinstances.IsObjectType<Array>()) {
+ if (!rule.GetFVVar().IsEmpty())
+ BOOST_THROW_EXCEPTION(ConfigError("Array iterator requires value to be an array.") << errinfo_debuginfo(di));
- Log(LogDebug, "Notification")
- << "Applying notification '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di;
+ Array::Ptr arr = vinstances;
- ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
- builder->SetType("Notification");
- builder->SetName(objName);
- builder->SetScope(locals);
+ ObjectLock olock(arr);
+ BOOST_FOREACH(const String& instance, arr) {
+ String name = rule.GetName();
- builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
- make_shared<Expression>(&Expression::OpLiteral, "host_name", di),
- make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
- di));
+ if (!rule.GetFKVar().IsEmpty()) {
+ locals->Set(rule.GetFKVar(), instance);
+ name += instance;
+ }
- if (service) {
- builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
- make_shared<Expression>(&Expression::OpLiteral, "service_name", di),
- make_shared<Expression>(&Expression::OpLiteral, service->GetShortName(), di),
- di));
+ EvaluateApplyRuleOneInstance(checkable, name, locals, rule);
}
-
- String zone = checkable->GetZone();
-
- if (!zone.IsEmpty()) {
- builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
- make_shared<Expression>(&Expression::OpLiteral, "zone", di),
- make_shared<Expression>(&Expression::OpLiteral, zone, di),
- di));
+ } else if (vinstances.IsObjectType<Dictionary>()) {
+ if (rule.GetFVVar().IsEmpty())
+ BOOST_THROW_EXCEPTION(ConfigError("Dictionary iterator requires value to be a dictionary.") << errinfo_debuginfo(di));
+
+ Dictionary::Ptr dict = vinstances;
+
+ ObjectLock olock(dict);
+ BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
+ locals->Set(rule.GetFKVar(), kv.first);
+ locals->Set(rule.GetFVVar(), kv.second);
+
+ EvaluateApplyRuleOneInstance(checkable, rule.GetName() + kv.first, locals, rule);
}
-
- builder->AddExpression(rule.GetExpression());
-
- ConfigItem::Ptr notificationItem = builder->Compile();
- notificationItem->Register();
- DynamicObject::Ptr dobj = notificationItem->Commit();
- dobj->OnConfigLoaded();
}
return true;
private:
void ExecuteNotificationHelper(NotificationType type, const User::Ptr& user, const CheckResult::Ptr& cr, bool force, const String& author = "", const String& text = "");
+ static void EvaluateApplyRuleOneInstance(const shared_ptr<Checkable>& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
static bool EvaluateApplyRuleOne(const shared_ptr<Checkable>& checkable, const ApplyRule& rule);
static void EvaluateApplyRule(const ApplyRule& rule);
static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
ApplyRule::RegisterType("ScheduledDowntime", targets, &ScheduledDowntime::EvaluateApplyRules);
}
-bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule)
+void ScheduledDowntime::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
+{
+ DebugInfo di = rule.GetDebugInfo();
+
+ Log(LogDebug, "ScheduledDowntime")
+ << "Applying scheduled downtime '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di;
+
+ ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
+ builder->SetType("ScheduledDowntime");
+ builder->SetName(name);
+ builder->SetScope(locals);
+
+ Host::Ptr host;
+ Service::Ptr service;
+ tie(host, service) = GetHostService(checkable);
+
+ builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
+ make_shared<Expression>(&Expression::OpLiteral, "host_name", di),
+ make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
+ di));
+
+ if (service) {
+ builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
+ make_shared<Expression>(&Expression::OpLiteral, "service_name", di),
+ make_shared<Expression>(&Expression::OpLiteral, service->GetShortName(), di),
+ di));
+ }
+
+ String zone = checkable->GetZone();
+
+ if (!zone.IsEmpty()) {
+ builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
+ make_shared<Expression>(&Expression::OpLiteral, "zone", di),
+ make_shared<Expression>(&Expression::OpLiteral, zone, di),
+ di));
+ }
+
+ builder->AddExpression(rule.GetExpression());
+
+ ConfigItem::Ptr downtimeItem = builder->Compile();
+ downtimeItem->Register();
+ DynamicObject::Ptr dobj = downtimeItem->Commit();
+ dobj->OnConfigLoaded();
+}
+
+bool ScheduledDowntime::EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule)
{
DebugInfo di = rule.GetDebugInfo();
if (!rule.EvaluateFilter(locals))
return false;
- Array::Ptr instances;
+ Value vinstances;
if (rule.GetFTerm()) {
- Value vinstances = rule.GetFTerm()->Evaluate(locals);
-
- if (!vinstances.IsObjectType<Array>())
- BOOST_THROW_EXCEPTION(std::invalid_argument("for expression must be an array"));
-
- instances = vinstances;
+ vinstances = rule.GetFTerm()->Evaluate(locals);
} else {
- instances = make_shared<Array>();
+ Array::Ptr instances = make_shared<Array>();
instances->Add("");
+ vinstances = instances;
}
- ObjectLock olock(instances);
- BOOST_FOREACH(const String& instance, instances) {
- String objName = rule.GetName();
-
- if (!rule.GetFVar().IsEmpty()) {
- locals->Set(rule.GetFVar(), instance);
- objName += "-" + instance;
- }
+ if (vinstances.IsObjectType<Array>()) {
+ if (!rule.GetFVVar().IsEmpty())
+ BOOST_THROW_EXCEPTION(ConfigError("Array iterator requires value to be an array.") << errinfo_debuginfo(di));
- Log(LogDebug, "ScheduledDowntime")
- << "Applying scheduled downtime '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di;
+ Array::Ptr arr = vinstances;
- ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
- builder->SetType("ScheduledDowntime");
- builder->SetName(objName);
- builder->SetScope(locals);
+ ObjectLock olock(arr);
+ BOOST_FOREACH(const String& instance, arr) {
+ String name = rule.GetName();
- builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
- make_shared<Expression>(&Expression::OpLiteral, "host_name", di),
- make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
- di));
+ if (!rule.GetFKVar().IsEmpty()) {
+ locals->Set(rule.GetFKVar(), instance);
+ name += instance;
+ }
- if (service) {
- builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
- make_shared<Expression>(&Expression::OpLiteral, "service_name", di),
- make_shared<Expression>(&Expression::OpLiteral, service->GetShortName(), di),
- di));
+ EvaluateApplyRuleOneInstance(checkable, name, locals, rule);
}
-
- String zone = checkable->GetZone();
-
- if (!zone.IsEmpty()) {
- builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
- make_shared<Expression>(&Expression::OpLiteral, "zone", di),
- make_shared<Expression>(&Expression::OpLiteral, zone, di),
- di));
+ } else if (vinstances.IsObjectType<Dictionary>()) {
+ if (rule.GetFVVar().IsEmpty())
+ BOOST_THROW_EXCEPTION(ConfigError("Dictionary iterator requires value to be a dictionary.") << errinfo_debuginfo(di));
+
+ Dictionary::Ptr dict = vinstances;
+
+ ObjectLock olock(dict);
+ BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
+ locals->Set(rule.GetFKVar(), kv.first);
+ locals->Set(rule.GetFVVar(), kv.second);
+
+ EvaluateApplyRuleOneInstance(checkable, rule.GetName() + kv.first, locals, rule);
}
-
- builder->AddExpression(rule.GetExpression());
-
- ConfigItem::Ptr downtimeItem = builder->Compile();
- downtimeItem->Register();
- DynamicObject::Ptr dobj = downtimeItem->Commit();
- dobj->OnConfigLoaded();
}
return true;
}
-void ScheduledDowntime::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
+void ScheduledDowntime::EvaluateApplyRule(const ApplyRule& rule)
{
int apply_count = 0;
- BOOST_FOREACH(const ApplyRule& rule, rules) {
- if (rule.GetTargetType() == "Host") {
- apply_count = 0;
-
- BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType<Host>()) {
- CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
-
- try {
- if (EvaluateApplyRule(host, rule))
- apply_count++;
- } catch (const ConfigError& ex) {
- const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
- ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
- }
+ if (rule.GetTargetType() == "Host") {
+ apply_count = 0;
+
+ BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType<Host>()) {
+ CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
+
+ try {
+ if (EvaluateApplyRuleOne(host, rule))
+ apply_count++;
+ } catch (const ConfigError& ex) {
+ const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
+ ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
}
+ }
- if (apply_count == 0)
- Log(LogWarning, "ScheduledDowntime")
- << "Apply rule '" << rule.GetName() << "' for host does not match anywhere!";
+ if (apply_count == 0)
+ Log(LogWarning, "ScheduledDowntime")
+ << "Apply rule '" << rule.GetName() << "' for host does not match anywhere!";
- } else if (rule.GetTargetType() == "Service") {
- apply_count = 0;
+ } else if (rule.GetTargetType() == "Service") {
+ apply_count = 0;
- BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjectsByType<Service>()) {
- CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'");
+ BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjectsByType<Service>()) {
+ CONTEXT("Evaluating 'apply' rules for Service '" + service->GetName() + "'");
- try {
- if(EvaluateApplyRule(service, rule))
- apply_count++;
- } catch (const ConfigError& ex) {
- const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
- ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
- }
+ try {
+ if(EvaluateApplyRuleOne(service, rule))
+ apply_count++;
+ } catch (const ConfigError& ex) {
+ const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
+ ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
}
+ }
- if (apply_count == 0)
- Log(LogWarning, "ScheduledDowntime")
- << "Apply rule '" << rule.GetName() << "' for service does not match anywhere!";
-
- } else {
+ if (apply_count == 0)
Log(LogWarning, "ScheduledDowntime")
- << "Wrong target type for apply rule '" << rule.GetName() << "'!";
- }
+ << "Apply rule '" << rule.GetName() << "' for service does not match anywhere!";
+
+ } else {
+ Log(LogWarning, "ScheduledDowntime")
+ << "Wrong target type for apply rule '" << rule.GetName() << "'!";
}
}
+
+void ScheduledDowntime::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
+{
+ ParallelWorkQueue upq;
+
+ BOOST_FOREACH(const ApplyRule& rule, rules) {
+ upq.Enqueue(boost::bind(&ScheduledDowntime::EvaluateApplyRule, boost::cref(rule)));
+ }
+
+ upq.Join();
+}
std::pair<double, double> FindNextSegment(void);
void CreateNextDowntime(void);
- static bool EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule);
+ static void EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
+ static bool EvaluateApplyRuleOne(const Checkable::Ptr& checkable, const ApplyRule& rule);
+ static void EvaluateApplyRule(const ApplyRule& rule);
static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
};
ApplyRule::RegisterType("Service", targets, &Service::EvaluateApplyRules);
}
+void Service::EvaluateApplyRuleOneInstance(const Host::Ptr& host, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
+{
+ DebugInfo di = rule.GetDebugInfo();
+
+ Log(LogDebug, "Service")
+ << "Applying service '" << name << "' to host '" << host->GetName() << "' for rule " << di;
+
+ ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
+ builder->SetType("Service");
+ builder->SetName(name);
+ builder->SetScope(locals);
+
+ builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
+ make_shared<Expression>(&Expression::OpLiteral, "host_name", di),
+ make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
+ di));
+
+ builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
+ make_shared<Expression>(&Expression::OpLiteral, "name", di),
+ make_shared<Expression>(&Expression::OpLiteral, name, di),
+ di));
+
+ String zone = host->GetZone();
+
+ if (!zone.IsEmpty()) {
+ builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
+ make_shared<Expression>(&Expression::OpLiteral, "zone", di),
+ make_shared<Expression>(&Expression::OpLiteral, zone, di),
+ di));
+ }
+
+ builder->AddExpression(rule.GetExpression());
+
+ ConfigItem::Ptr serviceItem = builder->Compile();
+ serviceItem->Register();
+ DynamicObject::Ptr dobj = serviceItem->Commit();
+ dobj->OnConfigLoaded();
+}
+
bool Service::EvaluateApplyRuleOne(const Host::Ptr& host, const ApplyRule& rule)
{
DebugInfo di = rule.GetDebugInfo();
if (!rule.EvaluateFilter(locals))
return false;
- Array::Ptr instances;
+ Value vinstances;
if (rule.GetFTerm()) {
- Value vinstances = rule.GetFTerm()->Evaluate(locals);
-
- if (!vinstances.IsObjectType<Array>())
- BOOST_THROW_EXCEPTION(std::invalid_argument("for expression must be an array"));
-
- instances = vinstances;
+ vinstances = rule.GetFTerm()->Evaluate(locals);
} else {
- instances = make_shared<Array>();
+ Array::Ptr instances = make_shared<Array>();
instances->Add("");
+ vinstances = instances;
}
- ObjectLock olock(instances);
- BOOST_FOREACH(const String& instance, instances) {
- String objName = rule.GetName();
-
- if (!rule.GetFVar().IsEmpty()) {
- locals->Set(rule.GetFVar(), instance);
- objName += "-" + instance;
- }
-
- Log(LogDebug, "Service")
- << "Applying service '" << objName << "' to host '" << host->GetName() << "' for rule " << di;
-
- ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
- builder->SetType("Service");
- builder->SetName(objName);
- builder->SetScope(locals);
+ if (vinstances.IsObjectType<Array>()) {
+ if (!rule.GetFVVar().IsEmpty())
+ BOOST_THROW_EXCEPTION(ConfigError("Array iterator requires value to be an array.") << errinfo_debuginfo(di));
- builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
- make_shared<Expression>(&Expression::OpLiteral, "host_name", di),
- make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
- di));
+ Array::Ptr arr = vinstances;
- builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
- make_shared<Expression>(&Expression::OpLiteral, "name", di),
- make_shared<Expression>(&Expression::OpLiteral, objName, di),
- di));
+ ObjectLock olock(arr);
+ BOOST_FOREACH(const String& instance, arr) {
+ String name = rule.GetName();
- String zone = host->GetZone();
+ if (!rule.GetFKVar().IsEmpty()) {
+ locals->Set(rule.GetFKVar(), instance);
+ name += instance;
+ }
- if (!zone.IsEmpty()) {
- builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
- make_shared<Expression>(&Expression::OpLiteral, "zone", di),
- make_shared<Expression>(&Expression::OpLiteral, zone, di),
- di));
+ EvaluateApplyRuleOneInstance(host, name, locals, rule);
+ }
+ } else if (vinstances.IsObjectType<Dictionary>()) {
+ if (rule.GetFVVar().IsEmpty())
+ BOOST_THROW_EXCEPTION(ConfigError("Dictionary iterator requires value to be a dictionary.") << errinfo_debuginfo(di));
+
+ Dictionary::Ptr dict = vinstances;
+
+ ObjectLock olock(dict);
+ BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
+ locals->Set(rule.GetFKVar(), kv.first);
+ locals->Set(rule.GetFVVar(), kv.second);
+
+ EvaluateApplyRuleOneInstance(host, rule.GetName() + kv.first, locals, rule);
}
-
- builder->AddExpression(rule.GetExpression());
-
- ConfigItem::Ptr serviceItem = builder->Compile();
- serviceItem->Register();
- DynamicObject::Ptr dobj = serviceItem->Commit();
- dobj->OnConfigLoaded();
}
return true;
private:
Host::Ptr m_Host;
+ static void EvaluateApplyRuleOneInstance(const Host::Ptr& host, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
static bool EvaluateApplyRuleOne(const Host::Ptr& host, const ApplyRule& rule);
static void EvaluateApplyRule(const ApplyRule& rule);
static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);