diff --git a/src/AlarmHandler.cpp b/src/AlarmHandler.cpp index 17a372a71ce64ce739efc5db68f8b6bfbab8c20d..d2c2dd0cb776fae38cd65328a13d2f75fdca3961 100644 --- a/src/AlarmHandler.cpp +++ b/src/AlarmHandler.cpp @@ -130,6 +130,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 +343,7 @@ void AlarmHandler::delete_device() delete[] attr_alarmSummary_read; delete[] attr_eventList_read; delete[] attr_eventSummary_read; + delete[] attr_alarmDisabled_read; } //-------------------------------------------------------- @@ -399,6 +401,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++) { @@ -629,6 +632,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 { @@ -1208,6 +1213,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 +} //-------------------------------------------------------- /** @@ -1480,7 +1503,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 +1515,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) { @@ -1806,7 +1831,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 +1843,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; @@ -1969,7 +1996,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 +2008,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 +2043,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 +2148,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 +2160,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 +2171,6 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin) /*----- PROTECTED REGION END -----*/ // AlarmHandler::silence } - //-------------------------------------------------------- /** * Command Modify related method @@ -2314,7 +2354,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 +2366,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; @@ -2499,7 +2541,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 +2551,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; @@ -2614,7 +2658,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 +2668,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 +2711,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; @@ -2743,7 +2790,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 +2802,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 +2888,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 +2900,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; @@ -3624,6 +3675,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); @@ -3635,6 +3687,7 @@ 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); } return; } @@ -3752,6 +3805,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); @@ -3763,6 +3817,7 @@ 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 { @@ -3998,6 +4053,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); @@ -4009,6 +4065,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; @@ -5083,6 +5140,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++) { @@ -5094,6 +5152,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; @@ -5167,6 +5226,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") + { + //cout << __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) @@ -5179,11 +5270,10 @@ 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]; + time_buf[64]; strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm); #ifndef ALM_SUM_STR @@ -5468,7 +5558,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()); } } @@ -5501,7 +5591,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; diff --git a/src/AlarmHandler.h b/src/AlarmHandler.h index e68f83aed1c4336143456526764a05657c3b1796..1a42f89fe6e69d22349dae3503a5e82faa64de37 100644 --- a/src/AlarmHandler.h +++ b/src/AlarmHandler.h @@ -117,6 +117,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 +141,7 @@ public: size_t alarmSummary_sz; size_t eventList_sz; size_t eventSummary_sz; + size_t alarmDisabled_sz; double last_statistics_reset_time; @@ -175,6 +177,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 +374,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: diff --git a/src/AlarmHandler.xmi b/src/AlarmHandler.xmi index 67cd96d1b3940abab9a94e53886e57343eead9e2..fda10e70d85042d13a84e1d46c3ec8945af361a7 100644 --- a/src/AlarmHandler.xmi +++ b/src/AlarmHandler.xmi @@ -306,6 +306,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"/> diff --git a/src/AlarmHandlerClass.cpp b/src/AlarmHandlerClass.cpp index f0ba4bd6814b8573adf06e49b43c80a0b64b476c..fa5a110b6cfaa11cebf63c3e0e8cc730590ab6cb 100644 --- a/src/AlarmHandlerClass.cpp +++ b/src/AlarmHandlerClass.cpp @@ -1145,8 +1145,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 +1169,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()); diff --git a/src/AlarmHandlerClass.h b/src/AlarmHandlerClass.h index 25df84e58089dcf0e81b5a386937e68aa394e402..31167fdceac1e9782a8f5bf40b0613292a3c2199 100644 --- a/src/AlarmHandlerClass.h +++ b/src/AlarmHandlerClass.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 diff --git a/src/AlarmHandlerStateMachine.cpp b/src/AlarmHandlerStateMachine.cpp index 8ffe5825f396d8e3c6e79d44a8bedfa8916c480e..9515db61145c01a66a439481f30ef123c06b72e0 100644 --- a/src/AlarmHandlerStateMachine.cpp +++ b/src/AlarmHandlerStateMachine.cpp @@ -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() diff --git a/src/event_table.cpp.new b/src/event_table.cpp.new new file mode 100644 index 0000000000000000000000000000000000000000..f01ca83a72f49db8490052e38d6d111d9749ae29 --- /dev/null +++ b/src/event_table.cpp.new @@ -0,0 +1,1518 @@ +/* + * event_table.cpp + * + * $Author: graziano $ + * + * $Revision: 1.5 $ + * + * $Log: event_table.cpp,v $ + * + * + * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale + * Strada Statale 14 - km 163,5 in AREA Science Park + * 34012 Basovizza, Trieste ITALY + */ + +#include <sys/time.h> +#include <tango.h> +#include "event_table.h" +#include "AlarmHandler.h" +#include "alarm_grammar.h" + +//for get_event_system_for_event_id, to know if ZMQ +#include <eventconsumer.h> +#include <regex> + +static const char __FILE__rev[] = __FILE__ " $Revision: 1.5 $"; + +/* + * event_list class methods + */ +void event_list::push_back(bei_t& e) +{ + this->lock(); + + try{ + l_event.push_back(e); + empty.signal(); + } + catch(omni_thread_fatal& ex) + { + ostringstream err; + err << "omni_thread_fatal exception signaling omni_condition, err=" << ex.error; + //WARN_STREAM << "event_list::push_back(): " << err.str() << endl; + printf("event_list::push_back(): %s", err.str().c_str()); + } + catch(Tango::DevFailed& ex) + { + ostringstream err; + err << "exception signaling omni_condition: '" << ex.errors[0].desc << "'"; + //WARN_STREAM << "event_list::push_back(): " << err.str() << endl; + printf("event_list::push_back: %s", err.str().c_str()); + Tango::Except::print_exception(ex); + } + catch(...) + { + //WARN_STREAM << "event_list::push_back(): catched unknown exception!!" << endl; + printf("event_list::push_back(): catched unknown exception signaling omni_condition!!"); + } + this->unlock(); +} + +const bei_t event_list::pop_front(void) +{ + this->lock(); + //omni_mutex_lock l((omni_mutex)this); //call automatically unlock on destructor and on exception + try{ + while (l_event.empty() == true) + empty.wait(); //wait release mutex while is waiting, then reacquire when signaled + } + catch(omni_thread_fatal& ex) + { + ostringstream err; + err << "omni_thread_fatal exception waiting on omni_condition, err=" << ex.error; + //WARN_STREAM << "event_list::pop_front(): " << err.str() << endl; + printf("event_list::pop_front(): %s", err.str().c_str()); + bei_t e; + this->unlock(); + sleep(1); + return(e); + } + catch(Tango::DevFailed& ex) + { + ostringstream err; + err << "exception waiting on omni_condition: '" << ex.errors[0].desc << "'"; + //WARN_STREAM << "event_list::pop_front(): " << err.str() << endl; + printf("event_list::pop_front: %s", err.str().c_str()); + Tango::Except::print_exception(ex); + bei_t e; + this->unlock(); + sleep(1); + return(e); + } + catch(...) + { + //WARN_STREAM << "event_list::pop_front(): catched unknown exception!!" << endl; + printf("event_list::pop_front(): catched unknown exception waiting on omni_condition!!"); + bei_t e; + this->unlock(); + sleep(1); + return(e); + } + /*const*/ bei_t e; + + e = *(l_event.begin()); + + l_event.pop_front(); + + this->unlock(); + return(e); +} + +void event_list::clear(void) +{ + //this->lock(); + l_event.clear(); + //this->unlock(); +} + +list<bei_t> event_list::show(void) +{ + list<bei_t> el; + + this->lock(); + el = l_event; + this->unlock(); + return(el); +} + +size_t event_list::size(void) +{ + size_t res; + + this->lock(); + res = l_event.size(); + this->unlock(); + return(res); +} + + +/* + * alarm_list class methods + */ +void alarm_list::push(string& a) +{ + l.lock(); + l_alarm.push_back(a); + l.unlock(); +} + +void alarm_list::pop(const string& a) +{ + l.lock(); + list<string>::iterator it = find(l_alarm.begin(), l_alarm.end(), a); + if(it != l_alarm.end()) + l_alarm.erase(it); + else + cout << "alarm_list::"<<__func__<< ": ALARM '"<< a << "' NOT FOUND!"<< endl; + + l.unlock(); + return; +} + +void alarm_list::clear(void) +{ + l.lock(); + l_alarm.clear(); + l.unlock(); +} + +list<string> alarm_list::show(void) +{ + list<string> al; + l.lock(); + al = l_alarm; + l.unlock(); + return(al); +} + +bool alarm_list::empty(void) +{ + bool res; + l.lock(); + res = l_alarm.empty(); + l.unlock(); + return(res); +} + + +/* + * event class methods + */ +event::event(string& s, value_t& v, Tango::TimeVal& t) : \ + name(s), value(v), ts(t) +{ + const char *c = name.c_str(); + int j = 0; + int num_slashes=3; //not FQDN + if(name.find("tango://") != string::npos) //FQDN!! + num_slashes = 6; + while (*c) { + if (*c == '/') + j++; + if (j < num_slashes) + devname.push_back(*c); + else if (*c != '/') + attname.push_back(*c); + c++; + } + type = -1; + event_id = SUB_ERR; + err_counter = 0; + valid = false; +} + +event::event(string& s) : name(s) +{ + const char *c = name.c_str(); + int j = 0; + int num_slashes=3; //not FQDN + if(name.find("tango://") != string::npos) //FQDN!! + num_slashes = 6; + while (*c) { + if (*c == '/') + j++; + if (j < num_slashes) + devname.push_back(*c); + else if (*c != '/') + attname.push_back(*c); + c++; + } + type = -1; + event_id = SUB_ERR; + err_counter = 0; + valid = false; +} + +bool event::operator==(const event& e) +{ + return(name == e.name); +} + +bool event::operator==(const string& s) +{ + return(name == s); +} + +/* + * event_table class methods + */ +/*void event_table::push_back(event e) +{ +// v_event.push_back(e);//TODO: replaced with add +}*/ + +void event_table::show(list<string> &evl) +{ + evl.clear(); + ReaderLock lock(veclock); + if (v_event.empty() == false) + { + vector<event>::iterator i = v_event.begin(); + while (i != v_event.end()) + { + //DEBUG_STREAM << "\t" << i->name << endl; + evl.push_back(i->name); + i++; + } + } +} + +void event_table::summary(list<string> &evs) +{ + evs.clear(); + ReaderLock lock(veclock); + if (v_event.empty() == false) + { + vector<event>::iterator i = v_event.begin(); + while (i != v_event.end()) + { + ostringstream ev_summary; + ev_summary << KEY(EVENT_KEY) << i->name << SEP; + tm time_tm; + time_t time_sec; + if(i->valid) + { + time_sec= i->ts.tv_sec; + } + else + { + timeval now; + gettimeofday(&now, NULL); + time_sec = now.tv_sec; + } + //gmtime_r(&time_sec,&time_tm); //-> UTC + localtime_r(&time_sec,&time_tm); + char time_buf[64]; + strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm); + + ev_summary << KEY(EVENT_TIME_KEY) << time_buf << SEP; + ostringstream tmp_val; + //if(i->valid) + { + tmp_val << "[" ; + if(i->type != Tango::DEV_STRING) + { + if(i->read_size > 0 && i->value.size() > 0) + { + for(size_t k=0; k<i->read_size && k<i->value.size(); k++) + { + tmp_val << i->value[k]; + if(k < i->read_size-1 && k<i->value.size()-1) + tmp_val << ","; + } + } + } + else + { + tmp_val << "\""<<i->value_string<<"\""; + } + tmp_val << "]"; + } + ev_summary << KEY(ATTR_VALUES_KEY) << tmp_val.str() << SEP; + ostringstream tmp_ex; + //tmp_ex.str(""); + if(!i->ex_reason.empty() || !i->ex_desc.empty() || !i->ex_origin.empty()) + { + tmp_ex << "{\"Reason\":\"" << i->ex_reason << "\",\"Desc\":\"" << i->ex_desc << "\",\"Origin\":\"" << i->ex_origin << "\"}"; + } + ev_summary << KEY(EXCEPTION_KEY) << tmp_ex.str() << SEP; + ev_summary << KEY(QUALITY_KEY); + try + { + ev_summary << quality_labels.at(i->quality) << SEP; + } catch(std::out_of_range& ex) + { + ev_summary << i->quality << SEP; + } + evs.push_back(ev_summary.str()); + i++; + } + } +} + +event_table::event_table(Tango::DeviceImpl *s):Tango::LogAdapter(s) +{ + mydev = s; + stop_it = false; + action.store(NOTHING); +} + +unsigned int event_table::size(void) +{ + ReaderLock lock(veclock); //TODO: necessary? + return(v_event.size()); +} +#if 0 +void event_table::init_proxy(void) throw(vector<string> &) +{ + vector<string> proxy_error; + if (v_event.empty() == false) { + for (vector<event>::iterator i = v_event.begin(); \ + i != v_event.end(); i++) + { + try { + i->dp = new Tango::DeviceProxy(i->device); + } catch(Tango::DevFailed& e) + { + ostringstream o; + o << "new DeviceProxy() failed for " \ + << i->device; + ERROR_STREAM << o.str() << endl; + //throw o.str(); + proxy_error.push_back(o.str()); + } + } + } + if(!proxy_error.empty()) + throw proxy_error; +} + +void event_table::free_proxy(void) +{ + if (v_event.empty() == false) { + for (vector<event>::iterator i = v_event.begin(); \ + i != v_event.end(); i++) { + try{ + delete i->dp; + DEBUG_STREAM << gettime().tv_sec << " event_table::free_proxy(): deleted proxy " << i->device << endl; + } catch(...) + { + ERROR_STREAM << "event_table::free_proxy: exception deleting proxy of event: " << i->name << endl; + } + } + } +} + +void event_table::subscribe(EventCallBack& ecb) throw(vector<string> &)//throw(string&) +{ + vector<string> subscribe_error; + if (v_event.empty() == false) { + for (vector<event>::iterator i = v_event.begin(); \ + i != v_event.end(); i++) { + try { + i->eid = i->dp->subscribe_event(i->attribute, \ + Tango::CHANGE_EVENT, \ + &ecb, i->filter); + } catch (...) { + ostringstream o; + o << "subscribe_event() failed for " \ + << i->name; + ERROR_STREAM << o.str() << endl; + //throw o.str(); + subscribe_error.push_back(o.str()); + } + } + } + if(!subscribe_error.empty()) + throw subscribe_error; +} + +void event_table::unsubscribe(void) throw(string&) +{ + ostringstream o; + if (v_event.empty() == false) { + for (vector<event>::iterator i = v_event.begin(); \ + i != v_event.end(); i++) { + try { + i->dp->unsubscribe_event(i->eid); + DEBUG_STREAM << gettime().tv_sec << " event_table::unsubscribe(): unsubscribed " << i->name << endl; + } catch (Tango::DevFailed& e) { + o << " unsubscribe_event() failed for " << i->name << " err=" << e.errors[0].desc; + ERROR_STREAM << gettime().tv_sec << " event_table::unsubscribe(): " << o.str() << endl; + //throw o.str(); + } catch (...) { + o << " unsubscribe_event() failed for " \ + << i->name; + ERROR_STREAM << gettime().tv_sec << " event_table::unsubscribe(): " << o.str() << endl; + //throw o.str(); + } + } + } + if(o.str().length() > 0) + throw o.str(); +} +#endif +//============================================================================= +/** + * get signal by name. + */ +//============================================================================= +event *event_table::get_signal(string signame) +{ + //omni_mutex_lock sync(*this); + for (unsigned int i=0 ; i<v_event.size() ; i++) + { + event *sig = &v_event[i]; + if (sig->name==signame) + return sig; + } + for (unsigned int i=0 ; i<v_event.size() ; i++) + { + event *sig = &v_event[i]; + if (static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_without_domain(sig->name,signame)) + return sig; + } + return NULL; +} + + +//============================================================================= +/** + * Stop saving on DB a signal. + */ +//============================================================================= +void event_table::stop(string &signame) +{ + DEBUG_STREAM <<"event_table::"<< __func__<<": entering signame="<< signame << endl; + ReaderLock lock(veclock); + for (unsigned int i=0 ; i<v_event.size() ; i++) + { + if (v_event[i].name==signame) + { + v_event[i].siglock->writerIn(); + if(!v_event[i].stopped) + { + v_event[i].stopped=true; + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read++; + if(v_event[i].running) + { + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStartedNumber_read--; + try + { + remove(signame, true); + } + catch (Tango::DevFailed &e) + { + //Tango::Except::print_exception(e); + INFO_STREAM << "event_table::stop: error removing " << signame << endl; + } + } + if(v_event[i].paused) + { + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--; + try + { + remove(signame, true); + } + catch (Tango::DevFailed &e) + { + //Tango::Except::print_exception(e); + INFO_STREAM << "event_table::stop: error removing " << signame << endl; + } + } + v_event[i].running=false; + v_event[i].paused=false; + } + v_event[i].siglock->writerOut(); + return; + } + } + for (unsigned int i=0 ; i<v_event.size() ; i++) + { +#ifndef _MULTI_TANGO_HOST + if (static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_without_domain(v_event[i].name,signame)) +#else + if (!static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_tango_names(v_event[i].name,signame)) +#endif + { + v_event[i].siglock->writerIn(); + if(!v_event[i].stopped) + { + v_event[i].stopped=true; + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read++; + if(v_event[i].running) + { + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStartedNumber_read--; + try + { + remove(signame, true); + } + catch (Tango::DevFailed &e) + { + //Tango::Except::print_exception(e); + INFO_STREAM << "event_table::stop: error removing " << signame << endl; + } + } + if(v_event[i].paused) + { + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--; + try + { + remove(signame, true); + } + catch (Tango::DevFailed &e) + { + //Tango::Except::print_exception(e); + INFO_STREAM << "event_table::stop: error removing " << signame << endl; + } + } + v_event[i].running=false; + v_event[i].paused=false; + } + v_event[i].siglock->writerOut(); + return; + } + } + + // if not found + Tango::Except::throw_exception( + (const char *)"BadSignalName", + "Signal " + signame + " NOT subscribed", + (const char *)"event_table::stop()"); +} + + +//============================================================================= +/** + * Remove a signal in the list. + */ +//============================================================================= +void event_table::remove(string &signame, bool stop) +{ + DEBUG_STREAM <<"event_table::"<< __func__<<": entering signame="<< signame << endl; + // Remove in signals list (vector) + { + if(!stop) + veclock.readerIn(); + event *sig = get_signal(signame); + int event_id = sig->event_id; + Tango::AttributeProxy *attr = sig->attr; + if(!stop) + veclock.readerOut(); + if(stop) + { + try + { + if(event_id != SUB_ERR && attr) + { + DEBUG_STREAM <<"event_table::"<< __func__<<": unsubscribing... "<< signame << endl; + //unlocking, locked in event_table::stop but possible deadlock if unsubscribing remote attribute with a faulty event connection + sig->siglock->writerOut(); + attr->unsubscribe_event(event_id); + sig->siglock->writerIn(); + DEBUG_STREAM <<"event_table::"<< __func__<<": unsubscribed... "<< signame << endl; + } + } + catch (Tango::DevFailed &e) + { + // Do nothing + // Unregister failed means Register has also failed + sig->siglock->writerIn(); + INFO_STREAM <<"event_table::"<< __func__<<": Exception unsubscribing " << signame << " err=" << e.errors[0].desc << endl; + } + } + + if(!stop) + veclock.writerIn(); + vector<event>::iterator pos = v_event.begin(); + + bool found = false; + for (unsigned int i=0 ; i<v_event.size() && !found ; i++, pos++) + { + event *sig = &v_event[i]; + if (sig->name==signame) + { + found = true; + if(stop) + { + DEBUG_STREAM <<"event_table::"<<__func__<< ": removing " << signame << endl; + //sig->siglock->writerIn(); //: removed, already locked in event_table::stop + try + { + if(sig->event_id != SUB_ERR) + { + delete sig->event_cb; + } + if(sig->attr) + delete sig->attr; + } + catch (Tango::DevFailed &e) + { + // Do nothing + // Unregister failed means Register has also failed + INFO_STREAM <<"event_table::"<< __func__<<": Exception deleting " << signame << " err=" << e.errors[0].desc << endl; + } + //sig->siglock->writerOut(); + DEBUG_STREAM <<"event_table::"<< __func__<<": stopped " << signame << endl; + } + if(!stop) + { + if(sig->running) + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStartedNumber_read--; + if(sig->paused) + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--; + if(sig->stopped) + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read--; + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeNumber_read--; + delete sig->siglock; + v_event.erase(pos); + DEBUG_STREAM <<"event_table::"<< __func__<<": removed " << signame << endl; + } + break; + } + } + pos = v_event.begin(); + if (!found) + { + for (unsigned int i=0 ; i<v_event.size() && !found ; i++, pos++) + { + event *sig = &v_event[i]; +#ifndef _MULTI_TANGO_HOST + if (static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_without_domain(sig->name,signame)) +#else + if (!static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_tango_names(sig->name,signame)) +#endif + { + found = true; + DEBUG_STREAM <<"event_table::"<<__func__<< ": removing " << signame << endl; + if(stop) + { + sig->siglock->writerIn(); + try + { + if(sig->event_id != SUB_ERR) + { + delete sig->event_cb; + } + if(sig->attr) + delete sig->attr; + } + catch (Tango::DevFailed &e) + { + // Do nothing + // Unregister failed means Register has also failed + INFO_STREAM <<"event_table::"<< __func__<<": Exception unsubscribing " << signame << " err=" << e.errors[0].desc << endl; + } + sig->siglock->writerOut(); + DEBUG_STREAM <<"event_table::"<< __func__<<": stopped " << signame << endl; + } + if(!stop) + { + if(sig->running) + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStartedNumber_read--; + if(sig->paused) + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--; + if(sig->stopped) + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read--; + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeNumber_read--; + delete sig->siglock; + v_event.erase(pos); + DEBUG_STREAM <<"event_table::"<< __func__<<": removed " << signame << endl; + } + break; + } + } + } + if(!stop) + veclock.writerOut(); + if (!found) + Tango::Except::throw_exception( + (const char *)"BadSignalName", + "Signal " + signame + " NOT subscribed", + (const char *)"event_table::remove()"); + } + // then, update property +/* if(!stop) + { + DEBUG_STREAM <<"event_table::"<< __func__<<": going to increase action... action="<<action<<"++" << endl; + if(action <= UPDATE_PROP) + action++; + //put_signal_property(); //TODO: wakeup thread and let it do it? -> signal() + signal(); + }*/ +} +void event_table::update_property() +{ + DEBUG_STREAM <<"event_table::"<< __func__<<": going to increase action... action="<<action.load()<<"++" << endl; + int expected=NOTHING; + action.compare_exchange_strong(expected, UPDATE_PROP); //if it is NOTHING, then change to UPDATE_PROP + signal(); +} +//============================================================================= +/** + * Remove a signal in the list. + */ +//============================================================================= +void event_table::unsubscribe_events() +{ + DEBUG_STREAM <<"event_table::"<<__func__<< " entering..."<< endl; + veclock.readerIn(); + vector<event> local_signals(v_event); + veclock.readerOut(); + for (unsigned int i=0 ; i<local_signals.size() ; i++) + { + event *sig = &local_signals[i]; + if (local_signals[i].event_id != SUB_ERR && sig->attr) + { + DEBUG_STREAM <<"event_table::"<<__func__<< " unsubscribe " << sig->name << " id="<<omni_thread::self()->id()<< endl; + try + { + sig->attr->unsubscribe_event(sig->event_id); + DEBUG_STREAM <<"event_table::"<<__func__<< " unsubscribed " << sig->name << endl; + } + catch (Tango::DevFailed &e) + { + // Do nothing + // Unregister failed means Register has also failed + INFO_STREAM <<"event_table::"<<__func__<< " ERROR unsubscribing " << sig->name << " err="<<e.errors[0].desc<< endl; + } + } + } + veclock.writerIn(); + for (unsigned int i=0 ; i<v_event.size() ; i++) + { + event *sig = &v_event[i]; + sig->siglock->writerIn(); + if (v_event[i].event_id != SUB_ERR && sig->attr) + { + delete sig->event_cb; + DEBUG_STREAM <<"event_table::"<<__func__<< " deleted cb " << sig->name << endl; + } + if(sig->attr) + { + delete sig->attr; + DEBUG_STREAM <<"event_table::"<<__func__<< " deleted proxy " << sig->name << endl; + } + sig->siglock->writerOut(); + delete sig->siglock; + DEBUG_STREAM <<"event_table::"<<__func__<< " deleted lock " << sig->name << endl; + } + DEBUG_STREAM <<"event_table::"<<__func__<< " ended loop, deleting vector" << endl; + + /*for (unsigned int j=0 ; j<signals.size() ; j++, pos++) + { + signals[j].event_id = SUB_ERR; + signals[j].event_conf_id = SUB_ERR; + signals[j].archive_cb = NULL; + signals[j].attr = NULL; + }*/ + v_event.clear(); + veclock.writerOut(); + DEBUG_STREAM <<"event_table::"<< __func__<< ": exiting..."<<endl; +} +//============================================================================= +/** + * Add a new signal. + */ +//============================================================================= +void event_table::add(string &signame, vector<string> contexts) +{ + DEBUG_STREAM << "event_table::"<<__func__<< " entering signame=" << signame << endl; + add(signame, contexts, NOTHING, false); +} +//============================================================================= +/** + * Add a new signal. + */ +//============================================================================= +void event_table::add(string &signame, vector<string> contexts, int to_do, bool start) +{ + DEBUG_STREAM << "event_table::"<<__func__<<": Adding " << signame << " to_do="<<to_do<<" start="<<(start ? "Y" : "N")<< endl; + { + veclock.readerIn(); + event *sig; + // Check if already subscribed + bool found = false; + for (unsigned int i=0 ; i<v_event.size() && !found ; i++) + { + sig = &v_event[i]; + found = (sig->name==signame); + } + for (unsigned int i=0 ; i<v_event.size() && !found ; i++) + { + sig = &v_event[i]; + found = static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_without_domain(sig->name,signame); + } + veclock.readerOut(); + //DEBUG_STREAM << "event_table::"<<__func__<<": signame="<<signame<<" found="<<(found ? "Y" : "N") << " start="<<(start ? "Y" : "N")<< endl; + if (found && !start) + Tango::Except::throw_exception( + (const char *)"BadSignalName", + "Signal " + signame + " already subscribed", + (const char *)"event_table::add()"); + event *signal; + if (!found && !start) + { + // on name, split device name and attrib name + string::size_type idx = signame.find_last_of("/"); + if (idx==string::npos) + { + Tango::Except::throw_exception( + (const char *)"SyntaxError", + "Syntax error in signal name " + signame, + (const char *)"event_table::add()"); + } + signal = new event(); + // Build Hdb Signal object + signal->name = signame; + signal->siglock = new(ReadersWritersLock); + signal->devname = signal->name.substr(0, idx); + signal->attname = signal->name.substr(idx+1); + signal->ex_reason = "NOT_connected"; + signal->ex_desc = "Attribute not subscribed"; + signal->ex_origin = "..."; + signal->attr = NULL; + signal->running = false; + signal->stopped = true; + signal->paused = false; + //DEBUG_STREAM << "event_table::"<<__func__<<": signame="<<signame<<" created signal"<< endl; + } + else if(found && start) + { + signal = sig; +#if 0 + signal->siglock->writerIn(); + signal->ex_reason = "NOT_connected"; + signal->ex_desc = "Attribute not subscribed"; + signal->ex_origin = "..."; + signal->siglock->writerOut(); +#endif + //DEBUG_STREAM << "created proxy to " << signame << endl; + // create Attribute proxy + signal->attr = new Tango::AttributeProxy(signal->name); //TODO: OK out of siglock? accessed only inside the same thread? + DEBUG_STREAM << "event_table::"<<__func__<<": signame="<<signame<<" created proxy"<< endl; + } + signal->event_id = SUB_ERR; + signal->evstate = Tango::ALARM; + signal->isZMQ = false; + signal->okev_counter = 0; + signal->okev_counter_freq = 0; + signal->nokev_counter = 0; + signal->nokev_counter_freq = 0; + signal->first = true; + signal->first_err = true; + clock_gettime(CLOCK_MONOTONIC, &signal->last_ev); + + if(found && start) + { + + } + + //DEBUG_STREAM <<"event_table::"<< __func__<< " created proxy to " << signame << endl; + if (!found && !start) + { + veclock.writerIn(); + // Add in vector + v_event.push_back(*signal); + delete signal; + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeNumber_read++; + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read++; + veclock.writerOut(); + //DEBUG_STREAM << "event_table::"<<__func__<<": signame="<<signame<<" push_back signal"<< endl; + } + else if(found && start) + { + + } + int act=action.load(); + DEBUG_STREAM <<"event_table::"<< __func__<<": going to increase action... action="<<act<<" += " << to_do << endl; + int expected=NOTHING; + action.compare_exchange_strong(expected, UPDATE_PROP); //if it is NOTHING, then change to UPDATE_PROP + } + DEBUG_STREAM <<"event_table::"<< __func__<<": exiting... " << signame << endl; + signal(); + //condition.signal(); +} +//============================================================================= +/** + * Subscribe archive event for each signal + */ +//============================================================================= +void event_table::subscribe_events() +{ + /*for (unsigned int ii=0 ; ii<v_event.size() ; ii++) + { + event *sig2 = &v_event[ii]; + int ret = pthread_rwlock_trywrlock(&sig2->siglock); + DEBUG_STREAM << __func__<<": pthread_rwlock_trywrlock i="<<ii<<" name="<<sig2->name<<" just entered " << ret << endl; + if(ret == 0) pthread_rwlock_unlock(&sig2->siglock); + }*/ + //omni_mutex_lock sync(*this); + list<string> l_events; + show(l_events); + DEBUG_STREAM << "event_table::" << __func__ << ": going to subscribe " << v_event.size() << " attributes" << endl; + for (auto it : l_events) + { + veclock.readerIn(); + event *sig = get_signal(it); + sig->siglock->readerIn(); + string sig_name(sig->name); + if (sig->event_id==SUB_ERR && !sig->stopped) + { + if(!sig->attr) + { + try + { + vector<string> contexts; //TODO!!! + add(sig->name, contexts, NOTHING, true); + } + catch (Tango::DevFailed &e) + { + string ex_reason(e.errors[0].reason); + ex_reason = std::regex_replace(ex_reason, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " " + string ex_desc(e.errors[0].desc); + ex_desc = std::regex_replace(ex_desc, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " " + string ex_origin(e.errors[0].origin); + ex_origin = std::regex_replace(ex_origin, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " " + bei_t ex; + ostringstream o; + o << "Error adding'" \ + << sig->name << "' error=" << ex_desc; + INFO_STREAM << "event_table::subscribe_events: " << o.str() << endl; + sig->ex_reason = ex.ex_reason = ex_reason; + sig->ex_desc = ex.ex_desc = ex_desc; +// sig->ex_desc.erase(std::remove(sig->ex_desc.begin(), sig->ex_desc.end(), '\n'), sig->ex_desc.end()); + sig->ex_origin = ex.ex_origin = ex_origin; + sig->ts = ex.ts = gettime(); + sig->quality = ex.quality = Tango::ATTR_INVALID; + ex.ev_name = sig->name; + sig->siglock->readerOut(); + veclock.readerOut(); + //TODO: since event callback not called for this attribute, need to manually trigger do_alarm to update internal structures ? + ex.type = TYPE_TANGO_ERR; + ex.msg=o.str(); + try + {//DevFailed for push events + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->do_alarm(ex); + } catch(Tango::DevFailed & ee) + { + WARN_STREAM << "event_table::"<<__func__<<": " << sig_name << " - EXCEPTION PUSHING EVENTS: " << ee.errors[0].desc << endl; + } + continue; + } + } + sig->event_cb = new EventCallBack(static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)); + sig->first = true; + sig->first_err = true; + DEBUG_STREAM << "event_table::"<<__func__<<":Subscribing for " << sig_name << " " << (sig->first ? "FIRST" : "NOT FIRST") << endl; + sig->siglock->readerOut(); + int event_id = SUB_ERR; + bool isZMQ = true; + bool err = false; + + try + { + event_id = sig->attr->subscribe_event( + Tango::CHANGE_EVENT, + sig->event_cb, + /*stateless=*/false); + /*sig->evstate = Tango::ON; + //sig->first = false; //first event already arrived at subscribe_event + sig->status.clear(); + sig->status = "Subscribed"; + DEBUG_STREAM << sig->name << " Subscribed" << endl;*/ + + // Check event source ZMQ/Notifd ? + /*Tango::ZmqEventConsumer *consumer = + Tango::ApiUtil::instance()->get_zmq_event_consumer();*/ + isZMQ = true;//(consumer->get_event_system_for_event_id(event_id) == Tango::ZMQ);//TODO: remove + + DEBUG_STREAM << sig_name << "(id="<< event_id <<"): Subscribed " << ((isZMQ)? "ZMQ Event" : "NOTIFD Event") << endl; + } + catch (Tango::DevFailed &e) + { + string ex_reason(e.errors[0].reason); + ex_reason = std::regex_replace(ex_reason, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " " + string ex_desc(e.errors[0].desc); + ex_desc = std::regex_replace(ex_desc, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " " + string ex_origin(e.errors[0].origin); + ex_origin = std::regex_replace(ex_origin, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " " + bei_t ex; + ostringstream o; + o << "Event exception for'" \ + << sig_name << "' error=" << ex_desc; + INFO_STREAM <<"event_table::"<<__func__<<": sig->attr->subscribe_event: " << o.str() << endl; + err = true; + Tango::Except::print_exception(e); + //sig->siglock->writerIn(); //not yet subscribed, no one can modify + sig->ex_reason = ex.ex_reason = ex_reason; + sig->ex_desc = ex.ex_desc = ex_desc; + sig->ex_origin = ex.ex_origin = ex_origin; + sig->event_id = SUB_ERR; + delete sig->event_cb; + sig->ts = ex.ts = gettime(); + sig->quality = ex.quality = Tango::ATTR_INVALID; + ex.ev_name = sig->name; + //sig->siglock->writerOut();//not yet subscribed, no one can modify + veclock.readerOut(); + //since event callback not called for this attribute, need to manually trigger do_alarm to update interlan structures + ex.type = TYPE_TANGO_ERR; + ex.msg=o.str(); + try + {//DevFailed for push events + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->do_alarm(ex); + } catch(Tango::DevFailed & ee) + { + WARN_STREAM << "event_table::"<<__func__<<": " << ex.ev_name << " - EXCEPTION PUSHING EVENTS: " << ee.errors[0].desc << endl; + } + continue; + } + if(!err) + { + //sig->siglock->writerIn(); //nobody else write event_id and isZMQ + sig->event_id = event_id; + sig->isZMQ = isZMQ; + //sig->siglock->writerOut();//nobody else write event_id and isZMQ + } + } + else + { + sig->siglock->readerOut(); + } + veclock.readerOut(); + } + initialized = true; +} + +void event_table::start(string &signame) +{ + DEBUG_STREAM << "event_table::"<<__func__<< " entering signame=" << signame << endl; + ReaderLock lock(veclock); + vector<string> contexts; + for (unsigned int i=0 ; i<v_event.size() ; i++) + { + if (v_event[i].name==signame) + { + v_event[i].siglock->writerIn(); + if(!v_event[i].running) + { + if(v_event[i].stopped) + { + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read--; + try + { + add(signame, contexts, NOTHING, true); + } + catch (Tango::DevFailed &e) + { + //Tango::Except::print_exception(e); + INFO_STREAM << "event_table::start: error adding " << signame <<" err="<< e.errors[0].desc << endl; + v_event[i].ex_reason = e.errors[0].reason; + v_event[i].ex_desc = e.errors[0].desc; + v_event[i].ex_origin = e.errors[0].origin; + /*v_event[i].siglock->writerOut(); + return;*/ + } + } + v_event[i].running=true; + if(v_event[i].paused) + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--; + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStartedNumber_read++; + v_event[i].paused=false; + v_event[i].stopped=false; + } + v_event[i].siglock->writerOut(); + return; + } + } + for (unsigned int i=0 ; i<v_event.size() ; i++) + { +#ifndef _MULTI_TANGO_HOST + if (static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_without_domain(v_event[i].name,signame)) +#else + if (!static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->compare_tango_names(v_event[i].name,signame)) +#endif + { + v_event[i].siglock->writerIn(); + if(!v_event[i].running) + { + if(v_event[i].stopped) + { + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read--; + try + { + add(signame, contexts, NOTHING, true); + } + catch (Tango::DevFailed &e) + { + //Tango::Except::print_exception(e); + INFO_STREAM << "event_table::start: error adding " << signame << endl; + v_event[i].ex_reason = e.errors[0].reason; + v_event[i].ex_desc = e.errors[0].desc; + v_event[i].ex_origin = e.errors[0].origin; + /*signals[i].siglock->writerOut(); + return;*/ + } + } + v_event[i].running=true; + if(v_event[i].paused) + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--; + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStartedNumber_read++; + v_event[i].paused=false; + v_event[i].stopped=false; + } + v_event[i].siglock->writerOut(); + return; + } + } + + // if not found + Tango::Except::throw_exception( + (const char *)"BadSignalName", + "Signal " + signame + " NOT subscribed", + (const char *)"event_table::start()"); +} + +void event_table::start_all() +{ + ReaderLock lock(veclock); + vector<string> contexts; + for (unsigned int i=0 ; i<v_event.size() ; i++) + { + v_event[i].siglock->writerIn(); + if(!v_event[i].running) + { + if(v_event[i].stopped) + { + string signame = v_event[i].name; + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStoppedNumber_read--; + try + { + add(signame, contexts, NOTHING, true); + } + catch (Tango::DevFailed &e) + { + //Tango::Except::print_exception(e); + INFO_STREAM << "event_table::start: error adding " << signame <<" err="<< e.errors[0].desc << endl; + v_event[i].ex_reason = e.errors[0].reason; + v_event[i].ex_desc = e.errors[0].desc; + v_event[i].ex_origin = e.errors[0].origin; + /*v_event[i].siglock->writerOut(); + return;*/ + } + } + v_event[i].running=true; + if(v_event[i].paused) + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributePausedNumber_read--; + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->attr_AttributeStartedNumber_read++; + v_event[i].paused=false; + v_event[i].stopped=false; + } + v_event[i].siglock->writerOut(); + } +} + + +//============================================================================= +//============================================================================= +bool event_table::get_if_stop() +{ + //omni_mutex_lock sync(*this); + return stop_it; +} +//============================================================================= +//============================================================================= +void event_table::stop_thread() +{ + //omni_mutex_lock sync(*this); + stop_it = true; + signal(); + //condition.signal(); +} +//============================================================================= +/** + * return number of signals to be subscribed + */ +//============================================================================= +int event_table::nb_sig_to_subscribe() +{ + ReaderLock lock(veclock); + + int nb = 0; + for (unsigned int i=0 ; i<v_event.size() ; i++) + { + v_event[i].siglock->readerIn(); + if (v_event[i].event_id == SUB_ERR && !v_event[i].stopped) + { + nb++; + } + v_event[i].siglock->readerOut(); + } + return nb; +} +//============================================================================= +/** + * build a list of signal to set HDB device property + */ +//============================================================================= +void event_table::put_signal_property() +{ + int act=action.load(); + DEBUG_STREAM << "event_table::"<<__func__<<": entering action=" << act << endl; + + if (act>NOTHING) + { + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->put_signal_property(); + int expected=UPDATE_PROP; + action.compare_exchange_strong(expected, NOTHING); //if it is UPDATE_PROP, then change to NOTHING + } + DEBUG_STREAM << "event_table::"<<__func__<<": exiting action=" << action.load() << endl; +} +//============================================================================= +/** + * build a list of signal to set HDB device property + */ +//============================================================================= +void event_table::check_signal_property() +{ + int act=action.load(); + DEBUG_STREAM << "event_table::"<<__func__<<": entering action=" << act << endl; + if (act>NOTHING) + return; + if (static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->check_signal_property()) + { + int expected=NOTHING; + action.compare_exchange_strong(expected, UPDATE_PROP); //if it is NOTHING, then change to UPDATE_PROP + } + DEBUG_STREAM << "event_table::"<<__func__<<": exiting action=" << action.load() << endl; +} + + +/* + * EventCallBack class methods + */ +EventCallBack::EventCallBack(Tango::DeviceImpl *s):Tango::LogAdapter(s) +{ + //e_ptr = NULL; + mydev = s; +} + +EventCallBack::~EventCallBack(void) +{ + //e_ptr = NULL; +} + +void EventCallBack::push_event(Tango::EventData* ev) +{ + string temp_name; + bei_t e; + e.ex_reason = string(""); + e.ex_desc = string(""); + e.ex_origin = string(""); + try { + //e.errors = ev->errors; + e.quality = Tango::ATTR_VALID; + //cout << "EVENT="<<ev->attr_name<<" quality="<<e.quality<<endl; + if (!ev->err) { + e.quality = (int)ev->attr_value->get_quality(); +#if 0//TANGO_VER >= 711 + string ev_name_str(ev->attr_name); + string::size_type pos = ev_name_str.find("tango://"); + if (pos != string::npos) + { + pos = ev_name_str.find('/',8); + ev_name_str = ev_name_str.substr(pos + 1); + } + e.ev_name = ev_name_str.c_str(); +#else + e.ev_name = ev->attr_name; +#endif + e.ts = ev->attr_value->time; + extract_values(ev->attr_value, e.value, e.value_string, e.type, e.read_size); + } else { + e.quality = Tango::ATTR_INVALID; +#if 0//TANGO_VER >= 711 + string ev_name_str(ev->attr_name); + string::size_type pos = ev_name_str.find("tango://"); + if (pos != string::npos) + { + pos = ev_name_str.find('/',8); + ev_name_str = ev_name_str.substr(pos + 1); + } + temp_name = ev_name_str.c_str() + string(".") + ev->event; +#else + temp_name = ev->attr_name + string(".") + ev->event; //TODO: BUG IN TANGO: part of attr_name after first dot continues in field event +#endif + size_t pos_change = temp_name.find(".change"); + if(pos_change != string::npos) + { + temp_name = temp_name.substr(0,pos_change); + } + ostringstream o; + o << "Tango error for '" << temp_name << "'=" << ev->errors[0].desc.in(); + e.ev_name = temp_name; + e.type = TYPE_TANGO_ERR; + //e.ev_name = INTERNAL_ERROR; + //e.type = -1; + e.msg = o.str(); + e.msg = std::regex_replace(e.msg, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " " + } + } + catch (string &err) { + e.msg = err + " for event '" + ev->attr_name + "'"; + e.ev_name = ev->attr_name; + e.type = TYPE_GENERIC_ERR; + //e.value.i = 0; + e.ts = gettime(); + //cerr << o.str() << endl; + } catch(Tango::DevFailed& Terr) + { + ostringstream o; + o << "Event exception for'" \ + << ev->attr_name << "' error=" << Terr.errors[0].desc; + e.ev_name = ev->attr_name; + e.type = TYPE_GENERIC_ERR; + //e.value.i = 0; + e.ts = gettime(); + e.msg = o.str(); + e.msg = std::regex_replace(e.msg, std::regex(R"((\n)|(\r)|(\t)|(\0))"), " "); //match raw string "\n" or "\t" and replace with " " + } + catch (...) { + ostringstream o; + o << "Generic Event exception for'" \ + << ev->attr_name << "'"; + e.ev_name = ev->attr_name; + e.type = TYPE_GENERIC_ERR; + //e.value.i = 0; + e.ts = gettime(); + e.msg = o.str(); + //cerr << o.str() << endl; + } + static_cast<AlarmHandler_ns::AlarmHandler *>(mydev)->evlist.push_back(e); +} /* push_event() */ + +void EventCallBack::extract_values(Tango::DeviceAttribute *attr_value, vector<double> &val, string &val_string, int &type, int &read_size) +{ + Tango::DevState stval; + vector<Tango::DevState> v_st; + vector<Tango::DevULong> v_ulo; + vector<Tango::DevUChar> v_uch; + vector<Tango::DevShort> v_sh; + vector<Tango::DevUShort> v_ush; + vector<Tango::DevLong> v_lo; + vector<Tango::DevDouble> v_do; + vector<Tango::DevFloat> v_fl; + vector<Tango::DevBoolean> v_bo; + vector<Tango::DevLong64> v_lo64; + vector<Tango::DevULong64> v_ulo64; + vector<Tango::DevEnum> v_enum; + vector<string> v_string; + val_string = string(""); + + //Tango::AttributeDimension attr_w_dim; + Tango::AttributeDimension attr_r_dim; + + //attr_value->reset_exceptions(Tango::DeviceAttribute::isempty_flag); //disable is_empty exception //commented to throw exceptions if empty + if(!attr_value->is_empty()) + { + //attr_w_dim = data->attr_value->get_w_dimension(); + attr_r_dim = attr_value->get_r_dimension(); + } + else + { + attr_r_dim.dim_x = 0; + //attr_w_dim.dim_x = 0; + attr_r_dim.dim_y = 0; + //attr_w_dim.dim_y = 0; + } + read_size = attr_r_dim.dim_x; + if(attr_r_dim.dim_y > 1) + read_size *= attr_r_dim.dim_y; + + if (attr_value->get_type() == Tango::DEV_UCHAR) { + *(attr_value) >> v_uch; + for(vector<Tango::DevUChar>::iterator it = v_uch.begin(); it != v_uch.end(); it++) + val.push_back((double)(*it)); //convert all to double + type = Tango::DEV_UCHAR; + } else if (attr_value->get_type() == Tango::DEV_SHORT) { + *(attr_value) >> v_sh; + for(vector<Tango::DevShort>::iterator it = v_sh.begin(); it != v_sh.end(); it++) + val.push_back((double)(*it)); //convert all to double + type = Tango::DEV_SHORT; + } else if (attr_value->get_type() == Tango::DEV_USHORT) { + *(attr_value) >> v_ush; + for(vector<Tango::DevUShort>::iterator it = v_ush.begin(); it != v_ush.end(); it++) + val.push_back((double)(*it)); //convert all to double + type = Tango::DEV_USHORT; + } else if (attr_value->get_type() == Tango::DEV_LONG) { + *(attr_value) >> v_lo; + for(vector<Tango::DevLong>::iterator it = v_lo.begin(); it != v_lo.end(); it++) + val.push_back((double)(*it)); //convert all to double + type = Tango::DEV_LONG; + } else if (attr_value->get_type() == Tango::DEV_STATE) { + //*(attr_value) >> v_st; //doesn't work in tango 5 + *(attr_value) >> stval; + v_st.push_back(stval); + for(vector<Tango::DevState>::iterator it = v_st.begin(); it != v_st.end(); it++) + val.push_back((double)(*it)); //convert all to double + type = Tango::DEV_STATE; +#if 1//TANGO_VER >= 600 + } else if (attr_value->get_type() == Tango::DEV_ULONG) { + *(attr_value) >> v_ulo; + for(vector<Tango::DevULong>::iterator it = v_ulo.begin(); it != v_ulo.end(); it++) + val.push_back((double)(*it)); //convert all to double + type = Tango::DEV_ULONG; +#endif //TANGO_VER >= 600 + } else if (attr_value->get_type() == Tango::DEV_DOUBLE) { + *(attr_value) >> v_do; + for(vector<Tango::DevDouble>::iterator it = v_do.begin(); it != v_do.end(); it++) + val.push_back((double)(*it)); //convert all to double + type = Tango::DEV_DOUBLE; + } else if (attr_value->get_type() == Tango::DEV_FLOAT) { + *(attr_value) >> v_fl; + for(vector<Tango::DevFloat>::iterator it = v_fl.begin(); it != v_fl.end(); it++) + val.push_back((double)(*it)); //convert all to double + type = Tango::DEV_FLOAT; + } else if (attr_value->get_type() == Tango::DEV_BOOLEAN) { + *(attr_value) >> v_bo; + for(vector<Tango::DevBoolean>::iterator it = v_bo.begin(); it != v_bo.end(); it++) + val.push_back((double)(*it)); //convert all to double + type = Tango::DEV_BOOLEAN; + } else if (attr_value->get_type() == Tango::DEV_LONG64) { + *(attr_value) >> v_lo64; + for(vector<Tango::DevLong64>::iterator it = v_lo64.begin(); it != v_lo64.end(); it++) + val.push_back((double)(*it)); //convert all to double + type = Tango::DEV_LONG64; + } else if (attr_value->get_type() == Tango::DEV_ULONG64) { + *(attr_value) >> v_ulo64; + for(vector<Tango::DevULong64>::iterator it = v_ulo64.begin(); it != v_ulo64.end(); it++) + val.push_back((double)(*it)); //convert all to double + type = Tango::DEV_ULONG64; + } else if (attr_value->get_type() == Tango::DEV_ENUM) { + *(attr_value) >> v_enum; + for(vector<Tango::DevEnum>::iterator it = v_enum.begin(); it != v_enum.end(); it++) + val.push_back((double)(*it)); //convert all to double + type = Tango::DEV_ENUM; + } else if (attr_value->get_type() == Tango::DEV_STRING) { + *(attr_value) >> v_string; + val_string = *(v_string.begin()); //TODO: support string spectrum attrbutes + type = Tango::DEV_STRING; + } + else { + ostringstream o; + o << "unknown type"; + throw o.str(); + } +} + +/*void EventCallBack::init(event_list* e) +{ + //e_ptr = e; +}*/ + + +Tango::TimeVal gettime(void) +{ + struct timeval tv; + struct timezone tz; + Tango::TimeVal t; + + gettimeofday(&tv, &tz); + t.tv_sec = tv.tv_sec; + t.tv_usec = tv.tv_usec; + t.tv_nsec = 0; + return t; +} + +/* EOF */