Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • cs/ds/alarm-handler
  • francesco.tripaldi/alarm-handler
2 results
Show changes
Showing
with 1471 additions and 2160 deletions
docs/images/free_properties.png

68.8 KiB

......@@ -37,6 +37,7 @@
#include <AlarmHandler.h>
#include <AlarmHandlerClass.h>
#include <ctype.h> //for tolower
#include <numeric> //for std::accumulate
#include "alarm-thread.h"
#include "alarm_grammar.h"
......@@ -372,7 +373,7 @@ void AlarmHandler::init_device()
if(instanceCounter > 1)
{
ERROR_STREAM << "More than one instance in the same executable of Alarm Server is not allowed!!" << endl;
cout << "ERROR: second instance of Alarm Server, exiting..." << endl;
TANGO_LOG << "ERROR: second instance of Alarm Server, exiting..." << endl;
exit(-1);
} //-------------------------------------------
alarmedlock = new(ReadersWritersLock);
......@@ -415,6 +416,7 @@ void AlarmHandler::init_device()
alarmSummary_read[i].resize(MAX_ATTR_SUMMARY);
}*/
// Initialize device
alarms.set_al_qual(setAlarmQuality);
alarms.set_err_delay(errorDelay);
thread->period = subscribeRetryPeriod;
......@@ -489,6 +491,8 @@ void AlarmHandler::init_device()
rule_names[formula_grammar::val_qualityID] = "ValQuality";
rule_names[formula_grammar::val_alarm_enum_stID] = "ValAlarmEnumStatus";
rule_names[formula_grammar::propertyID] = "EventProperty";
rule_names[formula_grammar::index_rangeID] = "RangeIndex";
rule_names[formula_grammar::index_listID] = "ListIndex";
/*
* get device attribute properties and initialize internal
......@@ -523,7 +527,7 @@ void AlarmHandler::init_device()
} catch(string & e)
{
ERROR_STREAM << "AlarmHandler::init_device(): " << e << endl;
cout << "Error: " << e << ". Exiting..." << endl;
TANGO_LOG << "Error: " << e << ". Exiting..." << endl;
exit(-4);
}
......@@ -753,7 +757,7 @@ void AlarmHandler::init_device()
}
}
set_change_event("alarm",true,false);
set_change_event("alarm",true,true);
/*
* create alarm processing thread
*/
......@@ -1271,7 +1275,10 @@ void AlarmHandler::read_AlarmState(Tango::Attribute &attr)
break;
}
}
bool error;
bool error=false;
bool enabled=true;
bool shelved=false;
int silenced=0;
if(it != alarms.v_alarm.end())
{
reason = it->second.ex_reason;
......@@ -1279,10 +1286,13 @@ void AlarmHandler::read_AlarmState(Tango::Attribute &attr)
origin = it->second.ex_origin;
quality = it->second.quality;
error = it->second.error;
enabled = it->second.enabled;
shelved = it->second.shelved;
silenced = it->second.silenced;
}
DEBUG_STREAM << "AlarmHandler::read_AlarmState: " << attr.get_name() << " desc=" << desc << endl;
alarms.vlock->readerOut();
if(error) //TODO: if needs to be considered err_delay also in single alarm attributes, error must be used
if(error && enabled && !(shelved && silenced >0)) //TODO: if needs to be considered err_delay also in single alarm attributes, error must be used
//if(desc.length() > 0)
{
Tango::Except::throw_exception(
......@@ -1434,7 +1444,7 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
*attr_value = _RTNUN;
try
{ //DevFailed for push events
if(!localv_alarm.error)
if(!localv_alarm.error || !localv_alarm.enabled || (localv_alarm.shelved && localv_alarm.silenced > 0))
{
timeval now;
gettimeofday(&now, NULL);
......@@ -1915,13 +1925,13 @@ Tango::DevVarStringArray *AlarmHandler::search_alarm(Tango::DevString argin)
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}*/
start_pos = filter.find("*", start_pos);
if(start_pos != std::string::npos && start_pos == filter.size()-1) //* is the only character or at the end of the filter
if(start_pos != std::string::npos && start_pos == filter.size()-1) // * is the only character or at the end of the filter
{
filter.replace(start_pos, 1, "");
filter_begin = filter;
DEBUG_STREAM << __func__ << ": updated filter to: " << filter_begin;
}
/*else if(start_pos != std::string::npos) //* is in the middle of the filter
/*else if(start_pos != std::string::npos) // * is in the middle of the filter
{
string filter_begin=filter.substr(0,start_pos);
string filter_end=filter.substr(start_pos+1);
......@@ -1951,7 +1961,7 @@ Tango::DevVarStringArray *AlarmHandler::search_alarm(Tango::DevString argin)
os.clear();
os << KEY(NAME_KEY) << ai->second.name << SEP << KEY(FORMULA_KEY) << ai->second.formula << SEP << KEY(ONDELAY_KEY) << ai->second.on_delay << SEP << KEY(OFFDELAY_KEY) << ai->second.off_delay <<
SEP << KEY(LEVEL_KEY) << ai->second.lev << SEP << KEY(SILENT_TIME_KEY) << ai->second.silent_time << SEP << KEY(GROUP_KEY) << ai->second.grp2str() << SEP << KEY(MESSAGE_KEY) << ai->second.msg << SEP << KEY(URL_KEY) << ai->second.url <<
SEP << KEY(ON_COMMAND_KEY) << ai->second.cmd_name_a << SEP << KEY(OFF_COMMAND_KEY) << ai->second.cmd_name_n << SEP << KEY(ENABLED_KEY) << (ai->second.enabled ? "1" : "0");
SEP << KEY(ON_COMMAND_KEY) << ai->second.cmd_name_a << SEP << KEY(OFF_COMMAND_KEY) << ai->second.cmd_name_n << SEP << KEY(RECEIVERS_KEY) << ai->second.receivers << SEP << KEY(ENABLED_KEY) << (ai->second.enabled ? "1" : "0");
alarm_filtered.push_back(os.str());
}
} /* for */
......@@ -2249,6 +2259,7 @@ void AlarmHandler::modify(Tango::DevString argin)
i->second.cmd_dp_n = alm.cmd_dp_n;
i->second.cmd_action_n = alm.cmd_action_n;
//i->second.send_arg_n = alm.send_arg_n;
i->second.receivers = alm.receivers;
i->second.enabled = alm.enabled;
//update attribute properties
......@@ -2346,7 +2357,7 @@ void AlarmHandler::modify(Tango::DevString argin)
//4: load modified alarm
//------------------------------
load(argin);
usleep(150000);//wait some time before updating attributes with prepare_alarm_attr so that event are subscribed and first evaluation done
prepare_alarm_attr();
try
{
......@@ -2510,7 +2521,9 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
*attr_value = _SHLVD;
try
{ //DevFailed for push events
#if 0//do not store errors for disabled alarms
if(!alm.error)
#endif
{
timeval now;
gettimeofday(&now, NULL);
......@@ -2525,6 +2538,7 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value);
}
}
#if 0//do not store errors for disabled alarms
else
{
Tango::DevErrorList errors(1);
......@@ -2537,6 +2551,7 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
push_change_event(alm.attr_name, &except);
push_archive_event(alm.attr_name, &except);
}
#endif
} catch(Tango::DevFailed & ex)
{
WARN_STREAM << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
......@@ -2757,7 +2772,9 @@ void AlarmHandler::disable(Tango::DevString argin)
*attr_value = _OOSRV;
try
{ //DevFailed for push events
#if 0 //do not store errors for disabled alarms
if(!alm.error)
#endif
{
timeval now;
gettimeofday(&now, NULL);
......@@ -2772,6 +2789,7 @@ void AlarmHandler::disable(Tango::DevString argin)
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value);
}
}
#if 0 //do not store errors for disabled alarms
else
{
Tango::DevErrorList errors(1);
......@@ -2784,6 +2802,7 @@ void AlarmHandler::disable(Tango::DevString argin)
push_change_event(alm.attr_name, &except);
push_archive_event(alm.attr_name, &except);
}
#endif
} catch(Tango::DevFailed & ex)
{
WARN_STREAM << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
......@@ -3018,8 +3037,13 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
if(it->second.error)
{
tmp_ex << "{\"Reason\":\"" << it->second.ex_reason << "\",\"Desc\":\"" << it->second.ex_desc << "\",\"Origin\":\"" << it->second.ex_origin << "\"}";
info.insert(make_pair(VALUE_KEY,string("ERROR")));
complete.push_back(KEY(VALUE_KEY)+string("ERROR"));
string almstate(tmp_val.str());
if(almstate != "SHLVD" && almstate != "OOSRV")
{
almstate = S_ERROR;
}
info.insert(make_pair(VALUE_KEY,almstate));
complete.push_back(KEY(VALUE_KEY)+almstate);
info.insert(make_pair(MESSAGE_KEY,tmp.str()));
complete.push_back(KEY(MESSAGE_KEY)+tmp.str());
info.insert(make_pair(URL_KEY,it->second.url));
......@@ -3043,6 +3067,17 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
complete.push_back(KEY(ATTR_VALUES_KEY)+it->second.attr_values);
}
tm time_tm;
time_t time_sec= it->second.ts.tv_sec;
//gmtime_r(&time_sec,&time_tm); //-> UTC
localtime_r(&time_sec,&time_tm);
char time_buf[64];
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
ostringstream time_s;
time_s << time_buf << "." << it->second.ts.tv_usec;
info.insert(make_pair(ALARM_TIME_KEY,time_s.str()));
complete.push_back(KEY(ALARM_TIME_KEY)+time_s.str());
ostringstream tmp_qual;
try
{
......@@ -3113,7 +3148,8 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
complete.push_back(KEY(ON_COMMAND_KEY)+it->second.cmd_name_a);
info.insert(make_pair(OFF_COMMAND_KEY,it->second.cmd_name_n));
complete.push_back(KEY(OFF_COMMAND_KEY)+it->second.cmd_name_n);
info.insert(make_pair(RECEIVERS_KEY,it->second.receivers));
complete.push_back(KEY(RECEIVERS_KEY)+it->second.receivers);
alarms.vlock->readerOut();
argout = new Tango::DevVarStringArray();
if(argin->length() == 1)
......@@ -3243,6 +3279,7 @@ void AlarmHandler::load_alarm(string alarm_string, alarm_t &alm, vector<string>
alm.send_arg_n = false;
alm.dp_n = NULL;
alm.enabled = 1;
alm.receivers.clear();
evn.clear();
alm.formula_tree =
......@@ -3263,6 +3300,7 @@ void AlarmHandler::load_alarm(string alarm_string, alarm_t &alm, vector<string>
std::transform(alm.lev.begin(), alm.lev.end(), alm.lev.begin(), (int(*)(int))tolower); //transform to lowercase
alm.msg = std::regex_replace(alm.msg, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
alm.url = std::regex_replace(alm.url, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
alm.receivers = std::regex_replace(alm.receivers, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
if(alm.cmd_name_a.length() > 0)
{
const char *c = alm.cmd_name_a.c_str();
......@@ -3327,6 +3365,7 @@ void AlarmHandler::load_alarm(string alarm_string, alarm_t &alm, vector<string>
DEBUG_STREAM << " lev = '" << alm.lev << "'" << endl;
DEBUG_STREAM << " action_a = '" << alm.cmd_name_a << "'" << endl;
DEBUG_STREAM << " action_n = '" << alm.cmd_name_n << "'" << endl;
DEBUG_STREAM << " receivers = '" << alm.receivers << "'" << endl;
DEBUG_STREAM << " enabled = '" << (alm.enabled ? "1" : "0") << "'" << endl;
if ((alm.name.empty() == false) && \
(alm.formula.empty() == false) && \
......@@ -3433,7 +3472,7 @@ void AlarmHandler::add_alarm(alarm_t& a, bool starting)
}
}
void AlarmHandler::add_event(alarm_t& a, vector<string> &evn) throw(string&)
void AlarmHandler::add_event(alarm_t& a, vector<string> &evn)
{
DEBUG_STREAM << "AlarmHandler::add_event(): formula '" << a.formula << "' found " << evn.size() << " events" << endl;
/*
......@@ -3621,6 +3660,7 @@ void AlarmHandler::do_alarm(bei_t& e)
}
if(found_ev != events->v_event.end())
{
found_ev->valid = false;
Tango::TimeVal ts = gettime();
found_ev->err_counter++;
if(e.type == TYPE_TANGO_ERR)
......@@ -3639,10 +3679,15 @@ void AlarmHandler::do_alarm(bei_t& e)
list<string>::iterator j = m_alarm.begin();
while (j != m_alarm.end())
{
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": before do_alarm_eval name=" << *j << " ev=" << e.ev_name << " err=" << found_ev_ex_desc << endl;
changed = do_alarm_eval(*j, e.ev_name, ts);
//if(!changed)
// continue; //TODO: check if OK
alarms.vlock->readerIn();
alarm_container_t::iterator it = alarms.v_alarm.find(*j);
if(it != alarms.v_alarm.end())
{
#if 0 //already done in alarm_table::update called by do_alarm_eval
it->second.err_counter++;
//if first error, reset ACK
if(it->second.ex_reason.empty() && it->second.ex_desc.empty() && it->second.ex_origin.empty())
......@@ -3676,9 +3721,12 @@ void AlarmHandler::do_alarm(bei_t& e)
}
it->second.error = true;
}
#endif
alarm_t alm = it->second;
alarms.vlock->readerOut();
if(alm.error)
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": after do_alarm_eval name=" << *j << " error=" << (int)alm.error << " enabled=" << alm.enabled << endl;
#if 0 //TODO: already pushed in do_alarm_eval, not necessary here ?
if(alm.error && alm.enabled && !(alm.shelved && alm.silenced > 0))
{
try
{
......@@ -3695,6 +3743,31 @@ void AlarmHandler::do_alarm(bei_t& e)
}catch(Tango::DevFailed &ex)
{}
}
else if(alm.error) //TODO: or if(changed) ?
{
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(alm.attr_name);
if(!alm.enabled)
{
*attr_value = _OOSRV;
}
else if(alm.shelved && alm.silenced > 0)
{
*attr_value = _SHLVD;
}
if(setAlarmQuality)
{
timeval now;
gettimeofday(&now, NULL);
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,static_cast<Tango::AttrQuality>(alm.quality), 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,static_cast<Tango::AttrQuality>(alm.quality), 1/*size*/, 0, false);
}
else
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value);
}
}
#endif
}
else
{
......@@ -3742,10 +3815,14 @@ void AlarmHandler::do_alarm(bei_t& e)
push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_archive_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
}
else
{
events->veclock.readerOut();
}
return;
}
}
//here not event error
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": arrived event=" << e.ev_name << endl;
formula_res_t res;
events->veclock.readerIn();
vector<event>::iterator found = \
find(events->v_event.begin(), events->v_event.end(), e.ev_name);
......@@ -3789,9 +3866,12 @@ void AlarmHandler::do_alarm(bei_t& e)
}
}
if (found != events->v_event.end())
{
{
found->value = e.value;
found->value_string = e.value_string;
found->read_size = e.read_size;
found->dim_x = e.dim_x;
found->dim_y = e.dim_y;
found->quality = e.quality;
//found->errors = e.errors;
found->ex_reason = e.ex_reason;
......@@ -3874,6 +3954,7 @@ void AlarmHandler::do_alarm(bei_t& e)
}
else
{
events->veclock.readerOut();
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": event=" << e.ev_name << "NOT FOUND IN EVENT TABLE" << endl;
}
} /* do_alarm() */
......@@ -3913,10 +3994,10 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
it->second.to_be_evaluated = false;
it->second.attr_values.erase(it->second.attr_values.size()-1);
it->second.attr_values += string("}");
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": Evaluation of " << it->second.formula << "; result=" << res.value << " quality=" << res.quality << endl;
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": Evaluation of " << it->second.formula << "; result=" << print_array(res.value,res.dim_x,res.dim_y) << " quality=" << res.quality << " valid=" << (int)res.valid << endl;
changed = alarms.update(tmpname, ts, res, it->second.attr_values, it->second.grp2str(), it->second.msg, it->second.formula); //update internal structure and log to db
changed = changed || prev_error;
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": changed=" << (int)changed << endl;
changed = changed || (prev_error && res.valid);
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": changed=" << (int)changed << " error=" << (int)it->second.error << endl;
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name);
if(!it->second.enabled)
*attr_value = _OOSRV;
......@@ -3937,7 +4018,7 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks
try
{ //DevFailed for push events
if(!it->second.error)
if(!it->second.error || !it->second.enabled || (it->second.shelved && it->second.silenced > 0))
{
timeval now;
gettimeofday(&now, NULL);
......@@ -3970,7 +4051,8 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
}
} catch(std::out_of_range& ex)
{
changed = !prev_error;
events->veclock.readerOut(); //readerIn called in eval_expression
changed = true;//force update attributes in case of modify/load alarm with out_of_range exception
it->second.to_be_evaluated = true;
ostringstream o;
o << tmpname << ": in formula array index out of range!";
......@@ -3981,16 +4063,29 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
Tango::DevErrorList errors(1);
errors.length(1);
it->second.ex_reason = string("OUT_OF_RANGE");
it->second.ex_desc = ev_name + ": " + o.str();
it->second.ex_desc = o.str();
it->second.ex_origin = ev_name;
errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str());
errors[0].severity = Tango::ERR;
errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str());
errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str());
Tango::DevFailed except(errors);
bool enabled=it->second.enabled;
bool shelved=it->second.shelved;
int silenced=it->second.silenced;
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name);
it->second.error=true;
it->second.quality = Tango::ATTR_INVALID;
if(enabled && !(shelved && silenced >0))
{
*attr_value = _ERROR;
}
alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks
push_change_event(attr_name, &except);
push_archive_event(attr_name, &except);
if(enabled && !(shelved && silenced >0))
{
push_change_event(attr_name, &except);
push_archive_event(attr_name, &except);
}
} catch(Tango::DevFailed & ex)
{
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << attr_name << " - EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
......@@ -4000,7 +4095,7 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
changed = !prev_error;
it->second.to_be_evaluated = true;
ostringstream o;
o << tmpname << ": in formula err=" << ex;
o << ex;
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl;
set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());
try
......@@ -4008,16 +4103,70 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
Tango::DevErrorList errors(1);
errors.length(1);
it->second.ex_reason = string("FORMULA_ERROR");
it->second.ex_desc = ev_name + ": " + o.str();
it->second.ex_desc = o.str();
it->second.ex_origin = ev_name;
errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str());
errors[0].severity = Tango::ERR;
errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str());
errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str());
Tango::DevFailed except(errors);
bool enabled=it->second.enabled;
bool shelved=it->second.shelved;
int silenced=it->second.silenced;
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name);
it->second.error=true;
it->second.quality = Tango::ATTR_INVALID;
if(enabled && !(shelved && silenced >0))
{
*attr_value = _ERROR;
}
alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks
if(enabled && !(shelved && silenced >0))
{
push_change_event(attr_name, &except);
push_archive_event(attr_name, &except);
}
} catch(Tango::DevFailed & ex)
{
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << attr_name << " - EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
}
}
catch(Tango::DevFailed & ex)
{
changed = !prev_error;
it->second.to_be_evaluated = true;
ostringstream o;
o << ex.errors[0].desc;
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl;
set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());
try
{ //DevFailed for push events
Tango::DevErrorList errors(1);
errors.length(1);
it->second.ex_reason = ex.errors[0].reason;
it->second.ex_desc = ex.errors[0].desc;
it->second.ex_origin = ex.errors[0].origin;
errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str());
errors[0].severity = Tango::ERR;
errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str());
errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str());
Tango::DevFailed except(errors);
bool enabled=it->second.enabled;
bool shelved=it->second.shelved;
int silenced=it->second.silenced;
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name);
it->second.error=true;
it->second.quality = Tango::ATTR_INVALID;
if(enabled && !(shelved && silenced >0))
{
*attr_value = _ERROR;
}
alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks
push_change_event(attr_name, &except);
push_archive_event(attr_name, &except);
if(enabled && !(shelved && silenced >0))
{
push_change_event(attr_name, &except);
push_archive_event(attr_name, &except);
}
} catch(Tango::DevFailed & ex)
{
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << attr_name << " - EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
......@@ -4026,6 +4175,7 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
}
else
{
alarms.vlock->readerOut();
ostringstream o;
//o << j->first << ": not found formula in alarm table" << ends;
o << (alm_name) << ": not found formula in alarm table";
......@@ -4086,6 +4236,7 @@ void AlarmHandler::timer_update()
{
return;
}
DEBUG_STREAM << "AlarmHandler::timer_update(): changed -> prepare_alarm_attr" << endl;
prepare_alarm_attr();//TODO: frequencyAlarm should be updated anyway
try
{
......@@ -4135,7 +4286,7 @@ void AlarmHandler::timer_update()
}
}
bool AlarmHandler::remove_alarm(string& s) throw(string&)
bool AlarmHandler::remove_alarm(string& s)
{
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": entering alm name=" << s << endl;
alarms.vlock->writerIn();
......@@ -4245,7 +4396,7 @@ bool AlarmHandler::remove_alarm(string& s) throw(string&)
} /* remove_alarm() */
/*void AlarmHandler::add_to_database(alarm_t& a) throw(string&)
/*void AlarmHandler::add_to_database(alarm_t& a)
{
Tango::DbDatum alarm("alarm");
Tango::DbData db_data;
......@@ -4370,14 +4521,59 @@ void AlarmHandler::set_internal_alarm(string name, Tango::TimeVal t, string msg,
//==============================================================
formula_res_t AlarmHandler::eval_formula(tree_parse_info_t tree, string &attr_values)
{
return eval_expression(tree.trees.begin(), attr_values);
formula_res_t res = eval_expression(tree.trees.begin(), attr_values);
res.extract_result(); //from Array res.value to Scalar res.value
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << __func__ << ": finally value=" << print_array(res.value,res.dim_x,res.dim_y) << " valid=" << (int)res.valid << " error='" << res.error << "' ex_desc='" << res.ex_desc<<"' quality=" << res.quality << endl;
#endif
if(res.valid)
{
res.ex_reason.clear();
res.ex_desc.clear();
res.ex_origin.clear();
res.error.clear();
}
return res;
}
formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values, int ev_ind) //throw (string &), std::out_of_range
void AlarmHandler::eval_index_range(iter_t const& i, string &attr_values, vector<double> & ind)
{
if(i->value.id() == formula_grammar::index_rangeID || i->value.id() == formula_grammar::indexID)
{
if(i->children.size() == 0)
{
std::string val_s(i->value.begin(), i->value.end());
long value = strtol(val_s.c_str(), NULL, 10);
if(value>=0)
{
ind.push_back(value);
}
else if(value == -1)
{
ind = {(double)(value)};
}
}
else if(i->children.size() == 2)
{
iter_t child = i->children.begin();
string val_s1(child->value.begin(), child->value.end());
long ind_start = strtol(val_s1.c_str(), NULL, 10);
string val_s2((child+1)->value.begin(), (child+1)->value.end());
long ind_end = strtol(val_s2.c_str(), NULL, 10);
if(ind_start>=0 && ind_end>=ind_start)
{
for(int ind_range=ind_start; ind_range<=ind_end; ind_range++)
ind.push_back((double)ind_range);
}
}
}
}
formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values, vector< vector<double> > ev_ind)
{
ostringstream err;
err << "Evaluating formula: ";
err << "";
//iter_t it = i->children.begin();
if (i->value.id() == formula_grammar::val_rID)
......@@ -4389,9 +4585,12 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
}
string val_d(i->value.begin(), i->value.end());
formula_res_t res;
res.value = strtod(val_d.c_str(), 0);
res.value = {(strtod(val_d.c_str(), 0))};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node value real = " << val_d << "(value="<<res.value<<" quality="<<res.quality<<")" << endl;
DEBUG_STREAM << " node value real = " << val_d << "(value="<<print_array(res.value,res.dim_x,res.dim_y)<<" quality="<<res.quality<<")" << endl;
#endif
return res;
}
......@@ -4407,7 +4606,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node value hex = " << val_d << endl;
#endif
formula_res_t res;
res.value = strtod(val_d.c_str(), 0);
res.value = {(strtod(val_d.c_str(), 0))};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
return res;
}
else if (i->value.id() == formula_grammar::val_stID)
......@@ -4423,7 +4625,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node value state : " << val_st << "=" << st << endl;
#endif
formula_res_t res;
res.value = st;
res.value = {(double)st};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
return res;
}
else if (i->value.id() == formula_grammar::val_alarm_enum_stID)
......@@ -4439,7 +4644,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node value alarm enum state : " << val_st << "=" << st << endl;
#endif
formula_res_t res;
res.value = st;
res.value = {(double)st};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
return res;
}
else if (i->value.id() == formula_grammar::val_qualityID)
......@@ -4456,7 +4664,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node value quality : " << val_quality << "=" << quality << endl;
#endif
formula_res_t res;
res.value = quality;
res.value = {(double)quality};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
return res;
}
else if (i->value.id() == formula_grammar::unary_exprID)
......@@ -4469,26 +4680,23 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
err << "in node unary_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
throw err.str();
}
formula_res_t res;
res = eval_expression(i->children.begin(), attr_values);
if (*i->value.begin() == '+')
{
res.value = + res.value;
return eval_expression(i->children.begin(), attr_values);
}
else if (*i->value.begin() == '-')
{
res.value = - res.value;
return -eval_expression(i->children.begin(), attr_values);
}
else if (*i->value.begin() == '!')
{
res.value = ! res.value;
return !eval_expression(i->children.begin(), attr_values);
}
else
{
err << "in node unary_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
throw err.str();
}
return res;
}
else if (i->value.id() == formula_grammar::mult_exprID)
{
......@@ -4548,49 +4756,104 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node event" << string(i->value.begin(), i->value.end()) << endl;
#endif
formula_res_t ind;
if(i->children.size() != 2)
if(i->children.size() < 2)
{
err << "in node event_ID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();;
throw err.str();
}
if((i->children.begin()+1)->value.id() == formula_grammar::indexID)
ind = eval_expression(i->children.begin()+1, attr_values); //array index
else if((i->children.begin()+1)->value.id() == formula_grammar::propertyID)
vector<vector<double> > indexes;
iter_t child = i->children.begin();
if(child->value.id() != formula_grammar::nameID)
{
if(string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end()) == ".quality")
err << "in node "<< rule_names[i->value.id()]<<"(" << string(i->value.begin(), i->value.end()) << ") expecting " << rule_names[formula_grammar::nameID] << " as first child";
throw err.str();
}
child++;
while(child != i->children.end() && child->value.id() != formula_grammar::propertyID) //eval indexes
{
if(child->value.id() == formula_grammar::index_rangeID || child->value.id() == formula_grammar::indexID)
{
vector<double> ind_range;
eval_index_range(child, attr_values, ind_range);
if(!ind_range.empty())
indexes.push_back(ind_range);
}
else if(child->value.id() == formula_grammar::index_listID)
{
formula_res_t res = eval_expression(i->children.begin(), attr_values, (int)ind.value);
res.value = res.quality;
vector<double> ind_list;
iter_t granchild = child->children.begin();
while(granchild != child->children.end() && granchild->value.id() == formula_grammar::index_rangeID) //eval indexes
{
eval_index_range(granchild, attr_values, ind_list);
granchild++;
}
if(!ind_list.empty())
indexes.push_back(ind_list);
}
child++;
}
if(child - i->children.begin() == (long int)i->children.size() -1 && child->value.id() == formula_grammar::propertyID)
{
if(string(child->value.begin(), child->value.end()) == ".quality")
{
formula_res_t res;
res = eval_expression(i->children.begin(), attr_values);
res.value = {(double)res.quality};
res.dim_x=1;
res.dim_y=0;
ostringstream temp_attr_val;
temp_attr_val << "\"" << res.attr_name << string(child->value.begin(), child->value.end()) << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node event.quality -> " << res.value << endl;
DEBUG_STREAM << " node event.quality -> " << print_array(res.value,res.dim_x,res.dim_y) << endl;
#endif
return res;
}
else if(string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end()) == ".alarm")
else if(string(child->value.begin(), child->value.end()) == ".alarm")
{
formula_res_t res = eval_expression(i->children.begin(), attr_values, (int)ind.value);
res.value = (res.value == _UNACK) || (res.value == _ACKED);
formula_res_t res;
if(!indexes.empty())
res = eval_expression(i->children.begin(), attr_values, indexes);
else
res = eval_expression(i->children.begin(), attr_values);
std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return (double)((n == _UNACK) || (n == _ACKED)); });
ostringstream temp_attr_val;
temp_attr_val << "\"" << res.attr_name << string(child->value.begin(), child->value.end()) << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node event.alarm -> " << res.value << endl;
DEBUG_STREAM << " node event.alarm -> " << print_array(res.value,res.dim_x,res.dim_y)<< endl;
#endif
return res;
}
else if(string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end()) == ".normal")
else if(string(child->value.begin(), child->value.end()) == ".normal")
{
formula_res_t res = eval_expression(i->children.begin(), attr_values, (int)ind.value);
res.value = (res.value == _NORM) || (res.value == _RTNUN);
formula_res_t res;
if(!indexes.empty())
res = eval_expression(i->children.begin(), attr_values, indexes);
else
res = eval_expression(i->children.begin(), attr_values);
std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return (double)((n == _NORM) || (n == _RTNUN)); });
ostringstream temp_attr_val;
temp_attr_val << "\"" << res.attr_name << string(child->value.begin(), child->value.end()) << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node event.normal -> " << res.value << endl;
DEBUG_STREAM << " node event.normal -> " << print_array(res.value,res.dim_x,res.dim_y) << endl;
#endif
return res;
}
}
else
else if(child - i->children.begin() < (long int)i->children.size() -1)//unsupported more indexes/qualities
{
err << "in node event_ID(" << string(i->value.begin(), i->value.end()) << ") children2 is not an index ->" << string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end());
err << "expecting indexes or properties after attribute name, found instead: "<< string(child->value.begin(), child->value.end());
throw err.str();
}
return eval_expression(i->children.begin(), attr_values, (int)ind.value);
if(!indexes.empty())
return eval_expression(i->children.begin(), attr_values, indexes);
else
return eval_expression(i->children.begin(), attr_values);
}
else if (i->value.id() == formula_grammar::nameID)
{
......@@ -4610,37 +4873,412 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
if(!it->valid)
{
if(it->ex_desc.length() > 0)
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' exception: '" << it->ex_desc << "'";
err << it->ex_desc << "";
else
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' value not valid!";
err << "attribute " << string(i->value.begin(), i->value.end()) << " value not valid while evaluating formula";
formula_res_t res;
res.valid = false;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
res.error = err.str();
res.attr_name = it->name;
ostringstream temp_attr_val;
temp_attr_val << "\"" << it->name << "\":{\"Reason\":\"" << res.ex_reason << "\",\"Desc\":\"" << res.ex_desc << "\",\"Origin\":\"" << res.ex_origin << "\"},";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " attribute -> " << string(i->value.begin(), i->value.end()) << " value not valid, desc=" << res.ex_desc << " quality=" << res.quality << endl;
#endif
events->veclock.readerOut();
throw err.str();
//throw err.str();
return res;
}
else if(it->type != Tango::DEV_STRING && it->value.empty())
{
if(it->ex_desc.length() > 0)
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' exception: '" << it->ex_desc << "'";
err << it->ex_desc << "";
else
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' value not initialized!!";
err << "attribute " << string(i->value.begin(), i->value.end()) << " value not initialized while evaluating formula";
formula_res_t res;
res.valid = false;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
res.error = err.str();
res.attr_name = it->name;
ostringstream temp_attr_val;
temp_attr_val << "\"" << it->name << "\":{\"Reason\":\"" << res.ex_reason << "\",\"Desc\":\"" << res.ex_desc << "\",\"Origin\":\"" << res.ex_origin << "\"},";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " attribute -> " << string(i->value.begin(), i->value.end()) << " value empty, desc=" << res.ex_desc << " quality=" << res.quality << endl;
#endif
events->veclock.readerOut();
throw err.str();
}
ostringstream temp_attr_val;
if(it->value.size() > 1)
temp_attr_val << "\"" << it->name << "[" << ev_ind << "]\":" <<it->value.at(ev_ind) << ",";//throw std::out_of_range
else
temp_attr_val << "\"" << it->name << "\":" <<it->value.at(ev_ind) << ",";//throw std::out_of_range
attr_values += temp_attr_val.str();
//throw err.str();
return res;
}
formula_res_t res;
res.valid = true;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
res.attr_name = it->name;
ostringstream temp_attr_val;
if(it->value.size() > 0)
{
if(!ev_ind.empty())
{
temp_attr_val << "\"" << it->name;
for(auto vei : ev_ind)
{
if(!vei.empty())
{
temp_attr_val << "[" << print_vector(vei) << "]";
}
}
temp_attr_val << "\":";
if(it->dim_y <=1)//1D array
{
if(ev_ind.size() ==1 && ev_ind[0].size() == 1 && ev_ind[0][0] != -1)//single element of 1D array (e.g. [0])
{
res.dim_x = 1;
res.dim_y = 0;
if(ev_ind[0][0] >= it->value.size())
{
err << "Requested element " << ev_ind[0][0] << " is out of bounds with dim=" << it->value.size();
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value = {it->value.at(ev_ind[0][0])};//throw std::out_of_range
temp_attr_val << "[" << res.value[0] << "],";
}
else if(ev_ind.size() ==1 && ev_ind[0].size() > 1)//multiple elements of 1D array (e.g. [0,1,2])
{
res.dim_y = 0;
for(auto ei0 : ev_ind[0])
{
if(ei0 < 0 || ei0 >= it->value.size())
{
err << "Requested element " << ei0 << " is out of bounds with dim=" << it->value.size();
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
else
{
res.value.push_back(it->value.at(ei0));//throw std::out_of_range
}
}
res.dim_x = res.value.size();
temp_attr_val << print_array(res.value, res.dim_x, res.dim_y) << ",";
}
else if(ev_ind.size() ==1 && ev_ind[0].size() == 1 && ev_ind[0][0]==-1)//all elements of 1D array (e.g. [-1])
{
res.dim_y = 0;
res.value = it->value;
res.dim_x = it->dim_x;
temp_attr_val << print_array(res.value, res.dim_x, res.dim_y) <<",";
}
else
{
err << "UNSUPPORTED additional indexes in 1D array: " << ev_ind.size() << " indexes given, dim_x=" << it->dim_x << " dim_y=" << it->dim_y;
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
events->veclock.readerOut();
throw err.str();
}
}
else if(it->dim_y > 1)//2D array
{
//single row of 2D array (e.g. [0] or [0][-1])
if((ev_ind.size() == 1 || //only first index
(ev_ind.size() == 2 && ev_ind[1].size() == 1 && ev_ind[1][0] == -1)) //or also second index = -1
&& ev_ind[0].size() == 1 && ev_ind[0][0] != -1) // and first index not -1
{
res.dim_y = 0;
if(ev_ind[0][0] >= it->dim_y)
{
err << "Requested row " << ev_ind[0][0] << " is out of bounds with dim_y=" << it->dim_y;
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
auto vstart = it->value.begin();//start iterator of a row in a vector containing a 2D array
auto vend = it->value.begin();//end iterator of a row in a vector containing a 2D array
advance(vstart,(int)(ev_ind[0][0] * (it->dim_x)));
advance(vend,(int)(ev_ind[0][0]+1) * it->dim_x);
res.value = value_t(vstart,vend);
temp_attr_val << "" << print_array(res.value,res.dim_x,res.dim_y) << ",";
}
else if((ev_ind.size() == 1 || //only first index
(ev_ind.size() == 2 && ev_ind[1].size() == 1 && ev_ind[1][0] == -1)) //or also second index = -1
&& ev_ind[0].size() > 1)//multiple rows of 2D array (e.g. [0,1,2] or [0,1,2][-1])
{
res.dim_x = it->dim_x;
res.dim_y = ev_ind[0].size();
for(auto ei0 : ev_ind[0])
{
if(ei0 < 0 || ei0 >= it->value.size())
{
err << "Requested element " << ei0 << " is out of bounds with dim=" << it->value.size();
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
else
{
auto vstart = it->value.begin();//start iterator of a row in a vector containing a 2D array
auto vend = it->value.begin();//end iterator of a row in a vector containing a 2D array
advance(vstart,(int)(ei0 * (it->dim_x)));
advance(vend,(int)(ei0+1) * it->dim_x);
value_t row = value_t(vstart,vend);
res.value.insert(
res.value.end(),
std::make_move_iterator(row.begin()),
std::make_move_iterator(row.end())
);
}
}
temp_attr_val << print_array(res.value,res.dim_x,res.dim_y) << ",";
}
else if((ev_ind.size() == 1 || //only first index
(ev_ind.size() == 2 && ev_ind[1].size() == 1 && ev_ind[1][0] == -1)) //or also second index = -1
&& ev_ind[0].size() == 1 && ev_ind[0][0] == -1)//all rows of 2D array (e.g. [-1] or [-1][-1])
{
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.value = it->value;
temp_attr_val << print_array(res.value,res.dim_x,res.dim_y) << ",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] != -1 && ev_ind[1].size() == 1 && ev_ind[1][0] != -1)//single element of 2D array (e.g. [0][1])
{
res.dim_x = 1;
res.dim_y = 0;
if(ev_ind[0][0] >= it->dim_y)
{
err << "Requested row " << ev_ind[0][0] << " is out of bounds with dim_y=" << it->dim_y;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
if(ev_ind[1][0] >= it->dim_x)
{
err << "Requested column " << ev_ind[1][0] << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value = {it->value.at(ev_ind[0][0]*it->dim_x + ev_ind[1][0])};//throw std::out_of_range
temp_attr_val << "[" <<res.value[0] << "],";//throw std::out_of_range
}
else if(ev_ind.size() == 2 && ev_ind[0].size() > 1 && ev_ind[1].size() == 1 && ev_ind[1][0] != -1)//single column slice of 2D array (e.g. [0,1,2][3])
{
res.dim_x = 1;
long ei1 = ev_ind[1][0];
if(ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
for(auto ei0 : ev_ind[0])
{
if(ei0 < 0 || ei0 >= it->dim_y)
{
err << "Requested row " << ei0 << " is out of bounds with dim_y=" << it->dim_y;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
res.dim_y = ev_ind[0].size();
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] == -1 && ev_ind[1].size() == 1 && ev_ind[1][0] != -1)//single column of 2D array (e.g. [-1][3])
{
res.dim_x = 1;
long ei1 = ev_ind[1][0];
if(ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
for(long ei0 = 0; ei0 < it->dim_y; ei0++)
{
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
res.dim_y = it->dim_y;
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] != -1 && ev_ind[1].size() > 1)//single row slice of 2D array (e.g. [0][1,2,3])
{
res.dim_y = 0;
long ei0 = ev_ind[0][0];
if(ei0 >= it->dim_y)
{
err << "Requested row " << ei0 << " is out of bounds with dim_y=" << it->dim_y;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
for(auto ei1 : ev_ind[1])
{
if(ei1 < 0 || ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
res.dim_x = ev_ind[1].size();
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() > 1 && ev_ind[1].size() > 1)//subarray of 2D array (e.g. [0,1][2,3])
{
for(auto ei0 : ev_ind[0])
{
if(ei0 < 0 || ei0 >= it->dim_y)
{
err << "Requested row " << ei0 << " is out of bounds with dim_y=" << it->dim_y;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
for(auto ei1 : ev_ind[1])
{
if(ei1 < 0 || ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
}
res.dim_x = ev_ind[1].size();
res.dim_y = ev_ind[0].size();
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] == -1 && ev_ind[1].size() > 1)//subarray of 2D array (e.g. [-1][2,3])
{
for(long ei0 = 0; ei0 < it->dim_y; ei0++)
{
for(auto ei1 : ev_ind[1])
{
if(ei1 < 0 || ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
}
res.dim_x = ev_ind[1].size();
res.dim_y = it->dim_y;
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else //ev_ind.size() > 2
{
err << "UNSUPPORTED additional indexes in 2D array: " << ev_ind.size() << " indexes given, dim_x=" << it->dim_x << " dim_y=" << it->dim_y;
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
events->veclock.readerOut();
throw err.str();
}
}
else //TODO N-DIMENSIONAL arrays
{
err << "UNSUPPORTED array indexes: " << ev_ind.size() << " indexes given, dim_x=" << it->dim_x << " dim_y=" << it->dim_y;
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
events->veclock.readerOut();
throw err.str();
}
}
else
{
res.value = it->value;
temp_attr_val << "\"" << it->name << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
}
}
else
temp_attr_val << "\"" << it->name << "\":[],";
attr_values += temp_attr_val.str();
events->veclock.readerOut();
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node name -> " << temp_attr_val.str() << " quality=" << res.quality << endl;
#endif
res.value = it->value.at(ev_ind); //throw std::out_of_range
events->veclock.readerOut();
#endif
return res;
}
else
......@@ -4662,7 +5300,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node index = " << val_d << endl;
#endif
formula_res_t res;
res.value = strtod(val_d.c_str(), 0);
res.valid = true;
res.value = {(strtod(val_d.c_str(), 0))};
res.dim_x=1;
res.dim_y=0;
return res;
}
else if (i->value.id() == formula_grammar::logical_exprID)
......@@ -4703,43 +5344,72 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
}
formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
res_2=eval_expression(i->children.begin()+1, attr_values);
long val_l1,val_l2;
vector<long> val_l1(res_1.value.size()),val_l2(res_2.value.size());
bool valid = res_1.valid && res_2.valid;
string err2("ERROR: non-int value in bitwise operation!");
val_l1 = (long)trunc(res_1.value); //transform to long
val_l2 = (long)trunc(res_2.value); //transform to long
if((val_l1 != res_1.value) || (val_l2 != res_2.value)) //if different, lost something with truncf
throw err2;
string err2("Non int value in bitwise operation");
std::transform(res_1.value.begin(), res_1.value.end(), val_l1.begin(),
[](double n) { return (long)trunc(n); });//transform to long
std::transform(res_2.value.begin(), res_2.value.end(), val_l2.begin(),
[](double n) { return (long)trunc(n); });//transform to long
size_t ii;
for(ii=0; ii<res_1.value.size(); ii++)
{
if(val_l1[ii] != res_1.value[ii]) //if different, lost something with truncf
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"FORMULA_ERROR",
err2,
string("Bitwise ") + string(i->value.begin(), i->value.end()));
}
for(ii=0; ii<res_2.value.size(); ii++)
{
if(val_l2[ii] != res_2.value[ii]) //if different, lost something with truncf
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"FORMULA_ERROR",
err2,
string("Bitwise ") + string(i->value.begin(), i->value.end()));
}
if (*i->value.begin() == '&')
{
formula_res_t res;
res.value = (double)(val_l1 & val_l2);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.valid = valid;
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
vectorUtils::applyVectorFunc(val_l1, res_1.dim_x,res_1.dim_y,val_l2,res_2.dim_x,res_2.dim_y,res.value,res.dim_x,res.dim_y, "Bitwise &", vectorUtils::fBitAnd);
return res;
}
else if (*i->value.begin() == '|')
{
formula_res_t res;
res.value = (double)(val_l1 | val_l2);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.valid = valid;
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
vectorUtils::applyVectorFunc(val_l1, res_1.dim_x,res_1.dim_y, val_l2,res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, "Bitwise |", vectorUtils::fBitOr);
return res;
}
else if (*i->value.begin() == '^')
{
formula_res_t res;
res.value = (double)(val_l1 ^ val_l2);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.valid = valid;
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
vectorUtils::applyVectorFunc(val_l1, res_1.dim_x,res_1.dim_y, val_l2,res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, "Bitwise ^", vectorUtils::fBitXor);
return res;
}
else
......@@ -4760,33 +5430,59 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
}
formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
res_2=eval_expression(i->children.begin()+1, attr_values);
long val_l1,val_l2;
vector<long> val_l1(res_1.value.size()),val_l2(res_2.value.size());
bool valid = res_1.valid && res_2.valid;
string err2("ERROR: non-int value in bitwise operation!");
val_l1 = (long)trunc(res_1.value); //transform to long
val_l2 = (long)trunc(res_2.value); //transform to long
if((val_l1 != res_1.value) || (val_l2 != res_2.value)) //if different, lost something with truncf
throw err2;
string err2("Non int value in bitwise operation");
std::transform(res_1.value.begin(), res_1.value.end(), val_l1.begin(),
[](double n) { return (long)trunc(n); });//transform to long
std::transform(res_2.value.begin(), res_2.value.end(), val_l2.begin(),
[](double n) { return (long)trunc(n); });//transform to long
bool non_int_error=false;
size_t ii;
for(ii=0; ii<res_1.value.size(); ii++)
{
if(val_l1[ii] != res_1.value[ii]) //if different, lost something with truncf
Tango::Except::throw_exception(//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"FORMULA_ERROR",
err2,
string("Bitwise ") + string(i->value.begin(), i->value.end()));
}
for(ii=0; ii<res_2.value.size(); ii++)
{
if(val_l2[ii] != res_2.value[ii]) //if different, lost something with truncf
Tango::Except::throw_exception(//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"FORMULA_ERROR",
err2,
string("Bitwise ") + string(i->value.begin(), i->value.end()));
}
if (string(i->value.begin(), i->value.end()) == string("<<"))
{
formula_res_t res;
res.value = (double)(val_l1 << val_l2);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.valid = valid;
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
vectorUtils::applyVectorFunc(val_l1, res_2.dim_x,res_2.dim_y, val_l2,res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, "Bitwise <<", vectorUtils::fBitShiftL);
return res;
}
else if (string(i->value.begin(), i->value.end()) == string(">>"))
{
formula_res_t res;
res.value = (double)(val_l1 >> val_l2);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
res.valid = valid;
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
vectorUtils::applyVectorFunc(val_l1, res_1.dim_x,res_1.dim_y, val_l2,res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, "Bitwise >>", vectorUtils::fBitShiftR);
return res;
}
else
......@@ -4832,20 +5528,45 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
err << "in node equality_exprID -> nameID(" << string(i2_1->value.begin(), i2_1->value.end()) << ") value not valid!";
if(it->ex_desc.length() > 0)
err << " EX: '" << it->ex_desc << "'";
res.valid = false;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
events->veclock.readerOut();
throw err.str();
/*Tango::Except::throw_exception( //throw exception to have error not delayed
it->ex_reason,//or Event_ERROR
it->ex_desc,
it->ex_origin);*/
return res;
}
else if(it->type != Tango::DEV_STRING && it->value.empty())
{
err << "in node nameID(" << string(i2_1->value.begin(), i2_1->value.end()) << ") value not initialized!!";
if(it->ex_desc.length() > 0)
err << " EX: '" << it->ex_desc << "'";
res.valid = false;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
events->veclock.readerOut();
throw err.str();
/*Tango::Except::throw_exception( //throw exception to have error not delayed
it->ex_reason,//or Event_ERROR
it->ex_desc,
it->ex_origin);*/
return res;
}
ostringstream temp_attr_val;
temp_attr_val << "\"" << it->name << "\":\"" <<it->value_string << "\",";
attr_values += temp_attr_val.str();
res.valid = true;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
......@@ -4868,12 +5589,16 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
if (string(i->value.begin(), i->value.end()) == string("!="))
{
res.value = attr_val != val_string;
res.value = {(double)(attr_val != val_string)};
res.dim_x=1;
res.dim_y=0;
return res;
}
else if (string(i->value.begin(), i->value.end()) == string("=="))
{
res.value = attr_val == val_string;
res.value = {(double)(attr_val == val_string)};
res.dim_x=1;
res.dim_y=0;
return res;
}
else
......@@ -4934,7 +5659,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
}
else
{
err << "in node equality_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
err << "in node compare_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
throw err.str();
}
}
......@@ -4953,109 +5678,49 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
if (string(i->value.begin(), i->value.end()) == string("abs"))
{
res = eval_expression(i->children.begin(), attr_values);
res.value = fabs(res.value);
std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return fabs(n); });
return res;
}
else if (string(i->value.begin(), i->value.end()) == string("cos"))
{
res = eval_expression(i->children.begin(), attr_values);
res.value = cos(res.value);
std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return cos(n); });
return res;
}
else if (string(i->value.begin(), i->value.end()) == string("sin"))
{
res = eval_expression(i->children.begin(), attr_values);
res.value = sin(res.value);
std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return sin(n); });
return res;
}
else if (string(i->value.begin(), i->value.end()) == string("quality"))
{
res = eval_expression(i->children.begin(), attr_values);
res.value = res.quality;
res.value = {(double)res.quality};//ignore values and keep quality as result
res.dim_x=1;
res.dim_y=0;
return res;
}
else if ((string(i->value.begin(), i->value.end()) == string("AND") || string(i->value.begin(), i->value.end()) == string("OR")) && i->children.begin()->value.id() == formula_grammar::nameID)
else if ((string(i->value.begin(), i->value.end()) == string("AND") || string(i->value.begin(), i->value.end()) == string("OR")))
{
events->veclock.readerIn();
vector<event>::iterator it = events->v_event.begin();
string s(i->children.begin()->value.begin(), i->children.begin()->value.end());
std::transform(s.begin(), s.end(), s.begin(), (int(*)(int))tolower); //transform to lowercase
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " -> " << string(i->value.begin(), i->value.end()) << "(" << s << ")" << endl;
#endif
while ((it != events->v_event.end()) && (it->name != s))
it++;
if (it != events->v_event.end())
res = eval_expression(i->children.begin(), attr_values);
res.dim_x=1;
res.dim_y=0;
if(string(i->value.begin(), i->value.end()) == string("AND"))
{
if(!it->valid)
{
err << "in node funcID(" << string(i->value.begin(), i->value.end()) << "), (" << s << ") value not valid!" << ends;
if(it->ex_desc.length() > 0)
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' exception: '" << it->ex_desc << "'";
else
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' value not valid!";
events->veclock.readerOut();
throw err.str();
}
else if(it->type != Tango::DEV_STRING && it->value.empty())
{
if(it->ex_desc.length() > 0)
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' exception: '" << it->ex_desc << "'";
else
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' value not initialized!!";
events->veclock.readerOut();
throw err.str();
}
ostringstream temp_attr_val;
bool result;
if (string(i->value.begin(), i->value.end()) == string("AND"))
result = true;
else if (string(i->value.begin(), i->value.end()) == string("OR"))
result = false;
temp_attr_val << "\"" << it->name << "\":";
if(it->read_size > 1)
temp_attr_val << "[";
for(int att_ind = 0; att_ind < it->read_size && att_ind < it->value.size(); att_ind++)
{
temp_attr_val << it->value.at(att_ind);
if (string(i->value.begin(), i->value.end()) == string("AND"))
{
result = result && (bool)it->value.at(att_ind);
if(!result) //comment to have all array values in attr_values
break; //comment to have all array values in attr_values
}
else if (string(i->value.begin(), i->value.end()) == string("OR"))
{
result = result || (bool)it->value.at(att_ind);
if(result) //comment to have all array values in attr_values
break; //comment to have all array values in attr_values
}
if(att_ind < it->read_size-1 && att_ind < it->value.size()-1)
temp_attr_val << ",";
}
if(it->read_size > 1)
temp_attr_val << "]";
temp_attr_val << ",";
attr_values += temp_attr_val.str();
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node name -> " << temp_attr_val.str() << " quality=" << res.quality << endl;
#endif
res.value = result;
events->veclock.readerOut();
return res;
res.value = {(double)std::accumulate(res.value.begin(), res.value.end(), (bool)true, [](bool acc, double n) { return (bool)(acc && (bool)(n));})};
}
else
else if(string(i->value.begin(), i->value.end()) == string("OR"))
{
events->veclock.readerOut();
err << "in function " << string(i->value.begin(), i->value.end()) << " event (" << s << ") not found in event table" << ends;
throw err.str();
res.value = {(double)std::accumulate(res.value.begin(), res.value.end(), (bool)false, [](bool acc, double n) { return (bool)(acc || (bool)(n));})};
}
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node funcID("<<string(i->value.begin(), i->value.end())<<") value="<<print_array(res.value,res.dim_x,res.dim_y)<<" quality="<<res.quality<< endl;
#endif
return res;
}
else
{
......@@ -5075,34 +5740,47 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
}
formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
res_2=eval_expression(i->children.begin()+1, attr_values);
bool valid = res_1.valid && res_2.valid;
if (string(i->value.begin(), i->value.end()) == string("min"))
{
formula_res_t res;
res.value = min(res_1.value, res_2.value);
vectorUtils::applyVectorFunc(res_1.value, res_1.dim_x,res_1.dim_y, res_2.value, res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, string(i->value.begin(), i->value.end()), vectorUtils::fMin);
res.valid = valid;
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
return res;
}
else if (string(i->value.begin(), i->value.end()) == string("max"))
{
formula_res_t res;
res.value = max(res_1.value, res_2.value);
vectorUtils::applyVectorFunc(res_1.value, res_1.dim_x,res_1.dim_y, res_2.value, res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, string(i->value.begin(), i->value.end()), vectorUtils::fMax);
res.valid = valid;
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
return res;
}
else if (string(i->value.begin(), i->value.end()) == string("pow"))
{
formula_res_t res;
res.value = pow(res_1.value, res_2.value);
vectorUtils::applyVectorFunc(res_1.value, res_1.dim_x,res_1.dim_y, res_2.value, res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, string(i->value.begin(), i->value.end()), vectorUtils::fPow);
res.valid = valid;
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
return res;
}
else
......@@ -5122,7 +5800,15 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
throw err.str();
}
formula_res_t res_1=eval_expression(i->children.begin(), attr_values);
if(res_1.value)
if(!res_1.valid || res_1.value.empty())
{
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node ternary_if expression: returning Error=" << res_1.ex_desc << endl;
#endif
return res_1;
}
res_1.extract_result();
if(res_1.value[0])
{
formula_res_t res = eval_expression(i->children.begin()+1, attr_values);
return res;
......@@ -5144,7 +5830,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
}
}
formula_res_t res;
res.value = 0;
res.value = {(double)0.0};
res.dim_x=1;
res.dim_y=0;
res.valid = false;
return res;
}
......@@ -5177,7 +5866,7 @@ void AlarmHandler::eval_node_event(iter_t const& i, vector<string> & ev)
std::transform(s.begin(), s.end(), s.begin(), (int(*)(int))tolower); //transform to lowercase
ev.push_back(s);
}
//cout << endl;
//TANGO_LOG << endl;
//iter_t it = i->children.begin();
for(iter_t it = i->children.begin(); it != i->children.end(); it++)
eval_node_event(it, ev);
......@@ -5236,7 +5925,7 @@ void AlarmHandler::prepare_alarm_attr()
}
else
{
if(ai->second.stat == S_ALARM && ai->second.ack == ACK)
if(ai->second.stat == S_ALARM && ai->second.ack == ACK && !ai->second.error)
{
acknowledgedAlarms_read[acknowledgedAlarms_sz] = ai->second.name;
attr_alarmAcknowledged_read[acknowledgedAlarms_sz] = const_cast<char*>(acknowledgedAlarms_read[acknowledgedAlarms_sz].c_str());
......@@ -5246,7 +5935,7 @@ void AlarmHandler::prepare_alarm_attr()
acknowledgedAlarms_sz++;
almstate = "ACKED";
}
else if(ai->second.stat == S_ALARM && ai->second.ack == NOT_ACK)
else if(ai->second.stat == S_ALARM && ai->second.ack == NOT_ACK && !ai->second.error)
{
unacknowledgedAlarms_read[unacknowledgedAlarms_sz] = ai->second.name;
attr_alarmUnacknowledged_read[unacknowledgedAlarms_sz] = const_cast<char*>(unacknowledgedAlarms_read[unacknowledgedAlarms_sz].c_str());
......@@ -5256,7 +5945,7 @@ void AlarmHandler::prepare_alarm_attr()
unacknowledgedAlarms_sz++;
almstate = "UNACK";
}
else if(ai->second.stat == S_NORMAL && ai->second.ack == NOT_ACK)
else if(ai->second.stat == S_NORMAL && ai->second.ack == NOT_ACK && !ai->second.error)
{
unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz] = ai->second.name;
attr_alarmUnacknowledgedNormal_read[unacknowledgedNormalAlarms_sz] = const_cast<char*>(unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz].c_str());
......@@ -5266,7 +5955,7 @@ void AlarmHandler::prepare_alarm_attr()
unacknowledgedNormalAlarms_sz++;
almstate = "RTNUN";
}
else if(ai->second.stat == S_NORMAL && ai->second.ack == ACK)
else if(ai->second.stat == S_NORMAL && ai->second.ack == ACK && !ai->second.error)
{
normalAlarms_read[normalAlarms_sz] = ai->second.name;
attr_alarmNormal_read[normalAlarms_sz] = const_cast<char*>(normalAlarms_read[normalAlarms_sz].c_str());
......@@ -5296,7 +5985,7 @@ void AlarmHandler::prepare_alarm_attr()
if(almstate == "OOSRV" || almstate == "SHLVD")
{
//cout << __func__ << ": " << ai->first << " silenced="<< ai->second.silenced << endl;
//TANGO_LOG << __func__ << ": " << ai->first << " silenced="<< ai->second.silenced << endl;
#if 0
alm_disabled << KEY(ALARM_TIME_KEY) << time_buf << "." << ai->second.ts.tv_usec << SEP;
alm_disabled << KEY(NAME_KEY) << ai->first << SEP;
......@@ -5334,7 +6023,6 @@ void AlarmHandler::prepare_alarm_attr()
time_sec= ai->second.ts.tv_sec;
//gmtime_r(&time_sec,&time_tm); //-> UTC
localtime_r(&time_sec,&time_tm);
time_buf[64];
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
#ifndef ALM_SUM_STR
......@@ -5432,7 +6120,7 @@ void AlarmHandler::prepare_alarm_attr()
* found, change stat only if switching from
* S_NORMAL or S_ALARM status to S_ERROR
*/
//cout << "read_attr(): S_ERROR: found: " << aid->name << endl;
//TANGO_LOG << "read_attr(): S_ERROR: found: " << aid->name << endl;
if (aid->stat != S_ERROR) {
aid->stat = S_ERROR;
aid->ack = NOT_ACK;
......@@ -5443,6 +6131,7 @@ void AlarmHandler::prepare_alarm_attr()
aid->grp = ai->second.grp;
aid->lev = ai->second.lev;
aid->is_new = ai->second.is_new; //copy is_new state
aid->receivers = ai->second.receivers;
//ai->second.is_new = 0; //and set state as not more new //12-06-08: StopNew command set it to 0
#ifdef _CNT_ATOMIC
aid->on_counter.store(ai->second.on_counter);
......@@ -5482,7 +6171,7 @@ void AlarmHandler::prepare_alarm_attr()
* found, change stat only if switching from
* S_NORMAL to S_ALARM status
*/
//cout << "read_attr(): S_ALARM: found: " << aid->name << endl;
//TANGO_LOG << "read_attr(): S_ALARM: found: " << aid->name << endl;
if (aid->stat == S_NORMAL || aid->stat == S_ERROR) {
aid->stat = S_ALARM;
aid->ack = NOT_ACK;
......@@ -5493,6 +6182,7 @@ void AlarmHandler::prepare_alarm_attr()
aid->grp = ai->second.grp;
aid->lev = ai->second.lev;
aid->is_new = ai->second.is_new; //copy is_new state
aid->receivers = ai->second.receivers;
//ai->second.is_new = 0; //and set state as not more new //12-06-08: StopNew command set it to 0
#ifdef _CNT_ATOMIC
aid->on_counter.store(ai->second.on_counter);
......@@ -5547,6 +6237,7 @@ void AlarmHandler::prepare_alarm_attr()
aid->is_new = ai->second.is_new; //copy is_new state
aid->silenced = ai->second.silenced; //update silenced from alarm table (maybe not necessary)
aid->silent_time = ai->second.silent_time; //if already alarmed and not saved correctly in properties needed to update
aid->receivers = ai->second.receivers;
//ai->second.is_new = 0; //and set state as not more new //12-06-08: StopNew command set it to 0
if (aid->ack == ACK) {
//if (aid->done) //TODO: done seems useless
......@@ -5749,7 +6440,7 @@ void AlarmHandler::put_signal_property()
DECLARE_TIME_VAR t0, t1;
GET_TIME(t0);
alarms.save_alarm_conf_db(it.second.attr_name,it.second.name,it.second.stat,it.second.ack,it.second.enabled,
it.second.formula,it.second.on_delay,it.second.off_delay,it.second.grp2str(),it.second.lev,it.second.msg,it.second.url,it.second.cmd_name_a,it.second.cmd_name_n,it.second.silent_time);
it.second.formula,it.second.on_delay,it.second.off_delay,it.second.grp2str(),it.second.lev,it.second.msg,it.second.url,it.second.cmd_name_a,it.second.cmd_name_n,it.second.receivers,it.second.silent_time);
GET_TIME(t1);
DEBUG_STREAM << __func__ << ": SAVED '" <<it.first << "' in " << ELAPSED(t0, t1) << " ms" << endl;
//alarms.vlock->readerOut();//TODO: avoid keeping lock
......@@ -5772,7 +6463,7 @@ void AlarmHandler::put_signal_property()
itmap->second = conf_string;
savedlock->readerOut();
alarms.save_alarm_conf_db(it.second.attr_name,it.second.name,it.second.stat,it.second.ack,it.second.enabled,
it.second.formula,it.second.on_delay,it.second.off_delay,it.second.grp2str(),it.second.lev,it.second.msg,it.second.url,it.second.cmd_name_a,it.second.cmd_name_n,it.second.silent_time);
it.second.formula,it.second.on_delay,it.second.off_delay,it.second.grp2str(),it.second.lev,it.second.msg,it.second.url,it.second.cmd_name_a,it.second.cmd_name_n,it.second.receivers,it.second.silent_time);
GET_TIME(t1);
DEBUG_STREAM << __func__ << ": UPDATED '" <<it.first << "' in " << ELAPSED(t0, t1) << " ms" << endl;
}
......@@ -5783,8 +6474,13 @@ void AlarmHandler::put_signal_property()
}
}
// Identify the alarms that need to be removed.
// The alarms that have been identified to be removed have their tag
// stored in a std::vector. The vector is later iterated over in a second
// step when the alarms get removed.
savedlock->readerIn();
map<string, string>::iterator it2=saved_alarms.begin();
vector< string > alarms_to_be_erased;
while(it2 != saved_alarms.end())
{
if(!it2->first.empty())//TODO: should not be needed, bug if it happens
......@@ -5792,25 +6488,30 @@ void AlarmHandler::put_signal_property()
auto found = local_alarms.find(it2->first);
if (found == local_alarms.end())
{
DEBUG_STREAM << __func__<<": DELETING '" << it2->first << "'" << endl;
DECLARE_TIME_VAR t0, t1;
GET_TIME(t0);
alarms.delete_alarm_conf_db(it2->first);
GET_TIME(t1);
DEBUG_STREAM << __func__ << ": DELETED '" <<it2->first << "' in " << ELAPSED(t0, t1) << " ms" << endl;
//savedlock->readerOut();//TODO: with boost shared lock to be released to take exclusive
savedlock->writerIn();
saved_alarms.erase(it2);
savedlock->writerOut();
//savedlock->readerIn();
alarms_to_be_erased.push_back(it2->first);
}
}
if(it2 != saved_alarms.end())
it2++;
}
savedlock->readerOut();
// Now remove the alarms from the property in the TangoDB and saved_alarms.
if(!alarms_to_be_erased.empty())
{
savedlock->writerIn();
for(auto iter{alarms_to_be_erased.begin()}; iter != alarms_to_be_erased.end(); ++iter)
{
DEBUG_STREAM << __func__<<": DELETING '" << *iter << "' saved_alarms.size=" << saved_alarms.size() << endl;
DECLARE_TIME_VAR t0, t1;
GET_TIME(t0);
alarms.delete_alarm_conf_db(*iter);
GET_TIME(t1);
DEBUG_STREAM << __func__ << ": DELETED '" << *iter << "' in " << ELAPSED(t0, t1) << " ms saved_alarms.size=" << saved_alarms.size() << endl;
saved_alarms.erase(saved_alarms.find(*iter));
}
savedlock->writerOut();
}
Tango::DbData data;
data.push_back(Tango::DbDatum("AlarmList"));
......@@ -5921,6 +6622,7 @@ void AlarmHandler::parse_alarm(string &alarm_string, alarm_t &alm)
alm.dp_n = NULL;
alm.enabled=true;
alm.shelved=false;
alm.receivers.clear();
alm.formula_tree =
//boost::spirit::tree_parse_info< std::string::iterator, factory_t> tmp =
......@@ -5944,6 +6646,7 @@ void AlarmHandler::parse_alarm(string &alarm_string, alarm_t &alm)
std::transform(alm.lev.begin(), alm.lev.end(), alm.lev.begin(), (int(*)(int))tolower); //transform to lowercase
alm.msg = std::regex_replace(alm.msg, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
alm.url = std::regex_replace(alm.url, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
alm.receivers = std::regex_replace(alm.receivers, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
if(alm.cmd_name_a.length() > 0)
{
const char *c = alm.cmd_name_a.c_str();
......
......@@ -33,7 +33,7 @@
#ifndef AlarmHandler_H
#define AlarmHandler_H
#include <tango.h>
#include <tango/tango.h>
#include <boost/version.hpp>
#if BOOST_VERSION >= 103600
......@@ -61,7 +61,15 @@ class update_thread;
# define ELAPSED(before, after) \
1000.0*(after.tv_sec-before.tv_sec) + \
((double)after.tv_usec-before.tv_usec) / 1000
#ifndef TANGO_LOG
#define TANGO_LOG cout
#endif
#ifndef TANGO_LOG_INFO
#define TANGO_LOG_INFO cout2
#endif
#ifndef TANGO_LOG_DEBUG
#define TANGO_LOG_DEBUG cout4
#endif
/*----- PROTECTED REGION END -----*/ // AlarmHandler.h
......@@ -585,13 +593,13 @@ private:
void init_alarms(map< string,vector<string> > &alarm_events);
#endif
void add_alarm(alarm_t& a, bool starting=false);
void add_event(alarm_t& a, vector<string> &evn) throw(string&);
void add_event(alarm_t& a, vector<string> &evn);
#if 0
void subscribe_event(alarm_t& a, EventCallBack& ecb, vector<string> &evn) throw(string&);
void subscribe_event(alarm_t& a, EventCallBack& ecb, vector<string> &evn);
#endif
// void do_alarm(bei_t& e); //gcc 4 problem??
bool remove_alarm(string& s) throw(string&);
//void add_to_database(alarm_t& a) throw(string&);
bool remove_alarm(string& s);
//void add_to_database(alarm_t& a);
void set_internal_alarm(string name, Tango::TimeVal t, string msg, unsigned int count=1);
void load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn);
......@@ -599,7 +607,8 @@ private:
formula_res_t eval_formula(tree_parse_info_t tree, string &attr_values);
void find_event_formula(tree_parse_info_t tree, vector<string> &);
formula_res_t eval_expression(iter_t const& i, string &attr_values, int ev_ind=0); //recursive tree node evaluation
formula_res_t eval_expression(iter_t const& i, string &attr_values, vector< vector<double> > ev_ind={}); //recursive tree node evaluation
void eval_index_range(iter_t const& i, string &attr_values, vector<double> & ind);
void eval_node_event(iter_t const& i, vector<string> & ev); //recursive tree node evaluation
void prepare_alarm_attr(); //for read attribute alarm and push_change_event
......
......@@ -199,8 +199,8 @@
</commands>
<attributes name="alarmAudible" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
<dataType xsi:type="pogoDsl:BooleanType"/>
<changeEvent fire="true" libCheckCriteria="false"/>
<archiveEvent fire="true" libCheckCriteria="false"/>
<changeEvent fire="true" libCheckCriteria="true"/>
<archiveEvent fire="true" libCheckCriteria="true"/>
<dataReadyEvent fire="false" libCheckCriteria="true"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="True if there is at least one alarm that needs audible indication on the GUI" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
......@@ -342,8 +342,8 @@
</dynamicAttributes>
<dynamicAttributes name="AlarmFormula" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="true">
<dataType xsi:type="pogoDsl:StringType"/>
<changeEvent fire="true" libCheckCriteria="false"/>
<archiveEvent fire="true" libCheckCriteria="false"/>
<changeEvent fire="true" libCheckCriteria="true"/>
<archiveEvent fire="true" libCheckCriteria="true"/>
<dataReadyEvent fire="false" libCheckCriteria="true"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
......
/*----- PROTECTED REGION ID(AlarmHandlerClass.cpp) ENABLED START -----*/
static const char *RcsId = "$Id: $";
static const char *TagName = "$Name: $";
static const char *CvsPath = "$Source: $";
static const char *SvnPath = "$HeadURL: $";
static const char *HttpServer = "http://www.esrf.eu/computing/cs/tango/tango_doc/ds_doc/";
//=============================================================================
//
// file : AlarmHandlerClass.cpp
......@@ -78,7 +73,7 @@ AlarmHandlerClass *AlarmHandlerClass::_instance = NULL;
//--------------------------------------------------------
AlarmHandlerClass::AlarmHandlerClass(string &s):Tango::DeviceClass(s)
{
cout2 << "Entering AlarmHandlerClass constructor" << endl;
TANGO_LOG_INFO << "Entering AlarmHandlerClass constructor" << endl;
set_default_property();
get_class_property();
write_class_property();
......@@ -87,7 +82,7 @@ AlarmHandlerClass::AlarmHandlerClass(string &s):Tango::DeviceClass(s)
/*----- PROTECTED REGION END -----*/ // AlarmHandlerClass::constructor
cout2 << "Leaving AlarmHandlerClass constructor" << endl;
TANGO_LOG_INFO << "Leaving AlarmHandlerClass constructor" << endl;
}
//--------------------------------------------------------
......@@ -167,7 +162,7 @@ AlarmHandlerClass *AlarmHandlerClass::instance()
//--------------------------------------------------------
CORBA::Any *AckClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "AckClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "AckClass::execute(): arrived" << endl;
const Tango::DevVarStringArray *argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->ack(argin));
......@@ -187,7 +182,7 @@ CORBA::Any *AckClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_an
//--------------------------------------------------------
CORBA::Any *LoadClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "LoadClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "LoadClass::execute(): arrived" << endl;
Tango::DevString argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->load(argin));
......@@ -207,7 +202,7 @@ CORBA::Any *LoadClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_a
//--------------------------------------------------------
CORBA::Any *RemoveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "RemoveClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "RemoveClass::execute(): arrived" << endl;
Tango::DevString argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->remove(argin));
......@@ -227,7 +222,7 @@ CORBA::Any *RemoveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in
//--------------------------------------------------------
CORBA::Any *SearchAlarmClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "SearchAlarmClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "SearchAlarmClass::execute(): arrived" << endl;
Tango::DevString argin;
extract(in_any, argin);
return insert((static_cast<AlarmHandler *>(device))->search_alarm(argin));
......@@ -246,7 +241,7 @@ CORBA::Any *SearchAlarmClass::execute(Tango::DeviceImpl *device, const CORBA::An
//--------------------------------------------------------
CORBA::Any *StopAudibleClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any))
{
cout2 << "StopAudibleClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "StopAudibleClass::execute(): arrived" << endl;
((static_cast<AlarmHandler *>(device))->stop_audible());
return new CORBA::Any();
}
......@@ -264,7 +259,7 @@ CORBA::Any *StopAudibleClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(co
//--------------------------------------------------------
CORBA::Any *SilenceClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "SilenceClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "SilenceClass::execute(): arrived" << endl;
const Tango::DevVarStringArray *argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->silence(argin));
......@@ -284,7 +279,7 @@ CORBA::Any *SilenceClass::execute(Tango::DeviceImpl *device, const CORBA::Any &i
//--------------------------------------------------------
CORBA::Any *ModifyClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "ModifyClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "ModifyClass::execute(): arrived" << endl;
Tango::DevString argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->modify(argin));
......@@ -304,7 +299,7 @@ CORBA::Any *ModifyClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in
//--------------------------------------------------------
CORBA::Any *ShelveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "ShelveClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "ShelveClass::execute(): arrived" << endl;
const Tango::DevVarStringArray *argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->shelve(argin));
......@@ -324,7 +319,7 @@ CORBA::Any *ShelveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in
//--------------------------------------------------------
CORBA::Any *EnableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "EnableClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "EnableClass::execute(): arrived" << endl;
Tango::DevString argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->enable(argin));
......@@ -344,7 +339,7 @@ CORBA::Any *EnableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in
//--------------------------------------------------------
CORBA::Any *DisableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "DisableClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "DisableClass::execute(): arrived" << endl;
Tango::DevString argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->disable(argin));
......@@ -364,7 +359,7 @@ CORBA::Any *DisableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &i
//--------------------------------------------------------
CORBA::Any *ResetStatisticsClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any))
{
cout2 << "ResetStatisticsClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "ResetStatisticsClass::execute(): arrived" << endl;
((static_cast<AlarmHandler *>(device))->reset_statistics());
return new CORBA::Any();
}
......@@ -382,7 +377,7 @@ CORBA::Any *ResetStatisticsClass::execute(Tango::DeviceImpl *device, TANGO_UNUSE
//--------------------------------------------------------
CORBA::Any *StopNewClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any))
{
cout2 << "StopNewClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "StopNewClass::execute(): arrived" << endl;
((static_cast<AlarmHandler *>(device))->stop_new());
return new CORBA::Any();
}
......@@ -400,7 +395,7 @@ CORBA::Any *StopNewClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const
//--------------------------------------------------------
CORBA::Any *GetAlarmInfoClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "GetAlarmInfoClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "GetAlarmInfoClass::execute(): arrived" << endl;
const Tango::DevVarStringArray *argin;
extract(in_any, argin);
return insert((static_cast<AlarmHandler *>(device))->get_alarm_info(argin));
......@@ -419,7 +414,7 @@ CORBA::Any *GetAlarmInfoClass::execute(Tango::DeviceImpl *device, const CORBA::A
//--------------------------------------------------------
CORBA::Any *ReLoadAllClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any))
{
cout2 << "ReLoadAllClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "ReLoadAllClass::execute(): arrived" << endl;
((static_cast<AlarmHandler *>(device))->re_load_all());
return new CORBA::Any();
}
......@@ -789,7 +784,7 @@ void AlarmHandlerClass::device_factory(const Tango::DevVarStringArray *devlist_p
// Create devices and add it into the device list
for (unsigned long i=0 ; i<devlist_ptr->length() ; i++)
{
cout4 << "Device name : " << (*devlist_ptr)[i].in() << endl;
TANGO_LOG_DEBUG << "Device name : " << (*devlist_ptr)[i].in() << endl;
device_list.push_back(new AlarmHandler(this, (*devlist_ptr)[i]));
}
......@@ -852,8 +847,8 @@ void AlarmHandlerClass::attribute_factory(vector<Tango::Attr *> &att_list)
// Not Polled
alarmaudible->set_disp_level(Tango::OPERATOR);
// Not Memorized
alarmaudible->set_change_event(true, false);
alarmaudible->set_archive_event(true, false);
alarmaudible->set_change_event(true, true);
alarmaudible->set_archive_event(true, true);
att_list.push_back(alarmaudible);
// Attribute : StatisticsResetTime
......@@ -1437,7 +1432,7 @@ void AlarmHandlerClass::create_static_attribute_list(vector<Tango::Attr *> &att_
defaultAttList.push_back(att_name);
}
cout2 << defaultAttList.size() << " attributes in default list" << endl;
TANGO_LOG_INFO << defaultAttList.size() << " attributes in default list" << endl;
/*----- PROTECTED REGION ID(AlarmHandlerClass::create_static_att_list) ENABLED START -----*/
......@@ -1473,7 +1468,7 @@ void AlarmHandlerClass::erase_dynamic_attributes(const Tango::DevVarStringArray
vector<string>::iterator ite_str = find(defaultAttList.begin(), defaultAttList.end(), att_name);
if (ite_str == defaultAttList.end())
{
cout2 << att_name << " is a UNWANTED dynamic attribute for device " << (*devlist_ptr)[i] << endl;
TANGO_LOG_INFO << att_name << " is a UNWANTED dynamic attribute for device " << (*devlist_ptr)[i] << endl;
Tango::Attribute &att = dev->get_device_attr()->get_attr_by_name(att_name.c_str());
dev->remove_attribute(att_list[att.get_attr_idx()], true, false);
--ite_att;
......
......@@ -37,7 +37,7 @@
#ifndef AlarmHandlerClass_H
#define AlarmHandlerClass_H
#include <tango.h>
#include <tango/tango.h>
#include <AlarmHandler.h>
......
......@@ -173,8 +173,8 @@ void AlarmHandler::add_AlarmFormula_dynamic_attribute(string attname)
// Not Polled
alarmformula->set_disp_level(Tango::OPERATOR);
// Not Memorized
alarmformula->set_change_event(true, false);
alarmformula->set_archive_event(true, false);
alarmformula->set_change_event(true, true);
alarmformula->set_archive_event(true, true);
char array[1];
array[0] = '\0';
AlarmFormula_data.insert(make_pair(attname, array));
......
cmake_minimum_required(VERSION 3.2)
# source files
set(SRC_FILES ${SRC_FILES}
${CMAKE_CURRENT_SOURCE_DIR}/AlarmHandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AlarmHandlerClass.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AlarmHandlerDynAttrUtils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AlarmHandlerStateMachine.cpp
${CMAKE_CURRENT_SOURCE_DIR}/alarm_table.cpp
${CMAKE_CURRENT_SOURCE_DIR}/alarm-thread.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ClassFactory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/cmd_thread.cpp
${CMAKE_CURRENT_SOURCE_DIR}/event_table.cpp
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SubscribeThread.cpp
${CMAKE_CURRENT_SOURCE_DIR}/update-thread.cpp
PARENT_SCOPE)
......@@ -32,7 +32,7 @@
// (Program Obviously used to Generate tango Object)
//=============================================================================
#include <tango.h>
#include <tango/tango.h>
#include <AlarmHandlerClass.h>
// Add class header files if needed
......
static const char *RcsId = "$Header: /home/cvsadm/cvsroot/fermi/servers/hdb++/hdb++es/src/SubscribeThread.cpp,v 1.6 2014-03-06 15:21:43 graziano Exp $";
//+=============================================================================
//
// file : HdbEventHandler.cpp
//
// description : C++ source for thread management
// project : TANGO Device Server
//
// $Author: graziano $
//
// $Revision: 1.6 $
//
// $Log: SubscribeThread.cpp,v $
// Revision 1.6 2014-03-06 15:21:43 graziano
// StartArchivingAtStartup,
// start_all and stop_all,
// archiving of first event received at subscribe
//
// Revision 1.5 2014-02-20 14:59:02 graziano
// name and path fixing
// removed start acquisition from add
//
// Revision 1.4 2013-09-24 08:42:21 graziano
// bug fixing
//
// Revision 1.3 2013-09-02 12:13:22 graziano
// cleaned
//
// Revision 1.2 2013-08-23 10:04:53 graziano
// development
//
// Revision 1.1 2013-07-17 13:37:43 graziano
// *** empty log message ***
//
//
//
// copyleft : European Synchrotron Radiation Facility
// BP 220, Grenoble 38043
// FRANCE
//
//-=============================================================================
#include "AlarmHandler.h"
#include "event_table.h"
......
//=============================================================================
//
// file : HdbEventHandler.h
//
// description : Include for the HDbDevice class.
//
// project : Tango Device Server
//
// $Author: graziano $
//
// $Revision: 1.5 $
//
// $Log: SubscribeThread.h,v $
// Revision 1.5 2014-03-06 15:21:43 graziano
// StartArchivingAtStartup,
// start_all and stop_all,
// archiving of first event received at subscribe
//
// Revision 1.4 2013-09-24 08:42:21 graziano
// bug fixing
//
// Revision 1.3 2013-09-02 12:11:32 graziano
// cleaned
//
// Revision 1.2 2013-08-23 10:04:53 graziano
// development
//
// Revision 1.1 2013-07-17 13:37:43 graziano
// *** empty log message ***
//
//
//
// copyleft : European Synchrotron Radiation Facility
// BP 220, Grenoble 38043
// FRANCE
//
//=============================================================================
#ifndef _SUBSCRIBE_THREAD_H
#define _SUBSCRIBE_THREAD_H
#include <tango.h>
#include <eventconsumer.h>
#include <tango/tango.h>
#include <stdint.h>
#include "event_table.h"
/**
* @author $Author: graziano $
* @version $Revision: 1.5 $
*/
// constants definitions here.
//-----------------------------------------------
// constants definitions here.
//-----------------------------------------------
namespace AlarmHandler_ns
{
......
/*
* alarm-thread.cpp
*
* $Author: claudio $
*
* $Revision: 1.7 $
*
* $Log: alarm-thread.cpp,v $
* Revision 1.7 2015-07-21 13:40:59 claudio
* minor cleanups
*
* Revision 1.6 2013-03-06 10:41:11 claudio
* commented out debug print statements
*
* Revision 1.5 2008-07-08 12:11:39 graziano
* omni_thread_fatal exception handling
*
* Revision 1.4 2008/07/07 09:13:12 graziano
* omni_thread_fatal exception handling
*
* Revision 1.3 2008/04/24 06:51:34 graziano
* small code cleanings
*
*
*
* copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
* Strada Statale 14 - km 163,5 in AREA Science Park
* 34012 Basovizza, Trieste ITALY
......@@ -36,7 +14,7 @@ static const char __FILE__rev[] = __FILE__ " $Revision: 1.7 $";
*/
alarm_thread::alarm_thread(AlarmHandler_ns::AlarmHandler *p) : p_Alarm(p)
{
//cout << __FILE__rev << endl;
//TANGO_LOG << __FILE__rev << endl;
}
/*
......@@ -142,21 +120,21 @@ void alarm_thread::run(void *)
ostringstream err;
err << "omni_thread_fatal exception running alarm thread, err=" << ex.error << ends;
//WARN_STREAM << "alarm_thread::run(): " << err.str() << endl;
printf("alarm_thread::run(): %s", err.str().c_str());
printf("alarm_thread::run(): %s\n", err.str().c_str());
}
catch(Tango::DevFailed& ex)
{
ostringstream err;
err << "exception running alarm thread: '" << ex.errors[0].desc << "'" << ends;
//WARN_STREAM << "alarm_thread::run(): " << err.str() << endl;
printf("alarm_thread::run(): %s", err.str().c_str());
Tango::Except::print_exception(ex);
printf("alarm_thread::run(): %s\n", err.str().c_str());
//Tango::Except::print_exception(ex);
}
catch(...)
{
//WARN_STREAM << "alarm_thread::run(): catched unknown exception!!" << endl;
printf("alarm_thread::run(): catched unknown exception!!");
printf("alarm_thread::run(): catched unknown exception!!\n");
}
}
//cout << "alarm_thread::run(): returning" << endl;
//TANGO_LOG << "alarm_thread::run(): returning" << endl;
} /* alarm_thread::run() */
/*
* alarm-thread.h
*
* $Author: graziano $
*
* $Revision: 1.3 $
*
* $Log: alarm-thread.h,v $
* Revision 1.3 2008-04-23 15:00:57 graziano
* small code cleanings
*
*
*
* copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
* Strada Statale 14 - km 163,5 in AREA Science Park
* 34012 Basovizza, Trieste ITALY
......@@ -20,7 +10,7 @@
#define ALARM_THREAD_H
#include <omnithread.h>
#include <tango.h>
#include <tango/tango.h>
#include <AlarmHandler.h>
#define ALARM_THREAD_EXIT "alarm_thread_exit"
......
/*
* alarm_grammar.h
*
* $Author: $
*
* $Revision: $
*
* $Log: alarm_grammar.h,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
......@@ -78,6 +71,7 @@
#define URL_KEY "url"
#define ON_COMMAND_KEY "on_command"
#define OFF_COMMAND_KEY "off_command"
#define RECEIVERS_KEY "receivers"
#define ENABLED_KEY "enabled"
#define SILENT_TIME_REMAINING_KEY "shlvd_end"
......@@ -228,6 +222,7 @@ struct alarm_parse : public grammar<alarm_parse>
no_node_d[separator] >> no_node_d[url] |
no_node_d[separator] >> no_node_d[on_command] |
no_node_d[separator] >> no_node_d[off_command] |
no_node_d[separator] >> no_node_d[receivers] |
no_node_d[separator] >> no_node_d[enabled]
;
......@@ -342,6 +337,16 @@ struct alarm_parse : public grammar<alarm_parse>
] //discard_node_d
| epsilon_p)
;
//------------------------------RECEIVERS------------------------------------
receivers
= discard_node_d[str_p(KEY(RECEIVERS_KEY))]
//>> ch_p('"')
>> (*(escChar | (anychar_p - ';'))) //zero ore more char except ';'
[
assign_a(self.m_alarm.receivers)
]
//>> '"'
;
//------------------------------ENABLED----------------------------------------
enabled
= discard_node_d[str_p(KEY(ENABLED_KEY))] >>
......@@ -361,7 +366,7 @@ struct alarm_parse : public grammar<alarm_parse>
rule_t expression, event, option;
rule<typename lexeme_scanner<ScannerT>::type> symbol; //needed to use lexeme_d in rule name
rule<typename lexeme_scanner<ScannerT>::type> symbol_attr_name; //needed to use lexeme_d in rule name
rule_t name, name_alm, val, token, oper, msg, url, group, level, on_delay, off_delay, silent_time, on_command, off_command, enabled, separator,escChar;
rule_t name, name_alm, val, token, oper, msg, url, group, level, on_delay, off_delay, silent_time, on_command, off_command, receivers, enabled, separator,escChar;
formula_grammar formula;
rule_t const&
......
/*
* 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 <tango/tango.h>
#include "alarm_table.h"
#include "alarm_grammar.h"
#include "cmd_thread.h"
......@@ -187,6 +180,7 @@ void alarm_t::confstr(string &s)
KEY(URL_KEY)<< url << SEP <<
KEY(ON_COMMAND_KEY)<< cmd_name_a << SEP <<
KEY(OFF_COMMAND_KEY)<< cmd_name_n << SEP <<
KEY(RECEIVERS_KEY)<< receivers << SEP <<
KEY(ENABLED_KEY)<< (enabled ? "1" : "0");
s = conf.str();
}
......@@ -362,23 +356,32 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_
}
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
status_err_delay = (!res.valid) && (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;
status_err_delay = (!res.valid);
found->second.ex_reason = res.ex_reason;
found->second.ex_desc = res.ex_desc;
found->second.ex_origin = res.ex_origin;
if(!status_err_delay && !res.valid) //formula result not valid, waiting for err_delay
{
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
found->second.err_counter++;
if(found->second.err_counter == 1)
found->second.ts_err_delay = gettime(); //first occurrance of this error, now begin to wait for err delay
vlock->readerOut();
return ret_changed;
}
found->second.quality = res.quality;
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
status_on_delay = ((bool)(!res.value.empty() && res.value[0] != 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);
status_on_delay = (bool)(!res.value.empty() && res.value[0] != 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
status_off_delay = (!(bool)(!res.value.empty() && res.value[0] != 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);
status_off_delay = !(bool)(!res.value.empty() && res.value[0] != 0);
//if status changed:
// - from S_NORMAL to S_ALARM considering also on delay
//or
......@@ -386,12 +389,12 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_
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))
if((bool)(!res.value.empty() && res.value[0] != 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 : "";
//a.msg = (int)(res.value[0]) ? 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))
if((bool)(!res.value.empty() && res.value[0] != 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
......@@ -427,7 +430,13 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_
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<<";url="<<found->second.url;
tm time_tm;
time_t time_sec= found->second.ts.tv_sec;
//gmtime_r(&time_sec,&time_tm); //-> UTC
localtime_r(&time_sec,&time_tm);
char time_buf[64];
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
tmp << "name=" << alm_name << ";groups=" << grp << ";msg="<<tmp_msg<<";values="<<tmp_attr_val<<";formula="<<formula<<";time="<<time_buf << "." << found->second.ts.tv_usec<<";url="<<found->second.url;
cmd_t arg;
arg.cmd_id = CMD_COMMAND;
arg.dp_add = (long)found->second.dp_a;
......@@ -473,7 +482,13 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_
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;
tm time_tm;
time_t time_sec= found->second.ts.tv_sec;
//gmtime_r(&time_sec,&time_tm); //-> UTC
localtime_r(&time_sec,&time_tm);
char time_buf[64];
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
tmp << "name=" << alm_name << ";groups=" << grp << ";msg="<<tmp_msg<<";values="<<tmp_attr_val<<";formula="<<formula<<";time="<<time_buf << "." << found->second.ts.tv_usec;
cmd_t arg;
arg.cmd_id = CMD_COMMAND;
arg.dp_add = (long)found->second.dp_n;
......@@ -510,14 +525,14 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_
found->second.error = true;
}
if((bool)(res.value != 0)) {
if((bool)(!res.value.empty() && res.value[0] != 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())
if(!res.valid)
{
found->second.err_counter++;
}
......@@ -560,7 +575,7 @@ bool alarm_table::timer_update()
bool status_on_delay=false;
bool status_off_delay=false;
bool status_err_delay=false;
if(err_delay > 0) //if enabled off delay
if(err_delay > 0) //if enabled err 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)
......@@ -660,7 +675,13 @@ bool alarm_table::timer_update()
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;
tm time_tm;
time_t time_sec= i->second.ts.tv_sec;
//gmtime_r(&time_sec,&time_tm); //-> UTC
localtime_r(&time_sec,&time_tm);
char time_buf[64];
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
tmp << "name=" << i->second.name << ";groups=" << i->second.grp2str() << ";msg="<<tmp_msg<<";values="<<tmp_attr_val<<";formula="<<i->second.formula<<";time="<<time_buf << "." << i->second.ts.tv_usec<<";url="<<i->second.url;
cmd_t arg;
arg.cmd_id = CMD_COMMAND;
arg.dp_add = (long)i->second.dp_a;
......@@ -706,7 +727,13 @@ bool alarm_table::timer_update()
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;
tm time_tm;
time_t time_sec= i->second.ts.tv_sec;
//gmtime_r(&time_sec,&time_tm); //-> UTC
localtime_r(&time_sec,&time_tm);
char time_buf[64];
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
tmp << "name=" << i->second.name << ";groups=" << i->second.grp2str() << ";msg="<<tmp_msg<<";values="<<tmp_attr_val<<";formula="<<i->second.formula<<";time="<<time_buf << "." << i->second.ts.tv_usec<<";url="<<i->second.url;
cmd_t arg;
arg.cmd_id = CMD_COMMAND;
arg.dp_add = (long)i->second.dp_n;
......@@ -738,12 +765,20 @@ bool alarm_table::timer_update()
*(i->second.attr_value) = _RTNUN;
try
{
if(!i->second.error)
if(!i->second.error || !i->second.enabled || (i->second.shelved && i->second.silenced > 0))
{
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);
if(setAlarmQuality)
{
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
{
mydev->push_change_event(i->second.attr_name,(Tango::DevEnum *)i->second.attr_value);
mydev->push_archive_event(i->second.attr_name,(Tango::DevEnum *)i->second.attr_value);
}
}
else
{
......@@ -846,7 +881,7 @@ void alarm_table::stop_cmdthread()
}
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)
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, const string &receivers, int silent_time)
{
// We want to put properties for attribute "att_name"
Tango::DbDatum dbd_att_name(att_name);
......@@ -862,9 +897,10 @@ void alarm_table::save_alarm_conf_db(const string &att_name, const string &name,
Tango::DbDatum dbd_oncommand(ON_COMMAND_KEY);
Tango::DbDatum dbd_offcommand(OFF_COMMAND_KEY);
Tango::DbDatum dbd_enabled(ENABLED_KEY);
Tango::DbDatum dbd_receivers(RECEIVERS_KEY);
Tango::DbData db_data;
dbd_att_name << (short int)12; // Twelve properties for attribute "att_name"
dbd_att_name << (short int)13; // Thirteen properties for attribute "att_name"
dbd_name << name.c_str();
dbd_formula << formula.c_str();
dbd_on_delay << (Tango::DevLong)on_delay;
......@@ -876,6 +912,7 @@ void alarm_table::save_alarm_conf_db(const string &att_name, const string &name,
dbd_url << url.c_str();
dbd_oncommand << cmd_a.c_str();
dbd_offcommand << cmd_n.c_str();
dbd_receivers << receivers.c_str();
dbd_enabled << (enabled ? (short int)1 : (short int)0);
db_data.push_back(dbd_att_name);
......@@ -891,6 +928,7 @@ void alarm_table::save_alarm_conf_db(const string &att_name, const string &name,
db_data.push_back(dbd_oncommand);
db_data.push_back(dbd_offcommand);
db_data.push_back(dbd_enabled);
db_data.push_back(dbd_receivers);
string dev_name(mydev->get_name());
......@@ -902,7 +940,7 @@ void alarm_table::save_alarm_conf_db(const string &att_name, const string &name,
}
catch(Tango::DevFailed &e)
{
cout << __func__ << ": Exception saving configuration = " << e.errors[0].desc<<endl;
TANGO_LOG << __func__ << ": Exception saving configuration = " << e.errors[0].desc<<endl;
}
}
......@@ -922,6 +960,7 @@ void alarm_table::delete_alarm_conf_db(string att_name)
Tango::DbDatum dbd_oncommand(ON_COMMAND_KEY);
Tango::DbDatum dbd_offcommand(OFF_COMMAND_KEY);
Tango::DbDatum dbd_enabled(ENABLED_KEY);
Tango::DbDatum dbd_receivers(RECEIVERS_KEY);
Tango::DbData db_data;
......@@ -938,6 +977,7 @@ void alarm_table::delete_alarm_conf_db(string att_name)
db_data.push_back(dbd_oncommand);
db_data.push_back(dbd_offcommand);
db_data.push_back(dbd_enabled);
db_data.push_back(dbd_receivers);
string dev_name(mydev->get_name());
......@@ -948,7 +988,7 @@ void alarm_table::delete_alarm_conf_db(string att_name)
}
catch(Tango::DevFailed &e)
{
cout << __func__ << ": Exception deleting " << att_name << " = " << e.errors[0].desc<<endl;
TANGO_LOG << __func__ << ": Exception deleting " << att_name << " = " << e.errors[0].desc<<endl;
}
}
......@@ -972,7 +1012,7 @@ void alarm_table::get_alarm_list_db(vector<string> &al_list, map<string, string>
}
catch(Tango::DevFailed &e)
{
cout << __func__ << ": Exception reading configuration = " << e.errors[0].desc<<endl;
TANGO_LOG << __func__ << ": Exception reading configuration = " << e.errors[0].desc<<endl;
}
savedlock->writerIn();
saved_alarms.clear();
......@@ -994,6 +1034,7 @@ void alarm_table::get_alarm_list_db(vector<string> &al_list, map<string, string>
string alm_on_command("");
string alm_off_command("");
string alm_enabled("1");
string alm_receivers("");
for (long k=0;k < nb_prop;k++)
{
string &prop_name = db_data[i].name;
......@@ -1022,9 +1063,11 @@ void alarm_table::get_alarm_list_db(vector<string> &al_list, map<string, string>
db_data[i] >> alm_off_command;
else if (prop_name == ENABLED_KEY)
db_data[i] >> alm_enabled;
else if (prop_name == RECEIVERS_KEY)
db_data[i] >> alm_receivers;
else
{
cout << "att_name="<<att_name<<" UNKWNOWN prop_name="<<prop_name<<endl;
TANGO_LOG << "att_name="<<att_name<<" UNKWNOWN prop_name="<<prop_name<<endl;
i++;
continue;
}
......@@ -1032,6 +1075,7 @@ void alarm_table::get_alarm_list_db(vector<string> &al_list, map<string, string>
}
alm_message = std::regex_replace(alm_message, std::regex(";"), "\\;");
alm_url = std::regex_replace(alm_url, std::regex(";"), "\\;");
alm_receivers = std::regex_replace(alm_receivers, std::regex(";"), "\\;");
stringstream alm;
alm << KEY(NAME_KEY)<<alm_name << SEP <<
KEY(FORMULA_KEY)<<alm_formula << SEP <<
......@@ -1044,10 +1088,11 @@ void alarm_table::get_alarm_list_db(vector<string> &al_list, map<string, string>
KEY(URL_KEY)<< alm_url << SEP <<
KEY(ON_COMMAND_KEY)<< alm_on_command << SEP <<
KEY(OFF_COMMAND_KEY)<< alm_off_command << SEP <<
KEY(RECEIVERS_KEY)<< alm_receivers << 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;
TANGO_LOG << __func__ << ": skipped '" << alm.str() << "'" << endl;
continue;
}
al_list.push_back(alm.str());
......
/*
* alarm_table.h
*
* $Author: graziano $
*
* $Revision: 1.5 $
*
* $Log: alarm_table.h,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
......@@ -21,8 +14,9 @@
#include <iostream>
#include <string>
#include <map>
#include <numeric> //for std::accumulate
#include <tango.h>
#include <tango/tango.h>
//spirit defines have to be put befor first inclusion of spirit headers
#ifndef BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT
......@@ -51,11 +45,12 @@
#endif
//#include "log_thread.h"
#define LOG_STREAM cout
#define MAX_ARRAY_PRINTED_CHARS 1000
#define LOG_STREAM TANGO_LOG
using namespace std;
typedef vector<Tango::DevDouble> value_t;
#if BOOST_VERSION < 103600
typedef std::string::iterator iterator_t;
......@@ -109,23 +104,161 @@ struct rwlock_t
rwlock_t(string n){name=n;};
rwlock_t(){name=string("RWLOCK");};
boost::shared_mutex mut;
void readerIn(){cout<<name<<": " << __func__<<endl;mut.lock_shared();}
void readerOut(){cout<<name<<": " << __func__<<endl;mut.unlock_shared();}
void writerIn(){cout<<name<<": " << __func__<<endl;mut.lock();}
void writerOut(){cout<<name<<": " << __func__<<endl;mut.unlock();}
void readerIn(){TANGO_LOG<<name<<": " << __func__<<endl;mut.lock_shared();}
void readerOut(){TANGO_LOG<<name<<": " << __func__<<endl;mut.unlock_shared();}
void writerIn(){TANGO_LOG<<name<<": " << __func__<<endl;mut.lock();}
void writerOut(){TANGO_LOG<<name<<": " << __func__<<endl;mut.unlock();}
};
#endif
template <typename T>
string print_vector(const std::vector<T>& v, const char * const separator = ",")
{
ostringstream out;
if(!v.empty())
{
std::copy(v.begin(),
--v.end(),
std::ostream_iterator<T>(out, separator));
out << v.back();
}
return out.str();
}
template <typename T>
string print_array(const std::vector<T>& v, long dim_x, long dim_y, const char * const separator = ",")
{
ostringstream out;
if(dim_y <1)
{
out <<"["<< print_vector(v);
out.seekp(0, ios::end);
stringstream::pos_type offset = out.tellp();
if(offset > MAX_ARRAY_PRINTED_CHARS)
{
out.seekp(MAX_ARRAY_PRINTED_CHARS, ios::beg);//limit size
out << "...]" << ends;
}
else
out << "]";
return out.str();
}
out << "[";
for(long i=0; i<dim_y; i++)
{
auto vstart = v.begin();//start iterator of a row in a vector containing a 2D array
auto vend = v.begin();//end iterator of a row in a vector containing a 2D array
advance(vstart,(int)(i * (dim_x)));
advance(vend,(int)((i+1) * dim_x));
value_t row = value_t(vstart,vend);
out <<"["<< print_vector(row);
out.seekp(0, ios::end);
stringstream::pos_type offset = out.tellp();
if(offset > MAX_ARRAY_PRINTED_CHARS)
{
out.seekp(MAX_ARRAY_PRINTED_CHARS, ios::beg);//limit size
out << "...]]" << ends;
break;
}
else
out << "]";
if(i < dim_y-1)
{
out << ",";
}
}
out << "]";
return out.str();
}
struct vectorUtils
{
static double fBitAnd(long a, long b){ return (double)(a & b);}
static double fBitOr(long a, long b){ return (double)(a | b);}
static double fBitXor(long a, long b){ return (double)(a ^ b);}
static double fBitShiftL(long a, long b){ return (double)(a << b);}
static double fBitShiftR(long a, long b){ return (double)(a >> b);}
static double fMin(double a, double b){ return (double)min(a, b);}
static double fMax(double a, double b){ return (double)max(a, b);}
static double fPow(double a, double b){ return (double)pow(a, b);}
static double fEqual(double a, double b){ return (double)(a == b);}
static double fDifferent(double a, double b){ return (double)(a != b);}
static double fGreaterEqual(double a, double b){ return (double)(a >= b);}
static double fGreater(double a, double b){ return (double)(a > b);}
static double fLessEqual(double a, double b){ return (double)(a <= b);}
static double fLess(double a, double b){ return (double)(a < b);}
static double fPlus(double a, double b){ return (double)(a + b);}
static double fMinus(double a, double b){ return (double)(a - b);}
static double fMult(double a, double b){ return (double)(a * b);}
static double fDiv(double a, double b){ return (double)(a / b);}
static double fAnd(double a, double b){ return (double)((bool)a && (bool)b);}
static double fOr(double a, double b){ return (double)((bool)a || (bool)b);}
template<class T >
static void applyVectorFunc(const vector<T> & v1, long v1_x, long v1_y, const vector<T> & v2, long v2_x, long v2_y, value_t &res, long &res_x, long &res_y, const string& origin, double (*func)(T, T))
{
if(v1.size() > 0 && v2.size() > 0 && (v1.size() == v2.size()))
{
res_x = v1_x;
res_y = v1_y;
if(v1_x != v2_x || (v1_y != v2_y && (v1_y > 1 || v2_y > 1)))//dim_y 0 and 1 are the same
{
ostringstream o;
o << "Array sizes do not match: " << (v1_y ? v1_y : 1) << "x" << v1_x << " != " << (v2_y ? v2_y : 1) << "x" << v2_x;
Tango::Except::throw_exception( //throw exception to have error not delayed
"FORMULA_ERROR",
o.str(),
origin);
}
res.resize(v1.size());
std::transform(v1.begin(), v1.end(), v2.begin(),res.begin(),
[func](T a, T b) { return func(a, b); });
}
else if(v2.size() == 1)
{
res_x = v1_x;
res_y = v1_y;
T b = v2[0];
res.resize(v1.size());
std::transform(v1.begin(), v1.end(), res.begin(),
[b,func](T a) { return func(a, b); });
}
else if(v1.size() == 1)
{
res_x = v2_x;
res_y = v2_y;
T a = v1[0];
res.resize(v2.size());
std::transform(v2.begin(), v2.end(), res.begin(),
[a,func](T b) { return func(a, b); });
}
else if(v1.size() > 0 && v2.size() > 0)
{
ostringstream o;
o << "Array sizes do not match: " << (v1_y ? v1_y : 1) << "x" << v1_x << " != " << (v2_y ? v2_y : 1) << "x" << v2_x;
Tango::Except::throw_exception( //throw exception to have error not delayed
"FORMULA_ERROR",
o.str(),
origin);
}
}
};
struct formula_res_t
{
formula_res_t(){value=0;quality=Tango::ATTR_VALID;ex_reason=string("");ex_desc=string("");ex_origin=string("");}
double value;
formula_res_t(){valid=false;quality=Tango::ATTR_VALID;ex_reason=string("");ex_desc=string("");ex_origin=string("");dim_x=0;dim_y=0;}
value_t value;
long dim_x;
long dim_y;
int quality;
bool valid;
string error;
Tango::DevErrorList errors; //TODO: error stack
string ex_reason;
string ex_desc;
string ex_origin;
string attr_name; //last evaluated attr name
int combine_quality(int quality1, int quality2)
{
int res;
......@@ -148,124 +281,218 @@ struct formula_res_t
else
return ex_2;
}
void extract_result()
{
if(!value.empty())
{
value = {(double)std::accumulate(value.begin(), value.end(), (bool)false, [](bool a, double b) { return (bool)(a || (bool)b); })};
dim_x=1;
dim_y=0;
}
}
formula_res_t operator==(const formula_res_t& e)
{
formula_res_t res;
res.value = value == e.value;
res.valid = valid && e.valid;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
if(!res.valid)
{
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
}
vectorUtils::applyVectorFunc(value,dim_x,dim_y,e.value,e.dim_x,e.dim_y,res.value,res.dim_x,res.dim_y,__func__,vectorUtils::fEqual);
return res;
}
formula_res_t operator!=(const formula_res_t& e)
{
formula_res_t res;
res.value = value != e.value;
res.valid = valid && e.valid;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
if(!res.valid)
{
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
}
vectorUtils::applyVectorFunc(value,dim_x,dim_y,e.value,e.dim_x,e.dim_y,res.value,res.dim_x,res.dim_y,__func__,vectorUtils::fDifferent);
return res;
}
formula_res_t operator<=(const formula_res_t& e)
{
formula_res_t res;
res.value = value <= e.value;
res.valid = valid && e.valid;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
if(!res.valid)
{
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
}
vectorUtils::applyVectorFunc(value,dim_x,dim_y,e.value,e.dim_x,e.dim_y,res.value,res.dim_x,res.dim_y,__func__,vectorUtils::fLessEqual);
return res;
}
formula_res_t operator>=(const formula_res_t& e)
{
formula_res_t res;
res.value = value >= e.value;
res.valid = valid && e.valid;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
if(!res.valid)
{
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
}
vectorUtils::applyVectorFunc(value,dim_x,dim_y,e.value,e.dim_x,e.dim_y,res.value,res.dim_x,res.dim_y,__func__,vectorUtils::fGreaterEqual);
return res;
}
formula_res_t operator<(const formula_res_t& e)
{
formula_res_t res;
res.value = value < e.value;
res.valid = valid && e.valid;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
if(!res.valid)
{
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
}
vectorUtils::applyVectorFunc(value,dim_x,dim_y,e.value,e.dim_x,e.dim_y,res.value,res.dim_x,res.dim_y,__func__,vectorUtils::fLess);
return res;
}
formula_res_t operator>(const formula_res_t& e)
{
formula_res_t res;
res.value = value > e.value;
res.valid = valid && e.valid;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
if(!res.valid)
{
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
}
vectorUtils::applyVectorFunc(value,dim_x,dim_y,e.value,e.dim_x,e.dim_y,res.value,res.dim_x,res.dim_y,__func__,vectorUtils::fGreater);
return res;
}
formula_res_t operator||(const formula_res_t& e)
{
formula_res_t res;
res.value = value || e.value;
if(value.size() <= 1 && e.value.size() <= 1) //apply special logic ov validity only if comparing scalars. Being careful that if valid=false, then size could be 0
{
res.value = {(double)((valid && value[0]) || (e.valid && e.value[0]))}; //in OR one operand TRUE and valid is enough
res.valid = (valid && value[0]) || (e.valid && e.value[0]) || (valid && e.valid); //in OR one operand TRUE and valid is enough, otherwise both valid as usual
}
else
res.valid = valid && e.valid;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
if(!res.valid)
{
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
}
if(!(value.size() <= 1 && e.value.size() <= 1))
{
vectorUtils::applyVectorFunc(value,dim_x,dim_y,e.value,e.dim_x,e.dim_y,res.value,res.dim_x,res.dim_y,__func__,vectorUtils::fOr);
}
return res;
}
formula_res_t operator&&(const formula_res_t& e)
{
formula_res_t res;
res.value = value && e.value;
if(value.size() <= 1 && e.value.size() <= 1) //apply special logic ov validity only if comparing scalars
{
res.value = {(double)(!((valid && !value[0]) || (e.valid && !e.value[0])) || (valid && value[0] && e.valid && e.value[0]))}; //if at least one operand is FALSE and valid, result is FALSE for sure (and valid)
res.valid = (valid && !value[0]) || (e.valid && !e.value[0]) || (valid && e.valid);
}
else
res.valid = valid && e.valid;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
if(!res.valid)
{
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
}
if(!(value.size() <= 1 && e.value.size() <= 1))
{
vectorUtils::applyVectorFunc(value,dim_x,dim_y,e.value,e.dim_x,e.dim_y,res.value,res.dim_x,res.dim_y,__func__,vectorUtils::fAnd);
}
return res;
}
formula_res_t operator+(const formula_res_t& e)
{
formula_res_t res;
res.value = value + e.value;
res.valid = valid && e.valid;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
if(!res.valid)
{
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
}
vectorUtils::applyVectorFunc(value,dim_x,dim_y,e.value,e.dim_x,e.dim_y,res.value,res.dim_x,res.dim_y,__func__,vectorUtils::fPlus);
return res;
}
formula_res_t operator-(const formula_res_t& e)
{
formula_res_t res;
res.value = value - e.value;
res.valid = valid && e.valid;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
if(!res.valid)
{
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
}
vectorUtils::applyVectorFunc(value,dim_x,dim_y,e.value,e.dim_x,e.dim_y,res.value,res.dim_x,res.dim_y,__func__,vectorUtils::fMinus);
return res;
}
formula_res_t operator*(const formula_res_t& e)
{
formula_res_t res;
res.value = value * e.value;
res.valid = valid && e.valid;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
if(!res.valid)
{
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
}
vectorUtils::applyVectorFunc(value,dim_x,dim_y,e.value,e.dim_x,e.dim_y,res.value,res.dim_x,res.dim_y,__func__,vectorUtils::fMult);
return res;
}
formula_res_t operator/(const formula_res_t& e)
{
formula_res_t res;
res.value = value / e.value;
res.valid = valid && e.valid;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
if(!res.valid)
{
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
}
vectorUtils::applyVectorFunc(value,dim_x,dim_y,e.value,e.dim_x,e.dim_y,res.value,res.dim_x,res.dim_y,__func__,vectorUtils::fDiv);
return res;
}
formula_res_t operator!()
{
formula_res_t res;
for(size_t ii=0; ii < value.size(); ii++)
{
res.value.push_back(!value[ii]);
}
return res;
}
formula_res_t operator-()
{
formula_res_t res;
for(size_t ii=0; ii < value.size(); ii++)
{
res.value.push_back(-value[ii]);
}
return res;
}
/*string operator<<(const formula_res_t& e)
......@@ -316,6 +543,7 @@ class alarm_t {
bool to_be_evaluated;
string msg;
string url;
string receivers;
unsigned int grp{0};
string lev;
set<string> s_event;
......@@ -371,7 +599,9 @@ class alarm_table {
public:
alarm_table() {}
~alarm_table() {del_rwlock();}
bool setAlarmQuality {false};
void set_dev(Tango::DeviceImpl* devImpl) {mydev=devImpl;}
void set_al_qual(bool set_al_qual) {setAlarmQuality=set_al_qual;}
//void init(vector<string>& avs);
//void init(vector<string>& avs, vector<string> &evn, map< string,vector<string> > &alarm_event);
......@@ -397,7 +627,7 @@ class alarm_table {
void del_rwlock();
void 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 &url, const string &lev, const string &msg, const string &cmd_a, const string &cmd_n, int silent_time);
const string &formula, unsigned int on_delay, unsigned int off_delay, const string &grp, const string &url, const string &lev, const string &msg, const string &cmd_a, const string &cmd_n, const string &receivers, int silent_time);
void delete_alarm_conf_db(string att_name);
void get_alarm_list_db(vector<string> &al_list, map<string, string> &saved_alarms, ReadersWritersLock *savedlock);
void init_cmdthread();
......
/*
* cmd_thread.cpp
*
* $Author: claudio $
*
* $Revision: 1.3 $
*
* $Log: cmd_thread.cpp,v $
* Revision 1.3 2015-07-21 13:40:59 claudio
* minor cleanups
*
* Revision 1.2 2008-11-17 13:13:21 graziano
* command action can be: without arguments or with string argument
*
* Revision 1.1 2008/11/10 10:53:31 graziano
* thread for execution of commands
*
*
*
*
*
* copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
* Strada Statale 14 - km 163,5 in AREA Science Park
* 34012 Basovizza, Trieste ITALY
......@@ -32,8 +14,8 @@ static const char __FILE__rev[] = __FILE__ " $Revision: 1.3 $";
*/
cmd_thread::cmd_thread()
{
cout << __FILE__rev << endl;
cout << gettime().tv_sec << " cmd_thread::cmd_thread(): constructor... !" << endl;
TANGO_LOG << __FILE__rev << endl;
TANGO_LOG << gettime().tv_sec << " cmd_thread::cmd_thread(): constructor... !" << endl;
//mutex_dp = new omni_mutex::omni_mutex();
}
......@@ -42,7 +24,7 @@ cmd_thread::cmd_thread()
*/
cmd_thread::~cmd_thread()
{
cout << gettime().tv_sec << " cmd_thread::~cmd_thread(): delete device entering..." << endl;
TANGO_LOG << gettime().tv_sec << " cmd_thread::~cmd_thread(): delete device entering..." << endl;
//delete mutex_dp;
}
......@@ -62,13 +44,13 @@ void cmd_thread::run(void *)
switch(cmd.cmd_id)
{
case CMD_THREAD_EXIT:
cout << gettime().tv_sec << " cmd_thread::run(): received command THREAD_EXIT -> exiting..." << endl;
TANGO_LOG << gettime().tv_sec << " cmd_thread::run(): received command THREAD_EXIT -> exiting..." << endl;
return;
case CMD_COMMAND:
{
try {
cout << gettime().tv_sec << " cmd_thread::run(): COMMAND ... action=" << cmd.arg_s3 << endl;
TANGO_LOG << gettime().tv_sec << " cmd_thread::run(): COMMAND ... action=" << cmd.arg_s3 << endl;
dp = (Tango::DeviceProxy *)cmd.dp_add;
if(cmd.arg_b)
{
......@@ -82,7 +64,7 @@ void cmd_thread::run(void *)
}
else
call_id = dp->command_inout_asynch(cmd.arg_s2);
cout << gettime().tv_sec << " cmd_thread::run() executed action: " << cmd.arg_s3 << " !!! call_id=" << call_id << endl;
TANGO_LOG << gettime().tv_sec << " cmd_thread::run() executed action: " << cmd.arg_s3 << " !!! call_id=" << call_id << endl;
/*cmd_t arg;
arg.cmd_id = CMD_RESPONSE;
arg.call_id = call_id;
......@@ -101,11 +83,11 @@ void cmd_thread::run(void *)
if(err.find("is not yet arrived") == string::npos) //TODO: change this!!
{
out_stream << "Failed to execute action " << cmd.arg_s3 << ", err=" << e.errors[0].desc << ends;
cout << gettime().tv_sec << " cmd_thread::run() ERROR: " << out_stream.str() << endl;
TANGO_LOG << gettime().tv_sec << " cmd_thread::run() ERROR: " << out_stream.str() << endl;
}
else
{
cout << gettime().tv_sec << " cmd_thread::run() exception 'is not yet arrived': pushing request of response, call_id=" << call_id << endl;
TANGO_LOG << gettime().tv_sec << " cmd_thread::run() exception 'is not yet arrived': pushing request of response, call_id=" << call_id << endl;
cmd.cmd_id = CMD_RESPONSE; //if no exception till now push in list request of response
cmd.call_id = call_id; //if no exception till now push in list request of response
list.push_back(cmd); //if no exception till now push in list request of response
......@@ -117,12 +99,12 @@ void cmd_thread::run(void *)
case CMD_RESPONSE:
{
//cout << gettime().tv_sec << " cmd_thread::run(): RESPONSE WAKE UP... action=" << cmd.arg_s3 << " call_id=" << cmd.call_id << endl;
//TANGO_LOG << gettime().tv_sec << " cmd_thread::run(): RESPONSE WAKE UP... action=" << cmd.arg_s3 << " call_id=" << cmd.call_id << endl;
Tango::DeviceData resp;
dp = (Tango::DeviceProxy *)cmd.dp_add;
try {
resp = dp->command_inout_reply(cmd.call_id);
cout << gettime().tv_sec << " cmd_thread::run() RECEIVED response to action " << cmd.arg_s3 << endl;
TANGO_LOG << gettime().tv_sec << " cmd_thread::run() RECEIVED response to action " << cmd.arg_s3 << endl;
} catch(Tango::DevFailed &e)
{
TangoSys_MemStream out_stream;
......@@ -136,7 +118,7 @@ void cmd_thread::run(void *)
}
else
{
cout << gettime().tv_sec << " cmd_thread::run() " << out_stream.str() << endl;
TANGO_LOG << gettime().tv_sec << " cmd_thread::run() " << out_stream.str() << endl;
Tango::Except::print_exception(e);
}
}
......@@ -145,19 +127,19 @@ void cmd_thread::run(void *)
}
/* if(cmd.arg_s == CMD_THREAD_EXIT)
{
cout << gettime().tv_sec << " cmd_thread::run(): received command THREAD_EXIT -> exiting..." << endl;
TANGO_LOG << gettime().tv_sec << " cmd_thread::run(): received command THREAD_EXIT -> exiting..." << endl;
return;
}
else
{
cout << gettime().tv_sec << " cmd_thread::run(): WAKE UP... action=" << cmd.arg_s << endl;
TANGO_LOG << gettime().tv_sec << " cmd_thread::run(): WAKE UP... action=" << cmd.arg_s << endl;
Tango::DeviceData resp;
dp = (Tango::DeviceProxy *)cmd.dp_add;
try {
mutex_dp->lock();
resp = dp->command_inout_reply(cmd.cmd_id);
mutex_dp->unlock();
cout << gettime().tv_sec << " cmd_thread::run() received response to action " << cmd.arg_s << endl;
TANGO_LOG << gettime().tv_sec << " cmd_thread::run() received response to action " << cmd.arg_s << endl;
} catch(Tango::DevFailed &e)
{
TangoSys_MemStream out_stream;
......@@ -170,7 +152,7 @@ void cmd_thread::run(void *)
omni_thread::sleep(0,300000000); //0.2 s
}
else
cout << gettime().tv_sec << " cmd_thread::run() " << out_stream.str() << endl;
TANGO_LOG << gettime().tv_sec << " cmd_thread::run() " << out_stream.str() << endl;
}
}*/
......@@ -196,7 +178,7 @@ void cmd_thread::run(void *)
printf("cmd_thread::run(): catched unknown exception!!");
}
}
//cout << "alarm_thread::run(): returning" << endl;
//TANGO_LOG << "alarm_thread::run(): returning" << endl;
} /* cmd_thread::run() */
/*
......@@ -206,7 +188,7 @@ void cmd_list::push_back(cmd_t& cmd)
{
this->lock();
//cout << "cmd_list::push_back: cmd_id=" << cmd.cmd_id << " call_id=" << cmd.call_id << endl;
//TANGO_LOG << "cmd_list::push_back: cmd_id=" << cmd.cmd_id << " call_id=" << cmd.call_id << endl;
try{
l_cmd.push_back(cmd);
empty.signal();
......@@ -273,7 +255,7 @@ const cmd_t cmd_list::pop_front(void)
/*const*/ cmd_t cmd;
cmd = *(l_cmd.begin());
//cout << "cmd_list::pop_front: " << e.name << " value=" << e.value[0] << endl;
//TANGO_LOG << "cmd_list::pop_front: " << e.name << " value=" << e.value[0] << endl;
l_cmd.pop_front();
this->unlock();
......
/*
*cmd_thread.h
*
* $Author: graziano $
*
* $Revision: 1.2 $
*
* $Log: cmd_thread.h,v $
* Revision 1.2 2008-11-17 13:10:36 graziano
* command action can be: without arguments or with string argument
*
* Revision 1.1 2008/11/10 10:53:31 graziano
* thread for execution of commands
*
* Revision 1.2 2008/10/07 14:03:07 graziano
* added handling of multi axis groups and spindle groups
*
* Revision 1.1 2008/09/30 09:46:32 graziano
* first version
*
* Revision 1.3 2008/04/23 15:00:57 graziano
* small code cleanings
*
*
* cmd_thread.h
*
* copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
* Strada Statale 14 - km 163,5 in AREA Science Park
......@@ -41,7 +19,7 @@
#define CMD_THREAD_EXIT 3
#include <omnithread.h>
#include <tango.h>
#include <tango/tango.h>
#include "AlarmHandler.h"
struct cmd_t
......
/*
* event_table.cpp
*
* $Author: graziano $
*
* $Revision: 1.5 $
*
* $Log: event_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 <tango/tango.h>
#include "event_table.h"
#include "AlarmHandler.h"
#include "alarm_grammar.h"
//for get_event_system_for_event_id, to know if ZMQ
#include <eventconsumer.h>
#include <regex>
static const char __FILE__rev[] = __FILE__ " $Revision: 1.5 $";
......@@ -48,8 +39,8 @@ void event_list::push_back(bei_t& e)
ostringstream err;
err << "exception signaling omni_condition: '" << ex.errors[0].desc << "'";
//WARN_STREAM << "event_list::push_back(): " << err.str() << endl;
printf("event_list::push_back: %s", err.str().c_str());
Tango::Except::print_exception(ex);
//printf("event_list::push_back: %s", err.str().c_str());
//Tango::Except::print_exception(ex);
}
catch(...)
{
......@@ -83,8 +74,8 @@ const bei_t event_list::pop_front(void)
ostringstream err;
err << "exception waiting on omni_condition: '" << ex.errors[0].desc << "'";
//WARN_STREAM << "event_list::pop_front(): " << err.str() << endl;
printf("event_list::pop_front: %s", err.str().c_str());
Tango::Except::print_exception(ex);
//printf("event_list::pop_front: %s", err.str().c_str());
//Tango::Except::print_exception(ex);
bei_t e;
this->unlock();
sleep(1);
......@@ -154,7 +145,7 @@ void alarm_list::pop(const string& a)
if(it != l_alarm.end())
l_alarm.erase(it);
else
cout << "alarm_list::"<<__func__<< ": ALARM '"<< a << "' NOT FOUND!"<< endl;
TANGO_LOG << "alarm_list::"<<__func__<< ": ALARM '"<< a << "' NOT FOUND!"<< endl;
l.unlock();
return;
......@@ -210,6 +201,8 @@ event::event(string& s, value_t& v, Tango::TimeVal& t) : \
event_id = SUB_ERR;
err_counter = 0;
valid = false;
dim_x=0;
dim_y=0;
}
event::event(string& s) : name(s)
......@@ -231,7 +224,9 @@ event::event(string& s) : name(s)
type = -1;
event_id = SUB_ERR;
err_counter = 0;
valid = false;
valid = false;
dim_x=0;
dim_y=0;
}
bool event::operator==(const event& e)
......@@ -298,27 +293,10 @@ void event_table::summary(list<string> &evs)
ev_summary << KEY(EVENT_TIME_KEY) << time_buf << SEP;
ostringstream tmp_val;
//if(i->valid)
{
tmp_val << "[" ;
if(i->type != Tango::DEV_STRING)
{
if(i->read_size > 0 && i->value.size() > 0)
{
for(size_t k=0; k<i->read_size && k<i->value.size(); k++)
{
tmp_val << i->value[k];
if(k < i->read_size-1 && k<i->value.size()-1)
tmp_val << ",";
}
}
}
else
{
tmp_val << "\""<<i->value_string<<"\"";
}
tmp_val << "]";
}
if(i->type != Tango::DEV_STRING)
tmp_val << print_array(i->value,i->dim_x,i->dim_y);
else
tmp_val << "[\""<<i->value_string<<"\"]";
ev_summary << KEY(ATTR_VALUES_KEY) << tmp_val.str() << SEP;
ostringstream tmp_ex;
//tmp_ex.str("");
......@@ -394,7 +372,7 @@ void event_table::free_proxy(void)
}
}
void event_table::subscribe(EventCallBack& ecb) throw(vector<string> &)//throw(string&)
void event_table::subscribe(EventCallBack& ecb)
{
vector<string> subscribe_error;
if (v_event.empty() == false) {
......@@ -418,7 +396,7 @@ void event_table::subscribe(EventCallBack& ecb) throw(vector<string> &)//throw(s
throw subscribe_error;
}
void event_table::unsubscribe(void) throw(string&)
void event_table::unsubscribe(void)
{
ostringstream o;
if (v_event.empty() == false) {
......@@ -847,6 +825,9 @@ void event_table::add(string &signame, vector<string> contexts, int to_do, bool
signal->running = false;
signal->stopped = true;
signal->paused = false;
signal->valid = false;
signal->dim_x=0;
signal->dim_y=0;
//DEBUG_STREAM << "event_table::"<<__func__<<": signame="<<signame<<" created signal"<< endl;
}
else if(found && start)
......@@ -1015,7 +996,7 @@ void event_table::subscribe_events()
<< sig_name << "' error=" << ex_desc;
INFO_STREAM <<"event_table::"<<__func__<<": sig->attr->subscribe_event: " << o.str() << endl;
err = true;
Tango::Except::print_exception(e);
//Tango::Except::print_exception(e);
//sig->siglock->writerIn(); //not yet subscribed, no one can modify
sig->ex_reason = ex.ex_reason = ex_reason;
sig->ex_desc = ex.ex_desc = ex_desc;
......@@ -1271,7 +1252,7 @@ void EventCallBack::push_event(Tango::EventData* ev)
try {
//e.errors = ev->errors;
e.quality = Tango::ATTR_VALID;
//cout << "EVENT="<<ev->attr_name<<" quality="<<e.quality<<endl;
//TANGO_LOG << "EVENT="<<ev->attr_name<<" quality="<<e.quality<<endl;
if (!ev->err) {
e.quality = (int)ev->attr_value->get_quality();
#if 0//TANGO_VER >= 711
......@@ -1287,7 +1268,7 @@ void EventCallBack::push_event(Tango::EventData* ev)
e.ev_name = ev->attr_name;
#endif
e.ts = ev->attr_value->time;
extract_values(ev->attr_value, e.value, e.value_string, e.type, e.read_size);
extract_values(ev->attr_value, e.value, e.value_string, e.type, e.read_size, e.dim_x, e.dim_y);
} else {
e.quality = Tango::ATTR_INVALID;
#if 0//TANGO_VER >= 711
......@@ -1308,7 +1289,7 @@ void EventCallBack::push_event(Tango::EventData* ev)
temp_name = temp_name.substr(0,pos_change);
}
ostringstream o;
o << "Tango error for '" << temp_name << "'=" << ev->errors[0].desc.in();
o << "Tango error for " << temp_name << ": " << ev->errors[0].desc.in();
e.ev_name = temp_name;
e.type = TYPE_TANGO_ERR;
//e.ev_name = INTERNAL_ERROR;
......@@ -1350,7 +1331,7 @@ void EventCallBack::push_event(Tango::EventData* ev)
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->evlist.push_back(e);
} /* push_event() */
void EventCallBack::extract_values(Tango::DeviceAttribute *attr_value, vector<double> &val, string &val_string, int &type, int &read_size)
void EventCallBack::extract_values(Tango::DeviceAttribute *attr_value, vector<double> &val, string &val_string, int &type, int &read_size, long &dim_x, long &dim_y)
{
Tango::DevState stval;
vector<Tango::DevState> v_st;
......@@ -1384,76 +1365,79 @@ void EventCallBack::extract_values(Tango::DeviceAttribute *attr_value, vector<do
attr_r_dim.dim_y = 0;
//attr_w_dim.dim_y = 0;
}
dim_x = attr_r_dim.dim_x;
dim_y = attr_r_dim.dim_y;
read_size = attr_r_dim.dim_x;
if(attr_r_dim.dim_y > 1)
read_size *= attr_r_dim.dim_y;
if (attr_value->get_type() == Tango::DEV_UCHAR) {
*(attr_value) >> v_uch;
attr_value->extract_read(v_uch);
for(vector<Tango::DevUChar>::iterator it = v_uch.begin(); it != v_uch.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_UCHAR;
} else if (attr_value->get_type() == Tango::DEV_SHORT) {
*(attr_value) >> v_sh;
attr_value->extract_read(v_sh);
for(vector<Tango::DevShort>::iterator it = v_sh.begin(); it != v_sh.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_SHORT;
} else if (attr_value->get_type() == Tango::DEV_USHORT) {
*(attr_value) >> v_ush;
attr_value->extract_read(v_ush);
for(vector<Tango::DevUShort>::iterator it = v_ush.begin(); it != v_ush.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_USHORT;
} else if (attr_value->get_type() == Tango::DEV_LONG) {
*(attr_value) >> v_lo;
attr_value->extract_read(v_lo);
for(vector<Tango::DevLong>::iterator it = v_lo.begin(); it != v_lo.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_LONG;
} else if (attr_value->get_type() == Tango::DEV_STATE) {
//*(attr_value) >> v_st; //doesn't work in tango 5
*(attr_value) >> stval;
v_st.push_back(stval);
for(vector<Tango::DevState>::iterator it = v_st.begin(); it != v_st.end(); it++)
val.push_back((double)(*it)); //convert all to double
//v_st.push_back(stval);
//attr_value->extract_read(stval);
//for(vector<Tango::DevState>::iterator it = v_st.begin(); it != v_st.end(); it++)
val.push_back((double)(stval)); //convert all to double
type = Tango::DEV_STATE;
#if 1//TANGO_VER >= 600
} else if (attr_value->get_type() == Tango::DEV_ULONG) {
*(attr_value) >> v_ulo;
attr_value->extract_read(v_ulo);
for(vector<Tango::DevULong>::iterator it = v_ulo.begin(); it != v_ulo.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_ULONG;
#endif //TANGO_VER >= 600
} else if (attr_value->get_type() == Tango::DEV_DOUBLE) {
*(attr_value) >> v_do;
attr_value->extract_read(v_do);
for(vector<Tango::DevDouble>::iterator it = v_do.begin(); it != v_do.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_DOUBLE;
} else if (attr_value->get_type() == Tango::DEV_FLOAT) {
*(attr_value) >> v_fl;
attr_value->extract_read(v_fl);
for(vector<Tango::DevFloat>::iterator it = v_fl.begin(); it != v_fl.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_FLOAT;
} else if (attr_value->get_type() == Tango::DEV_BOOLEAN) {
*(attr_value) >> v_bo;
attr_value->extract_read(v_bo);
for(vector<Tango::DevBoolean>::iterator it = v_bo.begin(); it != v_bo.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_BOOLEAN;
} else if (attr_value->get_type() == Tango::DEV_LONG64) {
*(attr_value) >> v_lo64;
attr_value->extract_read(v_lo64);
for(vector<Tango::DevLong64>::iterator it = v_lo64.begin(); it != v_lo64.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_LONG64;
} else if (attr_value->get_type() == Tango::DEV_ULONG64) {
*(attr_value) >> v_ulo64;
attr_value->extract_read(v_ulo64);
for(vector<Tango::DevULong64>::iterator it = v_ulo64.begin(); it != v_ulo64.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_ULONG64;
} else if (attr_value->get_type() == Tango::DEV_ENUM) {
*(attr_value) >> v_enum;
attr_value->extract_read(v_enum);
for(vector<Tango::DevEnum>::iterator it = v_enum.begin(); it != v_enum.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_ENUM;
} else if (attr_value->get_type() == Tango::DEV_STRING) {
*(attr_value) >> v_string;
attr_value->extract_read(v_string);
val_string = *(v_string.begin()); //TODO: support string spectrum attrbutes
type = Tango::DEV_STRING;
}
......@@ -1461,7 +1445,7 @@ void EventCallBack::extract_values(Tango::DeviceAttribute *attr_value, vector<do
ostringstream o;
o << "unknown type";
throw o.str();
}
}
}
/*void EventCallBack::init(event_list* e)
......
/*
* event_table.cpp
*
* $Author: graziano $
*
* $Revision: 1.5 $
*
* $Log: event_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 "event_table.h"
#include "AlarmHandler.h"
#include "alarm_grammar.h"
//for get_event_system_for_event_id, to know if ZMQ
#include <eventconsumer.h>
#include <regex>
static const char __FILE__rev[] = __FILE__ " $Revision: 1.5 $";
/*
* event_list class methods
*/
void event_list::push_back(bei_t& e)
{
this->lock();
try{
l_event.push_back(e);
empty.signal();
}
catch(omni_thread_fatal& ex)
{
ostringstream err;
err << "omni_thread_fatal exception signaling omni_condition, err=" << ex.error;
//WARN_STREAM << "event_list::push_back(): " << err.str() << endl;
printf("event_list::push_back(): %s", err.str().c_str());
}
catch(Tango::DevFailed& ex)
{
ostringstream err;
err << "exception signaling omni_condition: '" << ex.errors[0].desc << "'";
//WARN_STREAM << "event_list::push_back(): " << err.str() << endl;
printf("event_list::push_back: %s", err.str().c_str());
Tango::Except::print_exception(ex);
}
catch(...)
{
//WARN_STREAM << "event_list::push_back(): catched unknown exception!!" << endl;
printf("event_list::push_back(): catched unknown exception signaling omni_condition!!");
}
this->unlock();
}
const bei_t event_list::pop_front(void)
{
this->lock();
//omni_mutex_lock l((omni_mutex)this); //call automatically unlock on destructor and on exception
try{
while (l_event.empty() == true)
empty.wait(); //wait release mutex while is waiting, then reacquire when signaled
}
catch(omni_thread_fatal& ex)
{
ostringstream err;
err << "omni_thread_fatal exception waiting on omni_condition, err=" << ex.error;
//WARN_STREAM << "event_list::pop_front(): " << err.str() << endl;
printf("event_list::pop_front(): %s", err.str().c_str());
bei_t e;
this->unlock();
sleep(1);
return(e);
}
catch(Tango::DevFailed& ex)
{
ostringstream err;
err << "exception waiting on omni_condition: '" << ex.errors[0].desc << "'";
//WARN_STREAM << "event_list::pop_front(): " << err.str() << endl;
printf("event_list::pop_front: %s", err.str().c_str());
Tango::Except::print_exception(ex);
bei_t e;
this->unlock();
sleep(1);
return(e);
}
catch(...)
{
//WARN_STREAM << "event_list::pop_front(): catched unknown exception!!" << endl;
printf("event_list::pop_front(): catched unknown exception waiting on omni_condition!!");
bei_t e;
this->unlock();
sleep(1);
return(e);
}
/*const*/ bei_t e;
e = *(l_event.begin());
l_event.pop_front();
this->unlock();
return(e);
}
void event_list::clear(void)
{
//this->lock();
l_event.clear();
//this->unlock();
}
list<bei_t> event_list::show(void)
{
list<bei_t> el;
this->lock();
el = l_event;
this->unlock();
return(el);
}
size_t event_list::size(void)
{
size_t res;
this->lock();
res = l_event.size();
this->unlock();
return(res);
}
/*
* alarm_list class methods
*/
void alarm_list::push(string& a)
{
l.lock();
l_alarm.push_back(a);
l.unlock();
}
void alarm_list::pop(const string& a)
{
l.lock();
list<string>::iterator it = find(l_alarm.begin(), l_alarm.end(), a);
if(it != l_alarm.end())
l_alarm.erase(it);
else
cout << "alarm_list::"<<__func__<< ": ALARM '"<< a << "' NOT FOUND!"<< endl;
l.unlock();
return;
}
void alarm_list::clear(void)
{
l.lock();
l_alarm.clear();
l.unlock();
}
list<string> alarm_list::show(void)
{
list<string> al;
l.lock();
al = l_alarm;
l.unlock();
return(al);
}
bool alarm_list::empty(void)
{
bool res;
l.lock();
res = l_alarm.empty();
l.unlock();
return(res);
}
/*
* event class methods
*/
event::event(string& s, value_t& v, Tango::TimeVal& t) : \
name(s), value(v), ts(t)
{
const char *c = name.c_str();
int j = 0;
int num_slashes=3; //not FQDN
if(name.find("tango://") != string::npos) //FQDN!!
num_slashes = 6;
while (*c) {
if (*c == '/')
j++;
if (j < num_slashes)
devname.push_back(*c);
else if (*c != '/')
attname.push_back(*c);
c++;
}
type = -1;
event_id = SUB_ERR;
err_counter = 0;
valid = false;
}
event::event(string& s) : name(s)
{
const char *c = name.c_str();
int j = 0;
int num_slashes=3; //not FQDN
if(name.find("tango://") != string::npos) //FQDN!!
num_slashes = 6;
while (*c) {
if (*c == '/')
j++;
if (j < num_slashes)
devname.push_back(*c);
else if (*c != '/')
attname.push_back(*c);
c++;
}
type = -1;
event_id = SUB_ERR;
err_counter = 0;
valid = false;
}
bool event::operator==(const event& e)
{
return(name == e.name);
}
bool event::operator==(const string& s)
{
return(name == s);
}
/*
* event_table class methods
*/
/*void event_table::push_back(event e)
{
// v_event.push_back(e);//TODO: replaced with add
}*/
void event_table::show(list<string> &evl)
{
evl.clear();
ReaderLock lock(veclock);
if (v_event.empty() == false)
{
vector<event>::iterator i = v_event.begin();
while (i != v_event.end())
{
//DEBUG_STREAM << "\t" << i->name << endl;
evl.push_back(i->name);
i++;
}
}
}
void event_table::summary(list<string> &evs)
{
evs.clear();
ReaderLock lock(veclock);
if (v_event.empty() == false)
{
vector<event>::iterator i = v_event.begin();
while (i != v_event.end())
{
ostringstream ev_summary;
ev_summary << KEY(EVENT_KEY) << i->name << SEP;
tm time_tm;
time_t time_sec;
if(i->valid)
{
time_sec= i->ts.tv_sec;
}
else
{
timeval now;
gettimeofday(&now, NULL);
time_sec = now.tv_sec;
}
//gmtime_r(&time_sec,&time_tm); //-> UTC
localtime_r(&time_sec,&time_tm);
char time_buf[64];
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
ev_summary << KEY(EVENT_TIME_KEY) << time_buf << SEP;
ostringstream tmp_val;
//if(i->valid)
{
tmp_val << "[" ;
if(i->type != Tango::DEV_STRING)
{
if(i->read_size > 0 && i->value.size() > 0)
{
for(size_t k=0; k<i->read_size && k<i->value.size(); k++)
{
tmp_val << i->value[k];
if(k < i->read_size-1 && k<i->value.size()-1)
tmp_val << ",";
}
}
}
else
{
tmp_val << "\""<<i->value_string<<"\"";
}
tmp_val << "]";
}
ev_summary << KEY(ATTR_VALUES_KEY) << tmp_val.str() << SEP;
ostringstream tmp_ex;
//tmp_ex.str("");
if(!i->ex_reason.empty() || !i->ex_desc.empty() || !i->ex_origin.empty())
{
tmp_ex << "{\"Reason\":\"" << i->ex_reason << "\",\"Desc\":\"" << i->ex_desc << "\",\"Origin\":\"" << i->ex_origin << "\"}";
}
ev_summary << KEY(EXCEPTION_KEY) << tmp_ex.str() << SEP;
ev_summary << KEY(QUALITY_KEY);
try
{
ev_summary << quality_labels.at(i->quality) << SEP;
} catch(std::out_of_range& ex)
{
ev_summary << i->quality << SEP;
}
evs.push_back(ev_summary.str());
i++;
}
}
}
event_table::event_table(Tango::DeviceImpl *s):Tango::LogAdapter(s)
{
mydev = s;
stop_it = false;
action.store(NOTHING);
}
unsigned int event_table::size(void)
{
ReaderLock lock(veclock); //TODO: necessary?
return(v_event.size());
}
#if 0
void event_table::init_proxy(void) throw(vector<string> &)
{
vector<string> proxy_error;
if (v_event.empty() == false) {
for (vector<event>::iterator i = v_event.begin(); \
i != v_event.end(); i++)
{
try {
i->dp = new Tango::DeviceProxy(i->device);
} catch(Tango::DevFailed& e)
{
ostringstream o;
o << "new DeviceProxy() failed for " \
<< i->device;
ERROR_STREAM << o.str() << endl;
//throw o.str();
proxy_error.push_back(o.str());
}
}
}
if(!proxy_error.empty())
throw proxy_error;
}
void event_table::free_proxy(void)
{
if (v_event.empty() == false) {
for (vector<event>::iterator i = v_event.begin(); \
i != v_event.end(); i++) {
try{
delete i->dp;
DEBUG_STREAM << gettime().tv_sec << " event_table::free_proxy(): deleted proxy " << i->device << endl;
} catch(...)
{
ERROR_STREAM << "event_table::free_proxy: exception deleting proxy of event: " << i->name << endl;
}
}
}
}
void event_table::subscribe(EventCallBack& ecb) throw(vector<string> &)//throw(string&)
{
vector<string> subscribe_error;
if (v_event.empty() == false) {
for (vector<event>::iterator i = v_event.begin(); \
i != v_event.end(); i++) {
try {
i->eid = i->dp->subscribe_event(i->attribute, \
Tango::CHANGE_EVENT, \
&ecb, i->filter);
} catch (...) {
ostringstream o;
o << "subscribe_event() failed for " \
<< i->name;
ERROR_STREAM << o.str() << endl;
//throw o.str();
subscribe_error.push_back(o.str());
}
}
}
if(!subscribe_error.empty())
throw subscribe_error;
}
void event_table::unsubscribe(void) throw(string&)
{
ostringstream o;
if (v_event.empty() == false) {
for (vector<event>::iterator i = v_event.begin(); \
i != v_event.end(); i++) {
try {
i->dp->unsubscribe_event(i->eid);
DEBUG_STREAM << gettime().tv_sec << " event_table::unsubscribe(): unsubscribed " << i->name << endl;
} catch (Tango::DevFailed& e) {
o << " unsubscribe_event() failed for " << i->name << " err=" << e.errors[0].desc;
ERROR_STREAM << gettime().tv_sec << " event_table::unsubscribe(): " << o.str() << endl;
//throw o.str();
} catch (...) {
o << " unsubscribe_event() failed for " \
<< i->name;
ERROR_STREAM << gettime().tv_sec << " event_table::unsubscribe(): " << o.str() << endl;
//throw o.str();
}
}
}
if(o.str().length() > 0)
throw o.str();
}
#endif
//=============================================================================
/**
* get signal by name.
*/
//=============================================================================
event *event_table::get_signal(string signame)
{
//omni_mutex_lock sync(*this);
for (unsigned int i=0 ; i<v_event.size() ; i++)
{
event *sig = &v_event[i];
if (sig->name==signame)
return sig;
}
for (unsigned int i=0 ; i<v_event.size() ; i++)
{
event *sig = &v_event[i];
if (static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_without_domain(sig->name,signame))
return sig;
}
return NULL;
}
//=============================================================================
/**
* Stop saving on DB a signal.
*/
//=============================================================================
void event_table::stop(string &signame)
{
DEBUG_STREAM <<"event_table::"<< __func__<<": entering signame="<< signame << endl;
ReaderLock lock(veclock);
for (unsigned int i=0 ; i<v_event.size() ; i++)
{
if (v_event[i].name==signame)
{
v_event[i].siglock->writerIn();
if(!v_event[i].stopped)
{
v_event[i].stopped=true;
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read++;
if(v_event[i].running)
{
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStartedNumber_read--;
try
{
remove(signame, true);
}
catch (Tango::DevFailed &e)
{
//Tango::Except::print_exception(e);
INFO_STREAM << "event_table::stop: error removing " << signame << endl;
}
}
if(v_event[i].paused)
{
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--;
try
{
remove(signame, true);
}
catch (Tango::DevFailed &e)
{
//Tango::Except::print_exception(e);
INFO_STREAM << "event_table::stop: error removing " << signame << endl;
}
}
v_event[i].running=false;
v_event[i].paused=false;
}
v_event[i].siglock->writerOut();
return;
}
}
for (unsigned int i=0 ; i<v_event.size() ; i++)
{
#ifndef _MULTI_TANGO_HOST
if (static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_without_domain(v_event[i].name,signame))
#else
if (!static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_tango_names(v_event[i].name,signame))
#endif
{
v_event[i].siglock->writerIn();
if(!v_event[i].stopped)
{
v_event[i].stopped=true;
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read++;
if(v_event[i].running)
{
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStartedNumber_read--;
try
{
remove(signame, true);
}
catch (Tango::DevFailed &e)
{
//Tango::Except::print_exception(e);
INFO_STREAM << "event_table::stop: error removing " << signame << endl;
}
}
if(v_event[i].paused)
{
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--;
try
{
remove(signame, true);
}
catch (Tango::DevFailed &e)
{
//Tango::Except::print_exception(e);
INFO_STREAM << "event_table::stop: error removing " << signame << endl;
}
}
v_event[i].running=false;
v_event[i].paused=false;
}
v_event[i].siglock->writerOut();
return;
}
}
// if not found
Tango::Except::throw_exception(
(const char *)"BadSignalName",
"Signal " + signame + " NOT subscribed",
(const char *)"event_table::stop()");
}
//=============================================================================
/**
* Remove a signal in the list.
*/
//=============================================================================
void event_table::remove(string &signame, bool stop)
{
DEBUG_STREAM <<"event_table::"<< __func__<<": entering signame="<< signame << endl;
// Remove in signals list (vector)
{
if(!stop)
veclock.readerIn();
event *sig = get_signal(signame);
int event_id = sig->event_id;
Tango::AttributeProxy *attr = sig->attr;
if(!stop)
veclock.readerOut();
if(stop)
{
try
{
if(event_id != SUB_ERR && attr)
{
DEBUG_STREAM <<"event_table::"<< __func__<<": unsubscribing... "<< signame << endl;
//unlocking, locked in event_table::stop but possible deadlock if unsubscribing remote attribute with a faulty event connection
sig->siglock->writerOut();
attr->unsubscribe_event(event_id);
sig->siglock->writerIn();
DEBUG_STREAM <<"event_table::"<< __func__<<": unsubscribed... "<< signame << endl;
}
}
catch (Tango::DevFailed &e)
{
// Do nothing
// Unregister failed means Register has also failed
sig->siglock->writerIn();
INFO_STREAM <<"event_table::"<< __func__<<": Exception unsubscribing " << signame << " err=" << e.errors[0].desc << endl;
}
}
if(!stop)
veclock.writerIn();
vector<event>::iterator pos = v_event.begin();
bool found = false;
for (unsigned int i=0 ; i<v_event.size() && !found ; i++, pos++)
{
event *sig = &v_event[i];
if (sig->name==signame)
{
found = true;
if(stop)
{
DEBUG_STREAM <<"event_table::"<<__func__<< ": removing " << signame << endl;
//sig->siglock->writerIn(); //: removed, already locked in event_table::stop
try
{
if(sig->event_id != SUB_ERR)
{
delete sig->event_cb;
}
if(sig->attr)
delete sig->attr;
}
catch (Tango::DevFailed &e)
{
// Do nothing
// Unregister failed means Register has also failed
INFO_STREAM <<"event_table::"<< __func__<<": Exception deleting " << signame << " err=" << e.errors[0].desc << endl;
}
//sig->siglock->writerOut();
DEBUG_STREAM <<"event_table::"<< __func__<<": stopped " << signame << endl;
}
if(!stop)
{
if(sig->running)
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStartedNumber_read--;
if(sig->paused)
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--;
if(sig->stopped)
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read--;
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeNumber_read--;
delete sig->siglock;
v_event.erase(pos);
DEBUG_STREAM <<"event_table::"<< __func__<<": removed " << signame << endl;
}
break;
}
}
pos = v_event.begin();
if (!found)
{
for (unsigned int i=0 ; i<v_event.size() && !found ; i++, pos++)
{
event *sig = &v_event[i];
#ifndef _MULTI_TANGO_HOST
if (static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_without_domain(sig->name,signame))
#else
if (!static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_tango_names(sig->name,signame))
#endif
{
found = true;
DEBUG_STREAM <<"event_table::"<<__func__<< ": removing " << signame << endl;
if(stop)
{
sig->siglock->writerIn();
try
{
if(sig->event_id != SUB_ERR)
{
delete sig->event_cb;
}
if(sig->attr)
delete sig->attr;
}
catch (Tango::DevFailed &e)
{
// Do nothing
// Unregister failed means Register has also failed
INFO_STREAM <<"event_table::"<< __func__<<": Exception unsubscribing " << signame << " err=" << e.errors[0].desc << endl;
}
sig->siglock->writerOut();
DEBUG_STREAM <<"event_table::"<< __func__<<": stopped " << signame << endl;
}
if(!stop)
{
if(sig->running)
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStartedNumber_read--;
if(sig->paused)
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--;
if(sig->stopped)
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read--;
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeNumber_read--;
delete sig->siglock;
v_event.erase(pos);
DEBUG_STREAM <<"event_table::"<< __func__<<": removed " << signame << endl;
}
break;
}
}
}
if(!stop)
veclock.writerOut();
if (!found)
Tango::Except::throw_exception(
(const char *)"BadSignalName",
"Signal " + signame + " NOT subscribed",
(const char *)"event_table::remove()");
}
// then, update property
/* if(!stop)
{
DEBUG_STREAM <<"event_table::"<< __func__<<": going to increase action... action="<<action<<"++" << endl;
if(action <= UPDATE_PROP)
action++;
//put_signal_property(); //TODO: wakeup thread and let it do it? -> signal()
signal();
}*/
}
void event_table::update_property()
{
DEBUG_STREAM <<"event_table::"<< __func__<<": going to increase action... action="<<action.load()<<"++" << endl;
int expected=NOTHING;
action.compare_exchange_strong(expected, UPDATE_PROP); //if it is NOTHING, then change to UPDATE_PROP
signal();
}
//=============================================================================
/**
* Remove a signal in the list.
*/
//=============================================================================
void event_table::unsubscribe_events()
{
DEBUG_STREAM <<"event_table::"<<__func__<< " entering..."<< endl;
veclock.readerIn();
vector<event> local_signals(v_event);
veclock.readerOut();
for (unsigned int i=0 ; i<local_signals.size() ; i++)
{
event *sig = &local_signals[i];
if (local_signals[i].event_id != SUB_ERR && sig->attr)
{
DEBUG_STREAM <<"event_table::"<<__func__<< " unsubscribe " << sig->name << " id="<<omni_thread::self()->id()<< endl;
try
{
sig->attr->unsubscribe_event(sig->event_id);
DEBUG_STREAM <<"event_table::"<<__func__<< " unsubscribed " << sig->name << endl;
}
catch (Tango::DevFailed &e)
{
// Do nothing
// Unregister failed means Register has also failed
INFO_STREAM <<"event_table::"<<__func__<< " ERROR unsubscribing " << sig->name << " err="<<e.errors[0].desc<< endl;
}
}
}
veclock.writerIn();
for (unsigned int i=0 ; i<v_event.size() ; i++)
{
event *sig = &v_event[i];
sig->siglock->writerIn();
if (v_event[i].event_id != SUB_ERR && sig->attr)
{
delete sig->event_cb;
DEBUG_STREAM <<"event_table::"<<__func__<< " deleted cb " << sig->name << endl;
}
if(sig->attr)
{
delete sig->attr;
DEBUG_STREAM <<"event_table::"<<__func__<< " deleted proxy " << sig->name << endl;
}
sig->siglock->writerOut();
delete sig->siglock;
DEBUG_STREAM <<"event_table::"<<__func__<< " deleted lock " << sig->name << endl;
}
DEBUG_STREAM <<"event_table::"<<__func__<< " ended loop, deleting vector" << endl;
/*for (unsigned int j=0 ; j<signals.size() ; j++, pos++)
{
signals[j].event_id = SUB_ERR;
signals[j].event_conf_id = SUB_ERR;
signals[j].archive_cb = NULL;
signals[j].attr = NULL;
}*/
v_event.clear();
veclock.writerOut();
DEBUG_STREAM <<"event_table::"<< __func__<< ": exiting..."<<endl;
}
//=============================================================================
/**
* Add a new signal.
*/
//=============================================================================
void event_table::add(string &signame, vector<string> contexts)
{
DEBUG_STREAM << "event_table::"<<__func__<< " entering signame=" << signame << endl;
add(signame, contexts, NOTHING, false);
}
//=============================================================================
/**
* Add a new signal.
*/
//=============================================================================
void event_table::add(string &signame, vector<string> contexts, int to_do, bool start)
{
DEBUG_STREAM << "event_table::"<<__func__<<": Adding " << signame << " to_do="<<to_do<<" start="<<(start ? "Y" : "N")<< endl;
{
veclock.readerIn();
event *sig;
// Check if already subscribed
bool found = false;
for (unsigned int i=0 ; i<v_event.size() && !found ; i++)
{
sig = &v_event[i];
found = (sig->name==signame);
}
for (unsigned int i=0 ; i<v_event.size() && !found ; i++)
{
sig = &v_event[i];
found = static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_without_domain(sig->name,signame);
}
veclock.readerOut();
//DEBUG_STREAM << "event_table::"<<__func__<<": signame="<<signame<<" found="<<(found ? "Y" : "N") << " start="<<(start ? "Y" : "N")<< endl;
if (found && !start)
Tango::Except::throw_exception(
(const char *)"BadSignalName",
"Signal " + signame + " already subscribed",
(const char *)"event_table::add()");
event *signal;
if (!found && !start)
{
// on name, split device name and attrib name
string::size_type idx = signame.find_last_of("/");
if (idx==string::npos)
{
Tango::Except::throw_exception(
(const char *)"SyntaxError",
"Syntax error in signal name " + signame,
(const char *)"event_table::add()");
}
signal = new event();
// Build Hdb Signal object
signal->name = signame;
signal->siglock = new(ReadersWritersLock);
signal->devname = signal->name.substr(0, idx);
signal->attname = signal->name.substr(idx+1);
signal->ex_reason = "NOT_connected";
signal->ex_desc = "Attribute not subscribed";
signal->ex_origin = "...";
signal->attr = NULL;
signal->running = false;
signal->stopped = true;
signal->paused = false;
//DEBUG_STREAM << "event_table::"<<__func__<<": signame="<<signame<<" created signal"<< endl;
}
else if(found && start)
{
signal = sig;
#if 0
signal->siglock->writerIn();
signal->ex_reason = "NOT_connected";
signal->ex_desc = "Attribute not subscribed";
signal->ex_origin = "...";
signal->siglock->writerOut();
#endif
//DEBUG_STREAM << "created proxy to " << signame << endl;
// create Attribute proxy
signal->attr = new Tango::AttributeProxy(signal->name); //TODO: OK out of siglock? accessed only inside the same thread?
DEBUG_STREAM << "event_table::"<<__func__<<": signame="<<signame<<" created proxy"<< endl;
}
signal->event_id = SUB_ERR;
signal->evstate = Tango::ALARM;
signal->isZMQ = false;
signal->okev_counter = 0;
signal->okev_counter_freq = 0;
signal->nokev_counter = 0;
signal->nokev_counter_freq = 0;
signal->first = true;
signal->first_err = true;
clock_gettime(CLOCK_MONOTONIC, &signal->last_ev);
if(found && start)
{
}
//DEBUG_STREAM <<"event_table::"<< __func__<< " created proxy to " << signame << endl;
if (!found && !start)
{
veclock.writerIn();
// Add in vector
v_event.push_back(*signal);
delete signal;
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeNumber_read++;
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read++;
veclock.writerOut();
//DEBUG_STREAM << "event_table::"<<__func__<<": signame="<<signame<<" push_back signal"<< endl;
}
else if(found && start)
{
}
int act=action.load();
DEBUG_STREAM <<"event_table::"<< __func__<<": going to increase action... action="<<act<<" += " << to_do << endl;
int expected=NOTHING;
action.compare_exchange_strong(expected, UPDATE_PROP); //if it is NOTHING, then change to UPDATE_PROP
}
DEBUG_STREAM <<"event_table::"<< __func__<<": exiting... " << signame << endl;
signal();
//condition.signal();
}
//=============================================================================
/**
* Subscribe archive event for each signal
*/
//=============================================================================
void event_table::subscribe_events()
{
/*for (unsigned int ii=0 ; ii<v_event.size() ; ii++)
{
event *sig2 = &v_event[ii];
int ret = pthread_rwlock_trywrlock(&sig2->siglock);
DEBUG_STREAM << __func__<<": pthread_rwlock_trywrlock i="<<ii<<" name="<<sig2->name<<" just entered " << ret << endl;
if(ret == 0) pthread_rwlock_unlock(&sig2->siglock);
}*/
//omni_mutex_lock sync(*this);
list<string> l_events;
show(l_events);
DEBUG_STREAM << "event_table::" << __func__ << ": going to subscribe " << v_event.size() << " attributes" << endl;
for (auto it : l_events)
{
veclock.readerIn();
event *sig = get_signal(it);
sig->siglock->readerIn();
string sig_name(sig->name);
if (sig->event_id==SUB_ERR && !sig->stopped)
{
if(!sig->attr)
{
try
{
vector<string> contexts; //TODO!!!
add(sig->name, contexts, NOTHING, true);
}
catch (Tango::DevFailed &e)
{
string ex_reason(e.errors[0].reason);
ex_reason = std::regex_replace(ex_reason, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " "
string ex_desc(e.errors[0].desc);
ex_desc = std::regex_replace(ex_desc, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " "
string ex_origin(e.errors[0].origin);
ex_origin = std::regex_replace(ex_origin, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " "
bei_t ex;
ostringstream o;
o << "Error adding'" \
<< sig->name << "' error=" << ex_desc;
INFO_STREAM << "event_table::subscribe_events: " << o.str() << endl;
sig->ex_reason = ex.ex_reason = ex_reason;
sig->ex_desc = ex.ex_desc = ex_desc;
// sig->ex_desc.erase(std::remove(sig->ex_desc.begin(), sig->ex_desc.end(), '\n'), sig->ex_desc.end());
sig->ex_origin = ex.ex_origin = ex_origin;
sig->ts = ex.ts = gettime();
sig->quality = ex.quality = Tango::ATTR_INVALID;
ex.ev_name = sig->name;
sig->siglock->readerOut();
veclock.readerOut();
//TODO: since event callback not called for this attribute, need to manually trigger do_alarm to update internal structures ?
ex.type = TYPE_TANGO_ERR;
ex.msg=o.str();
try
{//DevFailed for push events
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->do_alarm(ex);
} catch(Tango::DevFailed & ee)
{
WARN_STREAM << "event_table::"<<__func__<<": " << sig_name << " - EXCEPTION PUSHING EVENTS: " << ee.errors[0].desc << endl;
}
continue;
}
}
sig->event_cb = new EventCallBack(static_cast<AlarmHandler_ns::AlarmHandler *>(mydev));
sig->first = true;
sig->first_err = true;
DEBUG_STREAM << "event_table::"<<__func__<<":Subscribing for " << sig_name << " " << (sig->first ? "FIRST" : "NOT FIRST") << endl;
sig->siglock->readerOut();
int event_id = SUB_ERR;
bool isZMQ = true;
bool err = false;
try
{
event_id = sig->attr->subscribe_event(
Tango::CHANGE_EVENT,
sig->event_cb,
/*stateless=*/false);
/*sig->evstate = Tango::ON;
//sig->first = false; //first event already arrived at subscribe_event
sig->status.clear();
sig->status = "Subscribed";
DEBUG_STREAM << sig->name << " Subscribed" << endl;*/
// Check event source ZMQ/Notifd ?
/*Tango::ZmqEventConsumer *consumer =
Tango::ApiUtil::instance()->get_zmq_event_consumer();*/
isZMQ = true;//(consumer->get_event_system_for_event_id(event_id) == Tango::ZMQ);//TODO: remove
DEBUG_STREAM << sig_name << "(id="<< event_id <<"): Subscribed " << ((isZMQ)? "ZMQ Event" : "NOTIFD Event") << endl;
}
catch (Tango::DevFailed &e)
{
string ex_reason(e.errors[0].reason);
ex_reason = std::regex_replace(ex_reason, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " "
string ex_desc(e.errors[0].desc);
ex_desc = std::regex_replace(ex_desc, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " "
string ex_origin(e.errors[0].origin);
ex_origin = std::regex_replace(ex_origin, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " "
bei_t ex;
ostringstream o;
o << "Event exception for'" \
<< sig_name << "' error=" << ex_desc;
INFO_STREAM <<"event_table::"<<__func__<<": sig->attr->subscribe_event: " << o.str() << endl;
err = true;
Tango::Except::print_exception(e);
//sig->siglock->writerIn(); //not yet subscribed, no one can modify
sig->ex_reason = ex.ex_reason = ex_reason;
sig->ex_desc = ex.ex_desc = ex_desc;
sig->ex_origin = ex.ex_origin = ex_origin;
sig->event_id = SUB_ERR;
delete sig->event_cb;
sig->ts = ex.ts = gettime();
sig->quality = ex.quality = Tango::ATTR_INVALID;
ex.ev_name = sig->name;
//sig->siglock->writerOut();//not yet subscribed, no one can modify
veclock.readerOut();
//since event callback not called for this attribute, need to manually trigger do_alarm to update interlan structures
ex.type = TYPE_TANGO_ERR;
ex.msg=o.str();
try
{//DevFailed for push events
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->do_alarm(ex);
} catch(Tango::DevFailed & ee)
{
WARN_STREAM << "event_table::"<<__func__<<": " << ex.ev_name << " - EXCEPTION PUSHING EVENTS: " << ee.errors[0].desc << endl;
}
continue;
}
if(!err)
{
//sig->siglock->writerIn(); //nobody else write event_id and isZMQ
sig->event_id = event_id;
sig->isZMQ = isZMQ;
//sig->siglock->writerOut();//nobody else write event_id and isZMQ
}
}
else
{
sig->siglock->readerOut();
}
veclock.readerOut();
}
initialized = true;
}
void event_table::start(string &signame)
{
DEBUG_STREAM << "event_table::"<<__func__<< " entering signame=" << signame << endl;
ReaderLock lock(veclock);
vector<string> contexts;
for (unsigned int i=0 ; i<v_event.size() ; i++)
{
if (v_event[i].name==signame)
{
v_event[i].siglock->writerIn();
if(!v_event[i].running)
{
if(v_event[i].stopped)
{
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read--;
try
{
add(signame, contexts, NOTHING, true);
}
catch (Tango::DevFailed &e)
{
//Tango::Except::print_exception(e);
INFO_STREAM << "event_table::start: error adding " << signame <<" err="<< e.errors[0].desc << endl;
v_event[i].ex_reason = e.errors[0].reason;
v_event[i].ex_desc = e.errors[0].desc;
v_event[i].ex_origin = e.errors[0].origin;
/*v_event[i].siglock->writerOut();
return;*/
}
}
v_event[i].running=true;
if(v_event[i].paused)
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--;
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStartedNumber_read++;
v_event[i].paused=false;
v_event[i].stopped=false;
}
v_event[i].siglock->writerOut();
return;
}
}
for (unsigned int i=0 ; i<v_event.size() ; i++)
{
#ifndef _MULTI_TANGO_HOST
if (static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_without_domain(v_event[i].name,signame))
#else
if (!static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_tango_names(v_event[i].name,signame))
#endif
{
v_event[i].siglock->writerIn();
if(!v_event[i].running)
{
if(v_event[i].stopped)
{
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read--;
try
{
add(signame, contexts, NOTHING, true);
}
catch (Tango::DevFailed &e)
{
//Tango::Except::print_exception(e);
INFO_STREAM << "event_table::start: error adding " << signame << endl;
v_event[i].ex_reason = e.errors[0].reason;
v_event[i].ex_desc = e.errors[0].desc;
v_event[i].ex_origin = e.errors[0].origin;
/*signals[i].siglock->writerOut();
return;*/
}
}
v_event[i].running=true;
if(v_event[i].paused)
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--;
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStartedNumber_read++;
v_event[i].paused=false;
v_event[i].stopped=false;
}
v_event[i].siglock->writerOut();
return;
}
}
// if not found
Tango::Except::throw_exception(
(const char *)"BadSignalName",
"Signal " + signame + " NOT subscribed",
(const char *)"event_table::start()");
}
void event_table::start_all()
{
ReaderLock lock(veclock);
vector<string> contexts;
for (unsigned int i=0 ; i<v_event.size() ; i++)
{
v_event[i].siglock->writerIn();
if(!v_event[i].running)
{
if(v_event[i].stopped)
{
string signame = v_event[i].name;
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read--;
try
{
add(signame, contexts, NOTHING, true);
}
catch (Tango::DevFailed &e)
{
//Tango::Except::print_exception(e);
INFO_STREAM << "event_table::start: error adding " << signame <<" err="<< e.errors[0].desc << endl;
v_event[i].ex_reason = e.errors[0].reason;
v_event[i].ex_desc = e.errors[0].desc;
v_event[i].ex_origin = e.errors[0].origin;
/*v_event[i].siglock->writerOut();
return;*/
}
}
v_event[i].running=true;
if(v_event[i].paused)
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--;
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStartedNumber_read++;
v_event[i].paused=false;
v_event[i].stopped=false;
}
v_event[i].siglock->writerOut();
}
}
//=============================================================================
//=============================================================================
bool event_table::get_if_stop()
{
//omni_mutex_lock sync(*this);
return stop_it;
}
//=============================================================================
//=============================================================================
void event_table::stop_thread()
{
//omni_mutex_lock sync(*this);
stop_it = true;
signal();
//condition.signal();
}
//=============================================================================
/**
* return number of signals to be subscribed
*/
//=============================================================================
int event_table::nb_sig_to_subscribe()
{
ReaderLock lock(veclock);
int nb = 0;
for (unsigned int i=0 ; i<v_event.size() ; i++)
{
v_event[i].siglock->readerIn();
if (v_event[i].event_id == SUB_ERR && !v_event[i].stopped)
{
nb++;
}
v_event[i].siglock->readerOut();
}
return nb;
}
//=============================================================================
/**
* build a list of signal to set HDB device property
*/
//=============================================================================
void event_table::put_signal_property()
{
int act=action.load();
DEBUG_STREAM << "event_table::"<<__func__<<": entering action=" << act << endl;
if (act>NOTHING)
{
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->put_signal_property();
int expected=UPDATE_PROP;
action.compare_exchange_strong(expected, NOTHING); //if it is UPDATE_PROP, then change to NOTHING
}
DEBUG_STREAM << "event_table::"<<__func__<<": exiting action=" << action.load() << endl;
}
//=============================================================================
/**
* build a list of signal to set HDB device property
*/
//=============================================================================
void event_table::check_signal_property()
{
int act=action.load();
DEBUG_STREAM << "event_table::"<<__func__<<": entering action=" << act << endl;
if (act>NOTHING)
return;
if (static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->check_signal_property())
{
int expected=NOTHING;
action.compare_exchange_strong(expected, UPDATE_PROP); //if it is NOTHING, then change to UPDATE_PROP
}
DEBUG_STREAM << "event_table::"<<__func__<<": exiting action=" << action.load() << endl;
}
/*
* EventCallBack class methods
*/
EventCallBack::EventCallBack(Tango::DeviceImpl *s):Tango::LogAdapter(s)
{
//e_ptr = NULL;
mydev = s;
}
EventCallBack::~EventCallBack(void)
{
//e_ptr = NULL;
}
void EventCallBack::push_event(Tango::EventData* ev)
{
string temp_name;
bei_t e;
e.ex_reason = string("");
e.ex_desc = string("");
e.ex_origin = string("");
try {
//e.errors = ev->errors;
e.quality = Tango::ATTR_VALID;
//cout << "EVENT="<<ev->attr_name<<" quality="<<e.quality<<endl;
if (!ev->err) {
e.quality = (int)ev->attr_value->get_quality();
#if 0//TANGO_VER >= 711
string ev_name_str(ev->attr_name);
string::size_type pos = ev_name_str.find("tango://");
if (pos != string::npos)
{
pos = ev_name_str.find('/',8);
ev_name_str = ev_name_str.substr(pos + 1);
}
e.ev_name = ev_name_str.c_str();
#else
e.ev_name = ev->attr_name;
#endif
e.ts = ev->attr_value->time;
extract_values(ev->attr_value, e.value, e.value_string, e.type, e.read_size);
} else {
e.quality = Tango::ATTR_INVALID;
#if 0//TANGO_VER >= 711
string ev_name_str(ev->attr_name);
string::size_type pos = ev_name_str.find("tango://");
if (pos != string::npos)
{
pos = ev_name_str.find('/',8);
ev_name_str = ev_name_str.substr(pos + 1);
}
temp_name = ev_name_str.c_str() + string(".") + ev->event;
#else
temp_name = ev->attr_name + string(".") + ev->event; //TODO: BUG IN TANGO: part of attr_name after first dot continues in field event
#endif
size_t pos_change = temp_name.find(".change");
if(pos_change != string::npos)
{
temp_name = temp_name.substr(0,pos_change);
}
ostringstream o;
o << "Tango error for '" << temp_name << "'=" << ev->errors[0].desc.in();
e.ev_name = temp_name;
e.type = TYPE_TANGO_ERR;
//e.ev_name = INTERNAL_ERROR;
//e.type = -1;
e.msg = o.str();
e.msg = std::regex_replace(e.msg, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " "
}
}
catch (string &err) {
e.msg = err + " for event '" + ev->attr_name + "'";
e.ev_name = ev->attr_name;
e.type = TYPE_GENERIC_ERR;
//e.value.i = 0;
e.ts = gettime();
//cerr << o.str() << endl;
} catch(Tango::DevFailed& Terr)
{
ostringstream o;
o << "Event exception for'" \
<< ev->attr_name << "' error=" << Terr.errors[0].desc;
e.ev_name = ev->attr_name;
e.type = TYPE_GENERIC_ERR;
//e.value.i = 0;
e.ts = gettime();
e.msg = o.str();
e.msg = std::regex_replace(e.msg, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " "
}
catch (...) {
ostringstream o;
o << "Generic Event exception for'" \
<< ev->attr_name << "'";
e.ev_name = ev->attr_name;
e.type = TYPE_GENERIC_ERR;
//e.value.i = 0;
e.ts = gettime();
e.msg = o.str();
//cerr << o.str() << endl;
}
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->evlist.push_back(e);
} /* push_event() */
void EventCallBack::extract_values(Tango::DeviceAttribute *attr_value, vector<double> &val, string &val_string, int &type, int &read_size)
{
Tango::DevState stval;
vector<Tango::DevState> v_st;
vector<Tango::DevULong> v_ulo;
vector<Tango::DevUChar> v_uch;
vector<Tango::DevShort> v_sh;
vector<Tango::DevUShort> v_ush;
vector<Tango::DevLong> v_lo;
vector<Tango::DevDouble> v_do;
vector<Tango::DevFloat> v_fl;
vector<Tango::DevBoolean> v_bo;
vector<Tango::DevLong64> v_lo64;
vector<Tango::DevULong64> v_ulo64;
vector<Tango::DevEnum> v_enum;
vector<string> v_string;
val_string = string("");
//Tango::AttributeDimension attr_w_dim;
Tango::AttributeDimension attr_r_dim;
//attr_value->reset_exceptions(Tango::DeviceAttribute::isempty_flag); //disable is_empty exception //commented to throw exceptions if empty
if(!attr_value->is_empty())
{
//attr_w_dim = data->attr_value->get_w_dimension();
attr_r_dim = attr_value->get_r_dimension();
}
else
{
attr_r_dim.dim_x = 0;
//attr_w_dim.dim_x = 0;
attr_r_dim.dim_y = 0;
//attr_w_dim.dim_y = 0;
}
read_size = attr_r_dim.dim_x;
if(attr_r_dim.dim_y > 1)
read_size *= attr_r_dim.dim_y;
if (attr_value->get_type() == Tango::DEV_UCHAR) {
*(attr_value) >> v_uch;
for(vector<Tango::DevUChar>::iterator it = v_uch.begin(); it != v_uch.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_UCHAR;
} else if (attr_value->get_type() == Tango::DEV_SHORT) {
*(attr_value) >> v_sh;
for(vector<Tango::DevShort>::iterator it = v_sh.begin(); it != v_sh.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_SHORT;
} else if (attr_value->get_type() == Tango::DEV_USHORT) {
*(attr_value) >> v_ush;
for(vector<Tango::DevUShort>::iterator it = v_ush.begin(); it != v_ush.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_USHORT;
} else if (attr_value->get_type() == Tango::DEV_LONG) {
*(attr_value) >> v_lo;
for(vector<Tango::DevLong>::iterator it = v_lo.begin(); it != v_lo.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_LONG;
} else if (attr_value->get_type() == Tango::DEV_STATE) {
//*(attr_value) >> v_st; //doesn't work in tango 5
*(attr_value) >> stval;
v_st.push_back(stval);
for(vector<Tango::DevState>::iterator it = v_st.begin(); it != v_st.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_STATE;
#if 1//TANGO_VER >= 600
} else if (attr_value->get_type() == Tango::DEV_ULONG) {
*(attr_value) >> v_ulo;
for(vector<Tango::DevULong>::iterator it = v_ulo.begin(); it != v_ulo.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_ULONG;
#endif //TANGO_VER >= 600
} else if (attr_value->get_type() == Tango::DEV_DOUBLE) {
*(attr_value) >> v_do;
for(vector<Tango::DevDouble>::iterator it = v_do.begin(); it != v_do.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_DOUBLE;
} else if (attr_value->get_type() == Tango::DEV_FLOAT) {
*(attr_value) >> v_fl;
for(vector<Tango::DevFloat>::iterator it = v_fl.begin(); it != v_fl.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_FLOAT;
} else if (attr_value->get_type() == Tango::DEV_BOOLEAN) {
*(attr_value) >> v_bo;
for(vector<Tango::DevBoolean>::iterator it = v_bo.begin(); it != v_bo.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_BOOLEAN;
} else if (attr_value->get_type() == Tango::DEV_LONG64) {
*(attr_value) >> v_lo64;
for(vector<Tango::DevLong64>::iterator it = v_lo64.begin(); it != v_lo64.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_LONG64;
} else if (attr_value->get_type() == Tango::DEV_ULONG64) {
*(attr_value) >> v_ulo64;
for(vector<Tango::DevULong64>::iterator it = v_ulo64.begin(); it != v_ulo64.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_ULONG64;
} else if (attr_value->get_type() == Tango::DEV_ENUM) {
*(attr_value) >> v_enum;
for(vector<Tango::DevEnum>::iterator it = v_enum.begin(); it != v_enum.end(); it++)
val.push_back((double)(*it)); //convert all to double
type = Tango::DEV_ENUM;
} else if (attr_value->get_type() == Tango::DEV_STRING) {
*(attr_value) >> v_string;
val_string = *(v_string.begin()); //TODO: support string spectrum attrbutes
type = Tango::DEV_STRING;
}
else {
ostringstream o;
o << "unknown type";
throw o.str();
}
}
/*void EventCallBack::init(event_list* e)
{
//e_ptr = e;
}*/
Tango::TimeVal gettime(void)
{
struct timeval tv;
struct timezone tz;
Tango::TimeVal t;
gettimeofday(&tv, &tz);
t.tv_sec = tv.tv_sec;
t.tv_usec = tv.tv_usec;
t.tv_nsec = 0;
return t;
}
/* EOF */