2 #include "ErrorHandler/MessageAnalyzer/ma_rule.h"
3 #include "ErrorHandler/MessageAnalyzer/ma_parse.h"
7 using fhicl::ParameterSet;
8 using namespace novadaq::errorhandler;
10 ma_rule::ma_rule( std::string
const & rule_name
11 , std::string
const & rule_desc
19 , description_( rule_desc )
28 , itor_last_alarm( alarms.end() )
29 , repeat_alarm( repeat )
30 , holdoff( holdoff_time )
31 , initialized( false )
39 ma_rule::parse( std::string
const & cond_expr
40 , std::string
const & alarm_message
41 , ParameterSet
const & act_pset
42 , cond_map_t * cond_map_ptr )
44 cond_map = cond_map_ptr;
45 condition_expr = cond_expr;
48 if( !parse_condition_expr( cond_expr,
this ) )
49 throw std::runtime_error(
"rule parsing failed");
52 alarm_msg.init(
this, alarm_message);
55 std::vector<std::string> keys = act_pset.get_pset_names();
56 for(
size_t i=0; i<keys.size(); ++i)
58 ParameterSet param = act_pset.get<ParameterSet>(keys[i]);
59 actions.push_back( ma_action_factory::create_instance( keys[i],
this, param ) );
63 if( domain_expr.empty() )
64 domains.push_back(ma_domain_ctor_any(conditions.size()));
71 ma_rule::insert_condition_ptr( std::string
const & name,
bool primitive )
74 assert (cond_map != NULL);
76 TLOG(TLVL_DEBUG) <<
"insert_cond_ptr: name = " << name <<
" "
77 <<
"primitive = " << primitive;
81 idx_t::const_iterator it = conditions_idx.find(name);
82 if( it != conditions_idx.end() )
85 primitive_cond[it->second] = primitive_cond[it->second] | primitive;
86 return cond_idx_t(conditions[it->second], it->second);;
91 cond_map_t::iterator it = cond_map->find(name);
93 if( it == cond_map->end() )
94 throw std::runtime_error(
"insert_cond_ptr: condition " + name +
" not found");
97 it->second.push_notify_status(
this);
100 cond_names_.push_back(name);
101 conditions.push_back(&it->second);
102 primitive_cond.push_back(primitive);
104 assert( conditions.size() == primitive_cond.size() );
105 size_t idx = conditions.size()-1;
107 conditions_idx.insert(std::make_pair(name, idx));
109 return cond_idx_t(&it->second, idx);
113 void ma_rule::evaluate_domain( )
115 assert( initialized );
119 domain_expr.evaluate(domains);
121 TLOG(TLVL_DEBUG) << description_
122 <<
": domain evaluated, size = " << domains.size();
125 bool ma_rule::recursive_evaluate ( ma_domain & value
127 , ma_domain
const & domain
131 assert( !domain_is_null(domain[n]) );
134 ma_cond_range src(D_NIL, D_NIL);
135 ma_cond_range target(D_NIL, D_NIL);
139 if (primitive_cond[n])
140 conditions[n]->get_cond_range(domain[n], src, target);
142 TLOG(TLVL_DEBUG) <<
"depth: " << n <<
" "
143 <<
"primitive_cond[n]: " << primitive_cond[n];
145 for(
int s = src.first; s<=src.second; ++s)
147 for(
int t = target.first; t<=target.second; ++t)
152 TLOG(TLVL_DEBUG) <<
"depth: " << n <<
" "
153 <<
"src: " << s <<
" "
156 if( n != domain.size()-1 )
158 if( recursive_evaluate(value, alarm, domain, n+1) )
164 if( boolean_evaluate(value, alarm, domain) )
173 bool ma_rule::evaluate( )
175 assert( initialized );
178 if( !enabled )
return false;
180 TLOG(TLVL_DEBUG) << description_ <<
": evaluate boolean expr...";
183 for ( ma_domains::const_iterator ait = domains.begin()
184 ; ait != domains.end(); ++ait )
187 ma_domain
const & domain = *ait;
190 assert( !domain_is_null(domain) );
193 ma_domain value = ma_domain_ctor_null(domain.size());
194 ma_domain alarm = ma_domain_ctor_null(domain.size());
197 if( recursive_evaluate(value, alarm, domain, 0) )
204 bool ma_rule::boolean_evaluate( ma_domain & value
206 , ma_domain
const & domain )
208 TLOG(TLVL_DEBUG) <<
"now evaluate boolean_expr with given value";
211 if (boolean_expr.evaluate(value, alarm, domain))
213 TLOG(TLVL_DEBUG) <<
"alarm (" << alarm[0].first <<
", "
214 << alarm[0].second <<
")";
216 std::map<ma_domain, timeval>::iterator it = alarms.find(alarm);
217 if ( it==alarms.end() )
220 timeval tv; gettimeofday(&tv, 0);
221 itor_last_alarm = alarms.insert(std::make_pair(alarm, tv)).first;
224 alarm = ma_domain_ctor_null( domain.size() );
234 else if ( repeat_alarm )
237 timeval tv; gettimeofday(&tv, 0);
238 timeval lt = it->second;
239 if( tv.tv_sec - lt.tv_sec > holdoff )
242 itor_last_alarm = alarms.insert(it, std::make_pair(alarm, tv));
245 alarm = ma_domain_ctor_null( domain.size() );
258 TLOG(TLVL_DEBUG) <<
"this alarm has already been triggered";
263 alarm = ma_domain_ctor_null( domain.size() );
272 for(ma_actions::const_iterator it = actions.begin()
273 , e = actions.end(); it != e; ++it )
275 if((*it)->exec())++mask;
280 void ma_rule::reset( )
283 boolean_expr.reset();
286 cond_vec_t::iterator it=conditions.begin();
287 for( ; it!=conditions.end(); ++it) (*it)->reset();
291 itor_last_alarm = alarms.end();
295 ma_domain
const & ma_rule::get_alarm()
const
298 throw std::runtime_error(
"get_alarm_message(): no alarm has been triggerd");
301 assert( itor_last_alarm!=alarms.end() );
303 return itor_last_alarm->first;
306 std::string ma_rule::get_alarm_message( )
308 return alarm_msg.message();
317 ma_rule::get_cond_idx( std::string
const & name )
const
319 idx_t::const_iterator it = conditions_idx.find(name);
320 if( it == conditions_idx.end() )
321 throw std::runtime_error(
"get_cond_idx: name '" + name +
"' not found");
322 return cond_idx_t(conditions[it->second], it->second);
327 ma_rule::get_cond( std::string
const & name )
const
329 idx_t::const_iterator it = conditions_idx.find(name);
330 if( it == conditions_idx.end() )
331 throw std::runtime_error(
"get_cond: name '" + name +
"' not found");
332 return conditions[it->second];
337 ma_rule::get_idx( std::string
const & name )
const
339 idx_t::const_iterator it = conditions_idx.find(name);
340 if( it == conditions_idx.end() )
341 throw std::runtime_error(
"get_cond: name '" + name +
"' not found");
347 ma_rule::get_cond_size()
const
349 assert( conditions.size() == conditions_idx.size() );
350 return conditions.size();
356 ma_rule::update_notify_list( std::string
const & name, arg_t arg )
358 idx_t::const_iterator it = conditions_idx.find(name);
360 if( it == conditions_idx.end() )
361 throw std::runtime_error(
"update_notify_list: name '" + name +
"' not found");
363 (arg==SOURCE) ? conditions[it->second]->push_notify_source(
this)
364 : conditions[it->second]->push_notify_target(
this);