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 1833 additions and 746 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"
......@@ -130,6 +131,7 @@ static const char __FILE__rev[] = __FILE__ " $Revision: 1.29 $";
// alarmSummary | Tango::DevString Spectrum ( max = 10000)
// eventList | Tango::DevString Spectrum ( max = 10000)
// eventSummary | Tango::DevString Spectrum ( max = 10000)
// alarmDisabled | Tango::DevString Spectrum ( max = 10000)
//================================================================
namespace AlarmHandler_ns
......@@ -342,6 +344,7 @@ void AlarmHandler::delete_device()
delete[] attr_alarmSummary_read;
delete[] attr_eventList_read;
delete[] attr_eventSummary_read;
delete[] attr_alarmDisabled_read;
}
//--------------------------------------------------------
......@@ -370,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);
......@@ -399,6 +402,7 @@ void AlarmHandler::init_device()
attr_alarmSummary_read = new Tango::DevString[10000];
attr_eventList_read = new Tango::DevString[10000];
attr_eventSummary_read = new Tango::DevString[10000];
attr_alarmDisabled_read = new Tango::DevString[10000];
/*----- PROTECTED REGION ID(AlarmHandler::init_device) ENABLED START -----*/
/* for(size_t i=0; i<MAX_ALARMS; i++)
{
......@@ -412,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;
......@@ -486,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
......@@ -520,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);
}
......@@ -629,6 +636,8 @@ void AlarmHandler::init_device()
for(alarm_container_t::iterator i = alarms.v_alarm.begin(); \
i!=alarms.v_alarm.end(); i++)
{
if(!i->second.enabled)
i->second.ts_time_silenced = gettime(); //TODO: save time when alarm was disabled
if(i->second.cmd_name_a.length() > 0)
{
try {
......@@ -748,7 +757,7 @@ void AlarmHandler::init_device()
}
}
set_change_event("alarm",true,false);
set_change_event("alarm",true,true);
/*
* create alarm processing thread
*/
......@@ -821,6 +830,7 @@ void AlarmHandler::get_device_property()
dev_prop.push_back(Tango::DbDatum("SubscribeRetryPeriod"));
dev_prop.push_back(Tango::DbDatum("StatisticsTimeWindow"));
dev_prop.push_back(Tango::DbDatum("ErrorDelay"));
dev_prop.push_back(Tango::DbDatum("SetAlarmQuality"));
// is there at least one property to be read ?
if (dev_prop.size()>0)
......@@ -879,6 +889,17 @@ void AlarmHandler::get_device_property()
// And try to extract ErrorDelay value from database
if (dev_prop[i].is_empty()==false) dev_prop[i] >> errorDelay;
// Try to initialize SetAlarmQuality from class property
cl_prop = ds_class->get_class_property(dev_prop[++i].name);
if (cl_prop.is_empty()==false) cl_prop >> setAlarmQuality;
else {
// Try to initialize SetAlarmQuality from default device value
def_prop = ds_class->get_default_device_property(dev_prop[i].name);
if (def_prop.is_empty()==false) def_prop >> setAlarmQuality;
}
// And try to extract SetAlarmQuality value from database
if (dev_prop[i].is_empty()==false) dev_prop[i] >> setAlarmQuality;
}
/*----- PROTECTED REGION ID(AlarmHandler::get_device_property_after) ENABLED START -----*/
......@@ -1208,6 +1229,24 @@ void AlarmHandler::read_eventSummary(Tango::Attribute &attr)
/*----- PROTECTED REGION END -----*/ // AlarmHandler::read_eventSummary
}
//--------------------------------------------------------
/**
* Read attribute alarmDisabled related method
* Description: List of alarms in out of service or shelved state
*
* Data type: Tango::DevString
* Attr type: Spectrum max = 10000
*/
//--------------------------------------------------------
void AlarmHandler::read_alarmDisabled(Tango::Attribute &attr)
{
//DEBUG_STREAM << "AlarmHandler::read_alarmDisabled(Tango::Attribute &attr) entering... " << endl;
/*----- PROTECTED REGION ID(AlarmHandler::read_alarmDisabled) ENABLED START -----*/
// Set the attribute value
attr.set_value(attr_alarmDisabled_read, alarmDisabled_sz);
/*----- PROTECTED REGION END -----*/ // AlarmHandler::read_alarmDisabled
}
//--------------------------------------------------------
/**
......@@ -1236,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;
......@@ -1244,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(
......@@ -1256,7 +1301,7 @@ void AlarmHandler::read_AlarmState(Tango::Attribute &attr)
origin, Tango::ERR);
}
// Set the attribute value
if(quality != Tango::ATTR_VALID)
if(quality != Tango::ATTR_VALID && setAlarmQuality)
{
timeval now;
gettimeofday(&now, NULL);
......@@ -1377,7 +1422,7 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
localalarmed = *found; //NOTE: copy before updating ack
localv_alarm = i->second;
//update alarm ack in alarmed table
found->ack = ACK;
alarmedlock->readerOut();
alarms.vlock->readerOut();
......@@ -1399,12 +1444,20 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
*attr_value = _RTNUN;
try
{ //DevFailed for push events
if(localv_alarm.ex_reason.empty())
if(!localv_alarm.error || !localv_alarm.enabled || (localv_alarm.shelved && localv_alarm.silenced > 0))
{
timeval now;
gettimeofday(&now, NULL);
push_change_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)localv_alarm.quality, 1/*size*/, 0, false);
push_archive_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)localv_alarm.quality, 1/*size*/, 0, false);
if(setAlarmQuality)
{
push_change_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)localv_alarm.quality, 1/*size*/, 0, false);
push_archive_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)localv_alarm.quality, 1/*size*/, 0, false);
}
else
{
push_change_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value);
}
}
else
{
......@@ -1480,7 +1533,8 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -1491,7 +1545,8 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0],alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
......@@ -1694,7 +1749,7 @@ void AlarmHandler::load(Tango::DevString argin)
alarms.vlock->readerOut();
#if 0//TODO
#if 1//TODO
prepare_alarm_attr();
try
{
......@@ -1806,7 +1861,8 @@ void AlarmHandler::remove(Tango::DevString argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -1817,7 +1873,8 @@ void AlarmHandler::remove(Tango::DevString argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -1868,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);
......@@ -1902,9 +1959,9 @@ Tango::DevVarStringArray *AlarmHandler::search_alarm(Tango::DevString argin)
{
ostringstream os;
os.clear();
os << ai->second.ts.tv_sec << SEP << 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 <<
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 */
......@@ -1969,7 +2026,8 @@ void AlarmHandler::stop_audible()
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -1980,7 +2038,8 @@ void AlarmHandler::stop_audible()
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -2014,6 +2073,16 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
alarm_container_t::iterator i = alarms.v_alarm.find(*si);
if(i != alarms.v_alarm.end())
{
if(!i->second.enabled)
{
ostringstream err;
err << *si << " is not enabled";
alarms.vlock->readerOut();
Tango::Except::throw_exception( \
(const char*)"NOT_ENABLED", \
(const char*)err.str().c_str(), \
(const char*)__func__, Tango::ERR);
}
if(i->second.silenced > 0)
{
Tango::TimeVal now = gettime();
......@@ -2109,7 +2178,8 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -2120,7 +2190,8 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -2130,7 +2201,6 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
/*----- PROTECTED REGION END -----*/ // AlarmHandler::silence
}
//--------------------------------------------------------
/**
* Command Modify related method
......@@ -2189,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
......@@ -2286,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
{
......@@ -2314,7 +2385,8 @@ void AlarmHandler::modify(Tango::DevString argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -2325,7 +2397,8 @@ void AlarmHandler::modify(Tango::DevString argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -2448,13 +2521,24 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
*attr_value = _SHLVD;
try
{ //DevFailed for push events
if(alm.ex_reason.empty())
#if 0//do not store errors for disabled alarms
if(!alm.error)
#endif
{
timeval now;
gettimeofday(&now, NULL);
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
if(setAlarmQuality)
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(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);
}
}
#if 0//do not store errors for disabled alarms
else
{
Tango::DevErrorList errors(1);
......@@ -2467,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;
......@@ -2499,7 +2584,8 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
push_change_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz);
push_change_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz);
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -2508,7 +2594,8 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
push_archive_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz);
push_archive_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz);
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -2565,12 +2652,20 @@ void AlarmHandler::enable(Tango::DevString argin)
*attr_value = _RTNUN;
try
{ //DevFailed for push events
if(alm.ex_reason.empty())
if(!alm.error)
{
timeval now;
gettimeofday(&now, NULL);
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
if(setAlarmQuality)
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(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);
}
}
else
{
......@@ -2614,7 +2709,8 @@ void AlarmHandler::enable(Tango::DevString argin)
push_change_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz);
push_change_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz);
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -2623,7 +2719,8 @@ void AlarmHandler::enable(Tango::DevString argin)
push_archive_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz);
push_archive_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz);
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -2665,6 +2762,7 @@ void AlarmHandler::disable(Tango::DevString argin)
i->second.enabled = false;
i->second.ts_time_silenced = gettime();
i->second.silenced = (i->second.silent_time > 0) ? 0 : -1; //0: can be silenced, -1: cannot be silenced
i->second.shelved = false;
alarm_t alm = i->second;
......@@ -2674,13 +2772,24 @@ void AlarmHandler::disable(Tango::DevString argin)
*attr_value = _OOSRV;
try
{ //DevFailed for push events
if(alm.ex_reason.empty())
#if 0 //do not store errors for disabled alarms
if(!alm.error)
#endif
{
timeval now;
gettimeofday(&now, NULL);
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
if(setAlarmQuality)
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(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);
}
}
#if 0 //do not store errors for disabled alarms
else
{
Tango::DevErrorList errors(1);
......@@ -2693,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;
......@@ -2743,7 +2853,8 @@ void AlarmHandler::disable(Tango::DevString argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -2754,7 +2865,8 @@ void AlarmHandler::disable(Tango::DevString argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -2839,7 +2951,8 @@ void AlarmHandler::stop_new()
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -2850,7 +2963,8 @@ void AlarmHandler::stop_new()
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -2917,11 +3031,23 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
ostringstream tmp_ex;
tmp_ex.str("");
ostringstream tmp;
tmp.str("");
tmp << "\"" << it->second.msg << "\"";
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));
complete.push_back(KEY(URL_KEY)+it->second.url);
info.insert(make_pair(FORMULA_KEY,it->second.formula));
complete.push_back(KEY(FORMULA_KEY)+it->second.formula);
info.insert(make_pair(ATTR_VALUES_KEY,tmp_ex.str()));
......@@ -2931,13 +3057,26 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
{
info.insert(make_pair(VALUE_KEY,tmp_val.str()));
complete.push_back(KEY(VALUE_KEY)+tmp_val.str());
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));
complete.push_back(KEY(URL_KEY)+it->second.url);
info.insert(make_pair(FORMULA_KEY,it->second.formula));
complete.push_back(KEY(FORMULA_KEY)+it->second.formula);
info.insert(make_pair(ATTR_VALUES_KEY,it->second.attr_values));
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
......@@ -2949,7 +3088,7 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
}
info.insert(make_pair(QUALITY_KEY,tmp_qual.str()));
complete.push_back(KEY(QUALITY_KEY)+tmp_qual.str());
ostringstream tmp;
//#if 0
tmp.str("");
tmp << (it->second.enabled ? "1" : "0");
......@@ -2964,6 +3103,7 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
info.insert(make_pair(ACKNOWLEDGED_KEY,tmp.str())); //TODO: redundant, information already in attr_value
complete.push_back(KEY(ACKNOWLEDGED_KEY)+tmp.str()); //TODO: redundant, information already in attr_value
//#endif
tmp.str("");
tmp << (it->second.is_new ? "1" : "0");
info.insert(make_pair(AUDIBLE_KEY,tmp.str()));
......@@ -3004,17 +3144,12 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
complete.push_back(KEY(SILENT_TIME_REMAINING_KEY)+tmp.str());
info.insert(make_pair(GROUP_KEY,it->second.grp2str()));
complete.push_back(KEY(GROUP_KEY)+it->second.grp2str());
tmp.str("");
tmp << "\"" << it->second.msg << "\"";
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));
complete.push_back(KEY(URL_KEY)+it->second.url);
info.insert(make_pair(ON_COMMAND_KEY,it->second.cmd_name_a));
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)
......@@ -3144,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 =
......@@ -3164,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();
......@@ -3228,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) && \
......@@ -3314,7 +3452,7 @@ void AlarmHandler::add_alarm(alarm_t& a, bool starting)
{
alarms.push_back(a); //take and release writer vlock
DEBUG_STREAM << "AlarmHandler::add_alarm(): added alarm '" \
<< a.name << "'" << endl;
<< a.name << "' starting=" << (int)starting << endl;
if(!starting)
{
alarms.vlock->readerIn();
......@@ -3334,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;
/*
......@@ -3450,6 +3588,7 @@ void AlarmHandler::add_event(alarm_t& a, vector<string> &evn) throw(string&)
}
}
} //for (vector<string>::iterator j = evn.begin(); ...
thread->signal(); //wake up subscibe thread if not waked by events->add
for(vector<string>::iterator j = evn.begin(); j != evn.end(); j++)
{
......@@ -3476,7 +3615,7 @@ void AlarmHandler::do_alarm(bei_t& e)
{
ostringstream o;
o << e.msg;
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl;
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << e.ev_name << ": " << o.str() << endl;
events->veclock.readerIn();
vector<event>::iterator found_ev = \
find(events->v_event.begin(), events->v_event.end(), e.ev_name);
......@@ -3521,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)
......@@ -3539,15 +3679,19 @@ 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())
{
it->second.ack = NOT_ACK;
it->second.ts_err_delay = gettime(); //first occurrance of this error, now begin to wait for err delay
}
if(e.type == TYPE_TANGO_ERR)
......@@ -3561,32 +3705,69 @@ void AlarmHandler::do_alarm(bei_t& e)
if((ts.tv_sec - errorDelay) > it->second.ts_err_delay.tv_sec) //error is present and err delay has passed
{
if(!it->second.error)
{
it->second.is_new = 1;
it->second.ack = NOT_ACK;//if first error, reset ACK
}
it->second.error = true;
}
}
else
{
if(!it->second.error)
{
it->second.is_new = 1;
it->second.ack = NOT_ACK;//if first error, reset ACK
}
it->second.error = true;
}
#endif
alarm_t alm = it->second;
alarms.vlock->readerOut();
try
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))
{
Tango::DevErrorList errors(1);
errors.length(1);
errors[0].desc = CORBA::string_dup(alm.ex_desc.c_str());
errors[0].severity = Tango::ERR;
errors[0].reason = CORBA::string_dup(alm.ex_reason.c_str());
errors[0].origin = CORBA::string_dup(alm.ex_origin.c_str());
Tango::DevFailed except(errors);
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": PUSHING EXCEPTION FOR " << alm.attr_name << " " << alm.ex_desc << "-" << alm.ex_reason << "-" << alm.ex_origin << endl;
push_change_event(alm.attr_name, &except);
push_archive_event(alm.attr_name, &except);
}catch(Tango::DevFailed &ex)
{}
try
{
Tango::DevErrorList errors(1);
errors.length(1);
errors[0].desc = CORBA::string_dup(alm.ex_desc.c_str());
errors[0].severity = Tango::ERR;
errors[0].reason = CORBA::string_dup(alm.ex_reason.c_str());
errors[0].origin = CORBA::string_dup(alm.ex_origin.c_str());
Tango::DevFailed except(errors);
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": PUSHING EXCEPTION FOR " << alm.attr_name << " " << alm.ex_desc << "-" << alm.ex_reason << "-" << alm.ex_origin << endl;
push_change_event(alm.attr_name, &except);
push_archive_event(alm.attr_name, &except);
}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
{
......@@ -3620,6 +3801,7 @@ void AlarmHandler::do_alarm(bei_t& e)
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_change_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -3631,11 +3813,16 @@ void AlarmHandler::do_alarm(bei_t& e)
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
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);
......@@ -3679,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;
......@@ -3748,6 +3938,7 @@ void AlarmHandler::do_alarm(bei_t& e)
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_change_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -3759,9 +3950,11 @@ void AlarmHandler::do_alarm(bei_t& e)
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_archive_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
}
else
{
events->veclock.readerOut();
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": event=" << e.ev_name << "NOT FOUND IN EVENT TABLE" << endl;
}
} /* do_alarm() */
......@@ -3801,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;
......@@ -3825,12 +4018,20 @@ 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);
push_change_event(attr_name,(Tango::DevEnum *)attr_value,now,quality, 1/*size*/, 0, false);
push_archive_event(attr_name,(Tango::DevEnum *)attr_value,now,quality, 1/*size*/, 0, false);
if(setAlarmQuality)
{
push_change_event(attr_name,(Tango::DevEnum *)attr_value,now,quality, 1/*size*/, 0, false);
push_archive_event(attr_name,(Tango::DevEnum *)attr_value,now,quality, 1/*size*/, 0, false);
}
else
{
push_change_event(attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(attr_name,(Tango::DevEnum *)attr_value);
}
}
else
{
......@@ -3850,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!";
......@@ -3861,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;
......@@ -3880,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
......@@ -3888,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;
......@@ -3906,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";
......@@ -3966,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
{
......@@ -3994,6 +4265,7 @@ void AlarmHandler::timer_update()
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_change_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -4005,6 +4277,7 @@ void AlarmHandler::timer_update()
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_archive_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -4013,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();
......@@ -4123,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;
......@@ -4248,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)
......@@ -4267,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;
}
......@@ -4285,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)
......@@ -4301,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)
......@@ -4317,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)
......@@ -4334,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)
......@@ -4347,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)
{
......@@ -4426,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)
{
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(string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end()) == ".quality")
if(child->value.id() == formula_grammar::index_rangeID || child->value.id() == formula_grammar::indexID)
{
formula_res_t res = eval_expression(i->children.begin(), attr_values, (int)ind.value);
res.value = res.quality;
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)
{
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)
{
......@@ -4488,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
......@@ -4540,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)
......@@ -4581,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
......@@ -4638,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
......@@ -4710,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;
......@@ -4746,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
......@@ -4812,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();
}
}
......@@ -4831,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
{
......@@ -4953,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
......@@ -5000,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;
......@@ -5022,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;
}
......@@ -5055,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);
......@@ -5079,6 +5890,7 @@ void AlarmHandler::prepare_alarm_attr()
silencedAlarms_sz=0;
listAlarms_sz=0;
alarmSummary_sz=0;
alarmDisabled_sz=0;
string almstate;
for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++) {
......@@ -5090,6 +5902,7 @@ void AlarmHandler::prepare_alarm_attr()
string alm_summary;
alm_summary += KEY(NAME_KEY) + ai->first + SEP;
#endif
stringstream alm_disabled;
if(ai->second.enabled == false)
{
outOfServiceAlarms_read[outOfServiceAlarms_sz] = ai->second.name;
......@@ -5112,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());
......@@ -5122,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());
......@@ -5132,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());
......@@ -5142,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());
......@@ -5163,6 +5976,38 @@ void AlarmHandler::prepare_alarm_attr()
}
}
tm time_tm;
time_t time_sec= ai->second.ts_time_silenced.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);
if(almstate == "OOSRV" || almstate == "SHLVD")
{
//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;
alm_disabled << KEY(VALUE_KEY) << almstate << SEP; //TODO: string or enum value?
alm_disabled << KEY(SILENT_TIME_REMAINING_KEY) << ai->second.silenced << SEP;
alm_disabled << KEY(MESSAGE_KEY) << ai->second.msg; //TODO: escape ';'
#else
alm_disabled << ai->second.ts.tv_sec << "\t";
alm_disabled << ai->second.ts.tv_usec << "\t";
alm_disabled << ai->first << "\t";
alm_disabled << almstate << "\t"; //TODO: string or enum value?
alm_disabled << ai->second.ack << "\t";
alm_disabled << ai->second.lev << "\t";
alm_disabled << ai->second.silenced << "\t";
alm_disabled << ai->second.grp2str() << "\t";
alm_disabled << ai->second.msg << "\t"; //TODO: escape ';'
#endif
alarmDisabled_read[alarmDisabled_sz] = alm_disabled.str();
attr_alarmDisabled_read[alarmDisabled_sz] = const_cast<char*>(alarmDisabled_read[alarmDisabled_sz].c_str());
alarmDisabled_sz++;
}
ostringstream tmp_ex;
//tmp_ex.str("");
if(ai->second.error)
......@@ -5175,11 +6020,9 @@ void AlarmHandler::prepare_alarm_attr()
}
}
tm time_tm;
time_t time_sec= ai->second.ts.tv_sec;
time_sec= ai->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);
#ifndef ALM_SUM_STR
......@@ -5277,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;
......@@ -5288,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);
......@@ -5327,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;
......@@ -5338,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);
......@@ -5392,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
......@@ -5464,7 +6310,7 @@ void AlarmHandler::prepare_alarm_attr()
is_new = (aid->is_new && aid->silenced <= 0) ? "NEW" : " ";
os << aid->ts.tv_sec << "\t" << aid->ts.tv_usec << "\t" \
<< aid->name << "\t" << aid->stat << "\t" << aid->ack \
<< "\t" << aid->on_counter << "\t" << aid->lev << "\t" << aid->silenced << "\t" << aid->grp2str() << "\t" << aid->msg << "\t" << is_new;
<< "\t" << aid->lev << "\t" << aid->silenced << "\t" << aid->grp2str() << "\t" << aid->msg << "\t" << is_new;
tmp_alarm_table.push_back(os.str());
}
}
......@@ -5497,7 +6343,7 @@ void AlarmHandler::prepare_alarm_attr()
ostringstream os1;
ds_num++;
os1.clear();
os1 << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << -1 << "\t" << 0 << "\t" << 0 << "\t ";
os1 << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << -1 << "\t" << 0 << "\t" << 0 << "\t ";
//ds[0] = CORBA::string_dup(os1.str().c_str());
size_t len=os1.str().length();
if(len >= 10124) len = 10124-1;
......@@ -5594,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
......@@ -5617,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;
}
......@@ -5628,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
......@@ -5637,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"));
......@@ -5766,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 =
......@@ -5789,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
......@@ -100,10 +108,6 @@ class AlarmHandler : public TANGO_BASE_CLASS
public:
bool compare_without_domain(string str1, string str2);
string remove_domain(string str);
//TODO: real attributes
Tango::DevLong attr_AttributeStartedNumber_read;
Tango::DevLong attr_AttributePausedNumber_read;
Tango::DevLong attr_AttributeStoppedNumber_read;
Tango::DevLong attr_AttributeNumber_read;
string normalAlarms_read[MAX_ALARMS];
......@@ -117,6 +121,7 @@ public:
string alarmSummary_read[MAX_ALARMS];
string eventList_read[MAX_ATTR_SUMMARY];
string eventSummary_read[MAX_ATTR_SUMMARY];
string alarmDisabled_read[MAX_ALARMS];
/* char c_normalAlarms_read[MAX_ALARMS][MAX_ATTR_NAME];
char c_unacknowledgedAlarms_read[MAX_ALARMS][MAX_ATTR_NAME];
......@@ -140,6 +145,7 @@ public:
size_t alarmSummary_sz;
size_t eventList_sz;
size_t eventSummary_sz;
size_t alarmDisabled_sz;
double last_statistics_reset_time;
......@@ -157,6 +163,8 @@ public:
vector<Tango::DevLong> statisticsTimeWindow;
// ErrorDelay: Delay in seconds before changing to ERROR state after an exception is received.
Tango::DevULong errorDelay;
// SetAlarmQuality: Set alarm attribute quality as computed using quality of attributes in the formula
Tango::DevBoolean setAlarmQuality;
// Attribute data members
public:
......@@ -175,6 +183,7 @@ public:
Tango::DevString *attr_alarmSummary_read;
Tango::DevString *attr_eventList_read;
Tango::DevString *attr_eventSummary_read;
Tango::DevString *attr_alarmDisabled_read;
// Constructors and destructors
public:
......@@ -371,6 +380,15 @@ public:
*/
virtual void read_eventSummary(Tango::Attribute &attr);
virtual bool is_eventSummary_allowed(Tango::AttReqType type);
/**
* Attribute alarmDisabled related methods
* Description: List of alarms in out of service or shelved state
*
* Data type: Tango::DevString
* Attr type: Spectrum max = 10000
*/
virtual void read_alarmDisabled(Tango::Attribute &attr);
virtual bool is_alarmDisabled_allowed(Tango::AttReqType type);
// Dynamic attribute methods
public:
......@@ -575,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);
......@@ -589,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
......
......@@ -24,6 +24,11 @@
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<DefaultPropValue>30</DefaultPropValue>
</classProperties>
<classProperties name="SetAlarmQuality" description="Set alarm attribute quality as computed using quality of attributes in the formula">
<type xsi:type="pogoDsl:BooleanType"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<DefaultPropValue>false</DefaultPropValue>
</classProperties>
<deviceProperties name="GroupNames" description="Labels for Group mask, first is for mask 0x00">
<type xsi:type="pogoDsl:StringVectorType"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
......@@ -43,6 +48,11 @@
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<DefaultPropValue>30</DefaultPropValue>
</deviceProperties>
<deviceProperties name="SetAlarmQuality" description="Set alarm attribute quality as computed using quality of attributes in the formula">
<type xsi:type="pogoDsl:BooleanType"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<DefaultPropValue>false</DefaultPropValue>
</deviceProperties>
<commands name="State" description="This command gets the device state (stored in its &lt;i>device_state&lt;/i> data member) and returns it to the caller." execMethod="dev_state" displayLevel="OPERATOR" polledPeriod="0">
<argin description="none.">
<type xsi:type="pogoDsl:VoidType"/>
......@@ -189,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=""/>
......@@ -306,6 +316,14 @@
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
</attributes>
<attributes name="alarmDisabled" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="10000" maxY="" allocReadMember="true" isDynamic="false">
<dataType xsi:type="pogoDsl:StringType"/>
<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="List of alarms in out of service or shelved state" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
</attributes>
<dynamicAttributes name="AlarmState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="true">
<dataType xsi:type="pogoDsl:EnumType"/>
<changeEvent fire="true" libCheckCriteria="true"/>
......@@ -324,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();
}
......@@ -491,6 +486,7 @@ void AlarmHandlerClass::get_class_property()
cl_prop.push_back(Tango::DbDatum("SubscribeRetryPeriod"));
cl_prop.push_back(Tango::DbDatum("StatisticsTimeWindow"));
cl_prop.push_back(Tango::DbDatum("ErrorDelay"));
cl_prop.push_back(Tango::DbDatum("SetAlarmQuality"));
// Call database and extract values
if (Tango::Util::instance()->_UseDb==true)
......@@ -546,6 +542,18 @@ void AlarmHandlerClass::get_class_property()
cl_prop[i] << errorDelay;
}
}
// Try to extract SetAlarmQuality value
if (cl_prop[++i].is_empty()==false) cl_prop[i] >> setAlarmQuality;
else
{
// Check default value for SetAlarmQuality
def_prop = get_default_class_property(cl_prop[i].name);
if (def_prop.is_empty()==false)
{
def_prop >> setAlarmQuality;
cl_prop[i] << setAlarmQuality;
}
}
/*----- PROTECTED REGION ID(AlarmHandlerClass::get_class_property_after) ENABLED START -----*/
// Check class property data members init
......@@ -624,6 +632,20 @@ void AlarmHandlerClass::set_default_property()
cl_def_prop.push_back(data);
add_wiz_class_prop(prop_name, prop_desc, prop_def);
}
else
add_wiz_class_prop(prop_name, prop_desc);
prop_name = "SetAlarmQuality";
prop_desc = "Set alarm attribute quality as computed using quality of attributes in the formula";
prop_def = "false";
vect_data.clear();
vect_data.push_back("false");
if (prop_def.length()>0)
{
Tango::DbDatum data(prop_name);
data << vect_data ;
cl_def_prop.push_back(data);
add_wiz_class_prop(prop_name, prop_desc, prop_def);
}
else
add_wiz_class_prop(prop_name, prop_desc);
......@@ -683,6 +705,20 @@ void AlarmHandlerClass::set_default_property()
}
else
add_wiz_dev_prop(prop_name, prop_desc);
prop_name = "SetAlarmQuality";
prop_desc = "Set alarm attribute quality as computed using quality of attributes in the formula";
prop_def = "false";
vect_data.clear();
vect_data.push_back("false");
if (prop_def.length()>0)
{
Tango::DbDatum data(prop_name);
data << vect_data ;
dev_def_prop.push_back(data);
add_wiz_dev_prop(prop_name, prop_desc, prop_def);
}
else
add_wiz_dev_prop(prop_name, prop_desc);
}
//--------------------------------------------------------
......@@ -748,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]));
}
......@@ -811,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
......@@ -1145,8 +1181,6 @@ void AlarmHandlerClass::attribute_factory(vector<Tango::Attr *> &att_list)
// Not Polled
eventlist->set_disp_level(Tango::OPERATOR);
// Not Memorized
//eventlist->set_change_event(true, true);
//eventlist->set_archive_event(true, true);
att_list.push_back(eventlist);
// Attribute : eventSummary
......@@ -1171,10 +1205,34 @@ void AlarmHandlerClass::attribute_factory(vector<Tango::Attr *> &att_list)
// Not Polled
eventsummary->set_disp_level(Tango::OPERATOR);
// Not Memorized
//eventsummary->set_change_event(true, true);
//eventsummary->set_archive_event(true, true);
att_list.push_back(eventsummary);
// Attribute : alarmDisabled
alarmDisabledAttrib *alarmdisabled = new alarmDisabledAttrib();
Tango::UserDefaultAttrProp alarmdisabled_prop;
alarmdisabled_prop.set_description("List of alarms in out of service or shelved state");
// label not set for alarmDisabled
// unit not set for alarmDisabled
// standard_unit not set for alarmDisabled
// display_unit not set for alarmDisabled
// format not set for alarmDisabled
// max_value not set for alarmDisabled
// min_value not set for alarmDisabled
// max_alarm not set for alarmDisabled
// min_alarm not set for alarmDisabled
// max_warning not set for alarmDisabled
// min_warning not set for alarmDisabled
// delta_t not set for alarmDisabled
// delta_val not set for alarmDisabled
alarmdisabled->set_default_properties(alarmdisabled_prop);
// Not Polled
alarmdisabled->set_disp_level(Tango::OPERATOR);
// Not Memorized
alarmdisabled->set_change_event(true, true);
alarmdisabled->set_archive_event(true, true);
att_list.push_back(alarmdisabled);
// Create a list of static attributes
create_static_attribute_list(get_class_attr()->get_attr_list());
......@@ -1374,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 -----*/
......@@ -1410,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>
......@@ -249,6 +249,19 @@ public:
{return (static_cast<AlarmHandler *>(dev))->is_eventSummary_allowed(ty);}
};
// Attribute alarmDisabled class definition
class alarmDisabledAttrib: public Tango::SpectrumAttr
{
public:
alarmDisabledAttrib():SpectrumAttr("alarmDisabled",
Tango::DEV_STRING, Tango::READ, 10000) {};
~alarmDisabledAttrib() {};
virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att)
{(static_cast<AlarmHandler *>(dev))->read_alarmDisabled(att);}
virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty)
{return (static_cast<AlarmHandler *>(dev))->is_alarmDisabled_allowed(ty);}
};
//=========================================
// Define classes for dynamic attributes
......@@ -633,6 +646,8 @@ class AlarmHandlerClass : public Tango::DeviceClass
vector<Tango::DevLong> statisticsTimeWindow;
// ErrorDelay: Delay in seconds before changing to ERROR state after an exception is received.
Tango::DevULong errorDelay;
// SetAlarmQuality: Set alarm attribute quality as computed using quality of attributes in the formula
Tango::DevBoolean setAlarmQuality;
public:
// write class properties data members
Tango::DbData cl_prop;
......
......@@ -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));
......
......@@ -284,6 +284,22 @@ bool AlarmHandler::is_eventSummary_allowed(TANGO_UNUSED(Tango::AttReqType type))
return true;
}
//--------------------------------------------------------
/**
* Method : AlarmHandler::is_alarmDisabled_allowed()
* Description : Execution allowed for alarmDisabled attribute
*/
//--------------------------------------------------------
bool AlarmHandler::is_alarmDisabled_allowed(TANGO_UNUSED(Tango::AttReqType type))
{
// Not any excluded states for alarmDisabled attribute in read access.
/*----- PROTECTED REGION ID(AlarmHandler::alarmDisabledStateAllowed_READ) ENABLED START -----*/
/*----- PROTECTED REGION END -----*/ // AlarmHandler::alarmDisabledStateAllowed_READ
return true;
}
//--------------------------------------------------------
/**
* Method : AlarmHandler::is_AlarmState_allowed()
......
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"
......@@ -64,6 +21,12 @@ void SubscribeThread::updateProperty()
}
//=============================================================================
//=============================================================================
void SubscribeThread::signal()
{
shared->signal();
}
//=============================================================================
//=============================================================================
void *SubscribeThread::run_undetached(void *ptr)
{
INFO_STREAM << "SubscribeThread id="<<omni_thread::self()->id()<<endl;
......
//=============================================================================
//
// 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
{
......@@ -82,6 +38,7 @@ public:
int period;
SubscribeThread(AlarmHandler *dev);
void updateProperty();
void signal();
/**
* Execute the thread loop.
* This thread is awaken when a command has been received
......
/*
* 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;
......@@ -503,18 +518,21 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_
if(status_err_delay)
{
if(!found->second.error)
{
found->second.is_new = 1;
found->second.ack = NOT_ACK;
}
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++;
}
......@@ -557,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)
......@@ -611,7 +629,10 @@ bool alarm_table::timer_update()
if(status_err_delay)
{
if(!i->second.error)
{
i->second.is_new = 1;
i->second.ack = NOT_ACK;
}
i->second.error = true;
}
......@@ -654,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;
......@@ -700,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;
......@@ -732,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
{
......@@ -840,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);
......@@ -856,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;
......@@ -870,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);
......@@ -885,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());
......@@ -896,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;
}
}
......@@ -916,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;
......@@ -932,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());
......@@ -942,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;
}
}
......@@ -966,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();
......@@ -988,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;
......@@ -1016,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;
}
......@@ -1026,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 <<
......@@ -1038,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) {
......@@ -466,7 +444,6 @@ event *event_table::get_signal(string signame)
return NULL;
}
//=============================================================================
/**
* Stop saving on DB a signal.
......@@ -484,10 +461,8 @@ void event_table::stop(string &signame)
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);
......@@ -500,7 +475,6 @@ void event_table::stop(string &signame)
}
if(v_event[i].paused)
{
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--;
try
{
remove(signame, true);
......@@ -530,10 +504,8 @@ void event_table::stop(string &signame)
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);
......@@ -546,7 +518,6 @@ void event_table::stop(string &signame)
}
if(v_event[i].paused)
{
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--;
try
{
remove(signame, true);
......@@ -572,7 +543,6 @@ void event_table::stop(string &signame)
(const char *)"event_table::stop()");
}
//=============================================================================
/**
* Remove a signal in the list.
......@@ -648,12 +618,6 @@ void event_table::remove(string &signame, bool stop)
}
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);
......@@ -699,12 +663,7 @@ void event_table::remove(string &signame, bool stop)
}
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);
......@@ -866,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)
......@@ -907,7 +869,7 @@ void event_table::add(string &signame, vector<string> contexts, int to_do, bool
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++;
//static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read++;
veclock.writerOut();
//DEBUG_STREAM << "event_table::"<<__func__<<": signame="<<signame<<" push_back signal"<< endl;
}
......@@ -1034,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;
......@@ -1089,7 +1051,6 @@ void event_table::start(string &signame)
{
if(v_event[i].stopped)
{
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read--;
try
{
add(signame, contexts, NOTHING, true);
......@@ -1106,9 +1067,6 @@ void event_table::start(string &signame)
}
}
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;
}
......@@ -1129,7 +1087,6 @@ void event_table::start(string &signame)
{
if(v_event[i].stopped)
{
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read--;
try
{
add(signame, contexts, NOTHING, true);
......@@ -1146,9 +1103,6 @@ void event_table::start(string &signame)
}
}
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;
}
......@@ -1176,7 +1130,6 @@ void event_table::start_all()
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);
......@@ -1193,9 +1146,6 @@ void event_table::start_all()
}
}
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;
}
......@@ -1203,7 +1153,6 @@ void event_table::start_all()
}
}
//=============================================================================
//=============================================================================
bool event_table::get_if_stop()
......@@ -1303,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
......@@ -1319,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
......@@ -1340,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;
......@@ -1382,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;
......@@ -1416,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;
}
......@@ -1493,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)
......