-
Graziano Scalamera authored6083f8e9
Forked from
cs / ds / alarm-handler
52 commits behind the upstream repository.
alarm_table.cpp 35.38 KiB
/*
* 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;
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;
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 */