Implement the ignore_on_error keyword

fixes #9960
This commit is contained in:
Gunnar Beutner 2015-10-05 12:44:11 +02:00
parent f0a5a0c23c
commit 8136cda367
15 changed files with 93 additions and 31 deletions

View File

@ -29,9 +29,9 @@ ApplyRule::TypeMap ApplyRule::m_Types;
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
@ -74,6 +74,11 @@ boost::shared_ptr<Expression> ApplyRule::GetFTerm(void) const
return m_FTerm;
}
bool ApplyRule::GetIgnoreOnError(void) const
{
return m_IgnoreOnError;
}
DebugInfo ApplyRule::GetDebugInfo(void) const
{
return m_DebugInfo;
@ -86,9 +91,9 @@ Dictionary::Ptr ApplyRule::GetScope(void) const
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

View File

@ -45,6 +45,7 @@ public:
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);
@ -53,7 +54,8 @@ public:
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);
@ -73,6 +75,7 @@ private:
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;
@ -82,7 +85,7 @@ private:
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);
};
}

View File

@ -195,6 +195,7 @@ if return T_IF;
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;

View File

@ -143,6 +143,7 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
%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)"
@ -192,6 +193,7 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
%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
@ -340,7 +342,7 @@ object:
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();
@ -349,7 +351,7 @@ object:
String type = *$3;
delete $3;
$6->MakeInline();
$7->MakeInline();
bool seen_assign = context->m_SeenAssign.top();
context->m_SeenAssign.pop();
@ -382,7 +384,7 @@ object:
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));
}
;
@ -882,6 +884,16 @@ target_type_specifier: /* empty */
}
;
ignore_specifier: /* empty */
{
$$ = false;
}
| T_IGNORE_ON_ERROR
{
$$ = true;
}
;
use_specifier: /* empty */
{
$$ = NULL;
@ -958,7 +970,7 @@ apply:
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();
@ -991,7 +1003,7 @@ apply:
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();
@ -1030,7 +1042,7 @@ apply:
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));
}
;

View File

@ -60,11 +60,11 @@ REGISTER_SCRIPTFUNCTION(commit_objects, &ConfigItem::CommitAndActivate);
*/
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)
{
@ -184,7 +184,18 @@ ConfigObject::Ptr ConfigItem::Commit(bool discard)
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();
@ -237,17 +248,24 @@ ConfigObject::Ptr ConfigItem::Commit(bool discard)
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();
@ -407,7 +425,8 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq, std::vector<ConfigItem::Ptr>& ne
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));
@ -422,7 +441,8 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq, std::vector<ConfigItem::Ptr>& ne
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));
@ -464,6 +484,9 @@ bool ConfigItem::CommitItems(WorkQueue& upq)
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()]++;
}

View File

@ -41,13 +41,14 @@ public:
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;
@ -80,6 +81,7 @@ private:
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. */

View File

@ -80,6 +80,11 @@ void ConfigItemBuilder::SetFilter(const boost::shared_ptr<Expression>& filter)
m_Filter = filter;
}
void ConfigItemBuilder::SetIgnoreOnError(bool ignoreOnError)
{
m_IgnoreOnError = ignoreOnError;
}
ConfigItem::Ptr ConfigItemBuilder::Compile(void)
{
if (m_Type.IsEmpty()) {
@ -116,6 +121,6 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
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);
}

View File

@ -48,6 +48,7 @@ public:
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);
@ -64,6 +65,7 @@ private:
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. */
};
}

View File

@ -738,7 +738,7 @@ ExpressionResult ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhin
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
@ -756,7 +756,7 @@ ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhi
}
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

View File

@ -804,11 +804,12 @@ class I2_CONFIG_API ApplyExpression : public DebuggableExpression
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)
@ -828,6 +829,7 @@ private:
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;
};
@ -837,9 +839,10 @@ class I2_CONFIG_API ObjectExpression : public DebuggableExpression
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)
@ -857,6 +860,7 @@ private:
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;
};

View File

@ -106,16 +106,16 @@ public:
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);
@ -149,6 +149,7 @@ public:
item->SetZone(zone);
item->SetPackage(package);
item->SetFilter(filter);
item->SetIgnoreOnError(ignoreOnError);
item->Compile()->Register();
return Empty;

View File

@ -55,6 +55,7 @@ bool Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, cons
builder->SetType("Dependency");
builder->SetName(name);
builder->SetScope(frame.Locals->ShallowClone());
builder->SetIgnoreOnError(rule.GetIgnoreOnError());
Host::Ptr host;
Service::Ptr service;

View File

@ -55,6 +55,7 @@ bool Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, co
builder->SetType("Notification");
builder->SetName(name);
builder->SetScope(frame.Locals->ShallowClone());
builder->SetIgnoreOnError(rule.GetIgnoreOnError());
Host::Ptr host;
Service::Ptr service;

View File

@ -54,6 +54,7 @@ bool ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkabl
builder->SetType("ScheduledDowntime");
builder->SetName(name);
builder->SetScope(frame.Locals->ShallowClone());
builder->SetIgnoreOnError(rule.GetIgnoreOnError());
Host::Ptr host;
Service::Ptr service;

View File

@ -53,6 +53,7 @@ bool Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& nam
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));