Skip to content
Snippets Groups Projects
AlarmHandler.cpp 201 KiB
Newer Older
				attr_alarmNormal_read[normalAlarms_sz] = c_normalAlarms_read[normalAlarms_sz];*/
				//attr_alarmNormal_read[normalAlarms_sz] = CORBA::string_dup(ai->second.name.c_str());
				almstate = "NORM";
				silencedAlarms_read[silencedAlarms_sz] = ai->second.name;
				attr_alarmSilenced_read[silencedAlarms_sz] = const_cast<char*>(silencedAlarms_read[silencedAlarms_sz].c_str());
				/*strcpy(c_silencedAlarms_read[silencedAlarms_sz], ai->second.name.c_str());
				attr_alarmSilenced_read[silencedAlarms_sz] = c_silencedAlarms_read[silencedAlarms_sz];*/
				//attr_alarmSilenced_read[silencedAlarms_sz] = CORBA::string_dup(ai->second.name.c_str());

		ostringstream tmp_ex;
		//tmp_ex.str("");
		if(ai->second.ex_reason.length() > 0 || ai->second.ex_desc.length() > 0 || ai->second.ex_origin.length() > 0)
		{
			tmp_ex << "{\"Reason\":\"" << ai->second.ex_reason << "\",\"Desc\":\"" << ai->second.ex_desc << "\",\"Origin\":\"" << ai->second.ex_origin << "\"}";
			DEBUG_STREAM << __func__ << ": " << tmp_ex.str();
			if(almstate != "SHLVD" && almstate != "OOSRV")
			{
				almstate = "ERROR";
			}
		}

		tm time_tm;
		time_t time_sec= ai->second.ts.tv_sec;
		//gmtime_r(&time_sec,&time_tm); //-> UTC
		localtime_r(&time_sec,&time_tm);
		char time_buf[64];
		strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
		alm_summary << KEY(VALUE_KEY) << almstate << SEP;	//TODO: string or enum value?
		alm_summary << KEY(LEVEL_KEY) << ai->second.lev << SEP;
		alm_summary << KEY(ALARM_TIME_KEY) << time_buf << "." << ai->second.ts.tv_usec << SEP;
		alm_summary << KEY(FORMULA_KEY) << ai->second.formula << SEP;
		alm_summary << KEY(MESSAGE_KEY) << ai->second.msg;	//TODO: escape ';'
#else
		alm_summary += string(KEY(VALUE_KEY)) + almstate + SEP;	//TODO: string or enum value?
		alm_summary += KEY(LEVEL_KEY) + ai->second.lev + SEP;
		stringstream sval;
		sval << time_buf << "." << ai->second.ts.tv_usec;
		alm_summary += KEY(ALARM_TIME_KEY) + sval.str() + SEP;
		alm_summary += KEY(FORMULA_KEY) + ai->second.formula + SEP;
		alm_summary += KEY(MESSAGE_KEY) + ai->second.msg;	//TODO: escape ';'
		alm_summary << KEY(ACKNOWLEDGED_KEY) << (ai->second.ack== ACK ? 1 : 0) << SEP;	//TODO: 1/0 or ACK, NOT_ACK ?
		alm_summary << KEY(ENABLED_KEY) << (ai->second.enabled ? 1 : 0) << SEP;
		alm_summary << KEY(SHELVED_KEY) << (ai->second.shelved ? 1 : 0) << SEP;
		alm_summary << KEY(GROUP_KEY) << ai->second.grp2str() << SEP;
		alm_summary << KEY(ON_COUNTER_KEY) << ai->second.on_counter << SEP;
		alm_summary << KEY(OFF_COUNTER_KEY) << ai->second.off_counter << SEP;
		alm_summary << KEY(FREQ_COUNTER_KEY) << ai->second.freq_counter << SEP;
		alm_summary << KEY(QUALITY_KEY) << ai->second.quality << SEP;
		alm_summary += string(KEY(ACKNOWLEDGED_KEY)) + (ai->second.ack== ACK ? "1" : "0") + SEP;	//TODO: 1/0 or ACK, NOT_ACK ?
		alm_summary += string(KEY(ENABLED_KEY)) + (ai->second.enabled ? "1" : "0") + SEP;
		alm_summary += string(KEY(SHELVED_KEY)) + (ai->second.shelved ? "1" : "0") + SEP;
		alm_summary += KEY(GROUP_KEY) + ai->second.grp2str() + SEP;
		sval.str("");
		sval << ai->second.on_counter;
		alm_summary += KEY(ON_COUNTER_KEY) + sval.str() + SEP;
		sval.str("");
		sval << ai->second.off_counter;
		alm_summary += KEY(OFF_COUNTER_KEY) + sval.str() + SEP;
		sval.str("");
		sval << ai->second.freq_counter;
		alm_summary += KEY(FREQ_COUNTER_KEY) + sval.str() + SEP;
		sval.str("");
		sval << ai->second.quality;
		alm_summary += KEY(QUALITY_KEY) + sval.str() + SEP;
#endif
		alm_summary << KEY(EXCEPTION_KEY) << tmp_ex.str() << SEP;
#else
		alm_summary += KEY(EXCEPTION_KEY) + tmp_ex.str() + SEP;
#endif
#ifndef ALM_SUM_STR
		alm_summary << KEY(SILENT_TIME_REMAINING_KEY) << ai->second.silenced << SEP;
#else
		sval.str("");
		sval << ai->second.silenced;
		alm_summary += KEY(SILENT_TIME_REMAINING_KEY) + sval.str() + SEP;
		attr_alarmFrequency_read[listAlarms_sz] = ai->second.freq_counter;
		listAlarms_read[listAlarms_sz] = ai->second.name;
		attr_alarmList_read[listAlarms_sz] = const_cast<char*>(listAlarms_read[listAlarms_sz].c_str());
		/*strcpy(c_listAlarms_read[listAlarms_sz], ai->second.name.c_str());
		attr_alarmList_read[listAlarms_sz] = c_listAlarms_read[listAlarms_sz];*/
		//attr_alarmList_read[listAlarms_sz] = CORBA::string_dup(ai->second.name.c_str());
		listAlarms_sz++;

		if(!is_audible && ai->second.is_new && ai->second.silenced <= 0 && ai->second.enabled && !ai->second.shelved)
			is_audible = true;
		alm_summary << KEY(AUDIBLE_KEY) << (is_audible ? 1 : 0) << SEP;
		alm_summary << KEY(ATTR_VALUES_KEY) << ai->second.attr_values << SEP;
#else
		alm_summary += string(KEY(AUDIBLE_KEY)) + (is_audible ? "1" : "0") + SEP;
		alm_summary += KEY(ATTR_VALUES_KEY) + ai->second.attr_values + SEP;
		if (ai->second.stat == S_ALARM && ai->second.enabled && !ai->second.shelved) {
			/*
			 * alarm status is S_ALARM
			 */
			alarmedlock->readerIn();
			aid = find(alarmed.begin(), alarmed.end(),ai->second.name);
			if (aid != alarmed.end()) {
				/*
				 * found, change stat only if switching from
				 * S_NORMAL to S_ALARM status
				 */
				//cout << "read_attr(): S_ALARM: found: " << aid->name << endl;
				if (aid->stat == S_NORMAL) {
					aid->stat = S_ALARM;
					aid->ack = NOT_ACK;
					aid->ts = ai->second.ts;
					aid->msg = ai->second.msg;
				}
				aid->grp = ai->second.grp;
				aid->lev = ai->second.lev;
				aid->is_new = ai->second.is_new;			//copy is_new state
				//ai->second.is_new = 0;						//and set state as not more new //12-06-08: StopNew command set it to 0
				aid->on_counter = ai->second.on_counter;
				aid->off_counter = ai->second.off_counter;
				aid->ack = ai->second.ack;					//if already acknowledged but has arrived new alarm ack is reset
				aid->silenced = ai->second.silenced;		//update silenced from alarm table (maybe not necessary)
				aid->silent_time = ai->second.silent_time;	//if already alarmed and not saved correctly in properties needed to update
			} else {
				/*
				 * not found: new "alarmed" item
				 */
				DEBUG_STREAM << __func__<<": S_ALARM: pushing new alarm: " \
						 				 << ai->second.name << "\t" << ai->second.stat << endl;
				alarmedlock->readerOut();
				alarmedlock->writerIn();
				alarmed.push_back(ai->second);
				//ai->second.is_new = 0;						//set state as not more new		//12-06-08: StopNew command set it to 0
				alarmedlock->writerOut();
				alarmedlock->readerIn();
			}
			alarmedlock->readerOut();
		} else if (ai->second.stat == S_NORMAL) {
			/*
			 * alarm status is S_NORMAL
			 */
			alarmedlock->readerIn();
			aid = find(alarmed.begin(), alarmed.end(), ai->second.name);
			if (aid != alarmed.end()) {
				/*
				 * found, as it should;
				 * switching from S_ALARM to S_NORMAL
				 */
				aid->stat = S_NORMAL;
				aid->ts = ai->second.ts;
				//aid->msg = " ";						/* no message again */
				aid->msg =ai->second.msg;
				aid->grp = ai->second.grp;
				aid->lev = ai->second.lev;
				aid->on_counter = ai->second.on_counter;
				aid->off_counter = ai->second.off_counter;
				aid->ack = ai->second.ack;					//if already acknowledged but has arrived new alarm ack is reset
				aid->is_new = ai->second.is_new;			//copy is_new state
				aid->silenced = ai->second.silenced;		//update silenced from alarm table (maybe not necessary)
				aid->silent_time = ai->second.silent_time;	//if already alarmed and not saved correctly in properties needed to update
				//ai->second.is_new = 0;						//and set state as not more new		//12-06-08: StopNew command set it to 0
				if (aid->ack == ACK) {
					if (aid->done) {
						/*
					 	 * if already ACKnowledged and visualized
					 	 * remove from "alarmed" list
					 	 */
						DEBUG_STREAM << __func__<<": S_NORMAL: " << aid->name \
								 				 << " ACKnowledged: removing" << endl;
						alarmedlock->readerOut();
						alarmedlock->writerIn();
						alarmed.erase(aid);
						alarmedlock->writerOut();
						alarmedlock->readerIn();
					} else {
						aid->done = true;
					}
				}	 /* if */
			}  /* if */
			alarmedlock->readerOut();
		}  /* if else if */
		alarmSummary_read[alarmSummary_sz] = alm_summary.str();
#else
		alarmSummary_read[alarmSummary_sz] = alm_summary;
#endif
		attr_alarmSummary_read[alarmSummary_sz] = const_cast<char*>(alarmSummary_read[alarmSummary_sz].c_str());
		/*strncpy(c_alarmSummary_read[alarmSummary_sz], alm_summary.c_str(), MAX_SUMMARY-1);
		c_alarmSummary_read[alarmSummary_sz][MAX_SUMMARY-1]=0;
		attr_alarmSummary_read[alarmSummary_sz] = c_alarmSummary_read[alarmSummary_sz];*/
		//attr_alarmSummary_read[alarmSummary_sz] = CORBA::string_dup(alm_summary.c_str());
		alarmSummary_sz++;
	*attr_alarmAudible_read = is_audible;
	prepare_alm_mtx->unlock();
	vector<string> tmp_alarm_table;
	string is_new;
	ostringstream os1;
	/*os1.clear();
	os1 << header << "\t" << alarmed.size() << ends;*/
	//tmp_alarm_table.push_back(os1.str());
	alarmedlock->readerIn();
	if (alarmed.empty() == false) {
		for (aid = alarmed.begin(); aid != alarmed.end(); aid++) {
			if(aid->silenced > 0)
			{
				Tango::TimeVal now = gettime();
				double dnow = now.tv_sec + ((double)now.tv_usec) / 1000000;
				double dsilent = aid->ts_time_silenced.tv_sec + ((double)aid->ts_time_silenced.tv_usec) / 1000000;
				double dminutes = (dnow - dsilent)/60;
				//silenced already calculated in alarm_table::update, but here updated for panel also if state not changed:
				//to see minutes countdown
				if(dminutes < aid->silent_time)
					aid->silenced = aid->silent_time - floor(dminutes);
			}
			ostringstream os;
			os.clear();
			is_new.clear();
			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;
			tmp_alarm_table.push_back(os.str());
		}
	}
	alarmedlock->readerOut();
	dslock->writerIn();
	int i;
// 	for (i = ds_num - 1; i >= 0; i--) {
// 		CORBA::string_free(ds[i]);
// 		//ds_num--;
// 	}
/*	for (i = 0; i < ds_num; i++) {
		if (ds[i] != 0) {
			CORBA::string_free(ds[i]);
			ds[i] = 0;
		}
	}*/
	ds_num = tmp_alarm_table.size();
	if(ds_num > MAX_ALARMS)
		ds_num = MAX_ALARMS;
	for (i = 0; i < ds_num; i++) {
		//ds[i] = CORBA::string_dup(tmp_alarm_table[i].c_str());
		size_t len=tmp_alarm_table[i].length();
		if(len >= 10124) len = 10124-1;
		strncpy(dss[i],tmp_alarm_table[i].c_str(), len);
		dss[i][len]=0;
	}
	if(ds_num == 0)
	{
		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 ";
		//ds[0] = CORBA::string_dup(os1.str().c_str());
		size_t len=os1.str().length();
		if(len >= 10124) len = 10124-1;
		strncpy(dss[i],os1.str().c_str(), len);
		dss[i][len]=0;
	}
	dslock->writerOut();
}

//=============================================================================
string AlarmHandler::remove_domain(string str)
{
	string::size_type	end1 = str.find(".");
	if (end1 == string::npos)
	{
		return str;
	}
	else
	{
		string::size_type	start = str.find("tango://");
		if (start == string::npos)
		{
			start = 0;
		}
		else
		{
			start = 8;	//tango:// len
		}
		string::size_type	end2 = str.find(":", start);
		if(end2 == string::npos) //not fqdn, so no tango host in the name
			return str;
		if(end1 > end2)	//'.' not in the tango host part
			return str;
		string th = str.substr(0, end1);
		th += str.substr(end2, str.size()-end2);
		return th;
	}
}
//=============================================================================
//=============================================================================
bool AlarmHandler::compare_without_domain(string str1, string str2)
{
	string str1_nd = remove_domain(str1);
	string str2_nd = remove_domain(str2);
	return (str1_nd==str2_nd);
}

//=============================================================================
//=============================================================================
void AlarmHandler::put_signal_property()
{
	vector<string> prop;
	alarms.vlock->readerIn();
	alarm_container_t::iterator it;
	for(it = alarms.v_alarm.begin(); it != alarms.v_alarm.end(); it++)
	{
		prop.push_back(it->first);

		string conf_str;
		it->second.confstr(conf_str);
		map<string,string>::iterator itmap = saved_alarms.find(it->first);
		if(itmap == saved_alarms.end())
		{
			DEBUG_STREAM << __func__<<": SAVING " << it->first << endl;
			alarms.save_alarm_conf_db(it->second.attr_name, it->second.name, it->second.stat, it->second.ack, it->second.enabled,
				it->second.formula, it->second.on_delay, it->second.off_delay, it->second.grp2str(), it->second.lev, it->second.msg, it->second.cmd_name_a, it->second.cmd_name_n, it->second.silent_time);
			saved_alarms.insert(make_pair(it->first,conf_str));

		}
		else
		{
			string conf_string;
			it->second.confstr(conf_string);
			//alarm found but configuration changed
			if(conf_string != itmap->second)
			{
				DEBUG_STREAM << __func__<<": UPDATING " << it->first << endl;
				alarms.save_alarm_conf_db(it->second.attr_name, it->second.name, it->second.stat, it->second.ack, it->second.enabled,
					it->second.formula, it->second.on_delay, it->second.off_delay, it->second.grp2str(), it->second.lev, it->second.msg, it->second.cmd_name_a, it->second.cmd_name_n, it->second.silent_time);
				itmap->second = conf_string;
			}
		}
	}
	map<string, string>::iterator it2=saved_alarms.begin();
	while(it2 != saved_alarms.end())
	{
		alarm_container_t::iterator found = alarms.v_alarm.find(it2->first);
		if (found == alarms.v_alarm.end())
		{
			DEBUG_STREAM << __func__<<": DELETING " << it2->first << endl;
			alarms.delete_alarm_conf_db(it2->first);
			saved_alarms.erase(it2);
		}
		if(it2 != saved_alarms.end())
			it2++;
	}
	alarms.vlock->readerOut();


	Tango::DbData	data;
	data.push_back(Tango::DbDatum("AlarmList"));
	data[0]  <<  prop;
#ifndef _USE_ELETTRA_DB_RW
#else
	//save properties using host_rw e port_rw to connect to database
	if(host_rw != "")
		db = new Tango::Database(host_rw,port_rw);
	else
		db = new Tango::Database();
	DEBUG_STREAM << __func__<<": connecting to db "<<host_rw<<":"<<port_rw;
#endif
	}
	catch(Tango::DevFailed &e)
	{
		stringstream o;
		o << " Error connecting to Tango DataBase='" << e.errors[0].desc << "'";
		WARN_STREAM << __FUNCTION__<< o.str();
		return;
	}
	try
	{
		DECLARE_TIME_VAR	t0, t1;
		GET_TIME(t0);
		db->set_timeout_millis(10000);
		db->put_device_property(get_name(), data);
		GET_TIME(t1);
		DEBUG_STREAM << __func__ << ": saving properties size="<<prop.size()<<" -> " << ELAPSED(t0, t1) << " ms" << endl;
	}
	catch(Tango::DevFailed &e)
	{
		stringstream o;
		o << " Error saving properties='" << e.errors[0].desc << "'";
		WARN_STREAM << __FUNCTION__<< o.str();
	}
	delete db;
}
//--------------------------------------------------------
/**
 *	remove a AlarmState dynamic attribute without cleaning DB.
 *
 *  parameter attname: attribute name to be removed.
 */
//--------------------------------------------------------
void AlarmHandler::remove_AlarmState_dynamic_attribute_no_clean_db(string attname)
{
	remove_attribute(attname, true, false);
	map<string,Tango::DevEnum>::iterator ite;
    if ((ite=AlarmState_data.find(attname))!=AlarmState_data.end())
    {
    	DEBUG_STREAM << __func__<<": entering name="<<attname;
		AlarmState_data.erase(ite);
	}
}
/*----- PROTECTED REGION END -----*/	//	AlarmHandler::namespace_ending