Skip to content
Snippets Groups Projects
AlarmHandler.cpp 223 KiB
Newer Older
/*----- 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>
#include <regex>

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.
//
//================================================================
//  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
//  ReLoadAll        |  re_load_all
//================================================================

//================================================================
//================================================================
//  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)
//  eventList                  |  Tango::DevString	Spectrum  ( max = 10000)
//  eventSummary               |  Tango::DevString	Spectrum  ( max = 10000)
//  alarmDisabled              |  Tango::DevString	Spectrum  ( max = 10000)
//================================================================

namespace AlarmHandler_ns
/*----- PROTECTED REGION ID(AlarmHandler::namespace_starting) ENABLED START -----*/
/*----- 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)
	/*----- PROTECTED REGION ID(AlarmHandler::constructor_1) ENABLED START -----*/
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::constructor_1
}
//--------------------------------------------------------
AlarmHandler::AlarmHandler(Tango::DeviceClass *cl, const char *s)
	/*----- PROTECTED REGION ID(AlarmHandler::constructor_2) ENABLED START -----*/
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::constructor_2
}
//--------------------------------------------------------
AlarmHandler::AlarmHandler(Tango::DeviceClass *cl, const char *s, const char *d)
	/*----- PROTECTED REGION ID(AlarmHandler::constructor_3) ENABLED START -----*/
	/*----- 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 -----*/
	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;

	updateloop->signal();
	DEBUG_STREAM << "AlarmHandler::delete_device(): after abortflag=true..." << endl;
		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);
Graziano Scalamera's avatar
Graziano Scalamera committed
	if(!shutting_down && !restarting)
		alarms.del_rwlock(); //otherwise moved in alarm_table destructor
	events->stop_thread();
	usleep(50000);
	DEBUG_STREAM << "AlarmHandler::delete_device(): stopped alarm and log threads!" << endl;
	delete events;
	thread->join(nullptr);
	sleep(1);		//wait for alarm_thread, update_thread and log_thread to exit
	DEBUG_STREAM << "AlarmHandler::delete_device(): deleted events" << 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;
	}	
Graziano Scalamera's avatar
Graziano Scalamera committed
	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;
			}
Graziano Scalamera's avatar
Graziano Scalamera committed
#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;
			}
Graziano Scalamera's avatar
Graziano Scalamera committed
#endif
	/*
	 * clear all data structures
	 */
	alarms.v_alarm.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);
#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();
		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 savedlock;
Graziano Scalamera's avatar
Graziano Scalamera committed
	instanceCounter--;
	delete prepare_alm_mtx;
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::delete_device
	delete[] attr_alarmAudible_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;
	delete[] attr_eventList_read;
	delete[] attr_eventSummary_read;
	delete[] attr_alarmDisabled_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();
	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);
	savedlock = new(ReadersWritersLock);
	/*----- 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];
	attr_eventList_read = new Tango::DevString[10000];
	attr_eventSummary_read = new Tango::DevString[10000];
	attr_alarmDisabled_read = new Tango::DevString[10000];
	/*----- PROTECTED REGION ID(AlarmHandler::init_device) ENABLED START -----*/
/*	for(size_t i=0; i<MAX_ALARMS; i++)
	{
		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);
	}*/
	alarms.set_al_qual(setAlarmQuality);
	alarms.set_err_delay(errorDelay);
	thread->period = subscribeRetryPeriod;
		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;
	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, savedlock);//holds write locks savedlock
		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);
Graziano Scalamera's avatar
Graziano Scalamera committed
			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.enabled)
			i->second.ts_time_silenced = gettime(); //TODO: save time when alarm was disabled
		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;
				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;
				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;
			}						
		}		
	}
	//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())
		{		
				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);
				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->m_alarm.pop(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
		}
	}
	/*
	 * 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();

	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 -----*/
	/*----- 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"));
	dev_prop.push_back(Tango::DbDatum("ErrorDelay"));
	dev_prop.push_back(Tango::DbDatum("SetAlarmQuality"));

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

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

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

	/*----- 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 -----*/
	/*----- 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 -----*/
	/*----- 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 -----*/
	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 -----*/
	if(ds_num == 0)
	{
		attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
	}
	else
	/*----- 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 -----*/
	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 -----*/
	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 -----*/
	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 -----*/
	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 -----*/
	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 -----*/
	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 -----*/
	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 -----*/
	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 -----*/
	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 eventList related method
 *	Description: List of all subscribed attributes
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void AlarmHandler::read_eventList(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AlarmHandler::read_eventList(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_eventList) ENABLED START -----*/
	prepare_event_list();
	//	Set the attribute value
	attr.set_value(attr_eventList_read, eventList_sz);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_eventList
}
//--------------------------------------------------------
/**
 *	Read attribute eventSummary related method
 *	Description: 
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void AlarmHandler::read_eventSummary(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AlarmHandler::read_eventSummary(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_eventSummary) ENABLED START -----*/
	prepare_event_summary();
	//	Set the attribute value
	attr.set_value(attr_eventSummary_read, eventSummary_sz);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_eventSummary
}
//--------------------------------------------------------
/**
 *	Read attribute alarmDisabled related method
 *	Description: List of alarms in out of service or shelved state
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum max = 10000
 */
//--------------------------------------------------------
void AlarmHandler::read_alarmDisabled(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AlarmHandler::read_alarmDisabled(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AlarmHandler::read_alarmDisabled) ENABLED START -----*/
	//	Set the attribute value
	attr.set_value(attr_alarmDisabled_read, alarmDisabled_sz);
	
	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::read_alarmDisabled
}
//--------------------------------------------------------
/**
 *	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;
		}
	}
	bool error=false;
	bool enabled=true;
	bool shelved=false;
	int silenced=0;
	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;
		error = it->second.error;
		enabled = it->second.enabled;
		shelved = it->second.shelved;
		silenced = it->second.silenced;
	DEBUG_STREAM << "AlarmHandler::read_AlarmState: " << attr.get_name() << " desc=" << desc << endl;
	if(error && enabled && !(shelved && silenced >0)) //TODO: if needs to be considered err_delay also in single alarm attributes, error must be used
	//if(desc.length() > 0)
	{
		Tango::Except::throw_exception(
				reason,
				desc,
				origin, Tango::ERR);
	}
	//	Set the attribute value
	if(quality != Tango::ATTR_VALID && setAlarmQuality)
	{
		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");
Graziano Scalamera's avatar
Graziano Scalamera committed
#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);
Graziano Scalamera's avatar
Graziano Scalamera committed
			*attr_value_formula = Tango::string_dup(i->second.formula.c_str());
			i->second.attr_value_formula = attr_value_formula;
Graziano Scalamera's avatar
Graziano Scalamera committed
#endif
	/*----- 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;
	alarm_t localalarmed, localv_alarm;
	
	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);
				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;

			localalarmed = *found; //NOTE: copy before updating ack
			localv_alarm = i->second;
			//update alarm ack in alarmed table
			found->ack = ACK;
			alarmedlock->readerOut();
			alarms.vlock->readerOut();

			if(localalarmed.ack == NOT_ACK)
				Tango::DevEnum *attr_value = get_AlarmState_data_ptr(localv_alarm.attr_name);
				if(!localv_alarm.enabled)
				else if(localv_alarm.shelved && localv_alarm.silenced > 0)
				else if((localv_alarm.stat == S_NORMAL) && localv_alarm.ack == ACK)
				else if((localv_alarm.stat == S_ALARM) && localv_alarm.ack == NOT_ACK)
				else if((localv_alarm.stat == S_ALARM) && localv_alarm.ack == ACK)
				else if((localv_alarm.stat == S_NORMAL) && localv_alarm.ack == NOT_ACK)
					*attr_value = _RTNUN;
				try
				{	//DevFailed for push events
					if(!localv_alarm.error || !localv_alarm.enabled || (localv_alarm.shelved && localv_alarm.silenced > 0))
						if(setAlarmQuality)
						{
							push_change_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)localv_alarm.quality, 1/*size*/, 0, false);
							push_archive_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)localv_alarm.quality, 1/*size*/, 0, false);
						}
						else
						{
							push_change_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value);
							push_archive_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value);
						}
					}
					else
					{
						Tango::DevErrorList errors(1);
						errors.length(1);
						errors[0].desc = CORBA::string_dup(localv_alarm.ex_desc.c_str());
						errors[0].reason = CORBA::string_dup(localv_alarm.ex_reason.c_str());
						errors[0].origin = CORBA::string_dup(localv_alarm.ex_origin.c_str());
						push_change_event(localv_alarm.attr_name, &except);
						push_archive_event(localv_alarm.attr_name, &except);
					WARN_STREAM << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
		else //not found in alarmed
		{
			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[0],alarmSummary_sz);
		push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
		push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		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[0],alarmSummary_sz);
		push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0],alarmDisabled_sz);
	} 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 -----*/
	DEBUG_STREAM << "AlarmHandler::LOAD ENTERING alm=" << argin << endl;
	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);//doesn't hold locks
		err << "error loading alarm=" << alm.name << " , " << e.errors[0].desc;
		WARN_STREAM << "AlarmHandler::load(): " << err.str() << endl;
				(const char*)"AlarmHandler::load()", \
				(const char*)"AlarmHandler::load()", Tango::ERR);
		add_alarm(alm);//holds alarm writer lock + reader lock
	} catch (string& err) {	//TODO: not throwing string exception
		WARN_STREAM << "AlarmHandler::load(): " << err << endl;
				(const char*)"AlarmHandler::load()", \
				(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
	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*)"AlarmHandler::load()", Tango::ERR);
#if 0//already saved attribute property by subscribe thread
	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.url, alm.cmd_name_a, alm.cmd_name_n, alm.silent_time);	//but if it fails remove it from table
	DEBUG_STREAM << "AlarmHandler::LOAD save_alarm_conf_db-" << alm.attr_name << endl;

	string conf_str;
	alm.confstr(conf_str);
	savedlock->writerIn();
	saved_alarms.insert(make_pair(alm.attr_name,conf_str));
	savedlock->writerOut();
#endif
	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 //holds alarm reader lock
		} 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->m_alarm.pop(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;
				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;
				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();
	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;
	}
DEBUG_STREAM << "AlarmHandler::LOAD EXITING alm=" << argin << endl;
	/*----- 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);
		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[0],alarmSummary_sz);
		push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
		push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		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[0],alarmSummary_sz);
		push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
	} 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)
	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 != string::npos))
			os << 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(URL_KEY) << ai->second.url <<
				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[0],alarmSummary_sz);
		push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
		push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		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[0],alarmSummary_sz);
		push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
	} 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.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)
					i->second.silenced = i->second.silent_time - floor(dminutes);
				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);
				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);
		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[0],alarmSummary_sz);
		push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
		push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
		push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
		push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
		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[0],alarmSummary_sz);
		push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
	} 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
Loading full blame...