ApplyRule::ApplyRule(const String& targetType, const String& name, const boost::shared_ptr<Expression>& expression,
const boost::shared_ptr<Expression>& filter, const String& package, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm,
- const DebugInfo& di, const Dictionary::Ptr& scope)
+ bool ignoreOnError, const DebugInfo& di, const Dictionary::Ptr& scope)
: m_TargetType(targetType), m_Name(name), m_Expression(expression), m_Filter(filter), m_Package(package), m_FKVar(fkvar),
- m_FVVar(fvvar), m_FTerm(fterm), m_DebugInfo(di), m_Scope(scope), m_HasMatches(false)
+ m_FVVar(fvvar), m_FTerm(fterm), m_IgnoreOnError(ignoreOnError), m_DebugInfo(di), m_Scope(scope), m_HasMatches(false)
{ }
String ApplyRule::GetTargetType(void) const
return m_FTerm;
}
+bool ApplyRule::GetIgnoreOnError(void) const
+{
+ return m_IgnoreOnError;
+}
+
DebugInfo ApplyRule::GetDebugInfo(void) const
{
return m_DebugInfo;
void ApplyRule::AddRule(const String& sourceType, const String& targetType, const String& name,
const boost::shared_ptr<Expression>& expression, const boost::shared_ptr<Expression>& filter, const String& package, const String& fkvar,
- const String& fvvar, const boost::shared_ptr<Expression>& fterm, const DebugInfo& di, const Dictionary::Ptr& scope)
+ const String& fvvar, const boost::shared_ptr<Expression>& fterm, bool ignoreOnError, const DebugInfo& di, const Dictionary::Ptr& scope)
{
- m_Rules[sourceType].push_back(ApplyRule(targetType, name, expression, filter, package, fkvar, fvvar, fterm, di, scope));
+ m_Rules[sourceType].push_back(ApplyRule(targetType, name, expression, filter, package, fkvar, fvvar, fterm, ignoreOnError, di, scope));
}
bool ApplyRule::EvaluateFilter(ScriptFrame& frame) const
String GetFKVar(void) const;
String GetFVVar(void) const;
boost::shared_ptr<Expression> GetFTerm(void) const;
+ bool GetIgnoreOnError(void) const;
DebugInfo GetDebugInfo(void) const;
Dictionary::Ptr GetScope(void) const;
void AddMatch(void);
bool EvaluateFilter(ScriptFrame& frame) const;
static void AddRule(const String& sourceType, const String& targetType, const String& name, const boost::shared_ptr<Expression>& expression,
- const boost::shared_ptr<Expression>& filter, const String& package, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm, const DebugInfo& di, const Dictionary::Ptr& scope);
+ const boost::shared_ptr<Expression>& filter, const String& package, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm,
+ bool ignoreOnError, const DebugInfo& di, const Dictionary::Ptr& scope);
static std::vector<ApplyRule>& GetRules(const String& type);
static void RegisterType(const String& sourceType, const std::vector<String>& targetTypes);
String m_FKVar;
String m_FVVar;
boost::shared_ptr<Expression> m_FTerm;
+ bool m_IgnoreOnError;
DebugInfo m_DebugInfo;
Dictionary::Ptr m_Scope;
bool m_HasMatches;
ApplyRule(const String& targetType, const String& name, const boost::shared_ptr<Expression>& expression,
const boost::shared_ptr<Expression>& filter, const String& package, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm,
- const DebugInfo& di, const Dictionary::Ptr& scope);
+ bool ignoreOnError, const DebugInfo& di, const Dictionary::Ptr& scope);
};
}
else return T_ELSE;
while return T_WHILE;
throw return T_THROW;
+ignore_on_error return T_IGNORE_ON_ERROR;
=\> return T_FOLLOWS;
\<\< return T_SHIFT_LEFT;
\>\> return T_SHIFT_RIGHT;
%token T_GLOBALS "globals (T_GLOBALS)"
%token T_LOCALS "locals (T_LOCALS)"
%token T_CONST "const (T_CONST)"
+%token T_IGNORE_ON_ERROR "ignore_on_error (T_IGNORE_ON_ERROR)"
%token T_USE "use (T_USE)"
%token T_OBJECT "object (T_OBJECT)"
%token T_TEMPLATE "template (T_TEMPLATE)"
%type <expr> apply
%type <expr> optional_rterm
%type <text> target_type_specifier
+%type <boolean> ignore_specifier
%type <cvlist> use_specifier
%type <cvlist> use_specifier_items
%type <cvitem> use_specifier_item
context->m_Assign.push(NULL);
context->m_Ignore.push(NULL);
}
- object_declaration identifier optional_rterm use_specifier rterm_scope_require_side_effect
+ object_declaration identifier optional_rterm use_specifier ignore_specifier rterm_scope_require_side_effect
{
context->m_ObjectAssign.pop();
String type = *$3;
delete $3;
- $6->MakeInline();
+ $7->MakeInline();
bool seen_assign = context->m_SeenAssign.top();
context->m_SeenAssign.pop();
BOOST_THROW_EXCEPTION(ScriptError("object rule 'ignore' is missing 'assign' for type '" + type + "'", DebugInfoRange(@2, @4)));
}
- $$ = new ObjectExpression(abstract, type, $4, filter, context->GetZone(), context->GetPackage(), $5, $6, DebugInfoRange(@2, @5));
+ $$ = new ObjectExpression(abstract, type, $4, filter, context->GetZone(), context->GetPackage(), $5, $6, $7, DebugInfoRange(@2, @6));
}
;
}
;
+ignore_specifier: /* empty */
+ {
+ $$ = false;
+ }
+ | T_IGNORE_ON_ERROR
+ {
+ $$ = true;
+ }
+ ;
+
use_specifier: /* empty */
{
$$ = NULL;
context->m_FVVar.push("");
context->m_FTerm.push(NULL);
}
- T_APPLY identifier optional_rterm apply_for_specifier target_type_specifier use_specifier rterm_scope_require_side_effect
+ T_APPLY identifier optional_rterm apply_for_specifier target_type_specifier use_specifier ignore_specifier rterm_scope_require_side_effect
{
context->m_Apply.pop();
BOOST_THROW_EXCEPTION(ScriptError("'apply' target type '" + target + "' is invalid", DebugInfoRange(@2, @5)));
}
- $8->MakeInline();
+ $9->MakeInline();
bool seen_assign = context->m_SeenAssign.top();
context->m_SeenAssign.pop();
Expression *fterm = context->m_FTerm.top();
context->m_FTerm.pop();
- $$ = new ApplyExpression(type, target, $4, filter, context->GetPackage(), fkvar, fvvar, fterm, $7, $8, DebugInfoRange(@2, @7));
+ $$ = new ApplyExpression(type, target, $4, filter, context->GetPackage(), fkvar, fvvar, fterm, $7, $8, $9, DebugInfoRange(@2, @8));
}
;
*/
ConfigItem::ConfigItem(const String& type, const String& name,
bool abstract, const boost::shared_ptr<Expression>& exprl,
- const boost::shared_ptr<Expression>& filter,
+ const boost::shared_ptr<Expression>& filter, bool ignoreOnError,
const DebugInfo& debuginfo, const Dictionary::Ptr& scope,
const String& zone, const String& package)
: m_Type(type), m_Name(name), m_Abstract(abstract),
- m_Expression(exprl), m_Filter(filter),
+ m_Expression(exprl), m_Filter(filter), m_IgnoreOnError(ignoreOnError),
m_DebugInfo(debuginfo), m_Scope(scope), m_Zone(zone),
m_Package(package)
{
ScriptFrame frame(dobj);
if (m_Scope)
m_Scope->CopyTo(frame.Locals);
- m_Expression->Evaluate(frame, &debugHints);
+ try {
+ m_Expression->Evaluate(frame, &debugHints);
+ } catch (const std::exception& ex) {
+ if (m_IgnoreOnError) {
+ Log(LogWarning, "ConfigObject")
+ << "Ignoring config object '" << m_Name << "' of type '" << m_Type << "' due to errors: " << DiagnosticInformation(ex);
+
+ return ConfigObject::Ptr();
+ }
+
+ throw;
+ }
if (discard)
m_Expression.reset();
di->Add(m_DebugInfo.LastColumn);
persistentItem->Set("debug_info", di);
- ConfigCompilerContext::GetInstance()->WriteObject(persistentItem);
- persistentItem.reset();
-
try {
DefaultValidationUtils utils;
dobj->Validate(FAConfig, utils);
} catch (ValidationError& ex) {
+ if (m_IgnoreOnError) {
+ Log(LogWarning, "ConfigObject")
+ << "Ignoring config object '" << m_Name << "' of type '" << m_Type << "' due to errors: " << DiagnosticInformation(ex);
+
+ return ConfigObject::Ptr();
+ }
+
ex.SetDebugHint(dhint);
throw;
}
+ ConfigCompilerContext::GetInstance()->WriteObject(persistentItem);
+ persistentItem.reset();
+
dhint.reset();
dobj->Register();
continue;
BOOST_FOREACH(const ConfigItem::Ptr& item, new_items) {
- ASSERT(item->m_Object);
+ if (!item->m_Object)
+ continue;
if (item->m_Type == type)
upq.Enqueue(boost::bind(&ConfigObject::OnAllConfigLoaded, item->m_Object));
BOOST_FOREACH(const String& loadDep, ptype->GetLoadDependencies()) {
BOOST_FOREACH(const ConfigItem::Ptr& item, new_items) {
- ASSERT(item->m_Object);
+ if (!item->m_Object)
+ continue;
if (item->m_Type == loadDep)
upq.Enqueue(boost::bind(&ConfigObject::CreateChildObjects, item->m_Object, ptype));
typedef std::map<Type::Ptr, int> ItemCountMap;
ItemCountMap itemCounts;
BOOST_FOREACH(const ConfigItem::Ptr& item, newItems) {
+ if (!item->m_Object)
+ continue;
+
itemCounts[item->m_Object->GetReflectionType()]++;
}
ConfigItem(const String& type, const String& name, bool abstract,
const boost::shared_ptr<Expression>& exprl,
const boost::shared_ptr<Expression>& filter,
- const DebugInfo& debuginfo,
+ bool ignoreOnError, const DebugInfo& debuginfo,
const Dictionary::Ptr& scope, const String& zone,
const String& package);
String GetType(void) const;
String GetName(void) const;
bool IsAbstract(void) const;
+ bool GetIgnoreOnError(void) const;
std::vector<ConfigItem::Ptr> GetParents(void) const;
boost::shared_ptr<Expression> m_Expression;
boost::shared_ptr<Expression> m_Filter;
+ bool m_IgnoreOnError;
DebugInfo m_DebugInfo; /**< Debug information. */
Dictionary::Ptr m_Scope; /**< variable scope. */
String m_Zone; /**< The zone. */
m_Filter = filter;
}
+void ConfigItemBuilder::SetIgnoreOnError(bool ignoreOnError)
+{
+ m_IgnoreOnError = ignoreOnError;
+}
+
ConfigItem::Ptr ConfigItemBuilder::Compile(void)
{
if (m_Type.IsEmpty()) {
exprl->MakeInline();
return new ConfigItem(m_Type, m_Name, m_Abstract, exprl, m_Filter,
- m_DebugInfo, m_Scope, m_Zone, m_Package);
+ m_IgnoreOnError, m_DebugInfo, m_Scope, m_Zone, m_Package);
}
void SetScope(const Dictionary::Ptr& scope);
void SetZone(const String& zone);
void SetPackage(const String& package);
+ void SetIgnoreOnError(bool ignoreOnError);
void AddExpression(Expression *expr);
void SetFilter(const boost::shared_ptr<Expression>& filter);
Dictionary::Ptr m_Scope; /**< variable scope. */
String m_Zone; /**< The zone. */
String m_Package; /**< The package name. */
+ bool m_IgnoreOnError; /**< Whether the object should be ignored when an error occurs in one of the expressions. */
};
}
CHECK_RESULT(nameres);
return VMOps::NewApply(frame, m_Type, m_Target, nameres.GetValue(), m_Filter,
- m_Package, m_FKVar, m_FVVar, m_FTerm, m_ClosedVars, m_Expression, m_DebugInfo);
+ m_Package, m_FKVar, m_FVVar, m_FTerm, m_ClosedVars, m_IgnoreOnError, m_Expression, m_DebugInfo);
}
ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
}
return VMOps::NewObject(frame, m_Abstract, m_Type, name, m_Filter, m_Zone,
- m_Package, m_ClosedVars, m_Expression, m_DebugInfo);
+ m_Package, m_IgnoreOnError, m_ClosedVars, m_Expression, m_DebugInfo);
}
ExpressionResult ForExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
public:
ApplyExpression(const String& type, const String& target, Expression *name,
Expression *filter, const String& package, const String& fkvar, const String& fvvar,
- Expression *fterm, std::map<String, Expression *> *closedVars,
+ Expression *fterm, std::map<String, Expression *> *closedVars, bool ignoreOnError,
Expression *expression, const DebugInfo& debugInfo = DebugInfo())
: DebuggableExpression(debugInfo), m_Type(type), m_Target(target),
m_Name(name), m_Filter(filter), m_Package(package), m_FKVar(fkvar), m_FVVar(fvvar),
- m_FTerm(fterm), m_ClosedVars(closedVars), m_Expression(expression)
+ m_FTerm(fterm), m_IgnoreOnError(ignoreOnError), m_ClosedVars(closedVars),
+ m_Expression(expression)
{ }
~ApplyExpression(void)
String m_FKVar;
String m_FVVar;
boost::shared_ptr<Expression> m_FTerm;
+ bool m_IgnoreOnError;
std::map<String, Expression *> *m_ClosedVars;
boost::shared_ptr<Expression> m_Expression;
};
public:
ObjectExpression(bool abstract, const String& type, Expression *name, Expression *filter,
const String& zone, const String& package, std::map<String, Expression *> *closedVars,
- Expression *expression, const DebugInfo& debugInfo = DebugInfo())
+ bool ignoreOnError, Expression *expression, const DebugInfo& debugInfo = DebugInfo())
: DebuggableExpression(debugInfo), m_Abstract(abstract), m_Type(type),
- m_Name(name), m_Filter(filter), m_Zone(zone), m_Package(package), m_ClosedVars(closedVars), m_Expression(expression)
+ m_Name(name), m_Filter(filter), m_Zone(zone), m_Package(package),
+ m_IgnoreOnError(ignoreOnError), m_ClosedVars(closedVars), m_Expression(expression)
{ }
~ObjectExpression(void)
boost::shared_ptr<Expression> m_Filter;
String m_Zone;
String m_Package;
+ bool m_IgnoreOnError;
std::map<String, Expression *> *m_ClosedVars;
boost::shared_ptr<Expression> m_Expression;
};
static inline Value NewApply(ScriptFrame& frame, const String& type, const String& target, const String& name, const boost::shared_ptr<Expression>& filter,
const String& package, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm, std::map<String, Expression *> *closedVars,
- const boost::shared_ptr<Expression>& expression, const DebugInfo& debugInfo = DebugInfo())
+ bool ignoreOnError, const boost::shared_ptr<Expression>& expression, const DebugInfo& debugInfo = DebugInfo())
{
ApplyRule::AddRule(type, target, name, expression, filter, package, fkvar,
- fvvar, fterm, debugInfo, EvaluateClosedVars(frame, closedVars));
+ fvvar, fterm, ignoreOnError, debugInfo, EvaluateClosedVars(frame, closedVars));
return Empty;
}
static inline Value NewObject(ScriptFrame& frame, bool abstract, const String& type, const String& name, const boost::shared_ptr<Expression>& filter,
- const String& zone, const String& package, std::map<String, Expression *> *closedVars, const boost::shared_ptr<Expression>& expression, const DebugInfo& debugInfo = DebugInfo())
+ const String& zone, const String& package, bool ignoreOnError, std::map<String, Expression *> *closedVars, const boost::shared_ptr<Expression>& expression, const DebugInfo& debugInfo = DebugInfo())
{
ConfigItemBuilder::Ptr item = new ConfigItemBuilder(debugInfo);
item->SetZone(zone);
item->SetPackage(package);
item->SetFilter(filter);
+ item->SetIgnoreOnError(ignoreOnError);
item->Compile()->Register();
return Empty;
builder->SetType("Dependency");
builder->SetName(name);
builder->SetScope(frame.Locals->ShallowClone());
+ builder->SetIgnoreOnError(rule.GetIgnoreOnError());
Host::Ptr host;
Service::Ptr service;
builder->SetType("Notification");
builder->SetName(name);
builder->SetScope(frame.Locals->ShallowClone());
+ builder->SetIgnoreOnError(rule.GetIgnoreOnError());
Host::Ptr host;
Service::Ptr service;
builder->SetType("ScheduledDowntime");
builder->SetName(name);
builder->SetScope(frame.Locals->ShallowClone());
+ builder->SetIgnoreOnError(rule.GetIgnoreOnError());
Host::Ptr host;
Service::Ptr service;
builder->SetType("Service");
builder->SetName(name);
builder->SetScope(frame.Locals->ShallowClone());
+ builder->SetIgnoreOnError(rule.GetIgnoreOnError());
builder->AddExpression(new SetExpression(MakeIndexer(ScopeThis, "host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di));