/* * alarm_table.cpp * * $Author: graziano $ * * $Revision: 1.5 $ * * $Log: alarm_table.cpp,v $ * * * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale * Strada Statale 14 - km 163,5 in AREA Science Park * 34012 Basovizza, Trieste ITALY */ #include <sys/time.h> #include <tango.h> #include "alarm_table.h" #include "alarm_grammar.h" #include "cmd_thread.h" #include <regex> static const char __FILE__rev[] = __FILE__ " $Revision: 1.5 $"; /* * alarm_t class methods */ bool alarm_t::operator==(const alarm_t &that) { // return((stat == that.stat) && (ack == that.ack)); //verify if stat not equal but only contained because added *n in internal alarm return((stat.find(that.stat) != std::string::npos) && (ack == that.ack)); } bool alarm_t::operator==(const string &n) { return(name == n); } void alarm_t::str2alm(const string &s) { istringstream is(s); ostringstream temp_msg; string temp_grp; unsigned int on_cnt; is >> ts.tv_sec >> ts.tv_usec >> name >> stat >> ack >> on_cnt >> lev >> silent_time >> temp_grp >> msg; //stop at first white space in msg #ifdef _CNT_ATOMIC on_counter.store(on_cnt); #else on_counter = on_cnt; #endif temp_msg << is.rdbuf(); //read all remaining characters as msg msg += temp_msg.str(); str2grp(temp_grp); } string alarm_t::alm2str(void) { ostringstream os; os.clear(); #ifdef _CNT_ATOMIC os << ts.tv_sec << "\t" << ts.tv_usec << "\t" << name << "\t" \ << stat << "\t" << ack << "\t" << on_counter.load() << "\t" << lev << "\t" << silent_time << "\t" << grp2str() << "\t" << msg << ends; #else os << ts.tv_sec << "\t" << ts.tv_usec << "\t" << name << "\t" \ << stat << "\t" << ack << "\t" << on_counter << "\t" << lev << "\t" << silent_time << "\t" << grp2str() << "\t" << msg << ends; #endif return(os.str()); } map<string, unsigned int> alarm_t::grp_str; //needed here because static void alarm_t::init_static_map(vector<string> &group_names) { //LOG_STREAM << "alarm_table::init_static_map(vector<string> &group_names): Entering..." << endl; int j=0; vector<string>::iterator i; if(grp_str.size() > 0) return; if(group_names.empty()) { //LOG_STREAM << "alarm_table::init_static_map(): inserting: default group " << GR_NONE_NAME << " = " << showbase << hex << GR_NONE << endl; grp_str.insert(make_pair(string(GR_NONE_NAME), GR_NONE)); } for (i = group_names.begin(); i != group_names.end(); i++) { if((*i) == string(GR_ALL_NAME)) continue; if(i == group_names.begin()) { //LOG_STREAM << "alarm_table::init_static_map(): inserting: group " << *i << " = " << showbase << hex << GR_NONE << endl; grp_str.insert(make_pair(*i, GR_NONE)); } else { //LOG_STREAM << "alarm_table::init_static_map(): inserting: group " << *i << " = " << showbase << hex << int(0x1 << j) << endl; grp_str.insert(make_pair(*i, 0x1 << j)); j++; } } //LOG_STREAM << "alarm_table::init_static_map(): inserting: group " << GR_ALL_NAME << " = " << showbase << hex << GR_ALL << endl; grp_str.insert(make_pair(string(GR_ALL_NAME), GR_ALL)); } string alarm_t::grp2str(void) { map<string, unsigned int>::iterator i = grp_str.begin(); bool first=true; string argout; if(grp == GR_ALL) argout = string(GR_ALL_NAME); else if(grp == GR_NONE) { if(i != grp_str.end()) argout = i->first; else argout = string(GR_NONE_NAME); } else { for (; i != grp_str.end(); i++) { if(i->first == string(GR_ALL_NAME)) continue; if(grp & i->second) { if(first) { argout = i->first; first = false; } else argout += string("|") + i->first; } } } return argout; } void alarm_t::add_grp_from_str(string &s) { map<string, unsigned int>::iterator i = grp_str.find(s); if(i != grp_str.end()) grp |= (*i).second; } void alarm_t::str2grp(string &s) { for(map<string, unsigned int>::iterator i=grp_str.begin(); i != grp_str.end(); i++) if(s.find(i->first) != string::npos) grp |= i->second; } void alarm_t::insert(const string& s) { s_event.insert(s); } void alarm_t::clear() { name.clear(); formula.clear(); msg.clear(); lev.clear(); grp=0; s_event.clear(); to_be_evaluated = false; stat.clear(); ack.clear(); done = false; // ts = 0; } void alarm_t::confstr(string &s) { ostringstream conf; conf << KEY(NAME_KEY)<<name << SEP << KEY(FORMULA_KEY)<<formula << SEP << KEY(ONDELAY_KEY)<<on_delay << SEP << KEY(OFFDELAY_KEY)<<off_delay << SEP << KEY(LEVEL_KEY)<< lev << SEP << KEY(SILENT_TIME_KEY)<<silent_time << SEP << KEY(GROUP_KEY)<< grp2str() << SEP << KEY(MESSAGE_KEY)<< msg << SEP << KEY(URL_KEY)<< url << SEP << KEY(ON_COMMAND_KEY)<< cmd_name_a << SEP << KEY(OFF_COMMAND_KEY)<< cmd_name_n << SEP << KEY(ENABLED_KEY)<< (enabled ? "1" : "0"); s = conf.str(); } /* * alarm_table class methods */ /* typedef std::string::iterator iterator_t; typedef boost::spirit::node_val_data_factory<unsigned int> factory_t; /////TEMP!!!!!!!!!!!!!!!!!!! typedef boost::spirit::tree_match<iterator_t, factory_t> parse_tree_match_t; typedef boost::spirit::tree_parse_info<iterator_t, factory_t> tree_parse_info_t; */ /* void alarm_table::init(vector<string>& avs, vector<string> &evn, map< string,vector<string> > &alarm_event) { //LOG_STREAM << "alarm_table::init(vector<string>& avs,map< string,vector<string> > &alarm_event): Entering..." << endl; alarm_t tmp_alm; LOG_STREAM << gettime().tv_sec << " " << __FILE__rev << endl; LOG_STREAM << gettime().tv_sec << " alarm_table::init(): Creating Spirit Parser..." << endl; alarm_parse al(tmp_alm); // Construct Spirit grammar if (avs.empty() == false) { for (vector<string>::iterator i = avs.begin(); \ i != avs.end(); i++) { tmp_alm.name.clear(); tmp_alm.formula.clear(); tmp_alm.msg.clear(); tmp_alm.lev.clear(); tmp_alm.grp=0; tree_parse_info_t info = ast_parse<factory_t>(i->begin(), i->end(), al, space_p); if (info.full) { LOG_STREAM << gettime().tv_sec << " Parsing succeeded: " << tmp_alm.name << endl; for (vector<string>::iterator i = evn.begin(); i != evn.end(); i++) LOG_STREAM << gettime().tv_sec << " READ Event! ->" << *i << endl; } else { LOG_STREAM << gettime().tv_sec << " Parsing failed, stopped at: " << string(info.stop, i->end()) << ends; //TODO } if ((tmp_alm.name.empty() == false) && \ (tmp_alm.formula.empty() == false) && \ ((tmp_alm.lev==LEV_LOG)||(tmp_alm.lev==LEV_WARNING)|| \ (tmp_alm.lev==LEV_FAULT)||(tmp_alm.lev.empty() == true))) { tmp_alm.stat = S_NORMAL; tmp_alm.ack = ACK; tmp_alm.done = false; if(tmp_alm.grp == 0) tmp_alm.grp = GR_DEFAULT; if(tmp_alm.lev.empty() == true) tmp_alm.lev = LEV_DEFAULT; push_back(tmp_alm); } else { cerr << gettime().tv_sec << " alarm_table::init(): syntax error in '" << *i \ << "', skipping!" << endl; } } } }*/ void alarm_table::push_back(alarm_t &a) { vlock->writerIn(); //v_alarm.push_back(a); v_alarm.insert(make_pair(a.name,a)); vlock->writerOut(); } void alarm_table::show(vector<string> &al_table_string) { vlock->readerIn(); ostringstream log_msg; string log_str; if (v_alarm.empty() == false) { log_msg << "### alarms table: ###" << ends; al_table_string.push_back(log_msg.str()); log_msg.str(string()); alarm_container_t::iterator i = v_alarm.begin(); unsigned int j = 0; while (i != v_alarm.end()) { log_msg << j << " - name: '" << i->second.name << "'" << ends; al_table_string.push_back(log_msg.str()); log_msg.str(string()); log_msg << " formula: '" << i->second.formula << "'" << ends; al_table_string.push_back(log_msg.str()); log_msg.str(string()); log_msg << " stat: '" << i->second.stat << "'" << ends; al_table_string.push_back(log_msg.str()); log_msg.str(string()); log_msg << " ack: '" << i->second.ack << "'" << ends; al_table_string.push_back(log_msg.str()); log_msg.str(string()); log_msg << " msg: '" << i->second.msg << "'" << ends; al_table_string.push_back(log_msg.str()); log_msg.str(string()); log_msg << " grp: '" << showbase << hex << i->second.grp << "'" << ends; al_table_string.push_back(log_msg.str()); log_msg.str(string()); log_msg << " lev: '" << i->second.lev << "'" << ends; al_table_string.push_back(log_msg.str()); log_msg.str(string()); i++; j++; } } vlock->readerOut(); } unsigned int alarm_table::size(void) { return(v_alarm.size()); } alarm_container_t& alarm_table::get(void) { return(v_alarm); } void alarm_table::stored(vector<alarm_t>& a) { vlock->readerIn(); if (a.empty() == false) { for (vector<alarm_t>::iterator i = a.begin(); i != a.end(); i++) { alarm_container_t::iterator found = v_alarm.find(i->name); if (found != v_alarm.end()) { found->second.ts = i->ts; found->second.stat = i->stat; found->second.ack = i->ack; found->second.done = i->done; found->second.is_new = i->is_new; } else { /* * shouldn't happen!!! */ LOG_STREAM << "alarm_table::stored(): " << i->name \ << " NOT found in alarm table" << endl; } } /* for */ } /* if */ vlock->readerOut(); } bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_t res, string &attr_values, string grp, string msg, string formula) { bool ret_changed=false; Tango::TimeVal now = gettime(); TangoSys_MemStream out_stream; vlock->readerIn(); alarm_container_t::iterator found = v_alarm.find(alm_name); if (found != v_alarm.end()) { if(found->second.silenced > 0) { Tango::TimeVal now = gettime(); double dnow = now.tv_sec + ((double)now.tv_usec) / 1000000; double dsilent = found->second.ts_time_silenced.tv_sec + ((double)found->second.ts_time_silenced.tv_usec) / 1000000; double dminutes = (dnow - dsilent)/60; if(dminutes < found->second.silent_time) { found->second.silenced = found->second.silent_time - floor(dminutes); } else { found->second.silenced = 0; found->second.shelved = false; found->second.is_new = 0; found->second.ack = ACK; } } bool status_err_delay; if(err_delay > 0) status_err_delay = (!res.ex_reason.empty() || !res.ex_desc.empty() || !res.ex_origin.empty()) && (found->second.err_counter >= 1) && ((now.tv_sec - err_delay) > found->second.ts_err_delay.tv_sec); //error is present and err delay has passed else status_err_delay = (!res.ex_reason.empty() || !res.ex_desc.empty() || !res.ex_origin.empty()); found->second.quality = res.quality; found->second.ex_reason = res.ex_reason; found->second.ex_desc = res.ex_desc; found->second.ex_origin = res.ex_origin; bool status_on_delay; if(found->second.on_delay > 0) //if enabled on delay status_on_delay = ((bool)(res.value != 0)) && (found->second.on_counter >= 1) && ((ts.tv_sec - found->second.on_delay) > found->second.ts_on_delay.tv_sec); //formula gives true and on delay has passed else status_on_delay = (bool)(res.value != 0); bool status_off_delay; if(found->second.off_delay > 0) //if enabled off delay status_off_delay = (!(bool)(res.value != 0)) && (found->second.off_counter >= 1) && ((ts.tv_sec - found->second.off_delay) > found->second.ts_off_delay.tv_sec); //formula gives false and off delay has passed else status_off_delay = !(bool)(res.value != 0); //if status changed: // - from S_NORMAL to S_ALARM considering also on delay //or // - from S_ALARM to S_NORMAL considering also off delay if((status_on_delay && (found->second.stat == S_NORMAL)) || (status_off_delay && (found->second.stat == S_ALARM))) { ret_changed=true; if((bool)(res.value != 0)) found->second.ack = NOT_ACK; //if changing from NORMAL to ALARM -> NACK //a.grp = found->second.grp2str(); //a.msg = (int)(res.value) ? found->second.msg : ""; found->second.ts = ts; /* store event timestamp into alarm timestamp */ //here update ts only if status changed if((bool)(res.value != 0)) { found->second.is_new = 1; //here set this alarm as new, read attribute set it to 0 //12-06-08: StopNew command set it to 0 if(found->second.dp_a && ((ts.tv_sec - startup_complete.tv_sec) > 10)) //action from S_NORMAL to S_ALARM { /*try { long call_id; ostringstream tmp; tmp << alm_name << ";" << attr_values; Tango::DevString str = CORBA::string_dup(tmp.str().c_str()); Tango::DeviceData Din; Din << str; CORBA::string_free(str); //found->second.dp_a->ping(); cmdloop->mutex_dp->lock(); //call_id = found->second.dp_a->command_inout_asynch(found->second.cmd_action_a, Din, true); //true -> "fire and forget" mode: client do not care at all about the server answer call_id = found->second.dp_a->command_inout_asynch(found->second.cmd_action_a, Din); //true -> "fire and forget" mode: client do not care at all about the server answer cmdloop->mutex_dp->unlock(); LOG_STREAM << "alarm_table::update() executed action: " << found->second.cmd_name_a << " !!!" << endl; cmd_t arg; arg.cmd_id = call_id; arg.dp_add = (long)found->second.dp_a; arg.arg_s = found->second.cmd_name_a; cmdloop->list.push_back(arg); } catch(Tango::DevFailed e) { string err(e.errors[0].desc); if(err.find("is not yet arrived") == string::npos) //TODO: change this!! out_stream << "Failed to execute action " << found->second.cmd_name_a << ", err=" << e.errors[0].desc << ends; //LOG_STREAM << "alarm_table::update() ERROR: " << out_stream.str() << endl; }*/ ostringstream tmp; string tmp_attr_val = attr_values; replace(tmp_attr_val.begin(), tmp_attr_val.end(), ';' , ','); string tmp_msg = msg; replace(tmp_msg.begin(), tmp_msg.end(), ';' , ','); tmp << "name=" << alm_name << ";groups=" << grp << ";msg="<<tmp_msg<<";values="<<tmp_attr_val<<";formula="<<formula; cmd_t arg; arg.cmd_id = CMD_COMMAND; arg.dp_add = (long)found->second.dp_a; arg.arg_s1 = tmp.str(); arg.arg_s2 = found->second.cmd_action_a; arg.arg_s3 = found->second.cmd_name_a; arg.arg_b = found->second.send_arg_a; cmdloop->list.push_back(arg); } } else { if(found->second.dp_n && ((ts.tv_sec - startup_complete.tv_sec) > 10)) //action from S_ALARM to S_NORMAL { /*try { long call_id; ostringstream tmp; tmp << alm_name << ";" << attr_values; Tango::DevString str = CORBA::string_dup(tmp.str().c_str()); Tango::DeviceData Din; Din << str; CORBA::string_free(str); //found->second.dp_n->ping(); cmdloop->mutex_dp->lock(); //call_id = found->second.dp_n->command_inout_asynch(found->second.cmd_action_n, Din, true); //true -> "fire and forget" mode: client do not care at all about the server answer call_id = found->second.dp_n->command_inout_asynch(found->second.cmd_action_n, Din); //true -> "fire and forget" mode: client do not care at all about the server answer cmdloop->mutex_dp->unlock(); LOG_STREAM << "alarm_table::update() executed action: " << found->second.cmd_name_n << " !!!" << endl; cmd_t arg; arg.cmd_id = call_id; arg.dp_add = (long)found->second.dp_n; arg.arg_s = found->second.cmd_name_n; cmdloop->list.push_back(arg); } catch(Tango::DevFailed e) { string err(e.errors[0].desc); if(err.find("is not yet arrived") == string::npos) //TODO: change this!! out_stream << "Failed to execute action " << found->second.cmd_name_n << ", err=" << e.errors[0].desc << ends; //LOG_STREAM << "alarm_table::update() ERROR: " << out_stream.str() << endl; }*/ ostringstream tmp; string tmp_attr_val = attr_values; replace(tmp_attr_val.begin(), tmp_attr_val.end(), ';' , ','); string tmp_msg = msg; replace(tmp_msg.begin(), tmp_msg.end(), ';' , ','); tmp << "name=" << alm_name << ";groups=" << grp << ";msg="<<tmp_msg<<";values="<<tmp_attr_val<<";formula="<<formula; cmd_t arg; arg.cmd_id = CMD_COMMAND; arg.dp_add = (long)found->second.dp_n; arg.arg_s1 = tmp.str(); arg.arg_s2 = found->second.cmd_action_n; arg.arg_s3 = found->second.cmd_name_n; arg.arg_b = found->second.send_arg_n; cmdloop->list.push_back(arg); } } } if (status_on_delay) { found->second.stat = S_ALARM; //found->second.ack = NOT_ACK; } else if (status_off_delay) { found->second.stat = S_NORMAL; } //if error changed: // - from false to true considering also err delay //or // - from true to false if((status_err_delay && !found->second.error) || (!status_err_delay)) { ret_changed=true; } if(status_err_delay) { if(!found->second.error) found->second.is_new = 1; found->second.error = true; } if((bool)(res.value != 0)) { found->second.on_counter++; found->second.off_counter = 0; } else { found->second.on_counter = 0; found->second.off_counter++; } if(!found->second.ex_reason.empty() || !found->second.ex_desc.empty() || !found->second.ex_origin.empty()) { found->second.err_counter++; } else { found->second.err_counter = 0; found->second.error = false; } found->second.attr_values_delay = attr_values; //save last attr_values to be used in timer_update if this alarm pass over on or off delay if(found->second.on_counter == 1) found->second.ts_on_delay = gettime(); //first occurrance of this alarm, now begin to wait for on delay if(found->second.off_counter == 1) found->second.ts_off_delay = gettime(); //first occurrance of back to normal, now begin to wait for off delay if(found->second.err_counter == 1) found->second.ts_err_delay = gettime(); //first occurrance of this error, now begin to wait for err delay //found->second.ts = ts; /* store event timestamp into alarm timestamp */ //here update ts everytime } else { /* * shouldn't happen!!!! */ out_stream << "couldn't find alarm '" << alm_name << "' in 'alarms' table" << ends; LOG_STREAM << gettime().tv_sec << " alarm_table::update(): " << out_stream.str() << endl; } vlock->readerOut(); if(out_stream.str().length() > 0) throw out_stream.str(); return ret_changed; } bool alarm_table::timer_update() { bool ret_changed=false; Tango::TimeVal ts = gettime(); TangoSys_MemStream out_stream; vlock->readerIn(); for(alarm_container_t::iterator i = v_alarm.begin(); i != v_alarm.end(); i++) { bool status_on_delay=false; bool status_off_delay=false; bool status_err_delay=false; if(err_delay > 0) //if enabled off delay status_err_delay = (i->second.err_counter >= 1) && ((ts.tv_sec - err_delay) > i->second.ts_err_delay.tv_sec); //waiting for err delay has passed if(i->second.on_delay == 0 && i->second.off_delay == 0 && err_delay == 0 && !i->second.shelved && i->second.silenced <=0) continue; //if not enabled on or off delay or not shelved, nothing to do in timer if(i->second.on_delay > 0) //if enabled on delay status_on_delay = (i->second.on_counter >= 1) && ((ts.tv_sec - i->second.on_delay) > i->second.ts_on_delay.tv_sec); //waiting for on delay has passed if(i->second.off_delay > 0) //if enabled off delay status_off_delay = (i->second.off_counter >= 1) && ((ts.tv_sec - i->second.off_delay) > i->second.ts_off_delay.tv_sec); //waiting for off delay has passed //look here also if shelved time ended bool old_shelved = i->second.shelved; int old_silenced = i->second.silenced; if(i->second.silenced > 0) { Tango::TimeVal now = gettime(); double dnow = now.tv_sec + ((double)now.tv_usec) / 1000000; double dsilent = i->second.ts_time_silenced.tv_sec + ((double)i->second.ts_time_silenced.tv_usec) / 1000000; double dminutes = (dnow - dsilent)/60; if(dminutes < i->second.silent_time) { i->second.silenced = i->second.silent_time - floor(dminutes); } else { i->second.silenced = 0; i->second.shelved = false; i->second.is_new = 0; i->second.ack = ACK; } } //if just ended silence time, set ret_changed to true so to push events //TODO: not interested in executing commands? if(old_silenced>0 && i->second.silenced == 0) { ret_changed = true; } //if status changed: // - from S_NORMAL to S_ALARM considering also on delay //or // - from S_ALARM to S_NORMAL considering also off delay //or // - from shelved to not shelved if((status_on_delay && (i->second.stat == S_NORMAL)) || (status_off_delay && (i->second.stat == S_ALARM)) || (old_shelved && !i->second.shelved) || (status_err_delay && !i->second.error)) { if(old_shelved && !i->second.shelved) //TODO: ok to execute on command and off command after shelving ends? { status_on_delay = i->second.stat == S_ALARM; status_off_delay = i->second.stat == S_NORMAL; } ret_changed = true; if(status_err_delay) { if(!i->second.error) i->second.is_new = 1; i->second.error = true; } if(status_on_delay) i->second.ack = NOT_ACK; //if changing from NORMAL to ALARM but not ended shelved time -> NACK i->second.ts = ts; /* store event timestamp into alarm timestamp */ //here update ts only if status changed if(status_on_delay) { i->second.is_new = 1; //here set this alarm as new, read attribute set it to 0 //12-06-08: StopNew command set it to 0 if(i->second.dp_a && ((ts.tv_sec - startup_complete.tv_sec) > 10)) { /*try { long call_id; ostringstream tmp; tmp << i->second.name << ";" << i->second.attr_values_on_delay; Tango::DevString str = CORBA::string_dup(tmp.str().c_str()); Tango::DeviceData Din; Din << str; CORBA::string_free(str); //i->second.dp_a->ping(); cmdloop->mutex_dp->lock(); //call_id = i->second.dp_a->command_inout_asynch(i->second.cmd_action_a, Din, true); //true -> "fire and forget" mode: client do not care at all about the server answer call_id = i->second.dp_a->command_inout_asynch(i->second.cmd_action_a, Din); cmdloop->mutex_dp->unlock(); LOG_STREAM << gettime().tv_sec << " alarm_table::timer_update() executed action: " << i->second.cmd_name_a << " !!!" << endl; cmd_t arg; arg.cmd_id = call_id; arg.dp_add = (long)i->second.dp_a; arg.arg_s = i->second.cmd_name_a; cmdloop->list.push_back(arg); } catch(Tango::DevFailed e) { string err(e.errors[0].desc); if(err.find("is not yet arrived") == string::npos) //TODO: change this!! out_stream << "Failed to execute action " << i->second.cmd_name_a << ", err=" << e.errors[0].desc << ends; //LOG_STREAM << "alarm_table::timer_update() ERROR: " << out_stream.str() << endl; }*/ ostringstream tmp; string tmp_attr_val = i->second.attr_values_delay; replace(tmp_attr_val.begin(), tmp_attr_val.end(), ';' , ','); string tmp_msg = i->second.msg; replace(tmp_msg.begin(), tmp_msg.end(), ';' , ','); tmp << "name=" << i->second.name << ";groups=" << i->second.grp2str() << ";msg="<<tmp_msg<<";values="<<tmp_attr_val<<";formula="<<i->second.formula<<";url="<<i->second.url; cmd_t arg; arg.cmd_id = CMD_COMMAND; arg.dp_add = (long)i->second.dp_a; arg.arg_s1 = tmp.str(); arg.arg_s2 = i->second.cmd_action_a; arg.arg_s3 = i->second.cmd_name_a; arg.arg_b = i->second.send_arg_a; cmdloop->list.push_back(arg); } } else if(status_off_delay && (i->second.stat == S_ALARM)) { if(i->second.dp_n && ((ts.tv_sec - startup_complete.tv_sec) > 10)) { /*try { long call_id; ostringstream tmp; tmp << i->second.name << ";" << i->second.attr_values_off_delay; Tango::DevString str = CORBA::string_dup(tmp.str().c_str()); Tango::DeviceData Din; Din << str; CORBA::string_free(str); //i->second.dp_n->ping(); cmdloop->mutex_dp->lock(); //call_id = i->second.dp_n->command_inout_asynch(i->second.cmd_action_n, Din, true); //true -> "fire and forget" mode: client do not care at all about the server answer call_id = i->second.dp_n->command_inout_asynch(i->second.cmd_action_n, Din); cmdloop->mutex_dp->unlock(); LOG_STREAM << gettime().tv_sec << " alarm_table::timer_update() executed action: " << i->second.cmd_name_n << " !!!" << endl; cmd_t arg; arg.cmd_id = call_id; arg.dp_add = (long)i->second.dp_n; arg.arg_s = i->second.cmd_name_n; cmdloop->list.push_back(arg); } catch(Tango::DevFailed e) { string err(e.errors[0].desc); if(err.find("is not yet arrived") == string::npos) //TODO: change this!! out_stream << "Failed to execute action " << i->second.cmd_name_n << ", err=" << e.errors[0].desc << ends; //LOG_STREAM << "alarm_table::timer_update() ERROR: " << out_stream.str() << endl; }*/ ostringstream tmp; string tmp_attr_val = i->second.attr_values_delay; replace(tmp_attr_val.begin(), tmp_attr_val.end(), ';' , ','); string tmp_msg = i->second.msg; replace(tmp_msg.begin(), tmp_msg.end(), ';' , ','); tmp << "name=" << i->second.name << ";groups=" << i->second.grp2str() << ";msg="<<tmp_msg<<";values="<<tmp_attr_val<<";formula="<<i->second.formula<<";url="<<i->second.url; cmd_t arg; arg.cmd_id = CMD_COMMAND; arg.dp_add = (long)i->second.dp_n; arg.arg_s1 = tmp.str(); arg.arg_s2 = i->second.cmd_action_n; arg.arg_s3 = i->second.cmd_name_n; arg.arg_b = i->second.send_arg_n; cmdloop->list.push_back(arg); } } if((int)(status_on_delay)) { i->second.off_counter = 0; } else if(status_off_delay) { i->second.on_counter = 0; } if(!i->second.enabled) *(i->second.attr_value) = _OOSRV; else if(i->second.shelved && i->second.silenced > 0) *(i->second.attr_value) = _SHLVD; else if((status_off_delay) && i->second.ack == ACK) *(i->second.attr_value) = _NORM; else if((status_on_delay) && i->second.ack == NOT_ACK) *(i->second.attr_value) = _UNACK; else if((status_on_delay) && i->second.ack == ACK) *(i->second.attr_value) = _ACKED; else if((status_off_delay) && i->second.ack == NOT_ACK) *(i->second.attr_value) = _RTNUN; try { if(!i->second.error) { timeval now; gettimeofday(&now, NULL); mydev->push_change_event(i->second.attr_name,(Tango::DevEnum *)i->second.attr_value,now,(Tango::AttrQuality)i->second.quality, 1/*size*/, 0, false); mydev->push_archive_event(i->second.attr_name,(Tango::DevEnum *)i->second.attr_value,now,(Tango::AttrQuality)i->second.quality, 1/*size*/, 0, false); } else { Tango::DevErrorList errors(1); errors.length(1); errors[0].desc = CORBA::string_dup(i->second.ex_desc.c_str()); errors[0].severity = Tango::ERR; errors[0].reason = CORBA::string_dup(i->second.ex_reason.c_str()); errors[0].origin = CORBA::string_dup(i->second.ex_origin.c_str()); Tango::DevFailed except(errors); mydev->push_change_event(i->second.attr_name, &except); mydev->push_archive_event(i->second.attr_name, &except); } } catch(Tango::DevFailed &e) {} } if (status_on_delay) { i->second.stat = S_ALARM; } else if (status_off_delay) { i->second.stat = S_NORMAL; } //found->second.ts = ts; /* store event timestamp into alarm timestamp */ //here update ts everytime } vlock->readerOut(); if(out_stream.str().length() > 0) throw out_stream.str(); return ret_changed; } void alarm_table::erase(alarm_container_t::iterator i) { vlock->writerIn(); v_alarm.erase(i); vlock->writerOut(); } bool alarm_table::exist(string& s) { alarm_container_t::iterator found = v_alarm.find(s); if (found != v_alarm.end()) return true; else return false; } unsigned int alarm_table::to_be_evaluated_num() { unsigned int ret=0; vlock->readerIn(); for(alarm_container_t::iterator i = v_alarm.begin(); i != v_alarm.end(); i++) { if(i->second.to_be_evaluated == true) ret++; } vlock->readerOut(); return ret; } vector<string> alarm_table::to_be_evaluated_list() { vector<string> ret; vlock->readerIn(); for(alarm_container_t::iterator i = v_alarm.begin(); i != v_alarm.end(); i++) { if(i->second.to_be_evaluated == true) ret.push_back(i->first); } vlock->readerOut(); return ret; } void alarm_table::new_rwlock() { #ifndef _USE_BOOST_LOCK vlock = new(ReadersWritersLock); #else vlock = new rwlock_t("VLOCK"); #endif } void alarm_table::del_rwlock() { delete vlock; } void alarm_table::init_cmdthread() { cmdloop = new cmd_thread(); cmdloop->start(); } void alarm_table::stop_cmdthread() { cmd_t arg; //arg.arg_s = CMD_THREAD_EXIT; arg.cmd_id = CMD_THREAD_EXIT; cmdloop->list.push_back(arg); } void alarm_table::save_alarm_conf_db(const string &att_name, const string &name, const string &status, const string &ack, bool enabled, const string &formula, unsigned int on_delay, unsigned int off_delay, const string &grp, const string &lev, const string &msg, const string &url, const string &cmd_a, const string &cmd_n, int silent_time) { // We want to put properties for attribute "att_name" Tango::DbDatum dbd_att_name(att_name); Tango::DbDatum dbd_name(NAME_KEY); Tango::DbDatum dbd_formula(FORMULA_KEY); Tango::DbDatum dbd_on_delay(ONDELAY_KEY); Tango::DbDatum dbd_off_delay(OFFDELAY_KEY); Tango::DbDatum dbd_level(LEVEL_KEY); Tango::DbDatum dbd_silence_time(SILENT_TIME_KEY); //TODO: silent_time Tango::DbDatum dbd_group(GROUP_KEY); Tango::DbDatum dbd_message(MESSAGE_KEY); Tango::DbDatum dbd_url(URL_KEY); Tango::DbDatum dbd_oncommand(ON_COMMAND_KEY); Tango::DbDatum dbd_offcommand(OFF_COMMAND_KEY); Tango::DbDatum dbd_enabled(ENABLED_KEY); Tango::DbData db_data; dbd_att_name << (short int)12; // Twelve properties for attribute "att_name" dbd_name << name.c_str(); dbd_formula << formula.c_str(); dbd_on_delay << (Tango::DevLong)on_delay; dbd_off_delay << (Tango::DevLong)off_delay; dbd_level << lev.c_str(); dbd_silence_time << (Tango::DevLong)silent_time; dbd_group << grp.c_str(); dbd_message << msg.c_str(); dbd_url << url.c_str(); dbd_oncommand << cmd_a.c_str(); dbd_offcommand << cmd_n.c_str(); dbd_enabled << (enabled ? (short int)1 : (short int)0); db_data.push_back(dbd_att_name); db_data.push_back(dbd_name); db_data.push_back(dbd_formula); db_data.push_back(dbd_on_delay); db_data.push_back(dbd_off_delay); db_data.push_back(dbd_level); db_data.push_back(dbd_silence_time); db_data.push_back(dbd_group); db_data.push_back(dbd_message); db_data.push_back(dbd_url); db_data.push_back(dbd_oncommand); db_data.push_back(dbd_offcommand); db_data.push_back(dbd_enabled); string dev_name(mydev->get_name()); try { Tango::DbDevice *db_dev = mydev->get_db_device(); db_dev->get_dbase()->put_device_attribute_property(dev_name,db_data); //Tango::Util::instance()->get_database()->put_device_attribute_property(dev_name,db_data); } catch(Tango::DevFailed &e) { cout << __func__ << ": Exception saving configuration = " << e.errors[0].desc<<endl; } } void alarm_table::delete_alarm_conf_db(string att_name) { // We want to put properties for attribute "att_name" Tango::DbDatum dbd_att_name(att_name); Tango::DbDatum dbd_name(NAME_KEY); Tango::DbDatum dbd_formula(FORMULA_KEY); Tango::DbDatum dbd_on_delay(ONDELAY_KEY); Tango::DbDatum dbd_off_delay(OFFDELAY_KEY); Tango::DbDatum dbd_level(LEVEL_KEY); Tango::DbDatum dbd_silence_time(SILENT_TIME_KEY); //TODO: silent_time Tango::DbDatum dbd_group(GROUP_KEY); Tango::DbDatum dbd_message(MESSAGE_KEY); Tango::DbDatum dbd_url(URL_KEY); Tango::DbDatum dbd_oncommand(ON_COMMAND_KEY); Tango::DbDatum dbd_offcommand(OFF_COMMAND_KEY); Tango::DbDatum dbd_enabled(ENABLED_KEY); Tango::DbData db_data; db_data.push_back(dbd_att_name); db_data.push_back(dbd_name); db_data.push_back(dbd_formula); db_data.push_back(dbd_on_delay); db_data.push_back(dbd_off_delay); db_data.push_back(dbd_level); db_data.push_back(dbd_silence_time); db_data.push_back(dbd_group); db_data.push_back(dbd_message); db_data.push_back(dbd_url); db_data.push_back(dbd_oncommand); db_data.push_back(dbd_offcommand); db_data.push_back(dbd_enabled); string dev_name(mydev->get_name()); try { Tango::DbDevice *db_dev = mydev->get_db_device(); db_dev->get_dbase()->delete_device_attribute_property(dev_name,db_data); } catch(Tango::DevFailed &e) { cout << __func__ << ": Exception deleting " << att_name << " = " << e.errors[0].desc<<endl; } } void alarm_table::get_alarm_list_db(vector<string> &al_list, map<string, string> &saved_alarms, ReadersWritersLock *savedlock) { string dev_name(mydev->get_name()); vector<string> att_list; Tango::DbDevice *db_dev = mydev->get_db_device(); db_dev->get_dbase()->get_device_attribute_list(dev_name,att_list); Tango::DbData db_data; vector<string>::iterator it; for(it = att_list.begin(); it!=att_list.end(); it++) { db_data.push_back(Tango::DbDatum(*it)); } try { db_dev->get_attribute_property(db_data); } catch(Tango::DevFailed &e) { cout << __func__ << ": Exception reading configuration = " << e.errors[0].desc<<endl; } savedlock->writerIn(); saved_alarms.clear(); for (size_t i=0;i < db_data.size();/*i++*/) { Tango::DevLong64 nb_prop; string &att_name = db_data[i].name; db_data[i] >> nb_prop; i++; string alm_name; string alm_formula; string alm_on_delay("0"); string alm_off_delay("0"); string alm_level; string alm_silence_time("-1"); string alm_group; string alm_message; string alm_url; string alm_on_command(""); string alm_off_command(""); string alm_enabled("1"); for (long k=0;k < nb_prop;k++) { string &prop_name = db_data[i].name; if (prop_name == NAME_KEY) db_data[i] >> alm_name; else if (prop_name == FORMULA_KEY) db_data[i] >> alm_formula; else if (prop_name == ONDELAY_KEY) db_data[i] >> alm_on_delay; else if (prop_name == OFFDELAY_KEY) db_data[i] >> alm_off_delay; else if (prop_name == LEVEL_KEY) db_data[i] >> alm_level; else if (prop_name == SILENT_TIME_KEY) db_data[i] >> alm_silence_time; else if (prop_name == GROUP_KEY) db_data[i] >> alm_group; else if (prop_name == MESSAGE_KEY) db_data[i] >> alm_message; else if (prop_name == URL_KEY) db_data[i] >> alm_url; else if (prop_name == ON_COMMAND_KEY) db_data[i] >> alm_on_command; else if (prop_name == OFF_COMMAND_KEY) db_data[i] >> alm_off_command; else if (prop_name == ENABLED_KEY) db_data[i] >> alm_enabled; else { cout << "att_name="<<att_name<<" UNKWNOWN prop_name="<<prop_name<<endl; i++; continue; } i++; } alm_message = std::regex_replace(alm_message, std::regex(";"), "\\;"); alm_url = std::regex_replace(alm_url, std::regex(";"), "\\;"); stringstream alm; alm << KEY(NAME_KEY)<<alm_name << SEP << KEY(FORMULA_KEY)<<alm_formula << SEP << KEY(ONDELAY_KEY)<<alm_on_delay << SEP << KEY(OFFDELAY_KEY)<<alm_off_delay << SEP << KEY(LEVEL_KEY)<< alm_level << SEP << KEY(SILENT_TIME_KEY)<<alm_silence_time << SEP << KEY(GROUP_KEY)<< alm_group << SEP << KEY(MESSAGE_KEY)<< alm_message << SEP << KEY(URL_KEY)<< alm_url << SEP << KEY(ON_COMMAND_KEY)<< alm_on_command << SEP << KEY(OFF_COMMAND_KEY)<< alm_off_command << SEP << KEY(ENABLED_KEY)<< alm_enabled; if(alm_name.empty() || alm_formula.empty() || alm_level.empty() || alm_group.empty() || alm_message.empty()) //TODO: decide if all mandatory { cout << __func__ << ": skipped '" << alm.str() << "'" << endl; continue; } al_list.push_back(alm.str()); saved_alarms.insert(make_pair(alm_name,alm.str())); } savedlock->writerOut(); #if 0 db_dev->get_attribute_property(db_data); //Tango::Util *tg = Tango::Util::instance(); //tg->get_database()->get_device_attribute_property("id11/motor/1", db_data); Tango::Util::instance()->get_database()->get_device_attribute_property("id11/motor/1", db_data); //mydev->get_device_attr(); #endif } /* EOF */