Commit e4004294 authored by Graziano Scalamera's avatar Graziano Scalamera
Browse files

Add eventList and eventSummary attributes

parent 09b2a964
......@@ -128,6 +128,8 @@ static const char __FILE__rev[] = __FILE__ " $Revision: 1.29 $";
// alarmList | Tango::DevString Spectrum ( max = 10000)
// alarmFrequency | Tango::DevDouble Spectrum ( max = 10000)
// alarmSummary | Tango::DevString Spectrum ( max = 10000)
// eventList | Tango::DevString Spectrum ( max = 10000)
// eventSummary | Tango::DevString Spectrum ( max = 10000)
//================================================================
namespace AlarmHandler_ns
......@@ -334,6 +336,8 @@ void AlarmHandler::delete_device()
delete[] attr_alarmList_read;
delete[] attr_alarmFrequency_read;
delete[] attr_alarmSummary_read;
delete[] attr_eventList_read;
delete[] attr_eventSummary_read;
}
//--------------------------------------------------------
......@@ -388,6 +392,8 @@ void AlarmHandler::init_device()
attr_alarmList_read = new Tango::DevString[10000];
attr_alarmFrequency_read = new Tango::DevDouble[10000];
attr_alarmSummary_read = new Tango::DevString[10000];
attr_eventList_read = new Tango::DevString[10000];
attr_eventSummary_read = new Tango::DevString[10000];
/*----- PROTECTED REGION ID(AlarmHandler::init_device) ENABLED START -----*/
/* for(size_t i=0; i<MAX_ALARMS; i++)
{
......@@ -1157,6 +1163,44 @@ void AlarmHandler::read_alarmSummary(Tango::Attribute &attr)
/*----- PROTECTED REGION END -----*/ // AlarmHandler::read_alarmSummary
}
//--------------------------------------------------------
/**
* Read attribute eventList related method
* Description: List of all subscribed attributes
*
* Data type: Tango::DevString
* Attr type: Spectrum max = 10000
*/
//--------------------------------------------------------
void AlarmHandler::read_eventList(Tango::Attribute &attr)
{
//DEBUG_STREAM << "AlarmHandler::read_eventList(Tango::Attribute &attr) entering... " << endl;
/*----- PROTECTED REGION ID(AlarmHandler::read_eventList) ENABLED START -----*/
prepare_event_list();
// Set the attribute value
attr.set_value(attr_eventList_read, eventList_sz);
/*----- PROTECTED REGION END -----*/ // AlarmHandler::read_eventList
}
//--------------------------------------------------------
/**
* Read attribute eventSummary related method
* Description:
*
* Data type: Tango::DevString
* Attr type: Spectrum max = 10000
*/
//--------------------------------------------------------
void AlarmHandler::read_eventSummary(Tango::Attribute &attr)
{
//DEBUG_STREAM << "AlarmHandler::read_eventSummary(Tango::Attribute &attr) entering... " << endl;
/*----- PROTECTED REGION ID(AlarmHandler::read_eventSummary) ENABLED START -----*/
prepare_event_summary();
// Set the attribute value
attr.set_value(attr_eventSummary_read, eventSummary_sz);
/*----- PROTECTED REGION END -----*/ // AlarmHandler::read_eventSummary
}
//--------------------------------------------------------
/**
......@@ -3401,7 +3445,7 @@ void AlarmHandler::do_alarm(bei_t& e)
if(e.type == TYPE_TANGO_ERR || e.type == TYPE_GENERIC_ERR)
{
ostringstream o;
o << e.msg << endl;
o << e.msg;
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl;
vector<event>::iterator found_ev = \
find(events->v_event.begin(), events->v_event.end(), e.ev_name);
......@@ -3454,6 +3498,7 @@ void AlarmHandler::do_alarm(bei_t& e)
found_ev->ex_reason = string("Alarm_ERROR");
found_ev->ex_desc = o.str();
found_ev->ex_origin = e.ev_name;
found_ev->quality = e.quality;
//LOOP ALARMS IN WHICH THIS EVENT IS USED
list<string> m_alarm=found_ev->m_alarm.show();
list<string>::iterator j = m_alarm.begin();
......@@ -5332,6 +5377,32 @@ void AlarmHandler::prepare_alarm_attr()
dslock->writerOut();
}
void AlarmHandler::prepare_event_list()
{
eventList_sz=0;
list<string> evl;
events->show(evl);
for(auto &ev : evl)
{
eventList_read[eventList_sz] = ev;
attr_eventList_read[eventList_sz] = const_cast<char*>(eventList_read[eventList_sz].c_str());
eventList_sz++;
}
}
void AlarmHandler::prepare_event_summary()
{
eventSummary_sz=0;
list<string> evs;
events->summary(evs);
for(auto &ev : evs)
{
eventSummary_read[eventSummary_sz] = ev;
attr_eventSummary_read[eventSummary_sz] = const_cast<char*>(eventSummary_read[eventSummary_sz].c_str());
eventSummary_sz++;
}
}
//=============================================================================
string AlarmHandler::remove_domain(string str)
{
......
......@@ -115,6 +115,8 @@ public:
string silencedAlarms_read[MAX_ALARMS];
string listAlarms_read[MAX_ALARMS];
string alarmSummary_read[MAX_ALARMS];
string eventList_read[MAX_ATTR_SUMMARY];
string eventSummary_read[MAX_ATTR_SUMMARY];
/* char c_normalAlarms_read[MAX_ALARMS][MAX_ATTR_NAME];
char c_unacknowledgedAlarms_read[MAX_ALARMS][MAX_ATTR_NAME];
......@@ -136,6 +138,8 @@ public:
size_t silencedAlarms_sz;
size_t listAlarms_sz;
size_t alarmSummary_sz;
size_t eventList_sz;
size_t eventSummary_sz;
double last_statistics_reset_time;
......@@ -169,6 +173,8 @@ public:
Tango::DevString *attr_alarmList_read;
Tango::DevDouble *attr_alarmFrequency_read;
Tango::DevString *attr_alarmSummary_read;
Tango::DevString *attr_eventList_read;
Tango::DevString *attr_eventSummary_read;
// Constructors and destructors
public:
......@@ -347,6 +353,24 @@ public:
*/
virtual void read_alarmSummary(Tango::Attribute &attr);
virtual bool is_alarmSummary_allowed(Tango::AttReqType type);
/**
* Attribute eventList related methods
* Description: List of all subscribed attributes
*
* Data type: Tango::DevString
* Attr type: Spectrum max = 10000
*/
virtual void read_eventList(Tango::Attribute &attr);
virtual bool is_eventList_allowed(Tango::AttReqType type);
/**
* Attribute eventSummary related methods
* Description:
*
* Data type: Tango::DevString
* Attr type: Spectrum max = 10000
*/
virtual void read_eventSummary(Tango::Attribute &attr);
virtual bool is_eventSummary_allowed(Tango::AttReqType type);
// Dynamic attribute methods
public:
......@@ -569,6 +593,9 @@ private:
void prepare_alarm_attr(); //for read attribute alarm and push_change_event
void prepare_event_list();
void prepare_event_summary();
void remove_AlarmState_dynamic_attribute_no_clean_db(string attname);
void parse_alarm(string &alarm_string, alarm_t &alm);
......
......@@ -290,6 +290,22 @@
<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="eventList" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="10000" maxY="" allocReadMember="true" isDynamic="false">
<dataType xsi:type="pogoDsl:StringType"/>
<changeEvent fire="false" libCheckCriteria="true"/>
<archiveEvent fire="false" libCheckCriteria="true"/>
<dataReadyEvent fire="false" libCheckCriteria="true"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="List of all subscribed attributes" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
</attributes>
<attributes name="eventSummary" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="10000" maxY="" allocReadMember="true" isDynamic="false">
<dataType xsi:type="pogoDsl:StringType"/>
<changeEvent fire="false" libCheckCriteria="true"/>
<archiveEvent fire="false" 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=""/>
</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"/>
......
......@@ -1123,6 +1123,58 @@ void AlarmHandlerClass::attribute_factory(vector<Tango::Attr *> &att_list)
alarmsummary->set_archive_event(true, true);
att_list.push_back(alarmsummary);
// Attribute : eventList
eventListAttrib *eventlist = new eventListAttrib();
Tango::UserDefaultAttrProp eventlist_prop;
eventlist_prop.set_description("List of all subscribed attributes");
// label not set for eventList
// unit not set for eventList
// standard_unit not set for eventList
// display_unit not set for eventList
// format not set for eventList
// max_value not set for eventList
// min_value not set for eventList
// max_alarm not set for eventList
// min_alarm not set for eventList
// max_warning not set for eventList
// min_warning not set for eventList
// delta_t not set for eventList
// delta_val not set for eventList
eventlist->set_default_properties(eventlist_prop);
// 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
eventSummaryAttrib *eventsummary = new eventSummaryAttrib();
Tango::UserDefaultAttrProp eventsummary_prop;
// description not set for eventSummary
// label not set for eventSummary
// unit not set for eventSummary
// standard_unit not set for eventSummary
// display_unit not set for eventSummary
// format not set for eventSummary
// max_value not set for eventSummary
// min_value not set for eventSummary
// max_alarm not set for eventSummary
// min_alarm not set for eventSummary
// max_warning not set for eventSummary
// min_warning not set for eventSummary
// delta_t not set for eventSummary
// delta_val not set for eventSummary
eventsummary->set_default_properties(eventsummary_prop);
// 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);
// Create a list of static attributes
create_static_attribute_list(get_class_attr()->get_attr_list());
......
......@@ -223,6 +223,32 @@ public:
{return (static_cast<AlarmHandler *>(dev))->is_alarmSummary_allowed(ty);}
};
// Attribute eventList class definition
class eventListAttrib: public Tango::SpectrumAttr
{
public:
eventListAttrib():SpectrumAttr("eventList",
Tango::DEV_STRING, Tango::READ, 10000) {};
~eventListAttrib() {};
virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att)
{(static_cast<AlarmHandler *>(dev))->read_eventList(att);}
virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty)
{return (static_cast<AlarmHandler *>(dev))->is_eventList_allowed(ty);}
};
// Attribute eventSummary class definition
class eventSummaryAttrib: public Tango::SpectrumAttr
{
public:
eventSummaryAttrib():SpectrumAttr("eventSummary",
Tango::DEV_STRING, Tango::READ, 10000) {};
~eventSummaryAttrib() {};
virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att)
{(static_cast<AlarmHandler *>(dev))->read_eventSummary(att);}
virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty)
{return (static_cast<AlarmHandler *>(dev))->is_eventSummary_allowed(ty);}
};
//=========================================
// Define classes for dynamic attributes
......
......@@ -252,6 +252,38 @@ bool AlarmHandler::is_alarmSummary_allowed(TANGO_UNUSED(Tango::AttReqType type))
return true;
}
//--------------------------------------------------------
/**
* Method : AlarmHandler::is_eventList_allowed()
* Description : Execution allowed for eventList attribute
*/
//--------------------------------------------------------
bool AlarmHandler::is_eventList_allowed(TANGO_UNUSED(Tango::AttReqType type))
{
// Not any excluded states for eventList attribute in read access.
/*----- PROTECTED REGION ID(AlarmHandler::eventListStateAllowed_READ) ENABLED START -----*/
/*----- PROTECTED REGION END -----*/ // AlarmHandler::eventListStateAllowed_READ
return true;
}
//--------------------------------------------------------
/**
* Method : AlarmHandler::is_eventSummary_allowed()
* Description : Execution allowed for eventSummary attribute
*/
//--------------------------------------------------------
bool AlarmHandler::is_eventSummary_allowed(TANGO_UNUSED(Tango::AttReqType type))
{
// Not any excluded states for eventSummary attribute in read access.
/*----- PROTECTED REGION ID(AlarmHandler::eventSummaryStateAllowed_READ) ENABLED START -----*/
/*----- PROTECTED REGION END -----*/ // AlarmHandler::eventSummaryStateAllowed_READ
return true;
}
//--------------------------------------------------------
/**
* Method : AlarmHandler::is_AlarmState_allowed()
......
......@@ -71,6 +71,8 @@ void *SubscribeThread::run_undetached(void *ptr)
{
// Try to subscribe
usleep(500000); //TODO: try to delay a bit subscribe_events
if(shared->get_if_stop())
break;
DEBUG_STREAM << "SubscribeThread::"<<__func__<<": AWAKE"<<endl;
updateProperty();
alarm_dev->events->subscribe_events();
......@@ -98,7 +100,7 @@ void *SubscribeThread::run_undetached(void *ptr)
//shared->unlock();
}
}
shared->unsubscribe_events();
//shared->unsubscribe_events();
INFO_STREAM <<"SubscribeThread::"<< __func__<<": exiting..."<<endl;
return NULL;
}
......
......@@ -84,7 +84,7 @@
#define SHELVED_KEY "shelved"
#define ACKNOWLEDGED_KEY "ack"
#define ATTR_VALUES_KEY "values"
#define VALUE_KEY "state"
#define VALUE_KEY "state"
#define ON_COUNTER_KEY "on_counter"
#define OFF_COUNTER_KEY "off_counter"
#define COUNTER_KEY "counter"
......@@ -93,6 +93,8 @@
#define AUDIBLE_KEY "audible"
#define FREQ_COUNTER_KEY "freq_counter"
#define ALARM_TIME_KEY "time"
#define EVENT_KEY "event"
#define EVENT_TIME_KEY ALARM_TIME_KEY
#define KEY(S_VAL) S_VAL "="
#define SEP ";"
......
......@@ -17,6 +17,7 @@
#include <tango.h>
#include "event_table.h"
#include "AlarmHandler.h"
#include "alarm_grammar.h"
//for get_event_system_for_event_id, to know if ZMQ
#include <eventconsumer.h>
......@@ -38,14 +39,14 @@ void event_list::push_back(bei_t& e)
catch(omni_thread_fatal& ex)
{
ostringstream err;
err << "omni_thread_fatal exception signaling omni_condition, err=" << ex.error << ends;
err << "omni_thread_fatal exception signaling omni_condition, err=" << ex.error;
//WARN_STREAM << "event_list::push_back(): " << err.str() << endl;
printf("event_list::push_back(): %s", err.str().c_str());
}
catch(Tango::DevFailed& ex)
{
ostringstream err;
err << "exception signaling omni_condition: '" << ex.errors[0].desc << "'" << ends;
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);
......@@ -69,7 +70,7 @@ const bei_t event_list::pop_front(void)
catch(omni_thread_fatal& ex)
{
ostringstream err;
err << "omni_thread_fatal exception waiting on omni_condition, err=" << ex.error << ends;
err << "omni_thread_fatal exception waiting on omni_condition, err=" << ex.error;
//WARN_STREAM << "event_list::pop_front(): " << err.str() << endl;
printf("event_list::pop_front(): %s", err.str().c_str());
bei_t e;
......@@ -80,7 +81,7 @@ const bei_t event_list::pop_front(void)
catch(Tango::DevFailed& ex)
{
ostringstream err;
err << "exception waiting on omni_condition: '" << ex.errors[0].desc << "'" << ends;
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);
......@@ -251,13 +252,90 @@ bool event::operator==(const string& s)
// v_event.push_back(e);//TODO: replaced with add
}*/
void event_table::show(void)
void event_table::show(list<string> &evl)
{
DEBUG_STREAM << "events found:" << endl;
if (v_event.empty() == false) {
evl.clear();
ReaderLock lock(veclock);
if (v_event.empty() == false)
{
vector<event>::iterator i = v_event.begin();
while (i != v_event.end()) {
DEBUG_STREAM << "\t" << i->name << endl;
while (i != v_event.end())
{
//DEBUG_STREAM << "\t" << i->name << endl;
evl.push_back(i->name);
i++;
}
}
}
void event_table::summary(list<string> &evs)
{
evs.clear();
ReaderLock lock(veclock);
if (v_event.empty() == false)
{
vector<event>::iterator i = v_event.begin();
while (i != v_event.end())
{
ostringstream ev_summary;
ev_summary << KEY(EVENT_KEY) << i->name << SEP;
tm time_tm;
time_t time_sec;
if(i->valid)
{
time_sec= i->ts.tv_sec;
}
else
{
timeval now;
gettimeofday(&now, NULL);
time_sec = now.tv_sec;
}
//gmtime_r(&time_sec,&time_tm); //-> UTC
localtime_r(&time_sec,&time_tm);
char time_buf[64];
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
ev_summary << KEY(EVENT_TIME_KEY) << time_buf << SEP;
ostringstream tmp_val;
//if(i->valid)
{
tmp_val << "[" ;
if(i->type != Tango::DEV_STRING)
{
if(i->read_size > 0 && i->value.size() > 0)
{
for(size_t k=0; k<i->read_size && k<i->value.size(); k++)
{
tmp_val << i->value[k];
if(k < i->read_size-1 && k<i->value.size()-1)
tmp_val << ",";
}
}
}
else
{
tmp_val << "\""<<i->value_string<<"\"";
}
tmp_val << "]";
}
ev_summary << KEY(ATTR_VALUES_KEY) << tmp_val.str() << SEP;
ostringstream tmp_ex;
//tmp_ex.str("");
if(!i->ex_reason.empty() || !i->ex_desc.empty() || !i->ex_origin.empty())
{
tmp_ex << "{\"Reason\":\"" << i->ex_reason << "\",\"Desc\":\"" << i->ex_desc << "\",\"Origin\":\"" << i->ex_origin << "\"}";
}
ev_summary << KEY(EXCEPTION_KEY) << tmp_ex.str() << SEP;
ev_summary << KEY(QUALITY_KEY);
try
{
ev_summary << quality_labels.at(i->quality) << SEP;
} catch(std::out_of_range& ex)
{
ev_summary << i->quality << SEP;
}
evs.push_back(ev_summary.str());
i++;
}
}
......@@ -272,6 +350,7 @@ event_table::event_table(Tango::DeviceImpl *s):Tango::LogAdapter(s)
unsigned int event_table::size(void)
{
ReaderLock lock(veclock); //TODO: necessary?
return(v_event.size());
}
#if 0
......@@ -288,7 +367,7 @@ void event_table::init_proxy(void) throw(vector<string> &)
{
ostringstream o;
o << "new DeviceProxy() failed for " \
<< i->device << ends;
<< i->device;
ERROR_STREAM << o.str() << endl;
//throw o.str();
proxy_error.push_back(o.str());
......@@ -328,7 +407,7 @@ void event_table::subscribe(EventCallBack& ecb) throw(vector<string> &)//throw(s
} catch (...) {
ostringstream o;
o << "subscribe_event() failed for " \
<< i->name << ends;
<< i->name;
ERROR_STREAM << o.str() << endl;
//throw o.str();
subscribe_error.push_back(o.str());
......@@ -877,24 +956,27 @@ void event_table::subscribe_events()
}
catch (Tango::DevFailed &e)
{
string ex_reason(e.errors[0].reason);
ex_reason = std::regex_replace(ex_reason, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " "
string ex_desc(e.errors[0].desc);
ex_desc = std::regex_replace(ex_desc, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " "
string ex_origin(e.errors[0].origin);
ex_origin = std::regex_replace(ex_origin, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " "
bei_t ex;
ostringstream o;
o << "Error adding'" \
<< sig->name << "' error=" << e.errors[0].desc << ends;
<< sig->name << "' error=" << ex_desc;
INFO_STREAM << "event_table::subscribe_events: " << o.str() << endl;
v_event[i].ex_reason = e.errors[0].reason;
v_event[i].ex_desc = e.errors[0].desc;
v_event[i].ex_reason = ex.ex_reason = ex_reason;
v_event[i].ex_desc = ex.ex_desc = ex_desc;
// v_event[i].ex_desc.erase(std::remove(v_event[i].ex_desc.begin(), v_event[i].ex_desc.end(), '\n'), v_event[i].ex_desc.end());
v_event[i].ex_origin = e.errors[0].origin;
v_event[i].siglock->writerOut();
//TODO: since event callback not called for this attribute, need to manually trigger do_alarm to update interlan structures ?
bei_t ex;
v_event[i].ex_origin = ex.ex_origin = ex_origin;
v_event[i].ts = ex.ts = gettime();
v_event[i].quality = ex.quality = Tango::ATTR_INVALID;
ex.ev_name = sig->name;
ex.quality = Tango::ATTR_INVALID;
ex.ex_reason = e.errors[0].reason;
ex.ex_desc = e.errors[0].desc;
ex.ex_origin = e.errors[0].origin;
v_event[i].siglock->writerOut();
//TODO: since event callback not called for this attribute, need to manually trigger do_alarm to update interlan structures ?
ex.type = TYPE_TANGO_ERR;
ex.ts = gettime();
ex.msg=o.str();
static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->do_alarm(ex);
continue;
......@@ -930,28 +1012,31 @@ void event_table::subscribe_events()
}
catch (Tango::DevFailed &e)
{
string ex_reason(e.errors[0].reason);
ex_reason = std::regex_replace(ex_reason, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " "
string ex_desc(e.errors[0].desc);
ex_desc = std::regex_replace(ex_desc, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " "
string ex_origin(e.errors[0].origin);
ex_origin = std::regex_replace(ex_origin, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " "
bei_t ex;
ostringstream o;
o << "Event exception for'" \
<< sig->name << "' error=" << e.errors[0].desc << ends;
<< sig->name << "' error=" << ex_desc;
INFO_STREAM <<"event_table::"<<__func__<<": sig->attr->subscribe_event: " << o.str() << endl;
err = true;
Tango::Except::print_exception(e);
sig->siglock->writerIn();
sig->ex_reason = e.errors[0].reason;
sig->ex_desc = e.errors[0].desc;
sig->ex_origin = e.errors[0].origin;
sig->ex_reason = ex.ex_reason = ex_reason;
sig->ex_desc = ex.ex_desc = ex_desc;
sig->ex_origin = ex.ex_origin = ex_origin;
sig->event_id = SUB_ERR;
delete sig->event_cb;
sig->ts = ex.ts = gettime();
sig->quality = ex.quality = Tango::ATTR_INVALID;
ex.ev_name = sig->name;
sig->siglock->writerOut();
//since event callback not called for this attribute, need to manually trigger do_alarm to update interlan structures
bei_t ex;
ex.ev_name = sig->name;
ex.quality = Tango::ATTR_INVALID;
ex.ex_reason = e.errors[0].reason;
ex.ex_desc = e.errors[0].desc;
ex.ex_origin = e.errors[0].origin;
ex.type = TYPE_TANGO_ERR;