/*----- PROTECTED REGION ID(AlarmHandler.cpp) ENABLED START -----*/
//=============================================================================
//
// file :        AlarmHandler.cpp
//
// description : C++ source for the AlarmHandler class and its commands.
//               The class is derived from Device. It represents the
//               CORBA servant object which will be accessed from the
//               network. All commands which can be executed on the
//               AlarmHandler are implemented in this file.
//
// project :     Elettra alarm handler device server
//
// This file is part of Tango device class.
// 
// Tango is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// Tango is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with Tango.  If not, see <http://www.gnu.org/licenses/>.
// 
//
//
//=============================================================================
//                This file is generated by POGO
//        (Program Obviously used to Generate tango Object)
//=============================================================================


#include <AlarmHandler.h>
#include <AlarmHandlerClass.h>
#include <ctype.h>		//for tolower

#include "alarm-thread.h"
#include "alarm_grammar.h"
#include "update-thread.h"

//#define _DUMP_TREE_XML
#ifdef _DUMP_TREE_XML
#if BOOST_VERSION  < 103600
#include <boost/spirit/iterator/fixed_size_queue.hpp>

#include <boost/spirit/core.hpp>
#include <boost/spirit/tree/ast.hpp>
#include <boost/spirit/tree/tree_to_xml.hpp>

using namespace boost::spirit;
#else
#include <boost/spirit/include/classic_fixed_size_queue.hpp>

#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_ast.hpp>
#include <boost/spirit/include/classic_tree_to_xml.hpp>

using namespace boost::spirit::classic;
#endif
#include <iostream>
#include <stack>
#include <functional>
#include <string>
#include <cassert>
#endif 		//_DUMP_TREE_XML
#include <sstream>

std::map<parser_id, std::string> rule_names;  //only for log messages

int AlarmHandler_ns::AlarmHandler::instanceCounter = 0;

#ifndef ALARM_BUILDTIME
#define ALARM_BUILDTIME    __DATE__ " "  __TIME__ " boost=" BOOST_LIB_VERSION
#endif

const char version_string[] = "$Build: @buildID@ " ALARM_BUILDTIME " $";
static const char __FILE__rev[] = __FILE__ " $Revision: 1.29 $";

/*----- PROTECTED REGION END -----*/	//	AlarmHandler.cpp

/**
 *  AlarmHandler class description:
 *    Elettra alarm handler device server
 */

//================================================================
//  The following table gives the correspondence
//  between command and method names.
//
//  Command name     |  Method name
//================================================================
//  State            |  Inherited (no method)
//  Status           |  Inherited (no method)
//  Ack              |  ack
//  Load             |  load
//  Remove           |  remove
//  SearchAlarm      |  search_alarm
//  StopAudible      |  stop_audible
//  Silence          |  silence
//  Modify           |  modify
//  Shelve           |  shelve
//  Enable           |  enable
//  Disable          |  disable
//  ResetStatistics  |  reset_statistics
//  StopNew          |  stop_new
//  GetAlarmInfo     |  get_alarm_info
//================================================================

//================================================================
//  Attributes managed are:
//================================================================
//  alarmAudible               |  Tango::DevBoolean	Scalar
//  StatisticsResetTime        |  Tango::DevDouble	Scalar
//  alarm                      |  Tango::DevString	Spectrum  ( max = 1024)
//  alarmNormal                |  Tango::DevString	Spectrum  ( max = 10000)
//  alarmUnacknowledged        |  Tango::DevString	Spectrum  ( max = 10000)
//  alarmAcknowledged          |  Tango::DevString	Spectrum  ( max = 10000)
//  alarmUnacknowledgedNormal  |  Tango::DevString	Spectrum  ( max = 10000)
//  alarmShelved               |  Tango::DevString	Spectrum  ( max = 10000)
//  alarmOutOfService          |  Tango::DevString	Spectrum  ( max = 10000)
//  alarmSilenced              |  Tango::DevString	Spectrum  ( max = 10000)
//  alarmList                  |  Tango::DevString	Spectrum  ( max = 10000)
//  alarmFrequency             |  Tango::DevDouble	Spectrum  ( max = 10000)
//  alarmSummary               |  Tango::DevString	Spectrum  ( max = 10000)
//================================================================

namespace AlarmHandler_ns
{
/*----- PROTECTED REGION ID(AlarmHandler::namespace_starting) ENABLED START -----*/

//	static initializations

/*----- PROTECTED REGION END -----*/	//	AlarmHandler::namespace_starting

//--------------------------------------------------------
/**
 *	Method      : AlarmHandler::AlarmHandler()
 *	Description : Constructors for a Tango device
 *                implementing the classAlarmHandler
 */
//--------------------------------------------------------
AlarmHandler::AlarmHandler(Tango::DeviceClass *cl, string &s)
 : TANGO_BASE_CLASS(cl, s.c_str())
{
	/*----- PROTECTED REGION ID(AlarmHandler::constructor_1) ENABLED START -----*/
	init_device();
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::constructor_1
}
//--------------------------------------------------------
AlarmHandler::AlarmHandler(Tango::DeviceClass *cl, const char *s)
 : TANGO_BASE_CLASS(cl, s)
{
	/*----- PROTECTED REGION ID(AlarmHandler::constructor_2) ENABLED START -----*/
	init_device();
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::constructor_2
}
//--------------------------------------------------------
AlarmHandler::AlarmHandler(Tango::DeviceClass *cl, const char *s, const char *d)
 : TANGO_BASE_CLASS(cl, s, d)
{
	/*----- PROTECTED REGION ID(AlarmHandler::constructor_3) ENABLED START -----*/
	init_device();
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::constructor_3
}

//--------------------------------------------------------
/**
 *	Method      : AlarmHandler::delete_device()
 *	Description : will be called at device destruction or at init command
 */
//--------------------------------------------------------
void AlarmHandler::delete_device()
{
	DEBUG_STREAM << "AlarmHandler::delete_device() " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::delete_device) ENABLED START -----*/
	
	//	Delete device allocated objects
		/*
	 * unsubscribe events and release memory
	 */
	bool starting = Tango::Util::instance()->is_svr_starting();
	bool shutting_down = Tango::Util::instance()->is_svr_shutting_down();
	bool restarting = Tango::Util::instance()->is_device_restarting(device_name);
	DEBUG_STREAM << __func__ << " starting="<<(int)starting << " shutting_down="<<(int)shutting_down<<" restarting="<<(int)restarting;

	abortflag = true;
	DEBUG_STREAM << "AlarmHandler::delete_device(): after abortflag=true..." << endl;
	try {
		events->unsubscribe_events();
	} catch (string& err) {
		ERROR_STREAM << err << endl;
	}
	DEBUG_STREAM << "AlarmHandler::delete_device(): events unsubscribed!" << endl;
	/*
	 * kill alarm thread
	 */
	bei_t e;
	e.ev_name = ALARM_THREAD_EXIT;
	e.value.push_back(ALARM_THREAD_EXIT_VALUE);
	e.value.push_back(ALARM_THREAD_EXIT_VALUE);
	evlist.push_back(e);
	if(!shutting_down && !restarting)
		alarms.del_rwlock(); //otherwise moved in alarm_table destructor
	alarms.stop_cmdthread();
	sleep(1);		//wait for alarm_thread and log_thread to exit
	//delete almloop;
	DEBUG_STREAM << "AlarmHandler::delete_device(): stopped alarm and log threads!" << endl;
	
	
	//delete proxy for actions
	for(alarm_container_t::iterator i = alarms.v_alarm.begin(); i!=alarms.v_alarm.end(); i++)
	{
		if(i->second.dp_a)
			delete i->second.dp_a;
		i->second.dp_a = NULL;
		if(i->second.dp_n)
			delete i->second.dp_n;
		i->second.dp_n = NULL;
	}	

	if(0/*shutting_down*/) //TODO: no need to remove attributes when shutting down ?
	{
		for(alarm_container_t::iterator it = alarms.v_alarm.begin(); it != alarms.v_alarm.end(); it++)
		{
			try
			{
				remove_AlarmState_dynamic_attribute_no_clean_db(it->second.attr_name);
			}
			catch(Tango::DevFailed &e)
			{
				INFO_STREAM << __func__<<": exception removing " << it->second.attr_name << ": " << e.errors[0].desc;
			}
#if _FORMULA_ATTR
			CORBA::string_free(*(it->second.attr_value_formula));
			try
			{
				remove_AlarmFormula_dynamic_attribute(it->second.attr_name_formula);
			}
			catch(Tango::DevFailed &e)
			{
				INFO_STREAM << __func__<<": exception removing " << it->second.attr_name_formula << ": " << e.errors[0].desc;
			}
#endif
		}
	}
	/*
	 * clear all data structures
	 */
	alarms.v_alarm.clear();
	events->v_event.clear();
	evlist.clear();
/*	for (int i = ds_num - 1; i >= 0; i--) {
		CORBA::string_free(ds[i]);
	}*/
	ds_num = 0;
	/*
	 * store current "alarmed" table status
	 */
	vector<string> vs;	
	for (vector<alarm_t>::iterator i = alarmed.begin(); \
			 i != alarmed.end(); i++) {
		vs.push_back(i->alm2str());
	}
	Tango::DbDatum as("AlarmStatus");
	Tango::DbData	data_del;
	data_del.push_back(as);
	//get_db_device()->delete_property(data_del);	
	as << vs;
	Tango::DbData	data_put;
	data_put.push_back(as);
	Tango::Database *db=NULL;
	try
	{
#ifndef _USE_ELETTRA_DB_RW
		db = new Tango::Database();
#else	
		//salvataggio proprietà usando host_rw e port_rw per connettersi al database
		if(host_rw != "")
			db = new Tango::Database(host_rw,port_rw);
		else
			db = new Tango::Database();
#endif
	}
	catch(Tango::DevFailed &e)
	{
		stringstream o;
		o << " Error connecting to Tango DataBase='" << e.errors[0].desc << "'";
		WARN_STREAM << __FUNCTION__<< o.str();
	}
	if(db)
	{
		try {
			db->put_device_property(get_name(), data_put);
			DEBUG_STREAM << "AlarmHandler::delete_device(): saved AlarmStatus in properties!!" << endl;
		}
		catch(Tango::DevFailed &e)
		{
			ERROR_STREAM << __FUNCTION__<< " error saving properties='" << e.errors[0].desc << "'";
		}
		delete db;
	}
	/*
	 * clear storage
	 */
	alarmed.clear();
	delete alarmedlock;
	delete internallock;
	delete dslock;
	delete events;

	instanceCounter--;
	//Tango::leavefunc();
	delete prepare_alm_mtx;
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::delete_device
	delete[] attr_alarmAudible_read;
	delete[] attr_StatisticsResetTime_read;
	delete[] attr_alarmNormal_read;
	delete[] attr_alarmUnacknowledged_read;
	delete[] attr_alarmAcknowledged_read;
	delete[] attr_alarmUnacknowledgedNormal_read;
	delete[] attr_alarmShelved_read;
	delete[] attr_alarmOutOfService_read;
	delete[] attr_alarmSilenced_read;
	delete[] attr_alarmList_read;
	delete[] attr_alarmFrequency_read;
	delete[] attr_alarmSummary_read;
}

//--------------------------------------------------------
/**
 *	Method      : AlarmHandler::init_device()
 *	Description : will be called at device initialization.
 */
//--------------------------------------------------------
void AlarmHandler::init_device()
{
	DEBUG_STREAM << "AlarmHandler::init_device() create device " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::init_device_before) ENABLED START -----*/
	bool starting = Tango::Util::instance()->is_svr_starting();
	bool shutting_down = Tango::Util::instance()->is_svr_shutting_down();
	bool restarting = Tango::Util::instance()->is_device_restarting(device_name);
	DEBUG_STREAM << __func__ << " starting="<<(int)starting << " shutting_down="<<(int)shutting_down<<" restarting="<<(int)restarting;
	//	Initialization before get_device_property() call
	int dbPortint=0;	
	abortflag = false;	
	instanceCounter++;
	prepare_alm_mtx = new omni_mutex();
	events = new event_table(this);
	thread = new SubscribeThread(this);
	//because of static map<string, unsigned int> grp_str and of exception while subscribing
	//more than one time the same event in the same executable, control the number of instances
	if(instanceCounter > 1)		
	{
		ERROR_STREAM << "More than one instance in the same executable of Alarm Server is not allowed!!" << endl;
		cout << "ERROR: second instance of Alarm Server, exiting..." << endl;
		exit(-1);
	}	//-------------------------------------------	
	alarmedlock = new(ReadersWritersLock);
	internallock = new(ReadersWritersLock);
	dslock = new(ReadersWritersLock);
	alarms.set_dev(this);

	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::init_device_before
	

	//	Get the device properties from database
	get_device_property();
	
	attr_alarmAudible_read = new Tango::DevBoolean[1];
	attr_StatisticsResetTime_read = new Tango::DevDouble[1];
	attr_alarmNormal_read = new Tango::DevString[10000];
	attr_alarmUnacknowledged_read = new Tango::DevString[10000];
	attr_alarmAcknowledged_read = new Tango::DevString[10000];
	attr_alarmUnacknowledgedNormal_read = new Tango::DevString[10000];
	attr_alarmShelved_read = new Tango::DevString[10000];
	attr_alarmOutOfService_read = new Tango::DevString[10000];
	attr_alarmSilenced_read = new Tango::DevString[10000];
	attr_alarmList_read = new Tango::DevString[10000];
	attr_alarmFrequency_read = new Tango::DevDouble[10000];
	attr_alarmSummary_read = new Tango::DevString[10000];
	/*----- PROTECTED REGION ID(AlarmHandler::init_device) ENABLED START -----*/
/*	for(size_t i=0; i<MAX_ALARMS; i++)
	{
		normalAlarms_read[i].resize(MAX_ATTR_NAME);
		unacknowledgedAlarms_read[i].resize(MAX_ATTR_NAME);
		acknowledgedAlarms_read[i].resize(MAX_ATTR_NAME);
		unacknowledgedNormalAlarms_read[i].resize(MAX_ATTR_NAME);
		shelvedAlarms_read[i].resize(MAX_ATTR_NAME);
		outOfServiceAlarms_read[i].resize(MAX_ATTR_NAME);
		silencedAlarms_read[i].resize(MAX_ATTR_NAME);
		alarmSummary_read[i].resize(MAX_ATTR_SUMMARY);
	}*/
	//	Initialize device
	thread->period = subscribeRetryPeriod;
	
#ifdef _USE_ELETTRA_DB_RW
	host_rw = "";
	Tango::Database *db=NULL;
	try
	{
		db = new Tango::Database();
	}catch(Tango::DevFailed &e)
	{
		ERROR_STREAM << __FUNCTION__ << " Error connecting to Tango DataBase='" << e.errors[0].desc << "'";
	}
	if(db)
	{
		try
		{
			Tango::DbData db_data;
			db_data.push_back((Tango::DbDatum("Host")));
			db_data.push_back((Tango::DbDatum("Port")));
			db->get_property("Database",db_data);

			db_data[0] >> host_rw;
			db_data[1] >> port_rw;
		}catch(Tango::DevFailed &e)
		{
			ERROR_STREAM << __FUNCTION__ << " Error reading Database property='" << e.errors[0].desc << "'";
		}
		delete db;
	}
#endif

	ds_num = 0;				//initialize number of lines returned by read_alarm
	internal_counter = 0;

	/*Tango::DbData db_data;
	db_data.push_back(Tango::DbDatum("alarm"));
	get_db_device()->get_attribute_property(db_data);*/
	/*
	 * connect to log database
	 */	
	alarms.new_rwlock();
	try {
		alarms.init_cmdthread();
	} catch(...)
	{
		WARN_STREAM << "AlarmHandler::init_device(): error creating cmd thread" << endl;
	}	
	
	rule_names[formula_grammar::val_rID] = "ValReal";
	rule_names[formula_grammar::val_hID] = "ValHex";
	rule_names[formula_grammar::val_stID] = "ValStatus";
	rule_names[formula_grammar::event_ID] = "EventFather";
	rule_names[formula_grammar::nameID] = "EventName";
	rule_names[formula_grammar::indexID] = "EventIndex";
	rule_names[formula_grammar::funcID] = "Function";
	rule_names[formula_grammar::logical_exprID] = "LogicalE";
	rule_names[formula_grammar::bitwise_exprID] = "BitwiseE";
	rule_names[formula_grammar::equality_exprID] = "EqualityE";
	rule_names[formula_grammar::compare_exprID] = "CompareE";
	rule_names[formula_grammar::add_exprID] = "AddE";
	rule_names[formula_grammar::mult_exprID] = "MultE";
	rule_names[formula_grammar::expr_atomID] = "AtomicE";
	rule_names[formula_grammar::shift_exprID] = "ShiftE";
	rule_names[formula_grammar::unary_exprID] = "UnaryE";
	rule_names[formula_grammar::val_stringID] = "ValString";
	rule_names[formula_grammar::func_dualID] = "FuncDualE";
	rule_names[formula_grammar::logical_expr_parenID] = "LogicalParenE";
	rule_names[formula_grammar::cond_exprID] = "ConditionalE";
	rule_names[formula_grammar::nonempty_exprID] = "NonEmptyE";
	rule_names[formula_grammar::exprID] = "Expression";
	rule_names[formula_grammar::val_qualityID] = "ValQuality";
	rule_names[formula_grammar::val_alarm_enum_stID] = "ValAlarmEnumStatus";
	rule_names[formula_grammar::propertyID] = "EventProperty";

	/*
	 * get device attribute properties and initialize internal
	 * data structures
	 */
//	short n_prop;
	string expr;
	string pr_name;
	vector<string> tmp_alm_vec;
/*	db_data[0] >> n_prop;
	INFO_STREAM << "Number alarm to load = " << n_prop << endl;
	for (int i = 1; i <= n_prop; i++) 
	{
		pr_name = db_data[i].name;
		db_data[i] >> expr;
		DEBUG_STREAM << "	-> attr property: " << pr_name << " = " << expr << endl;
    	size_t pos = pr_name.find('_');
    	int count_ = 1;
    	while(pos != string::npos) 	//TODO: better this control
    	{
      		pos = pr_name.find('_', pos+1);
      		count_++;
      		if((count_ == 3) && (pos != string::npos))	//if at least 3 _ in the attr property name, expr is OK  	//TODO: better this control
      		{
				tmp_alm_vec.push_back(expr);
				break;      		
      		}	
    	}
	}*/
	try {
		alarms.get_alarm_list_db(tmp_alm_vec, saved_alarms);
	} catch(string & e)
	{
		ERROR_STREAM << "AlarmHandler::init_device(): " << e << endl;
		cout << "Error: " << e << ". Exiting..." << endl;
		exit(-4);
	}		
	
	
	/*
	 * store the alarms into alarm table vector
	 */
	map< string,vector<string> > alarm_event;	//map alarm->vector event popolated by parser
	vector<string> evn;	 						//vector with all event (possibly duplicated) popolated by parser
	vector<string> temp_evn;	
	vector<string> tmp_alm_name_lst; 						
	//alarms.init(tmp_alm_vec, evn, alarm_event);
	alarm_t tmp_alm;
	evn.clear();
	for(vector<string>::iterator it_al = tmp_alm_vec.begin(); it_al!= tmp_alm_vec.end(); it_al++)
	{
		tmp_alm.clear();
		temp_evn.clear();
		try {		
			load_alarm(*it_al, tmp_alm, temp_evn);
			add_alarm(tmp_alm,/*starting*/true);
			tmp_alm_name_lst.push_back(tmp_alm.name);
		} catch(Tango::DevFailed& e)
		{
			ostringstream err;
			err << "error loading alarm=" << tmp_alm.name << " , " << e.errors[0].desc;
			WARN_STREAM << "AlarmHandler::init_device(): " << err.str() << endl;
			set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());
			continue;
		} catch (string& err) {
			ostringstream err_out;
			err_out << "error loading alarm=" << tmp_alm.name << " , " << err;
			WARN_STREAM << "AlarmHandler::init_device(): " << err_out.str() << endl;
			set_internal_alarm(INTERNAL_ERROR, gettime(), err_out.str());
			continue;
		}
		//eliminate duplicated event
		if (temp_evn.empty() == false) 
		{		
			sort(temp_evn.begin(), temp_evn.end());
			vector<string>::iterator new_end = \
				unique(temp_evn.begin(), temp_evn.end());
			while (temp_evn.end() != new_end) 
				temp_evn.pop_back();
		}
		alarm_event.insert(make_pair(tmp_alm.name,temp_evn));
		evn.insert(evn.end(),temp_evn.begin(),temp_evn.end());
/*		alarms.log_alarm_db(TYPE_LOG_DESC_SYNC, gettime(), tmp_alm.name, "", "", 		//remove if alarm with the same name exist but is changed
			tmp_alm.formula, tmp_alm.grp2str(), tmp_alm.lev, tmp_alm.msg);		
		alarms.log_alarm_db(TYPE_LOG_DESC_ADD, gettime(), tmp_alm.name, "", "", 		//add new alarm if there is not already one active with the same name
			tmp_alm.formula, tmp_alm.grp2str(), tmp_alm.lev, tmp_alm.msg);*/		
	}
/*	alarms.log_alarm_db(TYPE_LOG_DESC_UPD_OLD, gettime(), "", "", "", 		//set as not active all alarms not present in this list
		"", "", "", "", tmp_alm_name_lst);*/		
	DEBUG_STREAM << "alarms table size = " << alarms.size() << endl;
	
	vector<string> al_table_string;
	alarms.show(al_table_string);
	for(vector<string>::iterator str_it=al_table_string.begin(); str_it!=al_table_string.end(); str_it++)
		DEBUG_STREAM << (*str_it) << endl;

	/*
	 * check 'stored' alarms against current alarm table for consistency
	 */
	vector<string> to_remove_from_stored;
	if (stored.empty() == false) {
		for (vector<alarm_t>::iterator i = stored.begin(); \
			 	 i != stored.end(); i++) {
			alarm_container_t::iterator found = alarms.v_alarm.find(i->name);
			if (found == alarms.v_alarm.end()) {

				to_remove_from_stored.push_back(i->name);
				//stored.erase(i);
			}
		}
	}
	for(vector<string>::iterator k=to_remove_from_stored.begin(); k != to_remove_from_stored.end(); k++)
	{
		vector<alarm_t>::iterator rmv = find(stored.begin(),stored.end(),*k);
		if(rmv != stored.end())
		{
			ERROR_STREAM << "init_device(): alarm '" << *k \
							 << "' NOT found in alarm table! " \
			 	 			 << "Removing from 'stored' alarms" << endl;			
			stored.erase(rmv);
		}
		else
			WARN_STREAM << "init_device(): alarm " << *k << " not found while removing from stored !!!" << endl;
	}
	/*
	 * update "alarm" table with "stored" alarms
	 */
	alarms.stored(stored);
	/*
	 * update "alarmed" table with "stored" alarms
	 */ 
	if (stored.empty() == false) {
		alarmedlock->writerIn();
		for (vector<alarm_t>::iterator i = stored.begin(); \
			 	 i != stored.end(); i++) {
			alarmed.push_back(*i);
		}
		alarmedlock->writerOut();
	}

	for(alarm_container_t::iterator i = alarms.v_alarm.begin(); \
		i!=alarms.v_alarm.end(); i++)
	{
		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) && (info.in_type != Tango::DEV_VOID))
				{
					ostringstream err;
					err << i->second.name << ": error, command " << i->second.cmd_name_a << " does not accept a Tango::DevString or a Tango::DevVoid as input value";
					ERROR_STREAM << "AlarmHandler::init_device(): " << 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 << "AlarmHandler::init_device(): " << i->second.name << ": successfully connected to proxy=" << i->second.cmd_dp_a << " for action=" << i->second.cmd_action_a << endl;
				}
			} catch(Tango::DevFailed& e)
			{
				ostringstream err;
				err << i->second.name << ": error connecting to device proxy=" << i->second.cmd_dp_a << ", err=" << e.errors[0].desc;
				WARN_STREAM << "AlarmHandler::init_device(): " << err.str() << endl;
				set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());
				i->second.dp_a = NULL;
			}						
		}
		if(i->second.cmd_name_n.length() > 0)
		{
			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_n);
				if((info.in_type != Tango::DEV_STRING) && (info.in_type != Tango::DEV_VOID))
				{
					ostringstream err;
					err << i->second.name << ": error, command " << i->second.cmd_name_n << " does not accept a Tango::DevString or a Tango::DevVoid as input value";
					ERROR_STREAM << "AlarmHandler::init_device(): " << 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 << "AlarmHandler::init_device(): " << i->second.name << ": successfully connected to proxy=" << i->second.cmd_dp_n << " for action=" << i->second.cmd_action_n << endl;
				}
			} catch(Tango::DevFailed& e)
			{
				ostringstream err;
				err << i->second.name << ": error connecting to device proxy=" << i->second.cmd_dp_n << ", err=" << e.errors[0].desc;
				WARN_STREAM << "AlarmHandler::init_device(): " << err.str() << endl;
				set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());
				i->second.dp_n = NULL;
			}						
		}		
	}

	thread->start();
	
	//TODO:ecb.init(&evlist);
	for(map<string, vector<string> >::iterator al_ev_it=alarm_event.begin(); \
		al_ev_it!=alarm_event.end(); al_ev_it++)
	{
		alarm_container_t::iterator i = alarms.v_alarm.find(al_ev_it->first);
		if(i != alarms.v_alarm.end())
		{		
#if 1
			try {
				add_event(i->second, al_ev_it->second);//moved after events->add
				/*if(i->second.to_be_evaluated)		//moved after thread->start(); (subscribe thread started)
				{
					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);
				}*/
			} catch (string& err) {
				WARN_STREAM << "AlarmHandler::init_device(): " << err << endl;
				for(vector<string>::iterator j=al_ev_it->second.begin(); j!=al_ev_it->second.end(); j++)
				{
					DEBUG_STREAM << "AlarmHandler::init_device(): 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 << "AlarmHandler::init_device(): 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 << "AlarmHandler::init_device(): event=" << *j << " no more used, REMOVED!!!" << endl;
						}
					}
				}			
				set_internal_alarm(INTERNAL_ERROR, gettime(), err);
			}
#else
			try {
				add_event(i->second, al_ev_it->second);
			} catch (string& err) {
				WARN_STREAM << "AlarmHandler::init_device(): " << err << endl;
				set_internal_alarm(INTERNAL_ERROR, gettime(), err);
			}
			try {
				subscribe_event(i->second, ecb, al_ev_it->second);
			} catch (string& err) {
				WARN_STREAM << "AlarmHandler::init_device(): " << err << endl;
				set_internal_alarm(INTERNAL_ERROR, gettime(), err);
			}			
#endif
		}
	}

	set_change_event("alarm",true,false);
	/*
	 * create alarm processing thread
	 */

	//almloop = new alarm_thread::alarm_thread(/*this*/);
	almloop = new alarm_thread(this);
	almloop->start();
	
	updateloop = new update_thread(this);
	updateloop->start();

	//thread->start();

	events->start_all();
	
	for(map<string, vector<string> >::iterator al_ev_it=alarm_event.begin(); \
		al_ev_it!=alarm_event.end(); al_ev_it++)
	{
		alarm_container_t::iterator i = alarms.v_alarm.find(al_ev_it->first);
		if(i != alarms.v_alarm.end())
		{
			if(i->second.to_be_evaluated)		//moved after thread->start(); (subscribe thread started)
			{
				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);
			}
		}
	}

  	set_state(Tango::RUNNING);
	set_status("Alarm server is running");	
	alarms.startup_complete = gettime();			//enable actions execution in 10 seconds
	//

//	for (int i=0; i< MAX_ALARMS ; i++) ds[i]=0;
//	ds_num = 0;
	for (int i=0; i< MAX_ALARMS ; i++)
		ds[i]=(char *) (dss[i]);

	timespec now;
	clock_gettime(CLOCK_MONOTONIC, &now);
	double dnow = (now.tv_sec) + ((double)(now.tv_nsec))/1000000000;
	last_statistics_reset_time = dnow;
	INFO_STREAM << __func__ << ": exiting!";

	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::init_device
}

//--------------------------------------------------------
/**
 *	Method      : AlarmHandler::get_device_property()
 *	Description : Read database to initialize property data members.
 */
//--------------------------------------------------------
void AlarmHandler::get_device_property()
{
	/*----- PROTECTED REGION ID(AlarmHandler::get_device_property_before) ENABLED START -----*/
	
	//	Initialize property data members
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::get_device_property_before


	//	Read device properties from database.
	Tango::DbData	dev_prop;
	dev_prop.push_back(Tango::DbDatum("GroupNames"));
	dev_prop.push_back(Tango::DbDatum("SubscribeRetryPeriod"));
	dev_prop.push_back(Tango::DbDatum("StatisticsTimeWindow"));

	//	is there at least one property to be read ?
	if (dev_prop.size()>0)
	{
		//	Call database and extract values
		if (Tango::Util::instance()->_UseDb==true)
			get_db_device()->get_property(dev_prop);
	
		//	get instance on AlarmHandlerClass to get class property
		Tango::DbDatum	def_prop, cl_prop;
		AlarmHandlerClass	*ds_class =
			(static_cast<AlarmHandlerClass *>(get_device_class()));
		int	i = -1;

		//	Try to initialize GroupNames from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  groupNames;
		else {
			//	Try to initialize GroupNames from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  groupNames;
		}
		//	And try to extract GroupNames value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  groupNames;

		//	Try to initialize SubscribeRetryPeriod from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  subscribeRetryPeriod;
		else {
			//	Try to initialize SubscribeRetryPeriod from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  subscribeRetryPeriod;
		}
		//	And try to extract SubscribeRetryPeriod value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  subscribeRetryPeriod;

		//	Try to initialize StatisticsTimeWindow from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  statisticsTimeWindow;
		else {
			//	Try to initialize StatisticsTimeWindow from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  statisticsTimeWindow;
		}
		//	And try to extract StatisticsTimeWindow value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  statisticsTimeWindow;

	}

	/*----- PROTECTED REGION ID(AlarmHandler::get_device_property_after) ENABLED START -----*/
	
	//	Check device property data members init
	/*
	 * initialize groups
	 */	
	alarm_t tmp_alm;						
	tmp_alm.init_static_map(groupNames); 

	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::get_device_property_after
}

//--------------------------------------------------------
/**
 *	Method      : AlarmHandler::always_executed_hook()
 *	Description : method always executed before any command is executed
 */
//--------------------------------------------------------
void AlarmHandler::always_executed_hook()
{
	//DEBUG_STREAM << "AlarmHandler::always_executed_hook()  " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::always_executed_hook) ENABLED START -----*/
	
	//	code always executed before all requests
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::always_executed_hook
}

//--------------------------------------------------------
/**
 *	Method      : AlarmHandler::read_attr_hardware()
 *	Description : Hardware acquisition for attributes
 */
//--------------------------------------------------------
void AlarmHandler::read_attr_hardware(TANGO_UNUSED(vector<long> &attr_list))
{
	//DEBUG_STREAM << "AlarmHandler::read_attr_hardware(vector<long> &attr_list) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_attr_hardware) ENABLED START -----*/
	
	//	Add your own code
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_attr_hardware
}

//--------------------------------------------------------
/**
 *	Read attribute alarmAudible related method
 *	Description: True if there is at least one alarm that needs audible indication on the GUI
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void AlarmHandler::read_alarmAudible(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AlarmHandler::read_alarmAudible(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_alarmAudible) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_alarmAudible_read);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_alarmAudible
}
//--------------------------------------------------------
/**
 *	Read attribute StatisticsResetTime related method
 *	Description: Time elapsed in seconds since last Resetstatistics
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void AlarmHandler::read_StatisticsResetTime(Tango::Attribute &attr)
{
	DEBUG_STREAM << "AlarmHandler::read_StatisticsResetTime(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_StatisticsResetTime) ENABLED START -----*/
	timespec now;
	clock_gettime(CLOCK_MONOTONIC, &now);
	double dnow = (now.tv_sec) + ((double)(now.tv_nsec))/1000000000;
	*attr_StatisticsResetTime_read = dnow - last_statistics_reset_time;
	//	Set the attribute value
	attr.set_value(attr_StatisticsResetTime_read);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_StatisticsResetTime
}
//--------------------------------------------------------
/**
 *	Read attribute alarm related method
 *	Description: 
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 1024
 */
//--------------------------------------------------------
void AlarmHandler::read_alarm(Tango::Attribute &attr)
{
	DEBUG_STREAM << "AlarmHandler::read_alarm(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_alarm) ENABLED START -----*/
	// Add your own code here
#if 0
	alarm_container_t::iterator ai;
	vector<alarm_t>::iterator aid;
	for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++) {
		if (ai->second.stat == S_ALARM) {
			/*
			 * alarm status is S_ALARM
			 */
			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->counter = ai->second.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 << "read_attr(): S_ALARM: pushing new alarm: " \
						 				 << ai->second.name << "\t" << ai->second.stat << endl;
				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
			}
		} else if (ai->second.stat == S_NORMAL) {
			/*
			 * alarm status is S_NORMAL
			 */
			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->counter = ai->second.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 << "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 -----*/	//	AlarmHandler::read_alarm
}
//--------------------------------------------------------
/**
 *	Read attribute alarmNormal related method
 *	Description: List of alarms in normal state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void AlarmHandler::read_alarmNormal(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AlarmHandler::read_alarmNormal(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_alarmNormal) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_alarmNormal_read, normalAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_alarmNormal
}
//--------------------------------------------------------
/**
 *	Read attribute alarmUnacknowledged related method
 *	Description: List of alarms in unacknowledged state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void AlarmHandler::read_alarmUnacknowledged(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AlarmHandler::read_alarmUnacknowledged(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_alarmUnacknowledged) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_alarmUnacknowledged_read, unacknowledgedAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_alarmUnacknowledged
}
//--------------------------------------------------------
/**
 *	Read attribute alarmAcknowledged related method
 *	Description: List of alarms in acknowledged state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void AlarmHandler::read_alarmAcknowledged(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AlarmHandler::read_alarmAcknowledged(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_alarmAcknowledged) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_alarmAcknowledged_read, acknowledgedAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_alarmAcknowledged
}
//--------------------------------------------------------
/**
 *	Read attribute alarmUnacknowledgedNormal related method
 *	Description: List of alarms in unacknowledged normal state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void AlarmHandler::read_alarmUnacknowledgedNormal(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AlarmHandler::read_alarmUnacknowledgedNormal(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_alarmUnacknowledgedNormal) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_alarmUnacknowledgedNormal_read, unacknowledgedNormalAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_alarmUnacknowledgedNormal
}
//--------------------------------------------------------
/**
 *	Read attribute alarmShelved related method
 *	Description: List of alarms in shelved state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void AlarmHandler::read_alarmShelved(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AlarmHandler::read_alarmShelved(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_alarmShelved) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_alarmShelved_read, shelvedAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_alarmShelved
}
//--------------------------------------------------------
/**
 *	Read attribute alarmOutOfService related method
 *	Description: List of alarms in out of service state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void AlarmHandler::read_alarmOutOfService(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AlarmHandler::read_alarmOutOfService(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_alarmOutOfService) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_alarmOutOfService_read, outOfServiceAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_alarmOutOfService
}
//--------------------------------------------------------
/**
 *	Read attribute alarmSilenced related method
 *	Description: List of alarms in silenced state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void AlarmHandler::read_alarmSilenced(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AlarmHandler::read_alarmSilenced(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_alarmSilenced) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_alarmSilenced_read, silencedAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_alarmSilenced
}
//--------------------------------------------------------
/**
 *	Read attribute alarmList related method
 *	Description: List of all alarms
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void AlarmHandler::read_alarmList(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AlarmHandler::read_alarmList(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_alarmList) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_alarmList_read, listAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_alarmList
}
//--------------------------------------------------------
/**
 *	Read attribute alarmFrequency related method
 *	Description: List of frequency of evaluation of all alarms
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void AlarmHandler::read_alarmFrequency(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AlarmHandler::read_alarmFrequency(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_alarmFrequency) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_alarmFrequency_read, listAlarms_sz);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_alarmFrequency
}
//--------------------------------------------------------
/**
 *	Read attribute alarmSummary related method
 *	Description: 
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void AlarmHandler::read_alarmSummary(Tango::Attribute &attr)
{
	DEBUG_STREAM << "AlarmHandler::read_alarmSummary(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_alarmSummary) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_alarmSummary_read, alarmSummary_sz);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_alarmSummary
}

//--------------------------------------------------------
/**
 *	Read attribute AlarmState related method
 *	Description: 
 *
 *	Data type:	Tango::DevEnum (AlarmStateEnum)
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void AlarmHandler::read_AlarmState(Tango::Attribute &attr)
{
	DEBUG_STREAM << "AlarmHandler::read_AlarmState(Tango::Attribute &attr) entering... " << endl;
	Tango::DevEnum	*att_value = get_AlarmState_data_ptr(attr.get_name());
	/*----- PROTECTED REGION ID(AlarmHandler::read_AlarmState) ENABLED START -----*/
	string reason("");
	string desc("");
	string origin("");
	int quality = Tango::ATTR_VALID;
	alarms.vlock->readerIn();
	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 << "AlarmHandler::read_AlarmState: " << attr.get_name() << " desc=" << desc << endl;
	alarms.vlock->readerOut();
	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 -----*/	//	AlarmHandler::read_AlarmState
}
//--------------------------------------------------------
/**
 *	Read attribute AlarmFormula related method
 *	Description: 
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void AlarmHandler::read_AlarmFormula(Tango::Attribute &attr)
{
	DEBUG_STREAM << "AlarmHandler::read_AlarmFormula(Tango::Attribute &attr) entering... " << endl;
	Tango::DevString	*att_value = get_AlarmFormula_data_ptr(attr.get_name());
	/*----- PROTECTED REGION ID(AlarmHandler::read_AlarmFormula) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(att_value);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_AlarmFormula
}
//--------------------------------------------------------
/**
 *	Method      : AlarmHandler::add_dynamic_attributes()
 *	Description : Create the dynamic attributes if any
 *                for specified device.
 */
//--------------------------------------------------------
void AlarmHandler::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(AlarmHandler::add_dynamic_attributes) ENABLED START -----*/
	
	//	Add your own code to create and add dynamic attributes if any
	alarms.vlock->readerIn();
	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");
#if _FORMULA_ATTR
			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 = Tango::string_dup(i->second.formula.c_str());
			i->second.attr_value_formula = attr_value_formula;
#endif
		}
	}
	alarms.vlock->readerOut();
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::add_dynamic_attributes
}

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

			//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)
			{
				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 << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
				}
			}
			found->ack = ACK;
		}
		alarmedlock->readerOut();
		alarms.vlock->readerOut();
	}
	/*
	 * 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 << "AlarmHandler::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("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_change_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_change_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		push_change_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_change_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_change_event("alarmAudible",attr_alarmAudible_read);
		push_change_event("alarmSummary",attr_alarmSummary_read);
		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);
		push_archive_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_archive_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_archive_event("alarmAudible",attr_alarmAudible_read);
		push_archive_event("alarmSummary",attr_alarmSummary_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 -----*/	//	AlarmHandler::ack
}
//--------------------------------------------------------
/**
 *	Command Load related method
 *	Description: Load a new alarm.
 *
 *	@param argin Alarm entry
 */
//--------------------------------------------------------
void AlarmHandler::load(Tango::DevString argin)
{
	DEBUG_STREAM << "AlarmHandler::Load()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::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;
		WARN_STREAM << "AlarmHandler::load(): " << err.str() << endl;
		Tango::Except::throw_exception( \
				(const char*)"AlarmHandler::load()", \
				err.str(), \
				(const char*)"AlarmHandler::load()", Tango::ERR);
	}
	
	try {
		add_alarm(alm);
	} catch (string& err) {
		WARN_STREAM << "AlarmHandler::load(): " << err << endl;
		Tango::Except::throw_exception( \
				(const char*)"AlarmHandler::load()", \
				(const char*)err.c_str(), \
				(const char*)"AlarmHandler::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 << "AlarmHandler::" << __func__<<": alarm '" << alm.name << "' cannot push att_conf event, err="<<e.errors[0].desc ;
		INFO_STREAM << o.str() << endl;
	}
#endif
#if 0
	try {
		add_event(alm, evn);
	} catch (string& err) {
		WARN_STREAM << "AlarmHandler::load(): " << err << endl;
		alarms.vlock->writerIn();
		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
		alarms.vlock->writerOut();
		Tango::Except::throw_exception( \
				(const char*)"AlarmHandler::load()", \
				(const char*)err.c_str(), \
				(const char*)"AlarmHandler::load()", Tango::ERR);
	}
#endif
	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));

	alarms.vlock->readerIn();
	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 << "AlarmHandler::"<<__func__<<": string exception=" << err << endl;
			//TODO: handle error
#if 0
			for(vector<string>::iterator j = evn.begin(); j != evn.end(); j++)
			{
				DEBUG_STREAM << "AlarmHandler::"<<__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 << "AlarmHandler::"<<__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 << "AlarmHandler::"<<__func__<<": event=" << *j << " no more used, REMOVED!!!" << endl;
					}
				}
			}
			set_internal_alarm(INTERNAL_ERROR, gettime(), err);
#endif
		}
		catch (Tango::DevFailed &e) {
			WARN_STREAM << "AlarmHandler::"<<__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";
					ERROR_STREAM << "AlarmHandler::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 << "AlarmHandler::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;
				WARN_STREAM << "AlarmHandler::load(): " << err.str() << endl;
				set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());
			}
		}

		if(i->second.cmd_name_n.length() > 0)
		{
			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_n);
				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";
					ERROR_STREAM << "AlarmHandler::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 << "AlarmHandler::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;
				WARN_STREAM << "AlarmHandler::load(): " << err.str() << endl;
				set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());
			}				
		}
		DEBUG_STREAM << "AlarmHandler::"<<__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 << "AlarmHandler::"<<__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);
		}
	}
	alarms.vlock->readerOut();


#if 0//TODO
	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;
	}
#endif

	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::load
}
//--------------------------------------------------------
/**
 *	Command Remove related method
 *	Description: Remove alarm.
 *
 *	@param argin Alarm name
 */
//--------------------------------------------------------
void AlarmHandler::remove(Tango::DevString argin)
{
	DEBUG_STREAM << "AlarmHandler::Remove()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::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.";
		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*)"AlarmHandler::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*)"AlarmHandler::remove", Tango::ERR);
	}
	if (ret) {
		DEBUG_STREAM << "AlarmHandler::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("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_change_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_change_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		push_change_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_change_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_change_event("alarmAudible",attr_alarmAudible_read);
		push_change_event("alarmSummary",attr_alarmSummary_read);
		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);
		push_archive_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_archive_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_archive_event("alarmAudible",attr_alarmAudible_read);
		push_archive_event("alarmSummary",attr_alarmSummary_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 -----*/	//	AlarmHandler::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 *AlarmHandler::search_alarm(Tango::DevString argin)
{
	Tango::DevVarStringArray *argout;
	DEBUG_STREAM << "AlarmHandler::SearchAlarm()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::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 << "AlarmHandler::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;
	alarms.vlock->readerIn();
	for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++) 
	{
		found = 0;
		if(filter_begin.length() != 0)
		{
			found = ai->first.find(filter_begin);
		}
		if((filter_begin.length() == 0) || (found != string::npos))
		{
			ostringstream os;
			os.clear();
			os << ai->second.ts.tv_sec << SEP << KEY(NAME_KEY) << ai->second.name << SEP << KEY(FORMULA_KEY) << ai->second.formula << SEP << KEY(ONDELAY_KEY) << ai->second.on_delay << SEP << KEY(OFFDELAY_KEY) << ai->second.off_delay <<
				SEP << KEY(LEVEL_KEY) << ai->second.lev << SEP << KEY(SILENT_TIME_KEY) << ai->second.silent_time << SEP << KEY(GROUP_KEY) << ai->second.grp2str() << SEP << KEY(MESSAGE_KEY) << ai->second.msg <<
				SEP << KEY(ON_COMMAND_KEY) << ai->second.cmd_name_a << SEP << KEY(OFF_COMMAND_KEY) << ai->second.cmd_name_n << SEP << KEY(ENABLED_KEY) << (ai->second.enabled ? "1" : "0");
			alarm_filtered.push_back(os.str());
		}
	}  /* for */
	alarms.vlock->readerOut();
	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 -----*/	//	AlarmHandler::search_alarm
	return argout;
}
//--------------------------------------------------------
/**
 *	Command StopAudible related method
 *	Description: Stop audible indications on the GUI
 *
 */
//--------------------------------------------------------
void AlarmHandler::stop_audible()
{
	DEBUG_STREAM << "AlarmHandler::StopAudible()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::stop_audible) 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;
	alarms.vlock->readerIn();
	for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++) {
		ai->second.is_new = 0;		//set all alarm as no more new
	}
	alarms.vlock->readerOut();

	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("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_change_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_change_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		push_change_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_change_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_change_event("alarmAudible",attr_alarmAudible_read);
		push_change_event("alarmSummary",attr_alarmSummary_read);
		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);
		push_archive_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_archive_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_archive_event("alarmAudible",attr_alarmAudible_read);
		push_archive_event("alarmSummary",attr_alarmSummary_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 -----*/	//	AlarmHandler::stop_audible
}
//--------------------------------------------------------
/**
 *	Command Silence related method
 *	Description: Alarm temporarily silence
 *
 *	@param argin String array containing the alarms to be silenced
 */
//--------------------------------------------------------
void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
{
	DEBUG_STREAM << "AlarmHandler::Silence()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::silence) ENABLED START -----*/
	
	//	Add your own code
	vector<string> str;
	str << (*argin);
	vector<string>::iterator si;

	for (si = str.begin(); si != str.end(); si++)
	{
		alarms.vlock->readerIn();
		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;
					i->second.shelved = false;
				}
			}
			if(i->second.silenced > 0)
			{
				ostringstream err;
				err << "Alarm " << *si << " already silenced for " << i->second.silenced << " more minutes";
				alarms.vlock->readerOut();
				Tango::Except::throw_exception( \
							(const char*)"Alarm already silenced", \
							err.str(), \
							(const char*)"AlarmHandler::silence()", Tango::ERR);
			}
			if(i->second.silent_time <= 0)
			{
				ostringstream err;
				err << "Alarm " << *si << " cannot be silenced";
				alarms.vlock->readerOut();
				Tango::Except::throw_exception( \
							(const char*)"Alarm cannot be silenced", \
							err.str(), \
							(const char*)"AlarmHandler::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())
		{
			alarms.vlock->readerOut();
			ostringstream err;
			err << "Alarm " << *si << " not found";
			Tango::Except::throw_exception( \
						(const char*)"Alarm not found!!", \
						err.str(), \
						(const char*)"AlarmHandler::silence()", Tango::ERR);
		}
		alarms.vlock->readerOut();
	}

	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("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_change_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_change_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		push_change_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_change_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_change_event("alarmAudible",attr_alarmAudible_read);
		push_change_event("alarmSummary",attr_alarmSummary_read);
		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);
		push_archive_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_archive_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_archive_event("alarmAudible",attr_alarmAudible_read);
		push_archive_event("alarmSummary",attr_alarmSummary_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 -----*/	//	AlarmHandler::silence
}
//--------------------------------------------------------
/**
 *	Command Modify related method
 *	Description: Modify an existing alarm.
 *
 *	@param argin Alarm entry
 */
//--------------------------------------------------------
void AlarmHandler::modify(Tango::DevString argin)
{
	DEBUG_STREAM << "AlarmHandler::Modify()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::modify) ENABLED START -----*/
	
	//	Add your own code
	DEBUG_STREAM << "AlarmHandler::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;
	alm.silent_time = -1;
	alm.silenced = -1;
	alm.cmd_name_a.clear();
	alm.cmd_dp_a.clear();
	alm.cmd_action_a.clear();
	alm.send_arg_a = false;
	alm.dp_a = NULL;
	alm.cmd_name_n.clear();
	alm.cmd_dp_n.clear();
	alm.cmd_action_n.clear();
	alm.send_arg_n = false;
	alm.dp_n = NULL;
	alm.enabled=true;
	alm.shelved=false;

	alm.formula_tree =
	//boost::spirit::tree_parse_info< std::string::iterator, factory_t> tmp =
	ast_parse<factory_t>(alarm_string.begin(), alarm_string.end(), al_gr, space_p);	//parse string s with grammar al_gr, skipping white spaces
	if (alm.formula_tree.full)
	{
    	std::transform(alm.name.begin(), alm.name.end(), alm.name.begin(), (int(*)(int))tolower);		//transform to lowercase
    	//std::transform(alm.formula.begin(), alm.formula.end(), alm.formula.begin(), (int(*)(int))tolower);		//transform to lowercase: incorrect, state has to be written upercase
    	std::transform(alm.lev.begin(), alm.lev.end(), alm.lev.begin(), (int(*)(int))tolower);		//transform to lowercase

    	if(alm.cmd_name_a.length() > 0)
    	{
			const char *c = alm.cmd_name_a.c_str();
			int j = 0;
			while (*c) {
				if (*c == '/')
					j++;
				if (j < 3)
					alm.cmd_dp_a.push_back(*c);
				else if (*c != '/')
					alm.cmd_action_a.push_back(*c);
				c++;
			}
    	}
    	if(alm.cmd_name_n.length() > 0)
    	{
			const char *c = alm.cmd_name_n.c_str();
			int j = 0;
			while (*c) {
				if (*c == '/')
					j++;
				if (j < 3)
					alm.cmd_dp_n.push_back(*c);
				else if (*c != '/')
					alm.cmd_action_n.push_back(*c);
				c++;
			}
    	}

	}
    else
    {
       	ostringstream o;
		o << __func__<<": Parsing Failed, parsed up to '" << string(alarm_string.begin(), alm.formula_tree.stop) << "' not parsed '" << string(alm.formula_tree.stop, alarm_string.end()) << "'"; //TODO
       	DEBUG_STREAM << o.str() << endl;
       	Tango::Except::throw_exception( \
				(const char*)"Parsing Failed!", \
				(const char*)o.str().c_str(), \
				(const char*)__func__, Tango::ERR);
    }

	DEBUG_STREAM << "AlarmHandler::Modify: parsing ended: alm name=" << alm.name << endl;
	//------------------------------
	//2: if alarm already exist and
	//   formula is not changed
	//------------------------------
	alarms.vlock->writerIn();
	alarm_container_t::iterator i = alarms.v_alarm.find(alm.name);
	if (i != alarms.v_alarm.end())
	{
		if(i->second.formula == alm.formula)
		{
			Tango::TimeVal ts = gettime();
			string cmd_name_full = alm.cmd_name_a + string(";") + alm.cmd_name_n;

			if ((alm.name.empty() == false) && \
					(alm.formula.empty() == false) && \
					((alm.lev==LEV_LOG)||(alm.lev==LEV_WARNING)|| \
					(alm.lev==LEV_FAULT)||(alm.lev.empty() == true))) {
				i->second.stat = S_NORMAL;
				i->second.ack = ACK;
				i->second.done = false;

				i->second.msg = alm.msg;
				i->second.lev = alm.lev;
				i->second.grp = alm.grp;
				//i->second.to_be_evaluated = alm.to_be_evaluated;
				i->second.on_delay = alm.on_delay;
				i->second.off_delay = alm.off_delay;
				i->second.silent_time = alm.silent_time;
				i->second.silenced = (i->second.silent_time > 0) ? 0 : -1;	//0: can be silenced, -1: cannot be silencedd;
				i->second.cmd_name_a = alm.cmd_name_a;
				i->second.cmd_dp_a = alm.cmd_dp_a;
				i->second.cmd_action_a = alm.cmd_action_a;
				//i->second.send_arg_a = alm.send_arg_a;
				i->second.cmd_name_n = alm.cmd_name_n;
				i->second.cmd_dp_n = alm.cmd_dp_n;
				i->second.cmd_action_n = alm.cmd_action_n;
				//i->second.send_arg_n = alm.send_arg_n;
				i->second.enabled = alm.enabled;

			} else {
				ostringstream o;
				o << __func__<<": syntax error in '" << alarm_string << "'";
				WARN_STREAM << o.str() << endl;
				alarms.vlock->writerOut();
				Tango::Except::throw_exception( \
						(const char*)o.str().c_str(), \
						(const char*)"", \
						(const char*)__func__, Tango::ERR);
			}

			//update attribute properties
			events->update_property();

			//delete proxy for actions
			if(i->second.dp_a)
				delete i->second.dp_a;
			i->second.dp_a = NULL;
			if(i->second.dp_n)
				delete i->second.dp_n;
			i->second.dp_n = NULL;

			if(alm.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";
						ERROR_STREAM << __func__<<": " << 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 << __func__<<": 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;
					WARN_STREAM << __func__<<": " << err.str() << endl;
					set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());
				}
			}
			if(alm.cmd_name_n.length() > 0)
			{
				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";
						ERROR_STREAM << __func__<<": " << 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 << __func__<<": 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;
					WARN_STREAM << __func__<<": " << err.str() << endl;
					set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());
				}
			}
			alarms.vlock->writerOut();
			return;
		}
	}
	else
	{
		alarms.vlock->writerOut();
       	ostringstream o;
       	o << "Alarm '"<<alm.name<<"' not found";
       	DEBUG_STREAM << o.str() << endl;
       	Tango::Except::throw_exception( \
				(const char*)"Not found", \
				(const char*)o.str().c_str(), \
				(const char*)__func__, Tango::ERR);
	}
	alarms.vlock->writerOut();

	//------------------------------
	//3: remove (set active=0 on db)
	//------------------------------
	remove((Tango::DevString)alm.name.c_str());
	DEBUG_STREAM << "AlarmHandler::Modify: removed alm name=" << alm.name << endl;
	//------------------------------
	//4: load modified alarm
	//------------------------------
	load(argin);

	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("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_change_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_change_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		push_change_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_change_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_change_event("alarmAudible",attr_alarmAudible_read);
		push_change_event("alarmSummary",attr_alarmSummary_read);
		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);
		push_archive_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_archive_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_archive_event("alarmAudible",attr_alarmAudible_read);
		push_archive_event("alarmSummary",attr_alarmSummary_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 -----*/	//	AlarmHandler::modify
}
//--------------------------------------------------------
/**
 *	Command Shelve related method
 *	Description: Shelve an alarm: no state transition recorded, no audible nor visual indication
 *
 *	@param argin String array containing alarm to be shelved
 */
//--------------------------------------------------------
void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
{
	DEBUG_STREAM << "AlarmHandler::Shelve()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::shelve) ENABLED START -----*/
	
	//	Add your own code
	vector<string> str;
	str << (*argin);
	vector<string>::iterator si;

	for (si = str.begin(); si != str.end(); si++)
	{
		alarms.vlock->readerIn();
		alarm_container_t::iterator i = alarms.v_alarm.find(*si);
		if(i == alarms.v_alarm.end())
		{
			ostringstream err;
			err << *si << " not found in configured alarms";
			alarms.vlock->readerOut();
			Tango::Except::throw_exception( \
				(const char*)"NOT_FOUND", \
				(const char*)err.str().c_str(), \
				(const char*)__func__, Tango::ERR);
		}
		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();
			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)//TODO: shelve_time ?
			{
				i->second.silenced = i->second.silent_time - floor(dminutes);//TODO: shelve_time ?
			}
			else
			{
				i->second.silenced = 0;
				i->second.shelved = false;
			}
		}
		if(i->second.shelved)
		{
			ostringstream err;
			err << *si << " is already shelved";
			alarms.vlock->readerOut();
			Tango::Except::throw_exception( \
				(const char*)"ALREADY_SHELVED", \
				(const char*)err.str().c_str(), \
				(const char*)__func__, Tango::ERR);
		}
		if(i->second.silent_time <= 0)
		{
			ostringstream err;
			err << "Alarm " << *si << " cannot be shelved";
			alarms.vlock->readerOut();
			Tango::Except::throw_exception( \
						(const char*)"NOT_ALLOWED", \
						err.str(), \
						(const char*)__func__, Tango::ERR);
		}
		alarms.vlock->readerOut();
	}

	for (si = str.begin(); si != str.end(); si++)
	{
		alarms.vlock->readerIn();
		alarm_container_t::iterator i = alarms.v_alarm.find(*si);
		if(i == alarms.v_alarm.end())
			continue;
		i->second.shelved = true;

		//load silent time
		i->second.ts_time_silenced = gettime();
		i->second.silenced = i->second.silent_time;	//TODO: shelve_time ?
		//search also in alarmed
		alarmedlock->writerIn();
		vector<alarm_t>::iterator found = \
				find(alarmed.begin(), alarmed.end(), *si);
		if (found != alarmed.end())
		{
			alarmed.erase(found);
		}
		alarmedlock->writerOut();


		Tango::DevEnum *attr_value = get_AlarmState_data_ptr(i->second.attr_name);

		*attr_value = _SHLVD;
		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 << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
		}
		alarms.vlock->readerOut();
	}

	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("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_change_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_change_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		push_change_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_change_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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_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);
		push_archive_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_archive_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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);
	} 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 -----*/	//	AlarmHandler::shelve
}
//--------------------------------------------------------
/**
 *	Command Enable related method
 *	Description: Enable an alarm from Out of service state
 *
 *	@param argin Alarm name
 */
//--------------------------------------------------------
void AlarmHandler::enable(Tango::DevString argin)
{
	DEBUG_STREAM << "AlarmHandler::Enable()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::enable) ENABLED START -----*/
	
	//	Add your own code
	string arginname(argin);

	alarms.vlock->readerIn();
	alarm_container_t::iterator i = alarms.v_alarm.find(arginname);
	if(i == alarms.v_alarm.end())
	{
		ostringstream err;
		err << arginname << " not found in configured alarms";
		alarms.vlock->readerOut();
		Tango::Except::throw_exception( \
			(const char*)"NOT_FOUND", \
			(const char*)err.str().c_str(), \
			(const char*)__func__, Tango::ERR);
	}

	i->second.enabled = true;

	i->second.silenced = (i->second.silent_time > 0) ? 0 : -1;	//0: can be silenced, -1: cannot be silenced
	i->second.shelved = false;

	Tango::DevEnum *attr_value = get_AlarmState_data_ptr(i->second.attr_name);

	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 << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
	}

	alarms.vlock->readerOut();

	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("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_change_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_change_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		push_change_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_change_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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_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);
		push_archive_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_archive_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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);
	} catch(Tango::DevFailed& e)
	{
		ostringstream err;
		err << "error pushing alarm change event err=" << e.errors[0].desc;
		INFO_STREAM << __func__<<": " << err.str() << endl;
	}
	//update attribute properties
	events->update_property();
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::enable
}
//--------------------------------------------------------
/**
 *	Command Disable related method
 *	Description: Put an alarm in Out of service state
 *
 *	@param argin Alarm name
 */
//--------------------------------------------------------
void AlarmHandler::disable(Tango::DevString argin)
{
	DEBUG_STREAM << "AlarmHandler::Disable()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::disable) ENABLED START -----*/
	
	//	Add your own code
	string arginname(argin);

	alarms.vlock->readerIn();
	alarm_container_t::iterator i = alarms.v_alarm.find(arginname);
	if(i == alarms.v_alarm.end())
	{
		ostringstream err;
		err << arginname << " not found in configured alarms";
		alarms.vlock->readerOut();
		Tango::Except::throw_exception( \
			(const char*)"NOT_FOUND", \
			(const char*)err.str().c_str(), \
			(const char*)__func__, Tango::ERR);
	}

	i->second.enabled = false;

	i->second.silenced = (i->second.silent_time > 0) ? 0 : -1;	//0: can be silenced, -1: cannot be silenced
	i->second.shelved = false;

	Tango::DevEnum *attr_value = get_AlarmState_data_ptr(i->second.attr_name);

	*attr_value = _OOSRV;
	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 << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
	}

	alarms.vlock->readerOut();

	/*
	 * remove from alarmed
	 */
	bool go = true;
	while (go) {
		alarmedlock->writerIn();
		vector<alarm_t>::iterator found = \
				find(alarmed.begin(), alarmed.end(), arginname);
		if (found != alarmed.end()) {
			DEBUG_STREAM << "AlarmHandler::"<<__func__<<": " << found->name \
					 				 << " 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("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_change_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_change_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		push_change_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_change_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_change_event("alarmAudible",attr_alarmAudible_read);
		push_change_event("alarmSummary",attr_alarmSummary_read);
		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);
		push_archive_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_archive_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_archive_event("alarmAudible",attr_alarmAudible_read);
		push_archive_event("alarmSummary",attr_alarmSummary_read);
	} catch(Tango::DevFailed& e)
	{
		ostringstream err;
		err << "error pushing alarm change event err=" << e.errors[0].desc;
		INFO_STREAM << __func__<<": " << err.str() << endl;
	}
	//update attribute properties
	events->update_property();
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::disable
}
//--------------------------------------------------------
/**
 *	Command ResetStatistics related method
 *	Description: Reset statistics
 *
 */
//--------------------------------------------------------
void AlarmHandler::reset_statistics()
{
	DEBUG_STREAM << "AlarmHandler::ResetStatistics()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::reset_statistics) ENABLED START -----*/
	
	//	Add your own code
	alarms.vlock->readerIn();
	for(alarm_container_t::iterator i = alarms.v_alarm.begin(); i!= alarms.v_alarm.end(); i++)
	{
		i->second.freq_counter = 0;
	}
	timespec now;
	clock_gettime(CLOCK_MONOTONIC, &now);
	double dnow = (now.tv_sec) + ((double)(now.tv_nsec))/1000000000;
	last_statistics_reset_time = dnow;
	alarms.vlock->readerOut();
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::reset_statistics
}
//--------------------------------------------------------
/**
 *	Command StopNew related method
 *	Description: Stop audible indications on the GUI
 *
 */
//--------------------------------------------------------
void AlarmHandler::stop_new()
{
	DEBUG_STREAM << "AlarmHandler::StopNew()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::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;
	alarms.vlock->readerIn();
	for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++) {
		ai->second.is_new = 0;		//set all alarm as no more new
	}
	alarms.vlock->readerOut();

	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("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_change_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_change_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		push_change_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_change_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_change_event("alarmAudible",attr_alarmAudible_read);
		push_change_event("alarmSummary",attr_alarmSummary_read);
		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);
		push_archive_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_archive_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_archive_event("alarmAudible",attr_alarmAudible_read);
		push_archive_event("alarmSummary",attr_alarmSummary_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 -----*/	//	AlarmHandler::stop_new
}
//--------------------------------------------------------
/**
 *	Command GetAlarmInfo related method
 *	Description: Returns the complete attribute info as an array of key=value
 *
 *	@param argin Alarm name followed optionally by wanted key names
 *	@returns Complete attribute info as an array of key=value
 */
//--------------------------------------------------------
Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarStringArray *argin)
{
	Tango::DevVarStringArray *argout;
	DEBUG_STREAM << "AlarmHandler::GetAlarmInfo()  - " << device_name << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::get_alarm_info) ENABLED START -----*/
	
	if(argin->length() < 1)
	{
       	Tango::Except::throw_exception( \
				(const char*)"BAD PARAMETERS", \
				(const char*)"At least alarm name expected", \
				(const char*)__func__, Tango::ERR);
	}
	//	Add your own code
	alarms.vlock->readerIn();

	alarm_container_t::iterator it = alarms.v_alarm.find(string((*argin)[0]));
	map<string,string> info;
	vector<string> complete;

	if(it == alarms.v_alarm.end())
	{
		alarms.vlock->readerOut();
       	ostringstream o;
		o << "Alarm '" << argin << "' not found";
       	DEBUG_STREAM <<__func__ << ": " << o.str() << endl;
       	Tango::Except::throw_exception( \
				(const char*)"NOT FOUND", \
				(const char*)o.str().c_str(), \
				(const char*)__func__, Tango::ERR);
	}

	info.insert(make_pair(NAME_KEY,it->first));
	complete.push_back(KEY(NAME_KEY)+it->first);

	Tango::MultiAttribute *m_attr = get_device_attr();
	int attr_ind = m_attr->get_attr_ind_by_name(it->second.attr_name.c_str());
	Tango::Attribute &attribute = m_attr->get_attr_by_ind(attr_ind);

	ostringstream tmp_val;
	vector<string> enum_labels = attribute.get_enum_labels();
	if(*(it->second.attr_value) >= 0 && *(it->second.attr_value) < enum_labels.size())
		tmp_val << enum_labels[*(it->second.attr_value)];
	else
		tmp_val << "UNKNOWN_ENUM(" << *(it->second.attr_value) << ")";

	ostringstream tmp_ex;
	tmp_ex.str("");
	if(it->second.ex_reason.length() > 0 || it->second.ex_desc.length() > 0 || it->second.ex_origin.length() > 0)
	{
		tmp_ex << "{\"Reason\":\"" << it->second.ex_reason << "\",\"Desc\":\"" << it->second.ex_desc << "\",\"Origin\":\"" << it->second.ex_origin << "\"}";
		info.insert(make_pair(VALUE_KEY,string("ERROR")));
		complete.push_back(KEY(VALUE_KEY)+string("ERROR"));
		info.insert(make_pair(FORMULA_KEY,it->second.formula));
		complete.push_back(KEY(FORMULA_KEY)+it->second.formula);
		info.insert(make_pair(ATTR_VALUES_KEY,tmp_ex.str()));
		complete.push_back(KEY(ATTR_VALUES_KEY)+tmp_ex.str());
	}
	else
	{
		info.insert(make_pair(VALUE_KEY,tmp_val.str()));
		complete.push_back(KEY(VALUE_KEY)+tmp_val.str());
		info.insert(make_pair(FORMULA_KEY,it->second.formula));
		complete.push_back(KEY(FORMULA_KEY)+it->second.formula);
		info.insert(make_pair(ATTR_VALUES_KEY,it->second.attr_values));
		complete.push_back(KEY(ATTR_VALUES_KEY)+it->second.attr_values);
	}



	ostringstream tmp_qual;
	try
	{
		tmp_qual << quality_labels.at(it->second.quality);
	} catch(std::out_of_range& ex)
	{
		tmp_qual << it->second.quality;
	}
	info.insert(make_pair(QUALITY_KEY,tmp_qual.str()));
	complete.push_back(KEY(QUALITY_KEY)+tmp_qual.str());
	ostringstream tmp;
//#if 0
	tmp.str("");
	tmp << (it->second.enabled ? "1" : "0");
	info.insert(make_pair(ENABLED_KEY,tmp.str()));	//TODO: redundant, information already in attr_value
	complete.push_back(KEY(ENABLED_KEY)+tmp.str());	//TODO: redundant, information already in attr_value
	tmp.str("");
	tmp << (it->second.shelved ? "1" : "0");
	info.insert(make_pair(SHELVED_KEY,tmp.str()));	//TODO: redundant, information already in attr_value
	complete.push_back(KEY(SHELVED_KEY)+tmp.str());	//TODO: redundant, information already in attr_value
	tmp.str("");
	tmp << ((it->second.ack == "ACK") ? "1" : "0");
	info.insert(make_pair(ACKNOWLEDGED_KEY,tmp.str()));	//TODO: redundant, information already in attr_value
	complete.push_back(KEY(ACKNOWLEDGED_KEY)+tmp.str());	//TODO: redundant, information already in attr_value
//#endif
	tmp.str("");
	tmp << (it->second.is_new ? "1" : "0");
	info.insert(make_pair(AUDIBLE_KEY,tmp.str()));
	complete.push_back(KEY(AUDIBLE_KEY)+tmp.str());
	tmp.str("");
	if(it->second.stat == S_ALARM)
	{
		tmp << (it->second.on_counter);
	}
	else
	{
		tmp << (it->second.off_counter);
	}
	info.insert(make_pair(COUNTER_KEY,tmp.str()));
	complete.push_back(KEY(COUNTER_KEY)+tmp.str());
	tmp.str("");
	tmp << (it->second.freq_counter);
	info.insert(make_pair(FREQ_COUNTER_KEY,tmp.str()));
	complete.push_back(KEY(FREQ_COUNTER_KEY)+tmp.str());

	tmp.str("");
	tmp << (it->second.on_delay);
	info.insert(make_pair(ONDELAY_KEY,tmp.str()));
	complete.push_back(KEY(ONDELAY_KEY)+tmp.str());
	tmp.str("");
	tmp << (it->second.on_delay);
	info.insert(make_pair(OFFDELAY_KEY,tmp.str()));
	complete.push_back(KEY(OFFDELAY_KEY)+tmp.str());
	info.insert(make_pair(LEVEL_KEY,it->second.lev));
	complete.push_back(KEY(LEVEL_KEY)+it->second.lev);
	tmp.str("");
	tmp << (it->second.silent_time);
	info.insert(make_pair(SILENT_TIME_KEY,tmp.str()));
	complete.push_back(KEY(SILENT_TIME_KEY)+tmp.str());
	tmp.str("");
	tmp << (it->second.silenced);
	info.insert(make_pair(SILENT_TIME_REMAINING_KEY,tmp.str()));
	complete.push_back(KEY(SILENT_TIME_REMAINING_KEY)+tmp.str());
	info.insert(make_pair(GROUP_KEY,it->second.grp2str()));
	complete.push_back(KEY(GROUP_KEY)+it->second.grp2str());
	tmp.str("");
	tmp << "\"" << it->second.msg << "\"";
	info.insert(make_pair(MESSAGE_KEY,tmp.str()));
	complete.push_back(KEY(MESSAGE_KEY)+tmp.str());
	info.insert(make_pair(ON_COMMAND_KEY,it->second.cmd_name_a));
	complete.push_back(KEY(ON_COMMAND_KEY)+it->second.cmd_name_a);
	info.insert(make_pair(OFF_COMMAND_KEY,it->second.cmd_name_n));
	complete.push_back(KEY(OFF_COMMAND_KEY)+it->second.cmd_name_n);

	alarms.vlock->readerOut();
	argout = new Tango::DevVarStringArray();
	if(argin->length() == 1)
	{
		argout->length(complete.size());
		for(size_t i=0; i<complete.size(); i++)
			(*argout)[i] = Tango::string_dup(complete[i].c_str());
	}
	else
	{
		vector<string> out;
		//out.push_back(NAME_KEY + string("=") + it->first);
		for(size_t arg_i=0; arg_i < argin->length()-1; arg_i++)
		{
			map<string,string>::iterator it2 = info.find(string((*argin)[arg_i+1]));
			if(it2 != info.end())
			{
				out.push_back(it2->first + string("=") + it2->second);
			}
		}
		argout->length(out.size()/*+1*/);
		vector<string>::iterator it3;
		size_t i=0;
		for(it3=out.begin(); it3!=out.end(); it3++)
		{
			(*argout)[i] = Tango::string_dup(it3->c_str());
			i++;
		}
	}
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::get_alarm_info
	return argout;
}
//--------------------------------------------------------
/**
 *	Method      : AlarmHandler::add_dynamic_commands()
 *	Description : Create the dynamic commands if any
 *                for specified device.
 */
//--------------------------------------------------------
void AlarmHandler::add_dynamic_commands()
{
	/*----- PROTECTED REGION ID(AlarmHandler::add_dynamic_commands) ENABLED START -----*/
	
	//	Add your own code to create and add dynamic commands if any
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::add_dynamic_commands
}

/*----- PROTECTED REGION ID(AlarmHandler::namespace_ending) ENABLED START -----*/

//	Additional Methods
/*
 * private methods
 */
void AlarmHandler::load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn)
{	
	DEBUG_STREAM << "AlarmHandler::load_alarm(): Creating Spirit Parser... ->" << alarm_string << endl;
	alarm_parse al_gr(alm);    //  Construct Spirit grammar		
	alm.name.clear();
	alm.attr_name.clear();
	alm.quality = Tango::ATTR_INVALID;
	alm.ex_reason=string("NOT_SUBSCRIBED");
	alm.ex_desc=string("One or more events not subscribed");
	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;
	alm.silent_time = -1;
	alm.silenced = -1;
	alm.cmd_name_a.clear();
	alm.cmd_dp_a.clear();
	alm.cmd_action_a.clear();
	alm.send_arg_a = false;
	alm.dp_a = NULL;	
	alm.cmd_name_n.clear();
	alm.cmd_dp_n.clear();
	alm.cmd_action_n.clear();
	alm.send_arg_n = false;	
	alm.dp_n = NULL;
	alm.enabled = 1;
	evn.clear();	

	alm.formula_tree = 
	//boost::spirit::tree_parse_info< std::string::iterator, factory_t> tmp =
	ast_parse<factory_t>(alarm_string.begin(), alarm_string.end(), al_gr, space_p);	//parse string s with grammar al_gr, skipping white spaces
	if (alm.formula_tree.full)
	{
    	std::transform(alm.name.begin(), alm.name.end(), alm.name.begin(), (int(*)(int))tolower);		//transform to lowercase
    	//replace / with __
    	if(!alm.name.empty())
    	{
    		alm.attr_name = alm.name;
#if 0
			size_t start_pos = 0;
			string from("/");
			string to("__");
			while((start_pos = alm.attr_name.find(from, start_pos)) != std::string::npos)
			{
				alm.attr_name.replace(start_pos, from.length(), to);
				start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
			}
#endif
    	}
    	//std::transform(alm.formula.begin(), alm.formula.end(), alm.formula.begin(), (int(*)(int))tolower);		//transform to lowercase: incorrect, state has to be written uppercase
    	std::transform(alm.lev.begin(), alm.lev.end(), alm.lev.begin(), (int(*)(int))tolower);		//transform to lowercase
    	
    	if(alm.cmd_name_a.length() > 0)
    	{
			const char *c = alm.cmd_name_a.c_str();
			int j = 0;
			while (*c) {
				if (*c == '/')
					j++;
				if (j < 3)
					alm.cmd_dp_a.push_back(*c);
				else if (*c != '/')
					alm.cmd_action_a.push_back(*c);
				c++;
			}    
    	}
    	if(alm.cmd_name_n.length() > 0)
    	{
			const char *c = alm.cmd_name_n.c_str();
			int j = 0;
			while (*c) {
				if (*c == '/')
					j++;
				if (j < 3)
					alm.cmd_dp_n.push_back(*c);
				else if (*c != '/')
					alm.cmd_action_n.push_back(*c);
				c++;
			}    
		}

    	alm.silenced = (alm.silent_time > 0) ? 0 : -1;	//0: can be silenced, -1: cannot be silenced

		DEBUG_STREAM << "Parsing succeeded! ->" << alm.name << endl;
    	find_event_formula(alm.formula_tree,evn);				//populate event list found in this formula 
		ostringstream dbg_msg;
		dbg_msg << "In " << alm.name << " Event =";
		for (vector<string>::iterator i = evn.begin(); i != evn.end(); i++) 
			dbg_msg << *i << ", ";
		dbg_msg;
		DEBUG_STREAM << dbg_msg.str() << endl;	
	}
    else
    {
       	ostringstream o;
		o << "AlarmHandler::load_alarm(): Parsing Failed, '" << string(alarm_string.begin(), alm.formula_tree.stop) << "' parsed ok, BUT '" << string(alm.formula_tree.stop, alarm_string.end()) << "' not parsed"; //TODO
       	DEBUG_STREAM << o.str() << endl;
       	Tango::Except::throw_exception( \
				(const char*)"Parsing Failed!", \
				(const char*)o.str().c_str(), \
				(const char*)"AlarmHandler::load_alarm()", Tango::ERR);
    }	
	alm.ts = gettime();
	DEBUG_STREAM << "AlarmHandler::load_alarm(): name     = '" << alm.name << "'" << endl;
	DEBUG_STREAM << "               attr_name      = '" << alm.attr_name << "'" << endl;
	DEBUG_STREAM << "               formula        = '" << alm.formula << "'" << endl;
	DEBUG_STREAM << "               on_delay       = '" << alm.on_delay << "'" << endl;
	DEBUG_STREAM << "               off_delay      = '" << alm.off_delay << "'" << endl;
	DEBUG_STREAM << "               msg            = '" << alm.msg << "'" << endl;
	DEBUG_STREAM << "               grp            = '" << showbase << hex << alm.grp << "'=" << alm.grp2str() << endl;
	DEBUG_STREAM << "               silent_time    = '" << alm.silent_time << "'" << endl;
	DEBUG_STREAM << "               silenced       = '" << alm.silenced << "'" << endl;
	DEBUG_STREAM << "               lev            = '" << alm.lev << "'" << endl;
	DEBUG_STREAM << "               action_a       = '" << alm.cmd_name_a << "'" << endl;	
	DEBUG_STREAM << "               action_n       = '" << alm.cmd_name_n << "'" << endl;
	DEBUG_STREAM << "               enabled        = '" << (alm.enabled ? "1" : "0") << "'" << endl;
	if ((alm.name.empty() == false) && \
			(alm.formula.empty() == false) && \
			((alm.lev==LEV_LOG)||(alm.lev==LEV_WARNING)|| \
			(alm.lev==LEV_FAULT)||(alm.lev.empty() == true))) {
		alm.stat = S_NORMAL;
		alm.ack = ACK;
		alm.done = false;
//		alm.grp = GR_DEFAULT;
//		alm.lev = LEV_DEFAULT;
	} else {
		ostringstream o;
		o << "AlarmHandler::load_alarm(): syntax error in '" << alarm_string << "'";
		WARN_STREAM << o.str() << endl;
	
		Tango::Except::throw_exception( \
				(const char*)o.str().c_str(), \
				(const char*)"", \
				(const char*)"AlarmHandler::load_alarm()", Tango::ERR);
	}
	if (alarms.exist(alm.name)) {
		ostringstream o;
		o << "AlarmHandler::load_alarm(): alarm '" << alm.name << "' already exist";
		WARN_STREAM << o.str() << endl;
		Tango::Except::throw_exception( \
				(const char*)o.str().c_str(), \
				(const char*)o.str().c_str(), \
				(const char*)"AlarmHandler::load_alarm()", Tango::ERR);
	}
}
#if 0
void AlarmHandler::init_alarms(map< string,vector<string> > &alarm_events)
{
	alarms.vlock->readerIn();
	if (alarms.v_alarm.empty() == false) 
	{
		for (alarm_container_t::iterator i = alarms.v_alarm.begin(); \
			i != alarms.v_alarm.end(); i++) 
		{
			map< string,vector<string> >::iterator f = 					//looking in map for alarm name as key
//				find(alarm_events->begin(), alarm_events->end(), i->name);
				alarm_events.find(i->second.name);
			if(f == alarm_events.end())
				continue;				//ERROR: alarm not found in alarm_event map
			DEBUG_STREAM << "AlarmHandler::init_alarms(): found Alarm= " << i->second.name << endl;
			for(vector<string>::iterator j = f->second.begin(); \
				j != f->second.end(); j++)
			{
				vector<event>::iterator found = \
						find(events->v_event.begin(), events->v_event.end(), (*j));
				DEBUG_STREAM << "AlarmHandler::init_alarms(): looking in events table for Event= " << (*j) << endl;
				if (found != events->v_event.end())
				{
					i->second.insert(found->name);
					found->push_alarm(i->second.name);
					DEBUG_STREAM << "AlarmHandler::init_alarms(): found Event= " << found->name << " <- Alarm= " << i->second.name << endl;
					//break;		???
				}  /* if */
			}	/* for */
		}
	}
	alarms.vlock->readerOut();
}
#endif
void AlarmHandler::init_events(vector<string> &evn)
{
	if (evn.empty() == false) {		
		sort(evn.begin(), evn.end());
		vector<string>::iterator new_end = \
				unique(evn.begin(), evn.end());
		while (evn.end() != new_end) {
			evn.pop_back();
		}
		vector<string>::iterator j = evn.begin();
		while (j != evn.end()) {
			//TODOevents->push_back(event(*j));
			j++;
		}
	}  /* if */
}
void AlarmHandler::add_alarm(alarm_t& a, bool starting) throw(string&)
{
	alarms.push_back(a);
	DEBUG_STREAM << "AlarmHandler::add_alarm(): added alarm '" \
							 << a.name << "'" << endl;
	if(!starting)
	{
		alarm_container_t::iterator italm = alarms.v_alarm.find(a.name);
		add_AlarmState_dynamic_attribute(italm->second.attr_name);
		Tango::DevEnum *attr_value = get_AlarmState_data_ptr(italm->second.attr_name);
		italm->second.attr_value = attr_value;

		italm->second.attr_name_formula = italm->second.attr_name + string("Formula");
#if _FORMULA_ATTR
		add_AlarmFormula_dynamic_attribute(italm->second.attr_name_formula);
		Tango::DevString *attr_value_formula = get_AlarmFormula_data_ptr(italm->second.attr_name_formula);
		*attr_value_formula = Tango::string_dup(italm->second.formula.c_str());
		italm->second.attr_value_formula = attr_value_formula;
#endif
	}

}
void AlarmHandler::add_event(alarm_t& a, vector<string> &evn) throw(string&)
{
	DEBUG_STREAM << "AlarmHandler::add_event(): formula '" << a.formula << "' found " << evn.size() << " events" << endl;
	/*
	 * get the list of all the events in the formula
	 */


	for(vector<string>::iterator j = evn.begin(); j != evn.end(); j++)
	{
		vector<event>::iterator k = \
				find(events->v_event.begin(), events->v_event.end(), *j);
		if (k == events->v_event.end())	//if not already present
		{
			string name=*j;
			vector<string> context;//TODO
			events->add(name, context, UPDATE_PROP, false);//throws exception if already present
		}
	}

	for (vector<string>::iterator j = evn.begin(); j != evn.end(); j++) {
		vector<event>::iterator k = \
				find(events->v_event.begin(), events->v_event.end(), *j);
		if (k != events->v_event.end()) {
			/*
			 * the event already exist; push alarm name
			 * into the per-event alarm list
			 */
			k->push_alarm(a.name);
			a.to_be_evaluated = true;
			DEBUG_STREAM << "AlarmHandler::add_event(): '" << *j << "' found, added " \
									 << " alarm '"  << a.name << "' to list, valid=" << k->valid << endl;
			alarms.vlock->readerIn();
			alarm_container_t::iterator l = alarms.v_alarm.find(a.name);
			if (l != alarms.v_alarm.end()) 
			{
				l->second.insert(*j);			//insert event name in set<string> (s_event) in alarm_t 
			}
			else
			{
				WARN_STREAM << "AlarmHandler::add_event():	error inserting event '" << *j << "' in set of alarm '"
							<< a.name << "'" << endl;
			}
			alarms.vlock->readerOut();
		} 
		else 
		{
			/*
			 * new event; add to event table
			 */
			//event e(*j);
			//events->push_back(e);
			/*
			 * update per-alarm event list
			 */
			DEBUG_STREAM << "AlarmHandler::add_event(): adding '" << *j \
									 << "' to event list of alarm '" << a.name << "'" << endl;
			alarms.vlock->readerIn();
			alarm_container_t::iterator l = alarms.v_alarm.find(a.name);
			if (l != alarms.v_alarm.end()) 
			{			
				l->second.insert(*j);			//insert event name in set<string> in alarm_t 
			}
			else
			{
				WARN_STREAM << "AlarmHandler::add_event():	error inserting event '" << *j << "' in set of alarm '"
							<< a.name << "'" << endl;
			}
			alarms.vlock->readerOut();
			/*
			 * now, for the just-added event
			 */
			k = find(events->v_event.begin(), events->v_event.end(), *j);
			if (k != events->v_event.end())
			{
				k->push_alarm(a.name);
#if 0
				//now initialize value of this attribute
				try {
					Tango::DeviceAttribute attr_value;
					attr_value = k->dp->read_attribute(k->attribute);
					ecb.extract_values(&attr_value, k->value, k->type);
					k->valid = true;
					ostringstream msg;
					msg << "AlarmHandler::add_event(): initial values of " << k->name << " = ";
					for(vector<double>::iterator dd=k->value.begin(); dd!=k->value.end(); dd++)
						msg << (*dd) << " ";
					msg << ", valid=" << k->valid << ends;
					DEBUG_STREAM << msg.str() << endl;
					//delete attr_value;
				} catch(Tango::DevFailed& e)
				{
					TangoSys_MemStream out_stream;
					out_stream << "Failed to read initial value of " << k->name << " = " << e.errors[0].desc << ends;
					k->valid = false;
#if TANGO_VER < 611		//if using subscribe stateless, alarm is not removed if it fails the subscription					
					k->pop_alarm(a.name);		//remove alarm/formula just added to event
					//events->v_event.pop_back();
					events->v_event.erase(k);	//remove event just added to event_table
					//delete attr_value;
#endif										
					throw out_stream.str();
				} catch(string & e) 
				{
					TangoSys_MemStream out_stream;
					out_stream << "Error reading initial value of " << k->name << " = " << e << ends;
					k->pop_alarm(a.name);		//remove alarm/formula just added to event
					//events->v_event.pop_back();
					events->v_event.erase(k);	//remove event just added to event_table
					//delete attr_value;					
					throw out_stream.str();
				}
#endif
			}
		}
	} //for (vector<string>::iterator j = evn.begin(); ...

	for(vector<string>::iterator j = evn.begin(); j != evn.end(); j++)
	{
		vector<event>::iterator k = \
				find(events->v_event.begin(), events->v_event.end(), *j);
		if (k != events->v_event.end())	//if already present
		{
			string name=*j;
			events->start(name);//throws exception if not found
		}
	}
}

/*
 * because called asynchronously by alarm evaluating thread
 * will use an alarm to report errors
 */
void AlarmHandler::do_alarm(bei_t& e)
{
	bool changed=true;
	int num_changed=0;
	//if (e.name == INTERNAL_ERROR) {
	if(e.type == TYPE_TANGO_ERR || e.type == TYPE_GENERIC_ERR)
	{
		ostringstream o;
		o << e.msg << endl;
		WARN_STREAM << "AlarmHandler::"<<__func__<<": " <<  o.str() << endl;
		vector<event>::iterator found_ev = \
			find(events->v_event.begin(), events->v_event.end(), e.ev_name);
		if (found_ev == events->v_event.end())
		{
			//try to remove network domain and FQDN
			string ev_name_str(e.ev_name);
			string::size_type pos_slash = ev_name_str.find("tango://");
			if (pos_slash != string::npos)	//FQDN!!
			{
				//first remove network domain if any
				string::size_type pos_dot = ev_name_str.find(".",8);	//look for first . after tango://
				string::size_type pos_colon = ev_name_str.find(":",8);	//look for first : after tango://
				pos_slash = ev_name_str.find('/',8);					//look for first / after tango://
				if(pos_dot < pos_slash && pos_dot != string::npos && pos_colon != string::npos && pos_slash != string::npos)	//dot is in the TANGO_HOST part
				{
					string ev_name_str_no_domain = ev_name_str.substr(0,pos_dot) + ev_name_str.substr(pos_colon);
					//DEBUG_STREAM << "AlarmHandler::"<<__func__<<": event "<< e.ev_name << " not found, trying without domain: " << ev_name_str_no_domain;
					found_ev = \
								find(events->v_event.begin(), events->v_event.end(), ev_name_str_no_domain);
				}
				if (found_ev == events->v_event.end() && pos_slash != string::npos)
				{
					ev_name_str = ev_name_str.substr(pos_slash + 1);//remove FQDN
					//DEBUG_STREAM << "AlarmHandler::"<<__func__<<": event "<< e.ev_name << " not found, trying without fqdn: " << ev_name_str;
					found_ev = \
								find(events->v_event.begin(), events->v_event.end(), ev_name_str);
				}
			}

			if (found_ev == events->v_event.end())
			{
				/*
				 * shouldn't happen!!!
				 */
				ostringstream o;
				o <<  "TANGO Error but event '" \
					<< e.ev_name << "' not found in event table!";
				WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl;
				set_internal_alarm(e.ev_name, gettime(), o.str());
			}
		}
		if(found_ev != events->v_event.end())
		{
			found_ev->err_counter++;
			if(e.type == TYPE_TANGO_ERR)
				found_ev->ex_reason = string("Event_ERROR");
			else
				found_ev->ex_reason = string("Alarm_ERROR");
			found_ev->ex_desc = o.str();
			found_ev->ex_origin = e.ev_name;
			//LOOP ALARMS IN WHICH THIS EVENT IS USED
			vector<string>::iterator j = found_ev->m_alarm.begin();
			while (j != found_ev->m_alarm.end())
			{
				alarms.vlock->readerIn();
				alarm_container_t::iterator it = alarms.v_alarm.find(*j);
				if(it != alarms.v_alarm.end())
				{
					try
					{
						if(e.type == TYPE_TANGO_ERR)
							it->second.ex_reason = found_ev->ex_reason;
						else
							it->second.ex_reason = found_ev->ex_reason;
						it->second.ex_desc = found_ev->ex_desc;
						it->second.ex_origin = found_ev->ex_origin;
						Tango::DevErrorList errors(1);
						errors.length(1);
						errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str());
						errors[0].severity = Tango::ERR;
						errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str());
						errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str());
						Tango::DevFailed except(errors);
						DEBUG_STREAM << "AlarmHandler::"<<__func__<<": PUSHING EXCEPTION FOR " << it->second.attr_name << " " << it->second.ex_desc << "-" << it->second.ex_reason << "-" << it->second.ex_origin << endl;
						push_change_event(it->second.attr_name, &except);
						push_archive_event(it->second.attr_name, &except);
					}catch(Tango::DevFailed &ex)
					{}
				}
          		alarms.vlock->readerOut();
          		j++;
			}
		}
		return;
	}	
	DEBUG_STREAM << "AlarmHandler::"<<__func__<<": arrived event=" << e.ev_name << endl;
	
	formula_res_t res;
	vector<event>::iterator found = \
			find(events->v_event.begin(), events->v_event.end(), e.ev_name);
	if (found == events->v_event.end())
	{
		//try to remove network domain and FQDN
		string ev_name_str(e.ev_name);
		string::size_type pos_slash = ev_name_str.find("tango://");
		if (pos_slash != string::npos)	//FQDN!!
		{
			//first remove network domain if any
			string::size_type pos_dot = ev_name_str.find(".",8);	//look for first . after tango://
			string::size_type pos_colon = ev_name_str.find(":",8);	//look for first : after tango://
			pos_slash = ev_name_str.find('/',8);					//look for first / after tango://
			if(pos_dot < pos_slash && pos_dot != string::npos && pos_colon != string::npos && pos_slash != string::npos)	//dot is in the TANGO_HOST part
			{
				string ev_name_str_no_domain = ev_name_str.substr(0,pos_dot) + ev_name_str.substr(pos_colon);
				//DEBUG_STREAM << "AlarmHandler::"<<__func__<<": event "<< e.ev_name << " not found, trying without domain: " << ev_name_str_no_domain;
				found = \
							find(events->v_event.begin(), events->v_event.end(), ev_name_str_no_domain);
			}
			if (found == events->v_event.end() && pos_slash != string::npos)
			{
				ev_name_str = ev_name_str.substr(pos_slash + 1);//remove FQDN
				//DEBUG_STREAM << "AlarmHandler::"<<__func__<<": event "<< e.ev_name << " not found, trying without fqdn: " << ev_name_str;
				found = \
							find(events->v_event.begin(), events->v_event.end(), ev_name_str);
			}
		}

		if (found == events->v_event.end())
		{
			/*
			 * shouldn't happen!!!
			 */
			ostringstream o;
			o <<  "event '" \
				<< e.ev_name << "' not found in event table!";
			WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl;
			set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());
		}
	}
	if (found != events->v_event.end())
	{	
		found->value = e.value;
		found->value_string = e.value_string;
		found->quality = e.quality;
		//found->errors = e.errors;
		found->ex_reason = e.ex_reason;
		found->ex_desc = e.ex_desc;
		found->ex_origin = e.ex_origin;
		found->valid = true;
		found->ts = e.ts;
		found->type = e.type;
		found->err_counter = 0;
		vector<string>::iterator j = found->m_alarm.begin();
		while (j != found->m_alarm.end()) 
		{
			DEBUG_STREAM << "AlarmHandler::"<<__func__<<": before do_alarm_eval name=" << *j << " ev=" << e.ev_name << endl;
			changed = do_alarm_eval(*j, e.ev_name, found->ts);
			if(changed)
				num_changed++;
			j++;
		}

		if(num_changed==0)
		{
			prepare_alm_mtx->lock();
			alarms.vlock->readerIn();
			alarm_container_t::iterator ai;
			size_t freq_ind = 0;
			for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++)
			{
				attr_alarmFrequency_read[freq_ind] = ai->second.freq_counter;
				freq_ind++;
			}
			alarms.vlock->readerOut();
			prepare_alm_mtx->unlock();
			push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
			push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
			return;
		}
		prepare_alarm_attr();//TODO: frequencyAlarm should be updated anyway
		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("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_change_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_change_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		push_change_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_change_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_change_event("alarmAudible",attr_alarmAudible_read);
		push_change_event("alarmSummary",attr_alarmSummary_read, alarmSummary_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);
		push_archive_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_archive_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_archive_event("alarmAudible",attr_alarmAudible_read);
		push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
	}
	else
	{
		DEBUG_STREAM << "AlarmHandler::"<<__func__<<": event=" << e.ev_name << "NOT FOUND IN EVENT TABLE" << endl;
	}
}  /* do_alarm() */

bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal ts)
{
	bool changed = true;
	bool eval_err = false;
	formula_res_t res;
	//alarm_container_t::iterator it = alarms.v_alarm.find(j->first);
	DEBUG_STREAM << "AlarmHandler::"<<__func__<<": before lock name=" << alm_name<< " ev=" << ev_name << endl;
	alarms.vlock->readerIn();
	DEBUG_STREAM << "AlarmHandler::"<<__func__<<": after lock name=" << alm_name<< " ev=" << ev_name << endl;
	alarm_container_t::iterator it = alarms.v_alarm.find(alm_name);
	if(it != alarms.v_alarm.end())
	{
		if(ev_name == "FORCED_EVAL" && !it->second.to_be_evaluated)
		{
			alarms.vlock->readerOut();
			return 	false;
		}
		if(ev_name != "FORCED_EVAL")
				it->second.freq_counter++;
		string tmpname=it->first;
		try {
			it->second.attr_values = string("{");
			res = eval_formula(it->second.formula_tree, it->second.attr_values);
			it->second.attr_values.erase(it->second.attr_values.size()-1);
			it->second.attr_values += string("}");
			DEBUG_STREAM << "AlarmHandler::"<<__func__<<": Evaluation of " << it->second.formula << "; result=" << res.value << " quality=" << res.quality << endl;
			changed = alarms.update(tmpname, ts, res, it->second.attr_values, it->second.grp2str(), it->second.msg, it->second.formula); 		//update internal structure and log to db
			Tango::DevEnum *attr_value = get_AlarmState_data_ptr(it->second.attr_name);
			if(!it->second.enabled)
				*attr_value = _OOSRV;
			else if(it->second.shelved && it->second.silenced > 0)
				*attr_value = _SHLVD;
			else if((it->second.stat == S_NORMAL) && it->second.ack == ACK)
				*attr_value = _NORM;
			else if((it->second.stat == S_ALARM) && it->second.ack == NOT_ACK)
				*attr_value = _UNACK;
			else if((it->second.stat == S_ALARM) && it->second.ack == ACK)
				*attr_value = _ACKED;
			else if((it->second.stat == S_NORMAL) && it->second.ack == NOT_ACK)
				*attr_value = _RTNUN;
			try
			{	//DevFailed for push events
				if(it->second.ex_reason.length() == 0)
				{
					timeval now;
					gettimeofday(&now, NULL);
					push_change_event(it->second.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)it->second.quality, 1/*size*/, 0, false);
					push_archive_event(it->second.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)it->second.quality, 1/*size*/, 0, false);
				}
				else
				{
					Tango::DevErrorList errors(1);
					errors.length(1);
					errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str());
					errors[0].severity = Tango::ERR;
					errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str());
					errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str());
					Tango::DevFailed except(errors);
					push_change_event(it->second.attr_name, &except);
					push_archive_event(it->second.attr_name, &except);
				}
			} catch(Tango::DevFailed & ex)
			{
				WARN_STREAM << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
			}
		} catch(std::out_of_range& ex)
		{
			eval_err = true;
			ostringstream o;
			o << tmpname << ": in formula array index out of range!";
			WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl;
			set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());
			try
			{	//DevFailed for push events
				Tango::DevErrorList errors(1);
				errors.length(1);
				it->second.ex_reason = string("OUT_OF_RANGE");
				it->second.ex_desc = ev_name + ": " + o.str();
				it->second.ex_origin = ev_name;
				errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str());
				errors[0].severity = Tango::ERR;
				errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str());
				errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str());
				Tango::DevFailed except(errors);
				push_change_event(it->second.attr_name, &except);
				push_archive_event(it->second.attr_name, &except);
			} catch(Tango::DevFailed & ex)
			{
				WARN_STREAM << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
			}
		} catch(string & ex)
		{
			eval_err = true;
			ostringstream o;
			o << tmpname << ": in formula err=" << ex;
			WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl;
			set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());
			try
			{	//DevFailed for push events
				Tango::DevErrorList errors(1);
				errors.length(1);
				it->second.ex_reason = string("FORMULA_ERROR");
				it->second.ex_desc = ev_name + ": " + o.str();
				it->second.ex_origin = ev_name;
				errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str());
				errors[0].severity = Tango::ERR;
				errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str());
				errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str());
				Tango::DevFailed except(errors);
				push_change_event(it->second.attr_name, &except);
				push_archive_event(it->second.attr_name, &except);
			} catch(Tango::DevFailed & ex)
			{
				WARN_STREAM << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
			}
		}
		if(!eval_err)
		{
			it->second.to_be_evaluated = false;
		}
	}
	else
	{
		ostringstream o;
		//o << j->first << ": not found formula in alarm table" << ends;
		o << (alm_name) << ": not found formula in alarm table";
		WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl;
		set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());
#if 0	//TODO: attribute not existing -> cannot notify error pushing exception
		try
		{	//DevFailed for push events
			Tango::DevErrorList errors(1);
			errors.length(1);
			string ex_reason = string("NOT_FOUND");
			string ex_desc = ev_name + ": " + o.str();
			string ex_origin = ev_name;
			errors[0].desc = CORBA::string_dup(ex_desc.c_str());
			errors[0].severity = Tango::ERR;
			errors[0].reason = CORBA::string_dup(ex_reason.c_str());
			errors[0].origin = CORBA::string_dup(ex_origin.c_str());
			Tango::DevFailed except(errors);
			//push_change_event(it->second.attr_name, &except);
			//push_archive_event(it->second.attr_name, &except);
		} catch(Tango::DevFailed & ex)
		{
			WARN_STREAM << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
		}
#endif
	}
	alarms.vlock->readerOut();
	return 	changed;
}

void AlarmHandler::timer_update()
{
	bool changed=true;
	//DEBUG_STREAM << "AlarmHandler::timer_update(): entering..." << endl;
	try {
		changed=alarms.timer_update();
	} catch(string & e)
	{
		ostringstream o;
		o << "Error checking time thresholds and updating alarm status=" << e;
		WARN_STREAM << "AlarmHandler::timer_update(): " << o.str() << endl;
		set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());
/*		Tango::DevErrorList errors(1);
		errors.length(1);
		it->second.ex_reason = string("INTERNAL_ERROR");
		it->second.ex_desc = o.str();
		it->second.ex_origin = string("AlarmHandler::timer_update");
		errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str());
		errors[0].severity = Tango::ERR;
		errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str());
		errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str());
		Tango::DevFailed except(errors);
		push_change_event(it->second.attr_name, &except);
		push_archive_event(it->second.attr_name, &except);*/
	}

	if(!changed)
	{
		return;
	}
	prepare_alarm_attr();//TODO: frequencyAlarm should be updated anyway
	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("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_change_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_change_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		push_change_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_change_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_change_event("alarmAudible",attr_alarmAudible_read);
		push_change_event("alarmSummary",attr_alarmSummary_read, alarmSummary_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);
		push_archive_event("alarmUnacknowledgedNormal",&attr_alarmUnacknowledgedNormal_read[0], unacknowledgedNormalAlarms_sz);
		push_archive_event("alarmShelved",&attr_alarmShelved_read[0], shelvedAlarms_sz);
		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("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
		push_archive_event("alarmAudible",attr_alarmAudible_read);
		push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
	} catch(Tango::DevFailed& e)
	{
		ostringstream err;
		err << "error pushing alarm change event err=" << e.errors[0].desc;
		INFO_STREAM << __func__<<": " << err.str() << endl;
	}
}

bool AlarmHandler::remove_alarm(string& s) throw(string&)
{
	DEBUG_STREAM << "AlarmHandler::"<<__func__<<": entering alm name=" << s << endl;
	alarms.vlock->writerIn();
	alarm_container_t::iterator i = alarms.v_alarm.find(s);
	if (i != alarms.v_alarm.end()) {
		DEBUG_STREAM << "AlarmHandler::"<<__func__<<": found in table alm name=" << s << endl;
		for (set<string>::iterator j = i->second.s_event.begin(); \
				 j != i->second.s_event.end(); j++) {
			DEBUG_STREAM << "AlarmHandler::"<<__func__<<": looping event =" << *j << endl;
			/*
		 	 * for each event into the per-alarm event list find
			 * the event table entry and remove this alarm from
			 * per-event alarm list
		 	 */	 	 
			vector<event>::iterator k = \
					find(events->v_event.begin(), events->v_event.end(), *j);
			if (k != events->v_event.end()) {
				DEBUG_STREAM << "AlarmHandler::"<<__func__<<": found event =" << *j << " in vector events, removing from its alarm list name=" << i->second.name << endl;
				/*
				 * remove alarm
				 */			 
				k->pop_alarm(i->second.name);
				DEBUG_STREAM << "AlarmHandler::"<<__func__<<": after pop_alarm" << endl;
				if (k->m_alarm.empty()) {
					/*
					 * no more alarms associated to this event, unsubscribe
					 * and remove from event table
					 */
					DEBUG_STREAM << "AlarmHandler::remove_alarm(): removing event '" \
							 				<< k->name << "' from event table" << endl;
					try {
						events->stop(k->name);
						events->remove(k->name, false);
					} catch (...) {
						ostringstream o;
						o << "unsubscribe_event() failed for " \
						 	<< k->name;
						WARN_STREAM << "AlarmHandler::remove_alarm(): " << o.str() << endl;
						alarms.vlock->writerOut();
						throw o.str();
						//return false;
					}
					//events->v_event.erase(k);
				}
			} else {
				/*
				 * shouldn't happen!!!
				 */
				ostringstream o;
				o << "event '" << *j \
					<< "' not found in event table";
				WARN_STREAM << "AlarmHandler::remove_alarm(): " << o.str() << endl;
				alarms.vlock->writerOut();
				throw o.str();
				//return false;
			}
		}  /* for */
		events->update_property();
		//delete proxy for actions
		if(i->second.dp_a)
			delete i->second.dp_a;
		i->second.dp_a = NULL;
		if(i->second.dp_n)
			delete i->second.dp_n;
		i->second.dp_n = NULL;
		try
		{
			remove_AlarmState_dynamic_attribute(i->second.attr_name);
		}
		catch(Tango::DevFailed &e)
		{
			ostringstream o;
			o << "AlarmHandler::" << __func__<<": attname '" << i->second.attr_name << "' exception removing attribute err="<<e.errors[0].desc ;
			INFO_STREAM << o.str() << endl;
		}
#if _FORMULA_ATTR
		CORBA::string_free(*(i->second.attr_value_formula));
		try
		{
			remove_AlarmFormula_dynamic_attribute(i->second.attr_name_formula);
		}
		catch(Tango::DevFailed &e)
		{
			ostringstream o;
			o << "AlarmHandler::" << __func__<<": attname '" << i->second.attr_name_formula << "' exception removing attribute err="<<e.errors[0].desc ;
			INFO_STREAM << o.str() << endl;
		}
#endif
		/*
		 * remove this alarm from alarm table
		 */
		alarms.erase(i);
		alarms.vlock->writerOut();
		return true;
	}
	else
	{
		WARN_STREAM << "AlarmHandler::"<<__func__<<": NOT found in table alm name=" << s << endl;
	}
	alarms.vlock->writerOut();
	ostringstream o;
	o << "alarm '" \
		<< s << "' not found in alarm table";
	WARN_STREAM << "AlarmHandler::remove_alarm(): " << o.str() << endl;
	throw o.str();
	//return false;
}  /* remove_alarm() */


/*void AlarmHandler::add_to_database(alarm_t& a) throw(string&)
{
	Tango::DbDatum alarm("alarm");
	Tango::DbData db_data;
	
	alarm << (short)1;
	db_data.push_back(alarm);
	string tmpname;
	tmpname = a.name;
	while (true) {
		string::size_type j = tmpname.find_first_of("/.");
		if (j == string::npos)
			break;
		tmpname.replace(j, 1, "_");
	}
	Tango::DbDatum property(tmpname);
	ostringstream num;
	num.clear();
	num  << a.grp << ends;
//		sprintf(buf, "%02X-", buf2[j]);//change here the format of saved data
//	string pro = a.name+"\t"+"$"+a.formula+"$"+"\t"+"\""+a.msg+"\""+"\t"+num.str();
	//DEBUG_STREAM << "AlarmHandler::add_to_database(): a.name=" << a.name << " a.formula=" << a.formula << " a.lev=" << a.lev << " a.grp=" << a.grp2str() << " a.msg=" << a.msg << endl;
	string pro = a.name+"\t"+a.formula+"\t"+string(a.time_threshold)+"\t"+ a.lev+"\t"+a.grp2str()+"\t"+"\""+a.msg+"\""+"\t"+a.cmd_name+"\t";	//grp has been transformed to string
	DEBUG_STREAM << "AlarmHandler::add_to_database(): adding to database property=" << pro << endl;
	property << pro;			
	db_data.push_back(property);
	try {
		get_db_device()->put_attribute_property(db_data);
	} catch (...) {
		ostringstream o;
		o << "AlarmHandler::add_to_database(): put_device_attribute_property()" \
			<< " failed" << ends;
		ERROR_STREAM << o.str() << endl;
		throw o.str();
	}
}*/

void AlarmHandler::set_internal_alarm(string name, Tango::TimeVal t, string msg, unsigned int count)
{
	alarm_t alm;
	bool existing=false;
	ostringstream o;
	//o << (internal.size() + 1);
	if(internal.size() == 0)
		internal_counter = 0;
	o << internal_counter;
	internallock->writerIn();
	vector<alarm_t>::iterator it;
	for(it = internal.begin(); it != internal.end(); it++)
	{
		if(name == INTERNAL_ERROR)
		{
			if(it->msg == msg)
			{
				existing=true;
				break;
			}
		}
		else										//for tango error log only one internal error per event
		{
			if(it->msg.find(name) != string::npos)		
			{
				existing=true;
				if(it->on_counter < count)
					it->on_counter = count;
				break;
			}
		}			
	}
	if(existing) 
	{
		/*size_t index;
		int count;
		index = it->stat.find("*");
		ostringstream temp;
		if((index != std::string::npos) && (index+1 != std::string::npos))
		{
			
			size_t last = it->stat.size();
			string str_count= it->stat.substr(index+1, last - index+1);      
			count = strtol(str_count.c_str(), 0,10);
			count++;  
			temp << it->stat.substr(0,index+1) << count;
			it->stat = temp.str();
		}	
		else
			it->stat += "*2";*/
		it->on_counter++;
		it->msg = msg;		//update with the last message
	}
	else
	{	
		alm.name = string(INTERNAL_ERROR) + "_" + o.str();
		internal_counter++;
		alm.ts = t;
		/*ostringstream stat;
		if(count==0)
			stat << S_ALARM;
		else
			stat << S_ALARM << "*" << count;*/
		alm.on_counter = count;
		//alm.stat = stat.str();
		alm.stat = S_ALARM;
		alm.ack = NOT_ACK;
		alm.done = false;
		alm.msg = msg;
		//alm.grp = GR_DEFAULT;
		if(!alm.grp_str.empty())
			alm.grp = (alm.grp_str.begin())->second;		//set groupe 'none' to internal alarms
		else
			alm.grp = GR_DEFAULT;
		//alm.lev = LEV_DEFAULT;	
		alm.lev = LEV_LOG;	
		internal.push_back(alm);
	}
	internallock->writerOut();
}

//==============================================================
//------------------- AST evaluation methods -------------------
//==============================================================
formula_res_t AlarmHandler::eval_formula(tree_parse_info_t tree, string &attr_values)
{
    return eval_expression(tree.trees.begin(), attr_values);
}

formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values, int ev_ind) //throw (string &), std::out_of_range
{

    ostringstream err;
    err << "Evaluating formula: ";    
    //iter_t it = i->children.begin();

    if (i->value.id() == formula_grammar::val_rID)
    {
        if(i->children.size() != 0)
        {
        	err <<  "in node val_rID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }
        string val_d(i->value.begin(), i->value.end());
		formula_res_t res;
		res.value = strtod(val_d.c_str(), 0);
		DEBUG_STREAM << "		node value real = " << val_d << "(value="<<res.value<<" quality="<<res.quality<<")" << endl;
        return res;
    }
    else if (i->value.id() == formula_grammar::val_hID)
    {
        if(i->children.size() != 0)
        {
        	err <<  "in node val_hID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }        		
        string val_d(i->value.begin(), i->value.end());
		DEBUG_STREAM << "		node value hex = " << val_d << endl;
		formula_res_t res;
		res.value = strtod(val_d.c_str(), 0);
        return res;
    } 
    else if (i->value.id() == formula_grammar::val_stID)
    {
        if(i->children.size() != 0)
        {
        	err <<  "in node val_stID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }     		
        string val_st(i->value.begin(), i->value.end());
        double st =  i->value.value();			//get value directly from node saved with access_node_d
		DEBUG_STREAM << "		node value state : " << val_st << "=" << st << endl;
		formula_res_t res;
		res.value = st;
        return res;
    }
    else if (i->value.id() == formula_grammar::val_alarm_enum_stID)
    {
        if(i->children.size() != 0)
        {
        	err <<  "in node val_alarm_enum_stID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str();
        }
        string val_st(i->value.begin(), i->value.end());
        double st =  i->value.value();			//get value directly from node saved with access_node_d
		DEBUG_STREAM << "		node value alarm enum state : " << val_st << "=" << st << endl;
		formula_res_t res;
		res.value = st;
        return res;
    }
	else if (i->value.id() == formula_grammar::val_qualityID)
	{
		if(i->children.size() != 0)
		{
			err <<  "in node val_qualityID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
			throw err.str();
		}
		string val_quality(i->value.begin(), i->value.end());

		double quality =  i->value.value();			//get value directly from node saved with access_node_d
		DEBUG_STREAM << "		node value quality : " << val_quality << "=" << quality << endl;
		formula_res_t res;
		res.value = quality;
        return res;
	}
    else if (i->value.id() == formula_grammar::unary_exprID)
    {
		DEBUG_STREAM << "		node unary expression: " << string(i->value.begin(), i->value.end()) << endl;
		if(i->children.size() != 1)
        {
        	err <<  "in node unary_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }
		formula_res_t res;
		res = eval_expression(i->children.begin(), attr_values);
        if (*i->value.begin() == '+')
        {
        	res.value = + res.value;
        }
        else if (*i->value.begin() == '-')
        {
        	res.value = - res.value;
        }
        else if (*i->value.begin() == '!')
        {
        	res.value = ! res.value;
        }
        else
        {
        	err <<  "in node unary_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
        	throw err.str();
        }
        return res;
    }
    else if (i->value.id() == formula_grammar::mult_exprID)
    {
		DEBUG_STREAM << "		node mult expression: " << string(i->value.begin(), i->value.end()) << endl;
       	if(i->children.size() != 2)
        {
        	err <<  "in node mult_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }
        if (*i->value.begin() == '*')
        {
            return eval_expression(i->children.begin(), attr_values) *
                eval_expression(i->children.begin()+1, attr_values);
        }
        else if (*i->value.begin() == '/')
        {
            return eval_expression(i->children.begin(), attr_values) /
                eval_expression(i->children.begin()+1, attr_values);
        }
        else
        {
        	err <<  "in node mult_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
        	throw err.str(); 
        }
    }
    else if (i->value.id() == formula_grammar::add_exprID)
    {
        DEBUG_STREAM << "		node add expression: " << string(i->value.begin(), i->value.end()) << endl;
        if(i->children.size() != 2)
        {
        	err <<  "in node add_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }
        if (*i->value.begin() == '+')
        {
            return eval_expression(i->children.begin(), attr_values) +
                eval_expression(i->children.begin()+1, attr_values);
        }
        else if (*i->value.begin() == '-')
        {
            return eval_expression(i->children.begin(), attr_values) -
                eval_expression(i->children.begin()+1, attr_values);
        }
        else
        {
        	err <<  "in node add_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
        	throw err.str(); 
        }
    }
    else if (i->value.id() == formula_grammar::event_ID)
    {
		DEBUG_STREAM << "		node event" << string(i->value.begin(), i->value.end()) << endl;
		formula_res_t ind;
		if(i->children.size() != 2)		
		{
        	err <<  "in node event_ID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();;
        	throw err.str(); 
        }
		if((i->children.begin()+1)->value.id() == formula_grammar::indexID)
			ind = eval_expression(i->children.begin()+1, attr_values);		//array index
		else if((i->children.begin()+1)->value.id() == formula_grammar::propertyID)
		{
			if(string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end()) == ".quality")
			{
				formula_res_t res = eval_expression(i->children.begin(), attr_values, (int)ind.value);
				res.value = res.quality;
				DEBUG_STREAM << "		node event.quality -> " << res.value << endl;
				return res;
			}
			else if(string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end()) == ".alarm")
			{
				formula_res_t res = eval_expression(i->children.begin(), attr_values, (int)ind.value);
				res.value = (res.value == _UNACK) || (res.value == _ACKED);
				DEBUG_STREAM << "		node event.alarm -> " << res.value << endl;
				return res;
			}
			else if(string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end()) == ".normal")
			{
				formula_res_t res = eval_expression(i->children.begin(), attr_values, (int)ind.value);
				res.value = (res.value == _NORM) || (res.value == _RTNUN);
				DEBUG_STREAM << "		node event.normal -> " << res.value << endl;
				return res;
			}
		}
		else
		{
        	err <<  "in node event_ID(" << string(i->value.begin(), i->value.end()) << ") children2 is not an index ->" << string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end());
        	throw err.str(); 
        }
		return eval_expression(i->children.begin(), attr_values, (int)ind.value);
    }    
    else if (i->value.id() == formula_grammar::nameID)
    {
		if(i->children.size() != 0)		
		{
        	err <<  "in node nameID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }		
        vector<event>::iterator it = events->v_event.begin();
        string s(i->value.begin(), i->value.end());
        std::transform(s.begin(), s.end(), s.begin(), (int(*)(int))tolower);		//transform to lowercase
        while ((it != events->v_event.end()) && (it->name != s))
				it++;
		if (it != events->v_event.end())
		{
			if(!it->valid)
			{
				if(it->ex_desc.length() > 0)
					err <<  "attribute '" << string(i->value.begin(), i->value.end()) << "' exception: '" << it->ex_desc << "'";
				else
					err <<  "attribute '" << string(i->value.begin(), i->value.end()) << "' value not valid!";
        		throw err.str();
        	}	
			else if(it->type != Tango::DEV_STRING && it->value.empty())
			{
				if(it->ex_desc.length() > 0)
					err <<  "attribute '" << string(i->value.begin(), i->value.end()) << "' exception: '" << it->ex_desc << "'";
				else
					err <<  "attribute '" << string(i->value.begin(), i->value.end()) << "' value not initialized!!";
        		throw err.str();
        	}        	
			ostringstream temp_attr_val;
			if(it->value.size() > 1)
				temp_attr_val << "\"" <<  it->name << "[" << ev_ind << "]\":" <<it->value.at(ev_ind) << ",";//throw  std::out_of_range
			else
				temp_attr_val << "\"" <<  it->name << "\":" <<it->value.at(ev_ind) << ",";//throw  std::out_of_range
			attr_values += temp_attr_val.str();
			formula_res_t res;
			res.quality = it->quality;
			res.ex_reason = it->ex_reason;
			res.ex_desc = it->ex_desc;
			res.ex_origin = it->ex_origin;
			DEBUG_STREAM << "		node name -> " << temp_attr_val.str() << " quality=" << res.quality << endl;
			res.value = it->value.at(ev_ind);		//throw  std::out_of_range
			return 	res;
		}
		else
		{
			err <<  "in event: (" << string(i->value.begin(), i->value.end()) << ") not found in event table";
        	throw err.str();		
		}  
    } 
    else if (i->value.id() == formula_grammar::indexID)
    {
		if(i->children.size() != 0)		
		{
        	err <<  "in node indexID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }			
        string val_d(i->value.begin(), i->value.end());
     	DEBUG_STREAM << "		node index = " << val_d << endl;
     	formula_res_t res;
     	res.value = strtod(val_d.c_str(), 0);
        return res;
    }   
    else if (i->value.id() == formula_grammar::logical_exprID)
    {
		DEBUG_STREAM << "		node logical expression: " << string(i->value.begin(), i->value.end()) << endl;
		if(i->children.size() != 2)		
		{
        	err <<  "in node logical_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }	        		 
		if (string(i->value.begin(), i->value.end()) == string("&&"))
        {
            return eval_expression(i->children.begin(), attr_values) &&
                eval_expression(i->children.begin()+1, attr_values);
        }
		else if (string(i->value.begin(), i->value.end()) == string("||"))
        {
            return eval_expression(i->children.begin(), attr_values) ||
                eval_expression(i->children.begin()+1, attr_values);
        }             
        else
        {
        	err <<  "in node logical_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
        	throw err.str(); 
        }		  
    }   
    else if (i->value.id() == formula_grammar::bitwise_exprID)
    {
		DEBUG_STREAM << "		node bitwise expression: " << string(i->value.begin(), i->value.end()) << endl;
		if(i->children.size() != 2)		
		{
        	err <<  "in node bitwise_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }	 		
		formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
           	res_2=eval_expression(i->children.begin()+1, attr_values);
        long val_l1,val_l2;
            
    	string err2("ERROR: non-int value in bitwise operation!");
    	val_l1 = (long)trunc(res_1.value);		//transform to long
    	val_l2 = (long)trunc(res_2.value);		//transform to long

	    if((val_l1 != res_1.value) || (val_l2 != res_2.value))	//if different, lost something with truncf
    		throw err2;
    		  
        if (*i->value.begin() == '&')
        {
        	formula_res_t res;
        	res.value = (double)(val_l1 & val_l2);
        	res.quality = res.combine_quality(res_1.quality, res_2.quality);
        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
            return res;
        }
        else if (*i->value.begin() == '|')
        {      
        	formula_res_t res;
        	res.value = (double)(val_l1 | val_l2);
        	res.quality = res.combine_quality(res_1.quality, res_2.quality);
        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
            return res;
        }  
        else if (*i->value.begin() == '^')
        {
        	formula_res_t res;
        	res.value = (double)(val_l1 ^ val_l2);
        	res.quality = res.combine_quality(res_1.quality, res_2.quality);
        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
            return res;
        }  
        else
        {
        	err << "in node bitwise_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
        	throw err.str(); 
        }			   
    }   
    else if (i->value.id() == formula_grammar::shift_exprID)
    {
		DEBUG_STREAM << "		node shift expression: " << string(i->value.begin(), i->value.end()) << endl;
		if(i->children.size() != 2)		
		{
        	err <<  "in node shift_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }			
		formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
           	res_2=eval_expression(i->children.begin()+1, attr_values);
        long val_l1,val_l2;
            
    	string err2("ERROR: non-int value in bitwise operation!");
    	val_l1 = (long)trunc(res_1.value);		//transform to long
    	val_l2 = (long)trunc(res_2.value);		//transform to long

	    if((val_l1 != res_1.value) || (val_l2 != res_2.value))	//if different, lost something with truncf
    		throw err2;
    		  
        if (string(i->value.begin(), i->value.end()) == string("<<"))
        {
        	formula_res_t res;
        	res.value = (double)(val_l1 << val_l2);
        	res.quality = res.combine_quality(res_1.quality, res_2.quality);
        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
            return res;
        }
        else if (string(i->value.begin(), i->value.end()) == string(">>"))
        {
        	formula_res_t res;
        	res.value = (double)(val_l1 >> val_l2);
        	res.quality = res.combine_quality(res_1.quality, res_2.quality);
        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
            return res;
        }  
        else
        {
        	err <<  "in node shift_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
        	throw err.str(); 
        }		   
    }      
    else if (i->value.id() == formula_grammar::equality_exprID)
    {
		DEBUG_STREAM << "		node equality expression: " << string(i->value.begin(), i->value.end()) << endl;
        if(i->children.size() != 2)		
		{
        	err <<  "in node equality_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }


		//string comparison here
		iter_t const& i2_1 = i->children.begin();
		iter_t const& i2_2 = i->children.begin()+1;
		//OK only attr == 'string' or attr != 'string'
		if(i2_1->value.id() == formula_grammar::nameID && i2_2->value.id() == formula_grammar::val_stringID)
		{
			if(i2_1->children.size() == 0 && i2_2->children.size() == 0)
			{
				//retrieve string from attribute:
				string attr_val = "";
				string name_id(i2_1->value.begin(), i2_1->value.end());
				std::transform(name_id.begin(), name_id.end(), name_id.begin(), (int(*)(int))tolower);		//transform to lowercase
				formula_res_t res;
				vector<event>::iterator it = events->v_event.begin();

				while ((it != events->v_event.end()) && (it->name != name_id))
						it++;
				if (it != events->v_event.end())
				{
					if(!it->valid)
					{
						err <<  "in node equality_exprID -> nameID(" << string(i2_1->value.begin(), i2_1->value.end()) << ") value not valid!";
						if(it->ex_desc.length() > 0)
							err << " EX: '" << it->ex_desc << "'";
						throw err.str();
					}
					else if(it->type != Tango::DEV_STRING && it->value.empty())
					{
						err <<  "in node nameID(" << string(i2_1->value.begin(), i2_1->value.end()) << ") value not initialized!!";
						if(it->ex_desc.length() > 0)
							err << " EX: '" << it->ex_desc << "'";
						throw err.str();
					}
					ostringstream temp_attr_val;
					temp_attr_val << "\"" << it->name << "\":\"" <<it->value_string << "\",";
					attr_values += temp_attr_val.str();
					res.quality = it->quality;
					res.ex_reason = it->ex_reason;
					res.ex_desc = it->ex_desc;
					res.ex_origin = it->ex_origin;
					DEBUG_STREAM << "		node name -> " << temp_attr_val.str() << " quality=" << res.quality << endl;
					attr_val =  string("'") + it->value_string + string("'");
				}
				else
				{
					err <<  "in event: (" << string(i->value.begin(), i->value.end()) << ") not found in event table";
					throw err.str();
				}

				//retrieve string from formula
				string val_string(i2_2->value.begin(), i2_2->value.end());

				if (string(i->value.begin(), i->value.end()) == string("!="))
				{
					res.value = attr_val != val_string;
					return res;
				}
				else if (string(i->value.begin(), i->value.end()) == string("=="))
				{
					res.value = attr_val == val_string;
					return res;
				}
				else
				{
					err <<  "in node equality_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed (val_stringID)";
					throw err.str();
				}
			}
		}
		else
		{
			if (string(i->value.begin(), i->value.end()) == string("!="))
			{
				return eval_expression(i->children.begin(), attr_values) !=
					eval_expression(i->children.begin()+1, attr_values);
			}
			else if (string(i->value.begin(), i->value.end()) == string("=="))
			{
				return eval_expression(i->children.begin(), attr_values) ==
					eval_expression(i->children.begin()+1, attr_values);
			}
			else
			{
				err <<  "in node equality_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
				throw err.str();
			}
		}
    }   
    else if (i->value.id() == formula_grammar::compare_exprID)
    {
		DEBUG_STREAM << "		node compare expression: " << string(i->value.begin(), i->value.end()) << endl; 
		if(i->children.size() != 2)		
		{
        	err <<  "in node compare_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }	
		if (string(i->value.begin(), i->value.end()) == string("<="))
        {
            return eval_expression(i->children.begin(), attr_values) <=
                eval_expression(i->children.begin()+1, attr_values);
        }
		else if (string(i->value.begin(), i->value.end()) == string(">="))
        {
            return eval_expression(i->children.begin(), attr_values) >=
                eval_expression(i->children.begin()+1, attr_values);
        }        
        else if (*i->value.begin() == '<')
        {
            return eval_expression(i->children.begin(), attr_values) <
                eval_expression(i->children.begin()+1, attr_values);
        }
        else if (*i->value.begin() == '>')
        {
            return eval_expression(i->children.begin(), attr_values) >
                eval_expression(i->children.begin()+1, attr_values);
        }        
        else
        {
        	err <<  "in node equality_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
        	throw err.str(); 
        }	
    }   
    else if (i->value.id() == formula_grammar::funcID)
    {
		DEBUG_STREAM << "		node function: " << string(i->value.begin(), i->value.end()) << endl;
		if(i->children.size() != 1)		
		{
        	err <<  "in node funcID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }
		formula_res_t res;
		res = eval_expression(i->children.begin(), attr_values);

		if (string(i->value.begin(), i->value.end()) == string("abs"))
		{
			res.value = fabs(res.value);
			return res;
		}
		else if (string(i->value.begin(), i->value.end()) == string("cos"))
		{
			res.value = cos(res.value);
			return res;
		}
		else if (string(i->value.begin(), i->value.end()) == string("sin"))
		{
			res.value = sin(res.value);
			return res;
		}
		else if (string(i->value.begin(), i->value.end()) == string("quality"))
		{
			res.value = res.quality;
			return res;
		}
		else
		{
			err <<  "in node funcID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
			throw err.str();
		}
    }  
	else if (i->value.id() == formula_grammar::func_dualID)
	{
		DEBUG_STREAM << "		node function dual: " << string(i->value.begin(), i->value.end()) << endl;
		if(i->children.size() != 2)
		{
			err <<  "in node func_dualID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
			throw err.str();
		}
		formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
           	res_2=eval_expression(i->children.begin()+1, attr_values);
		if (string(i->value.begin(), i->value.end()) == string("min"))
		{
        	formula_res_t res;
        	res.value = min(res_1.value, res_2.value);
        	res.quality = res.combine_quality(res_1.quality, res_2.quality);
        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
            return res;
		}
		else if (string(i->value.begin(), i->value.end()) == string("max"))
		{
        	formula_res_t res;
        	res.value = max(res_1.value, res_2.value);
        	res.quality = res.combine_quality(res_1.quality, res_2.quality);
        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
            return res;
		}
		else if (string(i->value.begin(), i->value.end()) == string("pow"))
		{
        	formula_res_t res;
        	res.value = pow(res_1.value, res_2.value);
        	res.quality = res.combine_quality(res_1.quality, res_2.quality);
        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
            return res;
		}
		else
		{
			err <<  "in node func_dualID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
			throw err.str();
		}
	}
	else if (i->value.id() == formula_grammar::cond_exprID)
	{
		DEBUG_STREAM << "		node ternary_if expression: " << string(i->value.begin(), i->value.end()) << endl;
		if(i->children.size() != 3)
		{
			err <<  "in node ternary_ifID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
			throw err.str();
		}
		formula_res_t res_1=eval_expression(i->children.begin(), attr_values);
		if(res_1.value)
		{
        	formula_res_t res = eval_expression(i->children.begin()+1, attr_values);
            return res;
		}
		else
		{
        	formula_res_t res = eval_expression(i->children.begin()+2, attr_values);
            return res;
		}
	}
    else
    {
        DEBUG_STREAM << "		node unknown id: " << string(i->value.begin(), i->value.end()) << endl;
        {
        	err <<  "node unknown!! value=" << string(i->value.begin(), i->value.end());
        	throw err.str(); 
        }	
    }
    formula_res_t res;
    res.value = 0;
    return res;
}

void AlarmHandler::find_event_formula(tree_parse_info_t tree, vector<string> & ev)
{
    eval_node_event(tree.trees.begin(), ev);
    return;
}

void AlarmHandler::eval_node_event(iter_t const& i, vector<string> & ev)
{
	DEBUG_STREAM << "In eval_node_event. i->value = '" <<
        string(i->value.begin(), i->value.end()) <<
        "' i->children.size() = " << i->children.size() << " NODE=" << rule_names[i->value.id()] << endl;
    ostringstream err;
    err << "Looking for event in formula tree: "; 
    /*if (i->value.id() == formula_grammar::event_ID)
    {
    	DEBUG_STREAM << "eval_node_event(): in eventID!!!=" << string(i->value.begin(), i->value.end()) << endl;
    }
    else*/ if (i->value.id() == formula_grammar::nameID)
    {
    	DEBUG_STREAM << "eval_node_event(): find event name=" << string(i->value.begin(), i->value.end()) << endl;
    	if(i->children.size() != 0)		
		{
        	err <<  "in node nameID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
        	throw err.str(); 
        }
        string s(i->value.begin(), i->value.end());
        std::transform(s.begin(), s.end(), s.begin(), (int(*)(int))tolower);		//transform to lowercase
		ev.push_back(s);
    }
    //cout << endl;
    //iter_t it = i->children.begin();
    for(iter_t it = i->children.begin(); it != i->children.end(); it++)
    	eval_node_event(it, ev);
    return;
}


void AlarmHandler::prepare_alarm_attr()
{
	prepare_alm_mtx->lock();
	alarm_container_t::iterator ai;
	vector<alarm_t>::iterator aid;
	bool is_audible=false;
	alarms.vlock->readerIn();
	outOfServiceAlarms_sz=0;
	shelvedAlarms_sz=0;
	acknowledgedAlarms_sz=0;
	unacknowledgedAlarms_sz=0;
	unacknowledgedNormalAlarms_sz=0;
	normalAlarms_sz=0;
	silencedAlarms_sz=0;
	listAlarms_sz=0;
	alarmSummary_sz=0;
	string almstate;

	for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++) {
#ifndef ALM_SUM_STR
		stringstream alm_summary;
		alm_summary << KEY(NAME_KEY) << ai->first << SEP;
#else
		string alm_summary;
		alm_summary += KEY(NAME_KEY) + ai->first + SEP;
#endif
		if(ai->second.enabled == false)
		{
			outOfServiceAlarms_read[outOfServiceAlarms_sz] = ai->second.name;
			attr_alarmOutOfService_read[outOfServiceAlarms_sz] = const_cast<char*>(outOfServiceAlarms_read[outOfServiceAlarms_sz].c_str());
			/*strcpy(c_outOfServiceAlarms_read[outOfServiceAlarms_sz], ai->second.name.c_str());
			attr_alarmOutOfService_read[outOfServiceAlarms_sz] = c_outOfServiceAlarms_read[outOfServiceAlarms_sz];*/
			//attr_alarmOutOfService_read[outOfServiceAlarms_sz] = CORBA::string_dup(ai->second.name.c_str());
			outOfServiceAlarms_sz++;
			almstate = "OOSRV";
		}
		else if(ai->second.shelved)
		{
			shelvedAlarms_read[shelvedAlarms_sz] = ai->second.name;
			attr_alarmShelved_read[shelvedAlarms_sz] = const_cast<char*>(shelvedAlarms_read[shelvedAlarms_sz].c_str());
			/*strcpy(c_shelvedAlarms_read[shelvedAlarms_sz], ai->second.name.c_str());
			attr_alarmShelved_read[shelvedAlarms_sz] = c_shelvedAlarms_read[shelvedAlarms_sz];*/
			//attr_alarmShelved_read[shelvedAlarms_sz] = CORBA::string_dup(ai->second.name.c_str());
			shelvedAlarms_sz++;
			almstate = "SHLVD";
		}
		else
		{
			if(ai->second.stat == S_ALARM && ai->second.ack == ACK)
			{
				acknowledgedAlarms_read[acknowledgedAlarms_sz] = ai->second.name;
				attr_alarmAcknowledged_read[acknowledgedAlarms_sz] = const_cast<char*>(acknowledgedAlarms_read[acknowledgedAlarms_sz].c_str());
				/*strcpy(c_acknowledgedAlarms_read[acknowledgedAlarms_sz], ai->second.name.c_str());
				attr_alarmAcknowledged_read[acknowledgedAlarms_sz] = c_acknowledgedAlarms_read[acknowledgedAlarms_sz];*/
				//attr_alarmAcknowledged_read[acknowledgedAlarms_sz] = CORBA::string_dup(ai->second.name.c_str());
				acknowledgedAlarms_sz++;
				almstate = "ACKED";
			}
			else if(ai->second.stat == S_ALARM && ai->second.ack == NOT_ACK)
			{
				unacknowledgedAlarms_read[unacknowledgedAlarms_sz] = ai->second.name;
				attr_alarmUnacknowledged_read[unacknowledgedAlarms_sz] = const_cast<char*>(unacknowledgedAlarms_read[unacknowledgedAlarms_sz].c_str());
				/*strcpy(c_unacknowledgedAlarms_read[unacknowledgedAlarms_sz], ai->second.name.c_str());
				attr_alarmUnacknowledged_read[unacknowledgedAlarms_sz] = c_unacknowledgedAlarms_read[unacknowledgedAlarms_sz];*/
				//attr_alarmUnacknowledged_read[unacknowledgedAlarms_sz] = CORBA::string_dup(ai->second.name.c_str());
				unacknowledgedAlarms_sz++;
				almstate = "UNACK";
			}
			else if(ai->second.stat == S_NORMAL && ai->second.ack == NOT_ACK)
			{
				unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz] = ai->second.name;
				attr_alarmUnacknowledgedNormal_read[unacknowledgedNormalAlarms_sz] = const_cast<char*>(unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz].c_str());
				/*strcpy(c_unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz], ai->second.name.c_str());
				attr_alarmUnacknowledgedNormal_read[unacknowledgedNormalAlarms_sz] = c_unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz];*/
				//attr_alarmUnacknowledgedNormal_read[unacknowledgedNormalAlarms_sz] = CORBA::string_dup(ai->second.name.c_str());
				unacknowledgedNormalAlarms_sz++;
				almstate = "RTNUN";
			}
			else if(ai->second.stat == S_NORMAL && ai->second.ack == ACK)
			{
				normalAlarms_read[normalAlarms_sz] = ai->second.name;
				attr_alarmNormal_read[normalAlarms_sz] = const_cast<char*>(normalAlarms_read[normalAlarms_sz].c_str());
				/*strcpy(c_normalAlarms_read[normalAlarms_sz], ai->second.name.c_str());
				attr_alarmNormal_read[normalAlarms_sz] = c_normalAlarms_read[normalAlarms_sz];*/
				//attr_alarmNormal_read[normalAlarms_sz] = CORBA::string_dup(ai->second.name.c_str());
				normalAlarms_sz++;
				almstate = "NORM";
			}
			if(ai->second.silenced > 0)
			{
				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());
				silencedAlarms_sz++;
			}
		}

		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);

#ifndef ALM_SUM_STR
		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 ';'
#endif


#if 0
#ifndef ALM_SUM_STR
		alm_summary << SEP;
		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;
#else
		alm_summary += string(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
#endif

#if 0
#ifndef ALM_SUM_STR
		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;
#endif
#endif
		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;
#if 0
#ifndef ALM_SUM_STR
		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;
#endif
#endif
		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 */
#ifndef ALM_SUM_STR
		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++;
	}  /* for */
	*attr_alarmAudible_read = is_audible;
	alarms.vlock->readerOut();
	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);
				}
				else
				{
					aid->silenced = 0;
					aid->shelved = false;
				}
			}
			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;
	Tango::Database *db;
	try
	{
#ifndef _USE_ELETTRA_DB_RW
	db = new Tango::Database();
#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
} //	namespace