Skip to content
Snippets Groups Projects
Alarm.cpp 139 KiB
Newer Older
					 	 * if already ACKnowledged and visualized
					 	 * remove from "alarmed" list
					 	 */
						DEBUG_STREAM << "read_attr(): S_NORMAL: " << aid->name \
								 				 << " ACKnowledged: removing" << endl;
						alarmed.erase(aid);
					} else {
						aid->done = true;
					}
				}	 /* if */
			}  /* if */
		}  /* if else if */
	}  /* for */
	
	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());
	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 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);
			if(i != alarms.v_alarm.end())
			{
				//update alarm ack in alarm table
				i->second.ack = ACK;
				//update alarm status from alarm table
				found->stat = i->second.stat;
			}
			if(found->ack == NOT_ACK)
			{
				alarms.log_alarm_db(TYPE_LOG_STATUS, gettime(), found->name, found->stat, ACK, 
						"", 0, "", "", "", "", -1);

				Tango::DevEnum *attr_value = get_AlarmState_data_ptr(i->second.attr_name);
				//TODO: if not _SHLVD, _DSUPR, _OOSRV
				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;
				}
		} else {
			internallock->readerIn();
			found = find(internal.begin(), internal.end(), *si);
			if (found != internal.end()) {
				found->ack = ACK;
			} else {
				ostringstream o;
				o << "\"" << *si << "\" not in 'alarmed' or 'internal' table" << endl;
				WARN_STREAM << "Alarm::ack(): " << o.str() << endl;
				internallock->readerOut();
				alarmedlock->readerOut();
#ifndef _RW_LOCK
				alarms.unlock();
#else
				alarms.vlock->readerOut();
#endif
				Tango::Except::throw_exception( \
					(const char*)"Alarm not found!!", \
					o.str(), \
					(const char*)"Alarm::ack()", Tango::ERR);									 
				
			}
			internallock->readerOut();
		}
		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();
	}
	/*
	 * always remove internal ACKnowlwdged alarms as
	 * they'll wont switch to "NORMAL"
	 */
	to_be_removed.name = "";
	to_be_removed.formula = "";
	to_be_removed.stat = S_ALARM;
	to_be_removed.ack = ACK;
	go = true;
	while (go) {
		internallock->writerIn();
		vector<alarm_t>::iterator found = \
				find(internal.begin(), internal.end(), to_be_removed);
		if (found != internal.end()) {
			DEBUG_STREAM << "Alarm::ack(): " << found->name \
					 				 << " ACK, removing"  << endl;
			internal.erase(found);
		} else {
			go = false;
		}
		internallock->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);
	} 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);
	}
	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);
	}
	string cmd_name_full = alm.cmd_name_a + string(";") + alm.cmd_name_n;
	alarms.log_alarm_db(TYPE_LOG_DESC_ADD, ts, alm.name, "", "", 		//add new alarm on log before subscribe event
			alm.formula, alm.on_delay, alm.grp2str(), alm.lev, alm.msg, cmd_name_full, alm.silent_time);	//but if it fails remove it from table
	alarms.save_alarm_conf_db(alm.attr_name, ts, alm.name, "", "", 		//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
#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 */
	alarms.log_alarm_db(TYPE_LOG_DESC_DIS, gettime(), log_alm_name, "", "", 		//set active to 0
			"", 0, "", "", "", "", -1);
	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);
	} 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 Configured related method
 *	Description: Alarms configured
 *
 *	@param argin String containing a filter for output, if empty return all alarms
 *	@returns Alarms configured
 */
//--------------------------------------------------------
Tango::DevVarStringArray *Alarm::configured(Tango::DevString argin)
{
	Tango::DevVarStringArray *argout;
	DEBUG_STREAM << "Alarm::Configured()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(Alarm::configured) 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);
	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.length() != 0)
		{
			found = ai->first.find(filter);
		}
		if((filter.length() == 0) || (found != string::npos))
		{
			ostringstream os;
			os.clear();
			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::configured
	return argout;
}
//--------------------------------------------------------
/**
 *	Command StopNew related method
 *	Description: Remove "NEW" field from alarm string (so alarm panel stop sound)
 *
 */
//--------------------------------------------------------
void Alarm::stop_new()
{
	DEBUG_STREAM << "Alarm::StopNew()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(Alarm::stop_new) ENABLED START -----*/
	
	//	Add your own code
	//12-06-08: StopNew command set is_new to 0
	//	Add your own code to control device here
	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++) {
		ai->second.is_new = 0;		//set all alarm as no more new
	}
#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::stop_new
}
//--------------------------------------------------------
/**
 *	Command Silence related method
 *	Description: Alarm temporarily silence
 *
 *	@param argin String array containing the alarms to be silenced
 */
//--------------------------------------------------------
void Alarm::silence(const Tango::DevVarStringArray *argin)
{
	DEBUG_STREAM << "Alarm::Silence()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(Alarm::silence) 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
		alarm_container_t::iterator i = alarms.v_alarm.find(*si);
		if(i != alarms.v_alarm.end())
		{
			if(i->second.silenced > 0)
			{
				Tango::TimeVal now = gettime();
				double dnow = now.tv_sec + ((double)now.tv_usec) / 1000000;
				double dsilent = i->second.ts_time_silenced.tv_sec + ((double)i->second.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 < i->second.silent_time)
					i->second.silenced = i->second.silent_time - floor(dminutes);
				else
					i->second.silenced = 0;
			}
			if(i->second.silenced > 0)
			{
				ostringstream err;
				err << "Alarm " << *si << " already silenced for " << i->second.silenced << " more minutes" << ends;
#ifndef _RW_LOCK
				alarms.unlock();
#else
				alarms.vlock->readerOut();
#endif
				Tango::Except::throw_exception( \
							(const char*)"Alarm already silenced", \
							err.str(), \
							(const char*)"Alarm::silence()", Tango::ERR);
			}
			if(i->second.silent_time <= 0)
			{
				ostringstream err;
				err << "Alarm " << *si << " cannot be silenced" << ends;
#ifndef _RW_LOCK
				alarms.unlock();
#else
				alarms.vlock->readerOut();
#endif
				Tango::Except::throw_exception( \
							(const char*)"Alarm cannot be silenced", \
							err.str(), \
							(const char*)"Alarm::silence()", Tango::ERR);
			}

			//load silent time
			i->second.ts_time_silenced = gettime();
			i->second.silenced = i->second.silent_time;
			//search also in alarmed
			alarmedlock->readerIn();
			vector<alarm_t>::iterator found = \
					find(alarmed.begin(), alarmed.end(), *si);
			if (found != alarmed.end())
			{
				//load silent time from alarm table
				found->silenced = i->second.silent_time;
				found->ts_time_silenced = i->second.ts_time_silenced;
			}
			alarmedlock->readerOut();
		}
		//alarms.unlock();
		if(i == alarms.v_alarm.end())
		{
#ifndef _RW_LOCK
			alarms.unlock();
#else
			alarms.vlock->readerOut();
#endif
			ostringstream err;
			err << "Alarm " << *si << " not found" << ends;
			Tango::Except::throw_exception( \
						(const char*)"Alarm not found!!", \
						err.str(), \
						(const char*)"Alarm::silence()", Tango::ERR);
		}
#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::silence
}
//--------------------------------------------------------
/**
 *	Command Modify related method
 *	Description: Modify an existing alarm.
 *
 *	@param argin Alarm entry
 */
//--------------------------------------------------------
void Alarm::modify(Tango::DevString argin)
{
	DEBUG_STREAM << "Alarm::Modify()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(Alarm::modify) ENABLED START -----*/
	DEBUG_STREAM << "Alarm::Modify: " << argin << endl;
	//	Add your own code
	//------------------------------
	//1: parse to get alarm name
	//------------------------------
	string alarm_string(argin);
	alarm_t alm;
	alarm_parse al_gr(alm);    //  Construct Spirit grammar
	alm.name.clear();
	alm.attr_name.clear();
	alm.quality = Tango::ATTR_VALID;
	alm.ex_reason.clear();
	alm.ex_desc.clear();
	alm.ex_origin.clear();
	alm.formula.clear();
	alm.msg.clear();
	alm.lev.clear();
	alm.grp=0;
	alm.to_be_evaluated = false;
	alm.on_delay = 0;
	alm.off_delay = 0;