LCOV - code coverage report
Current view: top level - /opt/artdaq/srcs/artdaq-mfextensions/ErrorHandler/MessageAnalyzer - ma_rule.cpp (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 0.0 % 168 0
Test Date: 2025-09-04 00:45:34 Functions: 0.0 % 24 0

            Line data    Source code
       1              : 
       2              : #include "ErrorHandler/MessageAnalyzer/ma_rule.h"
       3              : #include "ErrorHandler/MessageAnalyzer/ma_parse.h"
       4              : 
       5              : #include <iostream>
       6              : 
       7              : using fhicl::ParameterSet;
       8              : using namespace novadaq::errorhandler;
       9              : 
      10            0 : ma_rule::ma_rule(std::string const& rule_name, std::string const& rule_desc, bool repeat, int holdoff_time)
      11            0 :     : conditions()
      12            0 :     , conditions_idx()
      13            0 :     , primitive_cond()
      14            0 :     , cond_map(NULL)
      15            0 :     , name_(rule_name)
      16            0 :     , description_(rule_desc)
      17            0 :     , condition_expr()
      18            0 :     , alarm_count(0)
      19            0 :     , cond_names_()
      20            0 :     , alarm_msg()
      21            0 :     , boolean_expr()
      22            0 :     , domain_expr()
      23            0 :     , domains()
      24            0 :     , alarms()
      25            0 :     , itor_last_alarm(alarms.end())
      26            0 :     , repeat_alarm(repeat)
      27            0 :     , holdoff(holdoff_time)
      28            0 :     , initialized(false)
      29            0 :     , enabled(true)
      30            0 :     , actions()
      31              : {
      32            0 : }
      33              : 
      34            0 : void ma_rule::parse(std::string const& cond_expr, std::string const& alarm_message, ParameterSet const& act_pset, cond_map_t* cond_map_ptr)
      35              : {
      36            0 :         cond_map = cond_map_ptr;
      37            0 :         condition_expr = cond_expr;
      38              : 
      39              :         // condition expression
      40            0 :         if (!parse_condition_expr(cond_expr, this))
      41            0 :                 throw std::runtime_error("rule parsing failed");
      42              : 
      43              :         // alarm message
      44            0 :         alarm_msg.init(this, alarm_message);
      45              : 
      46              :         // actions
      47            0 :         std::vector<std::string> keys = act_pset.get_pset_names();
      48            0 :         for (size_t i = 0; i < keys.size(); ++i)
      49              :         {
      50            0 :                 ParameterSet param = act_pset.get<ParameterSet>(keys[i]);
      51            0 :                 actions.push_back(ma_action_factory::create_instance(keys[i], this, param));
      52            0 :         }
      53              : 
      54              :         // init
      55            0 :         if (domain_expr.empty())
      56            0 :                 domains.push_back(ma_domain_ctor_any(conditions.size()));
      57              : 
      58            0 :         initialized = true;
      59            0 : }
      60              : 
      61              : cond_idx_t
      62            0 : ma_rule::insert_condition_ptr(std::string const& name, bool primitive)
      63              : {
      64              :         // cond_map must not be empty
      65            0 :         assert(cond_map != NULL);
      66              : 
      67            0 :         TLOG(TLVL_DEBUG) << "insert_cond_ptr: name = " << name << "  "
      68            0 :                          << "primitive = " << primitive;
      69              : 
      70              :         // the condition has already been added
      71              :         {
      72            0 :                 idx_t::const_iterator it = conditions_idx.find(name);
      73            0 :                 if (it != conditions_idx.end())
      74              :                 {
      75              :                         // primitive cond overrides non-primitive cond
      76            0 :                         primitive_cond[it->second] = primitive_cond[it->second] | primitive;
      77            0 :                         return cond_idx_t(conditions[it->second], it->second);
      78              :                         ;
      79              :                 }
      80              :         }
      81              : 
      82              :         // look for the cond in the rule_engine container
      83            0 :         cond_map_t::iterator it = cond_map->find(name);
      84              : 
      85            0 :         if (it == cond_map->end())  // name not found
      86            0 :                 throw std::runtime_error("insert_cond_ptr: condition " + name + " not found");
      87              : 
      88              :         // put this rule to the status notification list of the condition
      89            0 :         it->second.push_notify_status(this);
      90              : 
      91              :         // register the condition in the rule
      92            0 :         cond_names_.push_back(name);
      93            0 :         conditions.push_back(&it->second);
      94            0 :         primitive_cond.push_back(primitive);
      95              : 
      96            0 :         assert(conditions.size() == primitive_cond.size());
      97            0 :         size_t idx = conditions.size() - 1;
      98              : 
      99            0 :         conditions_idx.insert(std::make_pair(name, idx));
     100              : 
     101            0 :         return cond_idx_t(&it->second, idx);
     102              : }
     103              : 
     104            0 : void ma_rule::evaluate_domain()
     105              : {
     106            0 :         assert(initialized);
     107              : 
     108              :         // re-evaluate domains
     109            0 :         domains.clear();
     110            0 :         domain_expr.evaluate(domains);
     111              : 
     112            0 :         TLOG(TLVL_DEBUG) << description_
     113            0 :                          << ": domain evaluated, size = " << domains.size();
     114            0 : }
     115              : 
     116            0 : bool ma_rule::recursive_evaluate(ma_domain& value, ma_domain& alarm, ma_domain const& domain, size_t n)
     117              : {
     118              :         // pre-conditions
     119            0 :         assert(!domain_is_null(domain[n]));
     120              : 
     121              :         // get range
     122            0 :         ma_cond_range src(D_NIL, D_NIL);
     123            0 :         ma_cond_range target(D_NIL, D_NIL);
     124              : 
     125              :         // a primitive condition (Cn) or non-primitive ( COUNT(Cn.$s|t) )
     126              :         // we only loop through possible values for primitive conditions
     127            0 :         if (primitive_cond[n])
     128            0 :                 conditions[n]->get_cond_range(domain[n], src, target);
     129              : 
     130            0 :         TLOG(TLVL_DEBUG) << "depth: " << n << "  "
     131            0 :                          << "primitive_cond[n]: " << primitive_cond[n];
     132              : 
     133            0 :         for (int s = src.first; s <= src.second; ++s)
     134              :         {
     135            0 :                 for (int t = target.first; t <= target.second; ++t)
     136              :                 {
     137            0 :                         value[n].first = s;
     138            0 :                         value[n].second = t;
     139              : 
     140            0 :                         TLOG(TLVL_DEBUG) << "depth: " << n << "  "
     141            0 :                                          << "src: " << s << "  "
     142            0 :                                          << "tgt: " << t;
     143              : 
     144            0 :                         if (n != domain.size() - 1)
     145              :                         {
     146            0 :                                 if (recursive_evaluate(value, alarm, domain, n + 1))
     147            0 :                                         return true;
     148              :                         }
     149              :                         else
     150              :                         {
     151              :                                 // evaluate and, if found new alarm, no need to continue
     152            0 :                                 if (boolean_evaluate(value, alarm, domain))
     153            0 :                                         return true;
     154              :                         }
     155              :                 }
     156              :         }
     157              : 
     158            0 :         return false;
     159              : }
     160              : 
     161            0 : bool ma_rule::evaluate()
     162              : {
     163            0 :         assert(initialized);
     164              : 
     165              :         // if disabled, always returns false
     166            0 :         if (!enabled) return false;
     167              : 
     168            0 :         TLOG(TLVL_DEBUG) << description_ << ": evaluate boolean expr...";
     169              : 
     170              :         // loop through domain alternatives
     171            0 :         for (ma_domains::const_iterator ait = domains.begin(); ait != domains.end(); ++ait)
     172              :         {
     173              :                 // each domain consists a set of possible values for each condition
     174            0 :                 ma_domain const& domain = *ait;
     175              : 
     176              :                 // pre-condition
     177            0 :                 assert(!domain_is_null(domain));
     178              : 
     179              :                 // holds the one possible set of value
     180            0 :                 ma_domain value = ma_domain_ctor_null(domain.size());
     181            0 :                 ma_domain alarm = ma_domain_ctor_null(domain.size());
     182              : 
     183              :                 // recursively build and evaluate possible values from domain
     184            0 :                 if (recursive_evaluate(value, alarm, domain, 0))
     185            0 :                         return true;
     186            0 :         }
     187              : 
     188            0 :         return false;
     189              : }
     190              : 
     191            0 : bool ma_rule::boolean_evaluate(ma_domain& value, ma_domain& alarm, ma_domain const& domain)
     192              : {
     193            0 :         TLOG(TLVL_DEBUG) << "now evaluate boolean_expr with given value";
     194              : 
     195              :         // evaluate as true with given set of values
     196            0 :         if (boolean_expr.evaluate(value, alarm, domain))
     197              :         {
     198            0 :                 TLOG(TLVL_DEBUG) << "alarm (" << alarm[0].first << ", "
     199            0 :                                  << alarm[0].second << ")";
     200              : 
     201            0 :                 std::map<ma_domain, timeval>::iterator it = alarms.find(alarm);
     202            0 :                 if (it == alarms.end())
     203              :                 {
     204              :                         // this is a new alarm. push the current domain to alarm list
     205              :                         timeval tv;
     206            0 :                         gettimeofday(&tv, 0);
     207            0 :                         itor_last_alarm = alarms.insert(std::make_pair(alarm, tv)).first;
     208              : 
     209            0 :                         alarm.clear();
     210            0 :                         alarm = ma_domain_ctor_null(domain.size());
     211              : 
     212              :                         // trigger new alarm
     213              :                         // ...
     214              : 
     215            0 :                         ++alarm_count;
     216              : 
     217            0 :                         return true;
     218              :                 }
     219              : 
     220            0 :                 else if (repeat_alarm)
     221              :                 {
     222              :                         // not a new alarm, but the repeat_alarm flag has been set
     223              :                         timeval tv;
     224            0 :                         gettimeofday(&tv, 0);
     225            0 :                         timeval lt = it->second;
     226            0 :                         if (tv.tv_sec - lt.tv_sec > holdoff)
     227              :                         {
     228              :                                 // passed the holdoff time, can refire a new alarm
     229            0 :                                 itor_last_alarm = alarms.insert(it, std::make_pair(alarm, tv));
     230              : 
     231            0 :                                 alarm.clear();
     232            0 :                                 alarm = ma_domain_ctor_null(domain.size());
     233              : 
     234              :                                 // trigger new alarm
     235              :                                 // ...
     236              : 
     237            0 :                                 ++alarm_count;
     238              : 
     239            0 :                                 return true;
     240              :                         }
     241              :                 }
     242              : 
     243              :                 // otherwise, the alarm has already been triggered, or hasn't passed
     244              :                 // the holdoff time
     245            0 :                 TLOG(TLVL_DEBUG) << "this alarm has already been triggered";
     246              :         }
     247              : 
     248              :         // reset alarm
     249            0 :         alarm.clear();
     250            0 :         alarm = ma_domain_ctor_null(domain.size());
     251              : 
     252            0 :         return false;
     253              : }
     254              : 
     255            0 : int ma_rule::act()
     256              : {
     257            0 :         int mask = 0;
     258            0 :         for (ma_actions::const_iterator it = actions.begin(), e = actions.end(); it != e; ++it)
     259              :         {
     260            0 :                 if ((*it)->exec()) ++mask;
     261              :         }
     262            0 :         return mask;
     263              : }
     264              : 
     265            0 : void ma_rule::reset()
     266              : {
     267              :         // clear user function state
     268            0 :         boolean_expr.reset();
     269              : 
     270              :         // reset all related conds
     271            0 :         cond_vec_t::iterator it = conditions.begin();
     272            0 :         for (; it != conditions.end(); ++it) (*it)->reset();
     273              : 
     274              :         // domains.clear();
     275            0 :         alarms.clear();
     276            0 :         itor_last_alarm = alarms.end();
     277            0 :         alarm_count = 0;
     278            0 : }
     279              : 
     280            0 : ma_domain const& ma_rule::get_alarm() const
     281              : {
     282            0 :         if (alarms.empty())
     283            0 :                 throw std::runtime_error("get_alarm_message(): no alarm has been triggerd");
     284              : 
     285              :         // make sure that the itor_last_alarm points to something
     286            0 :         assert(itor_last_alarm != alarms.end());
     287              : 
     288            0 :         return itor_last_alarm->first;
     289              : }
     290              : 
     291            0 : std::string ma_rule::get_alarm_message()
     292              : {
     293            0 :         return alarm_msg.message();
     294              : }
     295              : 
     296              : // ----------------------------------------------------------------
     297              : //
     298              : // get condition index and pointer given a name
     299              : cond_idx_t
     300            0 : ma_rule::get_cond_idx(std::string const& name) const
     301              : {
     302            0 :         idx_t::const_iterator it = conditions_idx.find(name);
     303            0 :         if (it == conditions_idx.end())
     304            0 :                 throw std::runtime_error("get_cond_idx: name '" + name + "' not found");
     305            0 :         return cond_idx_t(conditions[it->second], it->second);
     306              : }
     307              : 
     308              : // get pointer to the condition
     309              : ma_condition*
     310            0 : ma_rule::get_cond(std::string const& name) const
     311              : {
     312            0 :         idx_t::const_iterator it = conditions_idx.find(name);
     313            0 :         if (it == conditions_idx.end())
     314            0 :                 throw std::runtime_error("get_cond: name '" + name + "' not found");
     315            0 :         return conditions[it->second];
     316              : }
     317              : 
     318              : // get index to the condition
     319              : size_t
     320            0 : ma_rule::get_idx(std::string const& name) const
     321              : {
     322            0 :         idx_t::const_iterator it = conditions_idx.find(name);
     323            0 :         if (it == conditions_idx.end())
     324            0 :                 throw std::runtime_error("get_cond: name '" + name + "' not found");
     325            0 :         return it->second;
     326              : }
     327              : 
     328              : // get the size of condition container
     329              : size_t
     330            0 : ma_rule::get_cond_size() const
     331              : {
     332            0 :         assert(conditions.size() == conditions_idx.size());
     333            0 :         return conditions.size();
     334              : }
     335              : 
     336              : // update the "notify_on_source" or "notify_on_target" list
     337              : // for corresponding conditions
     338            0 : void ma_rule::update_notify_list(std::string const& name, arg_t arg)
     339              : {
     340            0 :         idx_t::const_iterator it = conditions_idx.find(name);
     341              : 
     342            0 :         if (it == conditions_idx.end())
     343            0 :                 throw std::runtime_error("update_notify_list: name '" + name + "' not found");
     344              : 
     345            0 :         (arg == SOURCE) ? conditions[it->second]->push_notify_source(this)
     346            0 :                         : conditions[it->second]->push_notify_target(this);
     347            0 : }
        

Generated by: LCOV version 2.0-1