Skip to content
Snippets Groups Projects
Alarm.cpp 179 KiB
Newer Older
	/*os1.clear();
	os1 << header << "\t" << alarmed.size() << ends;*/
	//tmp_alarm_table.push_back(os1.str());
	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);
				else
					aid->silenced = 0;
			}
			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->counter << "\t" << aid->lev << "\t" << aid->silenced << "\t" << aid->grp2str() << "\t" << aid->msg << "\t" << is_new << ends;
			tmp_alarm_table.push_back(os.str());
		}
	}		
	if (internal.empty() == false) {
		for (aid = internal.begin(); aid != internal.end(); aid++) {
			
/*			size_t index;
			int count = 1;
			index = aid->stat.find("*");
			if((index != std::string::npos) && (index+1 != std::string::npos))
			{
				
				size_t last = aid->stat.size();
				string str_count= aid->stat.substr(index+1, last - index+1);      
				count = strtol(str_count.c_str(), 0,10); 
			}	
			//do not show internal alarms that have a molteplicity less then errThreshold
			if((aid->msg.find()) && (count < errThreshold))
				continue;*/			
			
			ostringstream os;
			os.clear();
			os << aid->ts.tv_sec << "\t" << aid->ts.tv_usec << "\t" \
			 	 << aid->name << "\t" << aid->stat << "\t" << aid->ack \
				 << "\t" << aid->counter << "\t" << aid->lev << "\t"<< -1/*silenced*/ <<"\t" << aid->grp2str() << "\t" << aid->msg << "\t "<< ends; //TODO: silenced for internal errors?
			tmp_alarm_table.push_back(os.str());
		}
	}
	int i;
	for (i = ds_num - 1; i >= 0; i--) {
		CORBA::string_free(ds[i]);
	}
	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());
	}
	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 "<< ends;
		ds[0] = CORBA::string_dup(os1.str().c_str());
	}
#else
	//bool changed;
	//prepare_alarm_attr(changed);//moved in do_alarm;
#endif
	if(ds_num == 0)
	{
		attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
	}
	else
		attr.set_value(ds, ds_num, 0, false);

	/*----- PROTECTED REGION END -----*/	//	Alarm::read_alarm
}
//--------------------------------------------------------
/**
 *	Read attribute normalAlarms related method
 *	Description: List of alarms in normal state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void Alarm::read_normalAlarms(Tango::Attribute &attr)
{
	DEBUG_STREAM << "Alarm::read_normalAlarms(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(Alarm::read_normalAlarms) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_normalAlarms_read, normalAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	Alarm::read_normalAlarms
}
//--------------------------------------------------------
/**
 *	Read attribute unacknowledgedAlarms related method
 *	Description: List of alarms in unacknowledged state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void Alarm::read_unacknowledgedAlarms(Tango::Attribute &attr)
{
	DEBUG_STREAM << "Alarm::read_unacknowledgedAlarms(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(Alarm::read_unacknowledgedAlarms) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_unacknowledgedAlarms_read, unacknowledgedAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	Alarm::read_unacknowledgedAlarms
}
//--------------------------------------------------------
/**
 *	Read attribute acknowledgedAlarms related method
 *	Description: List of alarms in acknowledged state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void Alarm::read_acknowledgedAlarms(Tango::Attribute &attr)
{
	DEBUG_STREAM << "Alarm::read_acknowledgedAlarms(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(Alarm::read_acknowledgedAlarms) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_acknowledgedAlarms_read, acknowledgedAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	Alarm::read_acknowledgedAlarms
}
//--------------------------------------------------------
/**
 *	Read attribute unacknowledgedNormalAlarms related method
 *	Description: List of alarms in unacknowledged normal state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void Alarm::read_unacknowledgedNormalAlarms(Tango::Attribute &attr)
{
	DEBUG_STREAM << "Alarm::read_unacknowledgedNormalAlarms(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(Alarm::read_unacknowledgedNormalAlarms) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_unacknowledgedNormalAlarms_read, unacknowledgedNormalAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	Alarm::read_unacknowledgedNormalAlarms
}
//--------------------------------------------------------
/**
 *	Read attribute shelvedAlarms related method
 *	Description: List of alarms in shelved state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void Alarm::read_shelvedAlarms(Tango::Attribute &attr)
{
	DEBUG_STREAM << "Alarm::read_shelvedAlarms(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(Alarm::read_shelvedAlarms) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_shelvedAlarms_read, shelvedAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	Alarm::read_shelvedAlarms
}
//--------------------------------------------------------
/**
 *	Read attribute outOfServiceAlarms related method
 *	Description: List of alarms in out of service state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void Alarm::read_outOfServiceAlarms(Tango::Attribute &attr)
{
	DEBUG_STREAM << "Alarm::read_outOfServiceAlarms(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(Alarm::read_outOfServiceAlarms) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_outOfServiceAlarms_read, outOfServiceAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	Alarm::read_outOfServiceAlarms
}
//--------------------------------------------------------
/**
 *	Read attribute silencedAlarms related method
 *	Description: List of alarms in silenced state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void Alarm::read_silencedAlarms(Tango::Attribute &attr)
{
	DEBUG_STREAM << "Alarm::read_silencedAlarms(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(Alarm::read_silencedAlarms) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_silencedAlarms_read, silencedAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	Alarm::read_silencedAlarms
}
//--------------------------------------------------------
/**
 *	Read attribute listAlarms related method
 *	Description: List of all alarms
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void Alarm::read_listAlarms(Tango::Attribute &attr)
{
	DEBUG_STREAM << "Alarm::read_listAlarms(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(Alarm::read_listAlarms) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_listAlarms_read, listAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	Alarm::read_listAlarms
}
//--------------------------------------------------------
/**
 *	Read attribute frequencyAlarms related method
 *	Description: List of frequency of evaluation of all alarms
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void Alarm::read_frequencyAlarms(Tango::Attribute &attr)
{
	DEBUG_STREAM << "Alarm::read_frequencyAlarms(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(Alarm::read_frequencyAlarms) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_frequencyAlarms_read, listAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	Alarm::read_frequencyAlarms
}
//--------------------------------------------------------
/**
 *	Read attribute AlarmState related method
 *	Description: 
 *
 *	Data type:	Tango::DevEnum (AlarmStateEnum)
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void Alarm::read_AlarmState(Tango::Attribute &attr)
{
	DEBUG_STREAM << "Alarm::read_AlarmState(Tango::Attribute &attr) entering... " << endl;
	Tango::DevEnum	*att_value = get_AlarmState_data_ptr(attr.get_name());
	/*----- PROTECTED REGION ID(Alarm::read_AlarmState) ENABLED START -----*/
	string reason("");
	string desc("");
	string origin("");
	int quality = Tango::ATTR_VALID;
#ifndef _RW_LOCK
	alarms.lock();
#else
	alarms.vlock->readerIn();
#endif
	alarm_container_t::iterator it;
	for(it = alarms.v_alarm.begin(); it != alarms.v_alarm.end(); it++)
	{
		if(it->second.attr_name == attr.get_name())
		{
			break;
		}
	}
	if(it != alarms.v_alarm.end())
	{
		reason = it->second.ex_reason;
		desc = it->second.ex_desc;
		origin = it->second.ex_origin;
		quality = it->second.quality;
	}
	DEBUG_STREAM << "Alarm::read_AlarmState: " << attr.get_name() << " desc=" << desc << endl;
#ifndef _RW_LOCK
	alarms.unlock();
#else
	alarms.vlock->readerOut();
#endif
	if(desc.length() > 0)
	{
		Tango::Except::throw_exception(
				reason,
				desc,
				origin, Tango::ERR);
	}
	//	Set the attribute value
	if(quality != Tango::ATTR_VALID)
	{
		timeval now;
		gettimeofday(&now, NULL);
		attr.set_value_date_quality(att_value, now/*TODO timestamp*/, (Tango::AttrQuality)quality);
	}
	else
	{
		attr.set_value(att_value);
	}
	
	/*----- PROTECTED REGION END -----*/	//	Alarm::read_AlarmState
}
//--------------------------------------------------------
/**
 *	Read attribute AlarmFormula related method
 *	Description: 
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void Alarm::read_AlarmFormula(Tango::Attribute &attr)
{
	DEBUG_STREAM << "Alarm::read_AlarmFormula(Tango::Attribute &attr) entering... " << endl;
	Tango::DevString	*att_value = get_AlarmFormula_data_ptr(attr.get_name());
	/*----- PROTECTED REGION ID(Alarm::read_AlarmFormula) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(att_value);
	
	/*----- PROTECTED REGION END -----*/	//	Alarm::read_AlarmFormula
}
//--------------------------------------------------------
/**
 *	Method      : Alarm::add_dynamic_attributes()
 *	Description : Create the dynamic attributes if any
 *                for specified device.
 */
//--------------------------------------------------------
void Alarm::add_dynamic_attributes()
{
	//	Example to add dynamic attribute:
	//	Copy inside the following protected area to create instance(s) at startup.
	//	add_AlarmState_dynamic_attribute("MyAlarmStateAttribute");
	//	add_AlarmFormula_dynamic_attribute("MyAlarmFormulaAttribute");
	/*----- PROTECTED REGION ID(Alarm::add_dynamic_attributes) ENABLED START -----*/
	
	//	Add your own code to create and add dynamic attributes if any
#ifndef _RW_LOCK
	alarms.lock();
#else
	alarms.vlock->readerIn();
#endif
	if (alarms.v_alarm.empty() == false)
	{
		for (alarm_container_t::iterator i = alarms.v_alarm.begin(); \
			i != alarms.v_alarm.end(); i++)
		{
			add_AlarmState_dynamic_attribute(i->second.attr_name);
			Tango::DevEnum *attr_value = get_AlarmState_data_ptr(i->second.attr_name);
			i->second.attr_value = attr_value;
			i->second.attr_name_formula = i->second.attr_name + string("Formula");
			add_AlarmFormula_dynamic_attribute(i->second.attr_name_formula);
			Tango::DevString *attr_value_formula = get_AlarmFormula_data_ptr(i->second.attr_name_formula);
			*attr_value_formula = CORBA::string_dup(i->second.formula.c_str());
			i->second.attr_value_formula = attr_value_formula;
		}
	}
#ifndef _RW_LOCK
	alarms.unlock();
#else
	alarms.vlock->readerOut();
#endif
	
	/*----- PROTECTED REGION END -----*/	//	Alarm::add_dynamic_attributes
}

//--------------------------------------------------------
/**
 *	Command Ack related method
 *	Description: Alarm acknowledge
 *
 *	@param argin String array containing the alarms to be acknowledged
 */
//--------------------------------------------------------
void Alarm::ack(const Tango::DevVarStringArray *argin)
{
	DEBUG_STREAM << "Alarm::Ack()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(Alarm::ack) ENABLED START -----*/
	
	//	Add your own code
	vector<string> str;
	str << (*argin);
	vector<string>::iterator si;
	
	for (si = str.begin(); si != str.end(); si++) {
#ifndef _RW_LOCK
		alarms.lock();
#else
		alarms.vlock->readerIn();
#endif
		alarmedlock->readerIn();
		vector<alarm_t>::iterator found = \
		find(alarmed.begin(), alarmed.end(), *si);
		if (found != alarmed.end()) 
		{
			alarm_container_t::iterator i = alarms.v_alarm.find(*si);
				INFO_STREAM << __func__ << ": alarm '" << *si << "' not found";
				alarmedlock->readerOut();
#ifndef _RW_LOCK
				alarms.unlock();
#else
				alarms.vlock->readerOut();
#endif
				continue;
			}
			if(!i->second.enabled || i->second.shelved)
			{
				DEBUG_STREAM << __func__ << ": alarm '" << *si << "' not enabled";
				alarmedlock->readerOut();
#ifndef _RW_LOCK
				alarms.unlock();
#else
				alarms.vlock->readerOut();
#endif
				continue;

			//update alarm ack in alarm table
			i->second.ack = ACK;
			//update alarm status from alarm table
			found->stat = i->second.stat;

				Tango::DevEnum *attr_value = get_AlarmState_data_ptr(i->second.attr_name);
				if(!i->second.enabled)
					*attr_value = _OOSRV;
				else if(i->second.shelved && i->second.silenced > 0)
					*attr_value = _SHLVD;
				else if((i->second.stat == S_NORMAL) && i->second.ack == ACK)
					*attr_value = _NORM;
				else if((i->second.stat == S_ALARM) && i->second.ack == NOT_ACK)
					*attr_value = _UNACK;
				else if((i->second.stat == S_ALARM) && i->second.ack == ACK)
					*attr_value = _ACKED;
				else if((i->second.stat == S_NORMAL) && i->second.ack == NOT_ACK)
					*attr_value = _RTNUN;
				try
				{	//DevFailed for push events
					if(i->second.ex_reason.length() == 0)
					{
						timeval now;
						gettimeofday(&now, NULL);
						push_change_event(i->second.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)i->second.quality, 1/*size*/, 0, false);
						push_archive_event(i->second.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)i->second.quality, 1/*size*/, 0, false);
					}
					else
					{
						Tango::DevErrorList errors(1);
						errors.length(1);
						errors[0].desc = CORBA::string_dup(i->second.ex_desc.c_str());
						errors[0].severity = Tango::ERR;
						errors[0].reason = CORBA::string_dup(i->second.ex_reason.c_str());
						errors[0].origin = CORBA::string_dup(i->second.ex_origin.c_str());
						Tango::DevFailed except(errors);
						push_change_event(i->second.attr_name, &except);
						push_archive_event(i->second.attr_name, &except);
					}
				} catch(Tango::DevFailed & ex)
				{
					WARN_STREAM << "Alarm::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
				}
		}
		alarmedlock->readerOut();
#ifndef _RW_LOCK
		alarms.unlock();
#else
		alarms.vlock->readerOut();
#endif
	}
	/*
	 * remove S_NORMAL status ACKnowledged alarms
	 */
	alarm_t to_be_removed;
	to_be_removed.name = "";
	to_be_removed.formula = "";
	to_be_removed.stat = S_NORMAL;
	to_be_removed.ack = ACK;
	bool go = true;
	while (go) {
		alarmedlock->writerIn();
		vector<alarm_t>::iterator found = \
				find(alarmed.begin(), alarmed.end(), to_be_removed);
		if (found != alarmed.end()) {
			DEBUG_STREAM << "Alarm::ack(): " << found->name \
					 				 << " S_NORMAL and ACK, removing"  << endl;
			alarmed.erase(found);
		} else {
			go = false;
		}
		alarmedlock->writerOut();
	}

	prepare_alarm_attr();
	try
	{
		if(ds_num == 0)
		{
			//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
			struct timeval now;
			gettimeofday(&now,NULL);
			push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
		}
		else
			//attr.set_value(ds, ds_num, 0, false);
			push_change_event("alarm",ds, ds_num, 0, false);
		}
		push_change_event("normalAlarms",&attr_normalAlarms_read[0], normalAlarms_sz);
		push_change_event("unacknowledgedAlarms",&attr_unacknowledgedAlarms_read[0], unacknowledgedAlarms_sz);
		push_change_event("acknowledgedAlarms",&attr_acknowledgedAlarms_read[0], acknowledgedAlarms_sz);
		push_change_event("unacknowledgedNormalAlarms",&attr_unacknowledgedNormalAlarms_read[0], unacknowledgedNormalAlarms_sz);
		push_change_event("shelvedAlarms",&attr_shelvedAlarms_read[0], shelvedAlarms_sz);
		push_change_event("outOfServiceAlarms",&attr_outOfServiceAlarms_read[0], outOfServiceAlarms_sz);
		push_change_event("silencedAlarms",&attr_silencedAlarms_read[0], silencedAlarms_sz);
		push_change_event("listAlarms",&attr_listAlarms_read[0], listAlarms_sz);
		push_change_event("frequencyAlarms",&attr_frequencyAlarms_read[0], listAlarms_sz);
		push_change_event("audibleAlarm",attr_audibleAlarm_read);
		push_archive_event("normalAlarms",&attr_normalAlarms_read[0], normalAlarms_sz);
		push_archive_event("unacknowledgedAlarms",&attr_unacknowledgedAlarms_read[0], unacknowledgedAlarms_sz);
		push_archive_event("acknowledgedAlarms",&attr_acknowledgedAlarms_read[0], acknowledgedAlarms_sz);
		push_archive_event("unacknowledgedNormalAlarms",&attr_unacknowledgedNormalAlarms_read[0], unacknowledgedNormalAlarms_sz);
		push_archive_event("shelvedAlarms",&attr_shelvedAlarms_read[0], shelvedAlarms_sz);
		push_archive_event("outOfServiceAlarms",&attr_outOfServiceAlarms_read[0], outOfServiceAlarms_sz);
		push_archive_event("silencedAlarms",&attr_silencedAlarms_read[0], silencedAlarms_sz);
		push_archive_event("listAlarms",&attr_listAlarms_read[0], listAlarms_sz);
		push_archive_event("frequencyAlarms",&attr_frequencyAlarms_read[0], listAlarms_sz);
		push_archive_event("audibleAlarm",attr_audibleAlarm_read);

	} catch(Tango::DevFailed& e)
	{
		ostringstream err;
		err << "error pushing alarm change event err=" << e.errors[0].desc;
		INFO_STREAM << __func__<<": " << err.str() << endl;
	}

	/*----- PROTECTED REGION END -----*/	//	Alarm::ack
}
//--------------------------------------------------------
/**
 *	Command Load related method
 *	Description: Load a new alarm.
 *
 *	@param argin Alarm entry
 */
//--------------------------------------------------------
void Alarm::load(Tango::DevString argin)
{
	DEBUG_STREAM << "Alarm::Load()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(Alarm::load) ENABLED START -----*/
	
	//	Add your own code
	string s;
	alarm_t alm;
	vector<string> evn;
	
	s = argin;
	//std::transform(s.begin(), s.end(), s.begin(), (int(*)(int))tolower);		//transform to lowercase
	Tango::TimeVal ts = gettime();
	try {
		load_alarm(s, alm, evn);
	} catch(Tango::DevFailed& e)
	{
		ostringstream err;
		err << "error loading alarm=" << alm.name << " , " << e.errors[0].desc << ends;
		WARN_STREAM << "Alarm::load(): " << err.str() << endl;
		Tango::Except::throw_exception( \
				(const char*)"Alarm::load()", \
				err.str(), \
				(const char*)"Alarm::load()", Tango::ERR);	
	}
	
	try {
		add_alarm(alm);
	} catch (string& err) {
		WARN_STREAM << "Alarm::load(): " << err << endl;
		Tango::Except::throw_exception( \
				(const char*)"Alarm::load()", \
				(const char*)err.c_str(), \
				(const char*)"Alarm::load()", Tango::ERR);
	}
#if 0
	try
	{
		Tango::Attribute attr = this->get_device_attr()->get_attr_by_name(alm.attr_name.c_str());
		push_att_conf_event(&attr);
	}
	catch(Tango::DevFailed &e)
	{
		ostringstream o;
		o << "Alarm::" << __func__<<": alarm '" << alm.name << "' cannot push att_conf event, err="<<e.errors[0].desc ;
		INFO_STREAM << o.str() << endl;
	}
#endif
	try {
		add_event(alm, evn);
	} catch (string& err) {
		WARN_STREAM << "Alarm::load(): " << err << endl;
#ifndef _RW_LOCK
		alarms.lock();
#else
		alarms.vlock->writerIn();
#endif
		alarm_container_t::iterator i = alarms.v_alarm.find(alm.name);		//look for alarm just added
		if (i != alarms.v_alarm.end())	
			alarms.erase(i);											//and remove from alarm_table
#ifndef _RW_LOCK
		alarms.unlock();
#else
		alarms.vlock->writerOut();
#endif
		Tango::Except::throw_exception( \
				(const char*)"Alarm::load()", \
				(const char*)err.c_str(), \
				(const char*)"Alarm::load()", Tango::ERR);
	}
	alarms.save_alarm_conf_db(alm.attr_name, alm.name, "", "", alm.enabled,		//add new alarm on log before subscribe event
			alm.formula, alm.on_delay, alm.off_delay, alm.grp2str(), alm.lev, alm.msg, alm.cmd_name_a, alm.cmd_name_n, alm.silent_time);	//but if it fails remove it from table
	string conf_str;
	alm.confstr(conf_str);
	saved_alarms.insert(make_pair(alm.attr_name,conf_str));
#ifndef _RW_LOCK
		alarms.lock();
#else
		alarms.vlock->readerIn();
#endif
	alarm_container_t::iterator i = alarms.v_alarm.find(alm.name);
	if(i != alarms.v_alarm.end())
	{
		try {
			add_event(i->second, evn);//moved after events->add
		} catch (string& err) {
			WARN_STREAM << "Alarm::"<<__func__<<": string exception=" << err << endl;
			//TODO: handle error
#if 0
			for(vector<string>::iterator j = evn.begin(); j != evn.end(); j++)
			{
				DEBUG_STREAM << "Alarm::"<<__func__<<": Removing alarm=" << i->second.name << " from event=" << *j << endl;
				vector<event>::iterator k = \
					find(events->v_event.begin(), events->v_event.end(), *j);
				if (k != events->v_event.end())
				{
					k->pop_alarm(i->second.name);		//remove alarm/formula just added to event
					DEBUG_STREAM << "Alarm::"<<__func__<<": Removed!!!! alarm=" << i->second.name << " from event=" << *j << endl;
					if(k->m_alarm.empty())
					{
						events->v_event.erase(k);	//remove event just added to event_table
						DEBUG_STREAM << "Alarm::"<<__func__<<": event=" << *j << " no more used, REMOVED!!!" << endl;
					}
				}
			}
			set_internal_alarm(INTERNAL_ERROR, gettime(), err);
#endif
		}
		catch (Tango::DevFailed &e) {
			WARN_STREAM << "Alarm::"<<__func__<<": Tango exception=" << e.errors[0].desc << endl;
		}


		if(i->second.cmd_name_a.length() > 0)
		{
			try {
				i->second.dp_a = new Tango::DeviceProxy(i->second.cmd_dp_a);
				i->second.dp_a->ping();
				Tango::CommandInfo info = i->second.dp_a->command_query(i->second.cmd_action_a);
				if(info.in_type != Tango::DEV_STRING)
				{
					ostringstream err;
					err << "Error: command " << i->second.cmd_name_a << " does not accept a Tango::DevString as input value" << ends;
					ERROR_STREAM << "Alarm::load(): " << err.str() << endl;
					set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());					
				}
				else
				{
					if(info.in_type == Tango::DEV_STRING)
						i->second.send_arg_a = true;
					else
						i->second.send_arg_a = false;
					DEBUG_STREAM << "Alarm::load(): successfully connected to proxy=" << i->second.cmd_dp_a << " for action=" << i->second.cmd_action_a << endl;
				}
			} catch(Tango::DevFailed& e)
			{
				ostringstream err;
				err << alm.name << ": error connecting to device proxy=" << i->second.cmd_dp_a << ", err=" << e.errors[0].desc << ends;
				WARN_STREAM << "Alarm::load(): " << err.str() << endl;
				set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());
		{
			try {
				i->second.dp_n = new Tango::DeviceProxy(i->second.cmd_dp_n);
				i->second.dp_n->ping();
				Tango::CommandInfo info = i->second.dp_n->command_query(i->second.cmd_action_a);
				if(info.in_type != Tango::DEV_STRING)
				{
					ostringstream err;
					err << "Error: command " << i->second.cmd_name_n << " does not accept a Tango::DevString as input value" << ends;
					ERROR_STREAM << "Alarm::load(): " << err.str() << endl;
					set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());						
				}
				else
				{
					if(info.in_type == Tango::DEV_STRING)
						i->second.send_arg_n = true;
					else
						i->second.send_arg_n = false;
					DEBUG_STREAM << "Alarm::load(): successfully connected to proxy=" << i->second.cmd_dp_n << " for action=" << i->second.cmd_action_n << endl;
				}
			} catch(Tango::DevFailed& e)
			{
				ostringstream err;
				err << alm.name << ": error connecting to device proxy=" << i->second.cmd_dp_n << ", err=" << e.errors[0].desc << ends;
				WARN_STREAM << "Alarm::load(): " << err.str() << endl;
				set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());
			}				
		}
		DEBUG_STREAM << "Alarm::"<<__func__<<": created command proxy, to_be_evaluated=" << (int)alm.to_be_evaluated << endl;
		//TODO: to be moved in subscribe thread after subscription
		//if at least one event was already existing, evaluate formula of just added alarm
		if(i->second.to_be_evaluated)							//TODO: remove this evaluation of the formula that is not necessary
		{
			DEBUG_STREAM << "Alarm::"<<__func__<<": to_be_evaluated!!"  << endl;
			bei_t e;
			e.ev_name = ALARM_THREAD_TO_BE_EVAL;
			e.value.push_back(ALARM_THREAD_TO_BE_EVAL_VALUE);
			e.value.push_back(ALARM_THREAD_TO_BE_EVAL_VALUE);
			evlist.push_back(e);
		}
	}
#ifndef _RW_LOCK
		alarms.unlock();
#else
		alarms.vlock->readerOut();
#endif


	prepare_alarm_attr();
	try
	{
		if(ds_num == 0)
		{
			//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
			struct timeval now;
			gettimeofday(&now,NULL);
			push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
		}
		else
			//attr.set_value(ds, ds_num, 0, false);
			push_change_event("alarm",ds, ds_num, 0, false);
	} catch(Tango::DevFailed& e)
	{
		ostringstream err;
		err << "error pushing alarm change event err=" << e.errors[0].desc;
		INFO_STREAM << __func__<<": " << err.str() << endl;
	}

	/*----- PROTECTED REGION END -----*/	//	Alarm::load
}
//--------------------------------------------------------
/**
 *	Command Remove related method
 *	Description: Remove alarm.
 *
 *	@param argin Alarm name
 */
//--------------------------------------------------------
void Alarm::remove(Tango::DevString argin)
{
	DEBUG_STREAM << "Alarm::Remove()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(Alarm::remove) ENABLED START -----*/
	
	//	Add your own code
	string s, log_alm_name;
	s = argin;
	log_alm_name = argin;
	bool ret = false;
	
	alarmedlock->readerIn();
	vector<alarm_t>::iterator found = find(alarmed.begin(), alarmed.end(), s);
	if (found != alarmed.end()) 
	{
		ostringstream err;
		err << s << " is in ALARM status! Acknowledge it before removing." << ends;
		if((found->stat == S_ALARM) && (found->ack == NOT_ACK))
		{
			alarmedlock->readerOut();
			Tango::Except::throw_exception( \
				(const char*)"Error removing alarm", \
				(const char*)err.str().c_str(), \
				(const char*)"Alarm::remove", Tango::ERR);
		}
	}
	alarmedlock->readerOut();
	try {
		ret = remove_alarm(s);
	} catch (string& err) {
		Tango::Except::throw_exception( \
				(const char*)"Error removing alarm", \
				(const char*)err.c_str(), \
				(const char*)"Alarm::remove", Tango::ERR);
	}
	if (ret) {
		DEBUG_STREAM << "Alarm::remove(): removing alarm '" \
								<< s << "'" << endl;
		while (true) {
			string::size_type i = s.find_first_of("/.");
			if (i == string::npos)
				break;
			s.replace(i, 1, "_");
		}
	}  /* end if */
	alarmedlock->writerIn();
	found = find(alarmed.begin(), alarmed.end(), s);	//look again because in the meanwhile lock was not acquired
	if (found != alarmed.end()) 
	{
		alarmed.erase(found);		//remove from alarmed table
	}
	alarmedlock->writerOut();

	prepare_alarm_attr();
	try
	{
		if(ds_num == 0)
		{
			//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
			struct timeval now;
			gettimeofday(&now,NULL);
			push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
		}
		else
			//attr.set_value(ds, ds_num, 0, false);
			push_change_event("alarm",ds, ds_num, 0, false);
		}
		push_change_event("normalAlarms",&attr_normalAlarms_read[0], normalAlarms_sz);
		push_change_event("unacknowledgedAlarms",&attr_unacknowledgedAlarms_read[0], unacknowledgedAlarms_sz);
		push_change_event("acknowledgedAlarms",&attr_acknowledgedAlarms_read[0], acknowledgedAlarms_sz);
		push_change_event("unacknowledgedNormalAlarms",&attr_unacknowledgedNormalAlarms_read[0], unacknowledgedNormalAlarms_sz);
		push_change_event("shelvedAlarms",&attr_shelvedAlarms_read[0], shelvedAlarms_sz);
		push_change_event("outOfServiceAlarms",&attr_outOfServiceAlarms_read[0], outOfServiceAlarms_sz);
		push_change_event("silencedAlarms",&attr_silencedAlarms_read[0], silencedAlarms_sz);
		push_change_event("listAlarms",&attr_listAlarms_read[0], listAlarms_sz);
		push_change_event("frequencyAlarms",&attr_frequencyAlarms_read[0], listAlarms_sz);
		push_change_event("audibleAlarm",attr_audibleAlarm_read);
		push_archive_event("normalAlarms",&attr_normalAlarms_read[0], normalAlarms_sz);
		push_archive_event("unacknowledgedAlarms",&attr_unacknowledgedAlarms_read[0], unacknowledgedAlarms_sz);
		push_archive_event("acknowledgedAlarms",&attr_acknowledgedAlarms_read[0], acknowledgedAlarms_sz);
		push_archive_event("unacknowledgedNormalAlarms",&attr_unacknowledgedNormalAlarms_read[0], unacknowledgedNormalAlarms_sz);
		push_archive_event("shelvedAlarms",&attr_shelvedAlarms_read[0], shelvedAlarms_sz);
		push_archive_event("outOfServiceAlarms",&attr_outOfServiceAlarms_read[0], outOfServiceAlarms_sz);
		push_archive_event("silencedAlarms",&attr_silencedAlarms_read[0], silencedAlarms_sz);
		push_archive_event("listAlarms",&attr_listAlarms_read[0], listAlarms_sz);
		push_archive_event("frequencyAlarms",&attr_frequencyAlarms_read[0], listAlarms_sz);
		push_archive_event("audibleAlarm",attr_audibleAlarm_read);
	} catch(Tango::DevFailed& e)
	{
		ostringstream err;
		err << "error pushing alarm change event err=" << e.errors[0].desc;
		INFO_STREAM << __func__<<": " << err.str() << endl;
	}

	/*----- PROTECTED REGION END -----*/	//	Alarm::remove
}
//--------------------------------------------------------
/**
 *	Command SearchAlarm related method
 *	Description: Return list of configured alarms matching the filter string
 *	@param argin String containing a filter for output, if empty or * return all alarms
 *	@returns Configured alarms
 */
//--------------------------------------------------------
Tango::DevVarStringArray *Alarm::search_alarm(Tango::DevString argin)
	DEBUG_STREAM << "Alarm::SearchAlarm()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(Alarm::search_alarm) ENABLED START -----*/
	
	//	Add your own code
	//	POGO has generated a method core with argout allocation.
	//	If you would like to use a static reference without copying,
	//	See "TANGO Device Server Programmer's Manual"
	//		(chapter : Writing a TANGO DS / Exchanging data)
	//------------------------------------------------------------
	argout  = new Tango::DevVarStringArray();
	//argout->length(1);
	//(*argout)[0] = CORBA::string_dup("dummy");
	DEBUG_STREAM << "Alarm::configured(): entering... !" << endl;

	//	Add your own code to control device here

	string filter(argin);
	string filter_begin(filter);
	string filter_end("");

	size_t start_pos = 0;
/*	string from("*");
	string to("");
	while((start_pos = filter.find(from, start_pos)) != std::string::npos)
	{
		filter.replace(start_pos, from.length(), to);
		start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
	}*/
	start_pos = filter.find("*", start_pos);
	if(start_pos != std::string::npos && start_pos == filter.size()-1) //* is the only character or at the end of the filter
	{
		filter.replace(start_pos, 1, "");
		filter_begin = filter;
		DEBUG_STREAM << __func__ << ": updated filter to: " << filter_begin;
	}
	/*else if(start_pos != std::string::npos) //* is in the middle of the filter
	{
		string filter_begin=filter.substr(0,start_pos);
		string filter_end=filter.substr(start_pos+1);
		DEBUG_STREAM << __func__ << ": splitted filter to: " << filter_begin << " - " << filter_end;
	}*/


	size_t found;
	vector<string> alarm_filtered;
	ostringstream os1;		
	os1.clear();
	/*os1 << headerConfig << "\t" << alarms.v_alarm.size() << ends;
	alarm_filtered.push_back(os1.str());*/

	alarm_container_t::iterator ai;
#ifndef _RW_LOCK
	alarms.lock();
#else
	alarms.vlock->readerIn();
#endif
	for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++) 
	{
		found = 0;
		if((filter_begin.length() == 0) || (found != string::npos))
			os << ai->second.ts.tv_sec << "\t" << ai->second.name << "\t" /*TODO<< KEY(FORMULA_KEY)*/ << ai->second.formula << "\t" << KEY(ONDELAY_KEY) << ai->second.on_delay << "\t" << KEY(OFFDELAY_KEY) << ai->second.off_delay <<
			"\t" << KEY(LEVEL_KEY) << ai->second.lev << "\t" << KEY(SILENT_TIME_KEY) << ai->second.silent_time << "\t" << KEY(GROUP_KEY) << ai->second.grp2str() << "\t" << KEY(MESSAGE_KEY) << ai->second.msg << "\t" <<
			KEY(ON_COMMAND_KEY) << ai->second.cmd_name_a << "\t" << KEY(OFF_COMMAND_KEY) << ai->second.cmd_name_n << ends;
			alarm_filtered.push_back(os.str());
		}
	}  /* for */
#ifndef _RW_LOCK
	alarms.unlock();
#else
	alarms.vlock->readerOut();
#endif
	argout->length(alarm_filtered.size());
	int i = 0;
	for (vector<string>::iterator it= alarm_filtered.begin(); it != alarm_filtered.end(); it++) 
	{
		(*argout)[i] = CORBA::string_dup(it->c_str());
		i++;
	}

	/*----- PROTECTED REGION END -----*/	//	Alarm::search_alarm
	return argout;
}
//--------------------------------------------------------
/**
 *	Command StopAudible related method
 *	Description: Stop audible indications on the GUI
 *
 */
//--------------------------------------------------------
	DEBUG_STREAM << "Alarm::StopAudible()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(Alarm::stop_audible) ENABLED START -----*/