From d836b06cc98605a3f51352e0ba7d53c8c0a6f72e Mon Sep 17 00:00:00 2001
From: gscalamera <graziano.scalamera@elettra.eu>
Date: Thu, 11 Aug 2016 16:02:44 +0200
Subject: [PATCH] Initial commit of Elettra alarm device server re-generated
 with a new pogo

---
 Make-8.1.2.c.in           |   66 +
 Make-9.2.2.in             |   89 +
 Makefile                  |   11 +
 src/Alarm.cpp             | 3567 +++++++++++++++++++++++++++++++++++++
 src/Alarm.h               |  337 ++++
 src/Alarm.xmi             |  134 ++
 src/AlarmClass.cpp        |  918 ++++++++++
 src/AlarmClass.h          |  291 +++
 src/AlarmStateMachine.cpp |  186 ++
 src/ClassFactory.cpp      |   49 +
 src/alarm-thread.cpp      |   90 +
 src/alarm-thread.h        |   41 +
 src/alarm_grammar.h       |  280 +++
 src/alarm_table.cpp       |  722 ++++++++
 src/alarm_table.h         |  212 +++
 src/cmd_thread.cpp        |  288 +++
 src/cmd_thread.h          |   85 +
 src/event_table.cpp       |  549 ++++++
 src/event_table.h         |  144 ++
 src/formula_grammar.h     |  291 +++
 src/log_thread.cpp        |  510 ++++++
 src/log_thread.h          |  133 ++
 src/main.cpp              |   88 +
 src/update-thread.cpp     |   65 +
 src/update-thread.h       |   39 +
 25 files changed, 9185 insertions(+)
 create mode 100644 Make-8.1.2.c.in
 create mode 100644 Make-9.2.2.in
 create mode 100644 Makefile
 create mode 100644 src/Alarm.cpp
 create mode 100644 src/Alarm.h
 create mode 100644 src/Alarm.xmi
 create mode 100644 src/AlarmClass.cpp
 create mode 100644 src/AlarmClass.h
 create mode 100644 src/AlarmStateMachine.cpp
 create mode 100644 src/ClassFactory.cpp
 create mode 100644 src/alarm-thread.cpp
 create mode 100644 src/alarm-thread.h
 create mode 100644 src/alarm_grammar.h
 create mode 100644 src/alarm_table.cpp
 create mode 100644 src/alarm_table.h
 create mode 100644 src/cmd_thread.cpp
 create mode 100644 src/cmd_thread.h
 create mode 100644 src/event_table.cpp
 create mode 100644 src/event_table.h
 create mode 100644 src/formula_grammar.h
 create mode 100644 src/log_thread.cpp
 create mode 100644 src/log_thread.h
 create mode 100644 src/main.cpp
 create mode 100644 src/update-thread.cpp
 create mode 100644 src/update-thread.h

diff --git a/Make-8.1.2.c.in b/Make-8.1.2.c.in
new file mode 100644
index 0000000..cc8413e
--- /dev/null
+++ b/Make-8.1.2.c.in
@@ -0,0 +1,66 @@
+CXXFLAGS += -std=gnu++98
+
+TANGO_DIR ?= /usr/local/tango-8.1.2.c
+OMNIORB_DIR ?= /usr/local/omniorb-4.1.6
+RUNTIME_DIR ?= /runtime
+
+TANGO_INC = ${TANGO_DIR}/include/tango
+OMNIORB_INC = ${OMNIORB_DIR}/include
+RUNTIME_INC = ${RUNTIME_DIR}/include
+
+INC_DIR = -I${TANGO_INC} -I${OMNIORB_INC} -I${RUNTIME_INC}
+
+TANGO_LIB = ${TANGO_DIR}/lib
+OMNIORB_LIB = ${OMNIORB_DIR}/lib
+RUNTIME_LIB = ${RUNTIME_DIR}/lib
+
+LIB_DIR = -L${TANGO_LIB} -L${OMNIORB_LIB} -L${RUNTIME_LIB} -L/usr/local/lib
+
+#-----------------------------------------
+#	 Default make entry
+#-----------------------------------------
+default: release
+release debug: bin/$(NAME_SRV)
+
+#-----------------------------------------
+#	Set CXXFLAGS and LDFLAGS
+#----------------------------------------r
+CXXFLAGS += -D__linux__ -D__OSVERSION__=2 -pedantic -Wall -Wextra \
+	-Wno-non-virtual-dtor -Wno-long-long -DOMNI_UNLOADABLE_STUBS \
+	$(INC_DIR) -Isrc
+LDFLAGS += $(LIB_DIR) -ltango -llog4tango -lomniORB4 -lomniDynamic4 \
+	-lCOS4 -lomnithread -lzmq
+
+#-----------------------------------------
+#	Set dependencies
+#-----------------------------------------
+SRC_FILES += $(wildcard src/*.cpp)
+OBJ_FILES += $(addprefix obj/,$(notdir $(SRC_FILES:.cpp=.o)))
+
+obj/%.o: $(SRC_FILES:%.cpp)
+	$(CXX) $(CXXFLAGS) -c -o $@ $<
+
+.nse_depinfo: $(SRC_FILES)
+	@$(CXX) $(CXXFLAGS) -M -MM $^ | sed 's/\(.*\)\.o/obj\/\1.o/g' > $@
+-include .nse_depinfo
+
+#-----------------------------------------
+#	 Main make entries
+#-----------------------------------------
+bin/$(NAME_SRV): bin obj $(OBJ_FILES)
+	$(CXX) $(CXXFLAGS) $(OBJ_FILES) -o bin/$(NAME_SRV) $(LDFLAGS)
+
+clean:
+	@rm -fr obj/ bin/ core* .nse_depinfo src/*~
+
+bin obj:
+	@mkdir $@
+
+#-----------------------------------------
+#	 Target specific options
+#-----------------------------------------
+release: CXXFLAGS += -O2 -DNDEBUG
+release: LDFLAGS += -s
+debug: CXXFLAGS += -ggdb3
+
+.PHONY: clean
diff --git a/Make-9.2.2.in b/Make-9.2.2.in
new file mode 100644
index 0000000..c261ce4
--- /dev/null
+++ b/Make-9.2.2.in
@@ -0,0 +1,89 @@
+CXXFLAGS += -std=c++0x
+
+GCCMAJOR := $(shell ${CXX} -dumpversion | cut -d"." -f1)
+GCCMINOR := $(shell ${CXX} -dumpversion | cut -d"." -f2)
+ifeq ($(GCCMAJOR),4)
+	ifneq ($(GCCMINOR),8)
+		SYSROOT  := $(shell ${CXX} -print-sysroot)
+	endif
+endif
+MACHINE  := $(shell ${CXX} -dumpmachine)
+
+TANGO_DIR := /usr/local/tango-9.2.2
+OMNIORB_DIR := /usr/local/omniorb-4.2.1
+ZMQ_DIR := /usr/local/zeromq-4.0.7
+RUNTIME_DIR := /runtime
+
+TANGO_INC := ${TANGO_DIR}/include/tango
+OMNIORB_INC := ${OMNIORB_DIR}/include
+RUNTIME_INC := ${RUNTIME_DIR}/include
+ZMQ_INC :=  ${ZMQ_DIR}/include
+
+ifeq ($(SYSROOT),)
+	INC_DIR = -I${TANGO_INC} -I${OMNIORB_INC} -I${ZMQ_INC} -I${RUNTIME_INC}
+else
+	INC_DIR = -I${SYSROOT}/usr/include/tango -I/srv/${MACHINE}/runtime/
+endif
+
+TANGO_LIB = ${TANGO_DIR}/lib
+OMNIORB_LIB = ${OMNIORB_DIR}/lib
+RUNTIME_LIB = ${RUNTIME_DIR}/lib
+ZMQ_LIB = ${ZMQ_DIR}/lib
+
+ifeq ($(SYSROOT),)
+LIB_DIR = -L${TANGO_LIB} -L${OMNIORB_LIB} -L${RUNTIME_LIB} -L${ZMQ_LIB}
+else
+	LIB_DIR = -L/srv/${MACHINE}/runtime/lib
+endif
+
+#-----------------------------------------
+#	 Default make entry
+#-----------------------------------------
+default: release
+release debug: bin/$(NAME_SRV)
+
+#-----------------------------------------
+#	Set CXXFLAGS and LDFLAGS
+#----------------------------------------r
+CXXFLAGS += -D__linux__ -D__OSVERSION__=2 -pedantic -Wall \
+	-Wno-non-virtual-dtor -Wno-long-long -DOMNI_UNLOADABLE_STUBS \
+	$(INC_DIR) -Isrc
+ifeq ($(GCCMAJOR),4)
+    CXXFLAGS += -Wextra
+endif
+LDFLAGS += $(LIB_DIR) -ltango -llog4tango -lomniORB4 -lomniDynamic4 \
+	-lCOS4 -lomnithread -lzmq
+
+#-----------------------------------------
+#	Set dependencies
+#-----------------------------------------
+SRC_FILES += $(wildcard src/*.cpp)
+OBJ_FILES += $(addprefix obj/,$(notdir $(SRC_FILES:.cpp=.o)))
+
+obj/%.o: $(SRC_FILES:%.cpp)
+	$(CXX) $(CXXFLAGS) -c -o $@ $<
+
+.nse_depinfo: $(SRC_FILES)
+	@$(CXX) $(CXXFLAGS) -M -MM $^ | sed 's/\(.*\)\.o/obj\/\1.o/g' > $@
+-include .nse_depinfo
+
+#-----------------------------------------
+#	 Main make entries
+#-----------------------------------------
+bin/$(NAME_SRV): bin obj $(OBJ_FILES)
+	$(CXX) $(CXXFLAGS) $(OBJ_FILES) -o bin/$(NAME_SRV) $(LDFLAGS)
+
+clean:
+	@rm -fr obj/ bin/ core* .nse_depinfo src/*~
+
+bin obj:
+	@mkdir $@
+
+#-----------------------------------------
+#	 Target specific options
+#-----------------------------------------
+release: CXXFLAGS += -O2 -DNDEBUG
+release: LDFLAGS += -s
+debug: CXXFLAGS += -ggdb3
+
+.PHONY: clean
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..6f580c3
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,11 @@
+NAME_SRV = alarm-srv
+
+
+
+CXXFLAGS += `mysql_config --include`
+
+
+LDFLAGS += `mysql_config --libs_r` -lboost_thread
+
+#include ./Make-8.1.2.c.in
+include ./Make-9.2.2.in
diff --git a/src/Alarm.cpp b/src/Alarm.cpp
new file mode 100644
index 0000000..6a4648d
--- /dev/null
+++ b/src/Alarm.cpp
@@ -0,0 +1,3567 @@
+/*----- PROTECTED REGION ID(Alarm.cpp) ENABLED START -----*/
+static const char *RcsId = "$Id:  $";
+//=============================================================================
+//
+// file :        Alarm.cpp
+//
+// description : C++ source for the Alarm 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
+//               Alarm are implemented in this file.
+//
+// project :     alarm
+//
+// 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/>.
+// 
+// $Author:  $
+//
+// $Revision:  $
+// $Date:  $
+//
+// $HeadURL:  $
+//
+//=============================================================================
+//                This file is generated by POGO
+//        (Program Obviously used to Generate tango Object)
+//=============================================================================
+
+
+#include <tango.h>
+#include <Alarm.h>
+#include <AlarmClass.h>
+#include <ctype.h>		//for tolower
+
+#include "alarm-thread.h"
+#include "alarm_grammar.h"
+#include "log_thread.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 Alarm_ns::Alarm::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 -----*/	//	Alarm.cpp
+
+/**
+ *  Alarm class description:
+ *    Elettra alarm 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
+//  Configured    |  configured
+//  StopNew       |  stop_new
+//  Silence       |  silence
+//  Modify        |  modify
+//================================================================
+
+//================================================================
+//  Attributes managed is:
+//================================================================
+//  alarm  |  Tango::DevString	Spectrum  ( max = 1024)
+//================================================================
+
+namespace Alarm_ns
+{
+/*----- PROTECTED REGION ID(Alarm::namespace_starting) ENABLED START -----*/
+
+//	static initializations
+
+/*----- PROTECTED REGION END -----*/	//	Alarm::namespace_starting
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::Alarm()
+ *	Description : Constructors for a Tango device
+ *                implementing the classAlarm
+ */
+//--------------------------------------------------------
+Alarm::Alarm(Tango::DeviceClass *cl, string &s)
+ : TANGO_BASE_CLASS(cl, s.c_str())
+{
+	/*----- PROTECTED REGION ID(Alarm::constructor_1) ENABLED START -----*/
+	init_device();
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::constructor_1
+}
+//--------------------------------------------------------
+Alarm::Alarm(Tango::DeviceClass *cl, const char *s)
+ : TANGO_BASE_CLASS(cl, s)
+{
+	/*----- PROTECTED REGION ID(Alarm::constructor_2) ENABLED START -----*/
+	init_device();
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::constructor_2
+}
+//--------------------------------------------------------
+Alarm::Alarm(Tango::DeviceClass *cl, const char *s, const char *d)
+ : TANGO_BASE_CLASS(cl, s, d)
+{
+	/*----- PROTECTED REGION ID(Alarm::constructor_3) ENABLED START -----*/
+	init_device();
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::constructor_3
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::delete_device()
+ *	Description : will be called at device destruction or at init command
+ */
+//--------------------------------------------------------
+void Alarm::delete_device()
+{
+	DEBUG_STREAM << "Alarm::delete_device() " << device_name << endl;
+	/*----- PROTECTED REGION ID(Alarm::delete_device) ENABLED START -----*/
+	
+	//	Delete device allocated objects
+	//	Delete device's allocated object
+	/*
+	 * unsubscribe events and release memory
+	 */
+	DEBUG_STREAM << "Alarm::delete_device(): entering..." << endl;
+	abortflag = true;
+	DEBUG_STREAM << "Alarm::delete_device(): after abortflag=true..." << endl;
+	try {
+		events->unsubscribe();
+	} catch (string& err) {
+		ERROR_STREAM << err << endl;
+	}
+	DEBUG_STREAM << "Alarm::delete_device(): events unsubscribed!" << endl;
+	events->free_proxy();
+	DEBUG_STREAM << "Alarm::delete_device(): device proxy deleted!" << 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);
+#ifdef _RW_LOCK
+	alarms.del_rwlock();
+#endif
+	alarms.stop_logdb();
+	alarms.stop_cmdthread();
+	sleep(1);		//wait for alarm_thread and log_thread to exit
+	//delete almloop;
+	DEBUG_STREAM << "Alarm::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;
+	}	
+	/*
+	 * 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);
+#ifndef _USE_ELETTRA_DB_RW
+	Tango::Database *db = new Tango::Database();
+#else	
+	//salvataggio proprietà usando host_rw e port_rw per connettersi al database
+	Tango::Database *db;
+	if(host_rw != "")
+		db = new Tango::Database(host_rw,port_rw);
+	else
+		db = new Tango::Database();
+#endif
+	try {
+
+		db->put_device_property(get_name(), data_put);
+	}
+	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;
+	DEBUG_STREAM << "Alarm::delete_device(): saved AlarmStatus in properties!!" << endl;
+	//Tango::leavefunc();
+
+	/*----- PROTECTED REGION END -----*/	//	Alarm::delete_device
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::init_device()
+ *	Description : will be called at device initialization.
+ */
+//--------------------------------------------------------
+void Alarm::init_device()
+{
+	DEBUG_STREAM << "Alarm::init_device() create device " << device_name << endl;
+	/*----- PROTECTED REGION ID(Alarm::init_device_before) ENABLED START -----*/
+	
+	//	Initialization before get_device_property() call
+	int dbPortint=0;	
+	abortflag = false;	
+	instanceCounter++;
+	events = new event_table(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);
+	}	//-------------------------------------------	
+	errThreshold = 0;
+	alarmedlock = new(ReadersWritersLock);
+	internallock = new(ReadersWritersLock);
+	dslock = new(ReadersWritersLock);
+
+
+	/*----- PROTECTED REGION END -----*/	//	Alarm::init_device_before
+	
+
+	//	Get the device properties from database
+	get_device_property();
+	
+	/*----- PROTECTED REGION ID(Alarm::init_device) ENABLED START -----*/
+	
+	//	Initialize device
+	
+#ifdef _USE_ELETTRA_DB_RW
+	host_rw = "";
+	Tango::Database *db = new Tango::Database();
+	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 << "'";
+	}
+	string server = "alarm-srv/test";
+	Tango::DbServerInfo info = db->get_server_info(server);
+	INFO_STREAM << " INFO: host=" << info.host;
+
+	delete db;
+#endif
+	
+	dbPortint = atoi(dbPort.c_str());
+	if(dbHost.empty() || dbUser.empty() || dbPasswd.empty() || dbName.empty() || (dbPortint == 0) || instanceName.empty())
+	{
+		ERROR_STREAM << "Alarm::init_device(): not all necessary properties are defined: DbHost="<<dbHost<<
+			" DbUser="<<dbUser<<" DbPasswd="<<dbPasswd<<" DbName="<<dbName<<" DbPort="<<dbPortint<<" InstanceName="<<instanceName<< endl;
+		cout << "Error: not all necessary properties are defined. Exiting..." << endl;
+		exit(-2);
+	}	
+	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
+	 */	
+#ifdef _RW_LOCK
+	alarms.new_rwlock();
+#endif
+	try {
+		if((!dbHost.empty()) && (!dbUser.empty()) && (!dbPasswd.empty()) && (!dbName.empty()) && (dbPortint != 0) )
+			//logloop = new log_thread(dbhost, dbuser, dbpw, dbname, dbportint,this);
+			alarms.init_logdb(dbHost, dbUser, dbPasswd, dbName, dbPortint, instanceName);
+	} catch(string & e)
+	{
+		ERROR_STREAM << "Alarm::init_device(): " << e << endl;
+		cout << "Error: " << e << ". Exiting..." << endl;
+		exit(-3);
+	}
+	
+	try {
+		alarms.init_cmdthread();
+	} catch(...)
+	{
+		WARN_STREAM << "Alarm::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";    	
+	
+	/*
+	 * 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);
+	} catch(string & e)
+	{
+		ERROR_STREAM << "Alarm::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);
+			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 << ends;
+			WARN_STREAM << "Alarm::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 << ends;
+			WARN_STREAM << "Alarm::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" << ends;
+					ERROR_STREAM << "Alarm::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 << "Alarm::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 << ends;
+				WARN_STREAM << "Alarm::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" << ends;
+					ERROR_STREAM << "Alarm::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 << "Alarm::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 << ends;
+				WARN_STREAM << "Alarm::init_device(): " << err.str() << endl;
+				set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());
+				i->second.dp_n = NULL;
+			}						
+		}		
+	}
+		
+	alarms.startup_complete = gettime();			//enable actions execution in 10 seconds
+	
+	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 TANGO_VER < 611
+			try {
+				add_event(i->second, al_ev_it->second);
+				subscribe_event(i->second, ecb, al_ev_it->second);
+			} catch (string& err) {
+				WARN_STREAM << "Alarm::init_device(): " << err << endl;				
+				for(vector<string>::iterator j=al_ev_it->second.begin(); j!=al_ev_it->second.end(); j++)
+				{
+					DEBUG_STREAM << "Alarm::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 << "Alarm::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 << "Alarm::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 << "Alarm::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 << "Alarm::init_device(): " << err << endl;
+				set_internal_alarm(INTERNAL_ERROR, gettime(), err);
+			}			
+#endif
+		}
+	}
+	
+
+	/*
+	 * update event table with fresh-subscribed event[s] data
+	 */
+	 
+	list<bei_t> el;
+	el = evlist.show();
+
+	try {
+		for (list<bei_t>::iterator j = el.begin(); j != el.end(); j++) 
+		{
+			//cout << "name = " << j->name << "\ttype = " << j->type << endl;
+			events->update_events(*j);
+		}
+	}
+	catch (string& err)
+	{
+		WARN_STREAM << "init_device(): error updating events = " << err << endl;
+	}
+	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();
+	
+  	set_state(Tango::RUNNING);
+	set_status("Alarm server is running");	
+
+	//
+
+//	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]);
+
+	/*----- PROTECTED REGION END -----*/	//	Alarm::init_device
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::get_device_property()
+ *	Description : Read database to initialize property data members.
+ */
+//--------------------------------------------------------
+void Alarm::get_device_property()
+{
+	/*----- PROTECTED REGION ID(Alarm::get_device_property_before) ENABLED START -----*/
+	
+	//	Initialize property data members
+	
+
+	/*----- PROTECTED REGION END -----*/	//	Alarm::get_device_property_before
+
+
+	//	Read device properties from database.
+	Tango::DbData	dev_prop;
+	dev_prop.push_back(Tango::DbDatum("AlarmStatus"));
+	dev_prop.push_back(Tango::DbDatum("GroupNames"));
+	dev_prop.push_back(Tango::DbDatum("ErrThreshold"));
+	dev_prop.push_back(Tango::DbDatum("DbHost"));
+	dev_prop.push_back(Tango::DbDatum("DbUser"));
+	dev_prop.push_back(Tango::DbDatum("DbPasswd"));
+	dev_prop.push_back(Tango::DbDatum("DbName"));
+	dev_prop.push_back(Tango::DbDatum("DbPort"));
+	dev_prop.push_back(Tango::DbDatum("InstanceName"));
+
+	//	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 AlarmClass to get class property
+		Tango::DbDatum	def_prop, cl_prop;
+		AlarmClass	*ds_class =
+			(static_cast<AlarmClass *>(get_device_class()));
+		int	i = -1;
+
+		//	Try to initialize AlarmStatus from class property
+		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
+		if (cl_prop.is_empty()==false)	cl_prop  >>  alarmStatus;
+		else {
+			//	Try to initialize AlarmStatus from default device value
+			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
+			if (def_prop.is_empty()==false)	def_prop  >>  alarmStatus;
+		}
+		//	And try to extract AlarmStatus value from database
+		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  alarmStatus;
+
+		//	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 ErrThreshold from class property
+		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
+		if (cl_prop.is_empty()==false)	cl_prop  >>  errThreshold;
+		else {
+			//	Try to initialize ErrThreshold from default device value
+			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
+			if (def_prop.is_empty()==false)	def_prop  >>  errThreshold;
+		}
+		//	And try to extract ErrThreshold value from database
+		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  errThreshold;
+
+		//	Try to initialize DbHost from class property
+		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
+		if (cl_prop.is_empty()==false)	cl_prop  >>  dbHost;
+		else {
+			//	Try to initialize DbHost from default device value
+			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
+			if (def_prop.is_empty()==false)	def_prop  >>  dbHost;
+		}
+		//	And try to extract DbHost value from database
+		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  dbHost;
+
+		//	Try to initialize DbUser from class property
+		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
+		if (cl_prop.is_empty()==false)	cl_prop  >>  dbUser;
+		else {
+			//	Try to initialize DbUser from default device value
+			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
+			if (def_prop.is_empty()==false)	def_prop  >>  dbUser;
+		}
+		//	And try to extract DbUser value from database
+		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  dbUser;
+
+		//	Try to initialize DbPasswd from class property
+		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
+		if (cl_prop.is_empty()==false)	cl_prop  >>  dbPasswd;
+		else {
+			//	Try to initialize DbPasswd from default device value
+			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
+			if (def_prop.is_empty()==false)	def_prop  >>  dbPasswd;
+		}
+		//	And try to extract DbPasswd value from database
+		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  dbPasswd;
+
+		//	Try to initialize DbName from class property
+		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
+		if (cl_prop.is_empty()==false)	cl_prop  >>  dbName;
+		else {
+			//	Try to initialize DbName from default device value
+			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
+			if (def_prop.is_empty()==false)	def_prop  >>  dbName;
+		}
+		//	And try to extract DbName value from database
+		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  dbName;
+
+		//	Try to initialize DbPort from class property
+		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
+		if (cl_prop.is_empty()==false)	cl_prop  >>  dbPort;
+		else {
+			//	Try to initialize DbPort from default device value
+			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
+			if (def_prop.is_empty()==false)	def_prop  >>  dbPort;
+		}
+		//	And try to extract DbPort value from database
+		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  dbPort;
+
+		//	Try to initialize InstanceName from class property
+		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
+		if (cl_prop.is_empty()==false)	cl_prop  >>  instanceName;
+		else {
+			//	Try to initialize InstanceName from default device value
+			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
+			if (def_prop.is_empty()==false)	def_prop  >>  instanceName;
+		}
+		//	And try to extract InstanceName value from database
+		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  instanceName;
+
+	}
+
+	/*----- PROTECTED REGION ID(Alarm::get_device_property_after) ENABLED START -----*/
+	
+	//	Check device property data members init
+	/*
+	 * initialize groups
+	 */	
+	alarm_t tmp_alm;						
+	tmp_alm.init_static_map(groupNames); 
+	
+	/*
+	 * retrive last saved alarms status
+	 */
+	if (alarmStatus.empty() == false) {
+		for (vector<string>::iterator i = alarmStatus.begin(); \
+			 	 i != alarmStatus.end(); i++) {
+			/*
+			 * test for string length; data[1].is_empty() will return false
+			 * when empty string eventually initialized with jive!!!!!!
+			 */
+			if (i->length() != 0) {
+				alarm_t tmp_alm;
+				tmp_alm.str2alm(*i);
+				tmp_alm.is_new = /*(tmp_alm.stat == S_ALARM) ? 1 :*/ 0; //don't beep at startup on old alarms
+				stored.push_back(tmp_alm);
+			}
+		}
+	}
+	DEBUG_STREAM << "saved alarms table:" << endl;
+	if (stored.empty() == false) {
+		for (vector<alarm_t>::iterator a = stored.begin(); \
+			 	 a != stored.end(); a++) {
+			DEBUG_STREAM << "\t" << a->alm2str() << endl;
+		}
+	}
+
+	/*----- PROTECTED REGION END -----*/	//	Alarm::get_device_property_after
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::always_executed_hook()
+ *	Description : method always executed before any command is executed
+ */
+//--------------------------------------------------------
+void Alarm::always_executed_hook()
+{
+	DEBUG_STREAM << "Alarm::always_executed_hook()  " << device_name << endl;
+	/*----- PROTECTED REGION ID(Alarm::always_executed_hook) ENABLED START -----*/
+	
+	//	code always executed before all requests
+	
+
+	/*----- PROTECTED REGION END -----*/	//	Alarm::always_executed_hook
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::read_attr_hardware()
+ *	Description : Hardware acquisition for attributes
+ */
+//--------------------------------------------------------
+void Alarm::read_attr_hardware(TANGO_UNUSED(vector<long> &attr_list))
+{
+	DEBUG_STREAM << "Alarm::read_attr_hardware(vector<long> &attr_list) entering... " << endl;
+	/*----- PROTECTED REGION ID(Alarm::read_attr_hardware) ENABLED START -----*/
+	
+	//	Add your own code
+	//DEBUG_STREAM << "In read_attr_hardware for " << attr_list.size() << " attribute(s)" << endl;
+	
+	//	Add your own code here
+	//---------------------------------
+
+	/*----- PROTECTED REGION END -----*/	//	Alarm::read_attr_hardware
+}
+
+//--------------------------------------------------------
+/**
+ *	Read attribute alarm related method
+ *	Description: 
+ *
+ *	Data type:	Tango::DevString
+ *	Attr type:	Spectrum max = 1024
+ */
+//--------------------------------------------------------
+void Alarm::read_alarm(Tango::Attribute &attr)
+{
+	DEBUG_STREAM << "Alarm::read_alarm(Tango::Attribute &attr) entering... " << endl;
+	/*----- PROTECTED REGION ID(Alarm::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 -----*/	//	Alarm::read_alarm
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::add_dynamic_attributes()
+ *	Description : Create the dynamic attributes if any
+ *                for specified device.
+ */
+//--------------------------------------------------------
+void Alarm::add_dynamic_attributes()
+{
+	/*----- PROTECTED REGION ID(Alarm::add_dynamic_attributes) ENABLED START -----*/
+	
+	//	Add your own code to create and add dynamic attributes if any
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::add_dynamic_attributes
+}
+
+//--------------------------------------------------------
+/**
+ *	Command Ack related method
+ *	Description: Alarm acknowledge
+ *
+ *	@param argin String array containing the alarms to be acknowledged
+ */
+//--------------------------------------------------------
+void Alarm::ack(const Tango::DevVarStringArray *argin)
+{
+	DEBUG_STREAM << "Alarm::Ack()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(Alarm::ack) ENABLED START -----*/
+	
+	//	Add your own code
+	vector<string> str;
+	str << (*argin);
+	vector<string>::iterator si;
+	
+	for (si = str.begin(); si != str.end(); si++) {
+#ifndef _RW_LOCK
+		alarms.lock();
+#else
+		alarms.vlock->readerIn();
+#endif
+		alarmedlock->readerIn();
+		vector<alarm_t>::iterator found = \
+		find(alarmed.begin(), alarmed.end(), *si);
+		if (found != alarmed.end()) 
+		{
+			alarm_container_t::iterator i = alarms.v_alarm.find(*si);
+			if(i != alarms.v_alarm.end())
+			{
+				//update alarm ack in alarm table
+				i->second.ack = ACK;
+				//update alarm status from alarm table
+				found->stat = i->second.stat;
+			}
+			if(found->ack == NOT_ACK)
+			{
+				alarms.log_alarm_db(TYPE_LOG_STATUS, gettime(), found->name, found->stat, ACK, 
+						"", 0, "", "", "", "", -1);
+			}
+			found->ack = ACK;		
+		} else {
+			internallock->readerIn();
+			found = find(internal.begin(), internal.end(), *si);
+			if (found != internal.end()) {
+				found->ack = ACK;
+			} else {
+				ostringstream o;
+				o << "\"" << *si << "\" not in 'alarmed' or 'internal' table" << endl;
+				WARN_STREAM << "Alarm::ack(): " << o.str() << endl;
+				internallock->readerOut();
+				alarmedlock->readerOut();
+#ifndef _RW_LOCK
+				alarms.unlock();
+#else
+				alarms.vlock->readerOut();
+#endif
+				Tango::Except::throw_exception( \
+					(const char*)"Alarm not found!!", \
+					o.str(), \
+					(const char*)"Alarm::ack()", Tango::ERR);									 
+				
+			}
+			internallock->readerOut();
+		}
+		alarmedlock->readerOut();
+#ifndef _RW_LOCK
+		alarms.unlock();
+#else
+		alarms.vlock->readerOut();
+#endif
+	}
+	/*
+	 * remove S_NORMAL status ACKnowledged alarms
+	 */
+	alarm_t to_be_removed;
+	to_be_removed.name = "";
+	to_be_removed.formula = "";
+	to_be_removed.stat = S_NORMAL;
+	to_be_removed.ack = ACK;
+	bool go = true;
+	while (go) {
+		alarmedlock->writerIn();
+		vector<alarm_t>::iterator found = \
+				find(alarmed.begin(), alarmed.end(), to_be_removed);
+		if (found != alarmed.end()) {
+			DEBUG_STREAM << "Alarm::ack(): " << found->name \
+					 				 << " S_NORMAL and ACK, removing"  << endl;
+			alarmed.erase(found);
+		} else {
+			go = false;
+		}
+		alarmedlock->writerOut();
+	}
+	/*
+	 * always remove internal ACKnowlwdged alarms as
+	 * they'll wont switch to "NORMAL"
+	 */
+	to_be_removed.name = "";
+	to_be_removed.formula = "";
+	to_be_removed.stat = S_ALARM;
+	to_be_removed.ack = ACK;
+	go = true;
+	while (go) {
+		internallock->writerIn();
+		vector<alarm_t>::iterator found = \
+				find(internal.begin(), internal.end(), to_be_removed);
+		if (found != internal.end()) {
+			DEBUG_STREAM << "Alarm::ack(): " << found->name \
+					 				 << " ACK, removing"  << endl;
+			internal.erase(found);
+		} else {
+			go = false;
+		}
+		internallock->writerOut();
+	}
+
+	prepare_alarm_attr();
+	try
+	{
+		if(ds_num == 0)
+		{
+			//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
+			struct timeval now;
+			gettimeofday(&now,NULL);
+			push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
+		}
+		else
+			//attr.set_value(ds, ds_num, 0, false);
+			push_change_event("alarm",ds, ds_num, 0, false);
+	} catch(Tango::DevFailed& e)
+	{
+		ostringstream err;
+		err << "error pushing alarm change event err=" << e.errors[0].desc;
+		INFO_STREAM << __func__<<": " << err.str() << endl;
+	}
+
+	/*----- PROTECTED REGION END -----*/	//	Alarm::ack
+}
+//--------------------------------------------------------
+/**
+ *	Command Load related method
+ *	Description: Load a new alarm.
+ *
+ *	@param argin Alarm entry
+ */
+//--------------------------------------------------------
+void Alarm::load(Tango::DevString argin)
+{
+	DEBUG_STREAM << "Alarm::Load()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(Alarm::load) ENABLED START -----*/
+	
+	//	Add your own code
+	string s;
+	alarm_t alm;
+	vector<string> evn;
+	
+	s = argin;
+	//std::transform(s.begin(), s.end(), s.begin(), (int(*)(int))tolower);		//transform to lowercase
+	Tango::TimeVal ts = gettime();
+	try {
+		load_alarm(s, alm, evn);
+	} catch(Tango::DevFailed& e)
+	{
+		ostringstream err;
+		err << "error loading alarm=" << alm.name << " , " << e.errors[0].desc << ends;
+		WARN_STREAM << "Alarm::load(): " << err.str() << endl;
+		Tango::Except::throw_exception( \
+				(const char*)"Alarm::load()", \
+				err.str(), \
+				(const char*)"Alarm::load()", Tango::ERR);	
+	}
+	
+	try {
+		add_alarm(alm);
+	} catch (string& err) {
+		WARN_STREAM << "Alarm::load(): " << err << endl;
+		Tango::Except::throw_exception( \
+				(const char*)"Alarm::load()", \
+				(const char*)err.c_str(), \
+				(const char*)"Alarm::load()", Tango::ERR);
+	}
+	try {
+		add_event(alm, evn);
+	} catch (string& err) {
+		WARN_STREAM << "Alarm::load(): " << err << endl;
+#ifndef _RW_LOCK
+		alarms.lock();
+#else
+		alarms.vlock->writerIn();
+#endif
+		alarm_container_t::iterator i = alarms.v_alarm.find(alm.name);		//look for alarm just added
+		if (i != alarms.v_alarm.end())	
+			alarms.erase(i);											//and remove from alarm_table
+#ifndef _RW_LOCK
+		alarms.unlock();
+#else
+		alarms.vlock->writerOut();
+#endif
+		Tango::Except::throw_exception( \
+				(const char*)"Alarm::load()", \
+				(const char*)err.c_str(), \
+				(const char*)"Alarm::load()", Tango::ERR);
+	}
+	string cmd_name_full = alm.cmd_name_a + string(";") + alm.cmd_name_n;
+	alarms.log_alarm_db(TYPE_LOG_DESC_ADD, ts, alm.name, "", "", 		//add new alarm on log before subscribe event
+			alm.formula, alm.time_threshold, alm.grp2str(), alm.lev, alm.msg, cmd_name_full, alm.silent_time);	//but if it fails remove it from table
+	try {
+		subscribe_event(alm, ecb, evn);
+	} catch (string& err) {
+		WARN_STREAM << "Alarm::load(): " << err << endl;
+#ifndef _RW_LOCK
+		alarms.lock();
+#else
+		alarms.vlock->writerIn();
+#endif
+		alarm_container_t::iterator i = alarms.v_alarm.find(alm.name);		//look for alarm just added
+		if (i != alarms.v_alarm.end())	
+			alarms.erase(i);											//and remove from alarm_table
+#ifndef _RW_LOCK
+		alarms.unlock();
+#else
+		alarms.vlock->writerOut();
+#endif
+		alarms.log_alarm_db(TYPE_LOG_DESC_REM, ts, alm.name, "", "", 		//remove alarm just added
+			"", 0, "", "", "", "", -1);
+		Tango::Except::throw_exception( \
+				(const char*)"Alarm::load()", \
+				(const char*)err.c_str(), \
+				(const char*)"Alarm::load()", Tango::ERR);
+	}
+	
+	if(alm.cmd_name_a.length() > 0)
+	{
+#ifndef _RW_LOCK
+		alarms.lock();
+#else
+		alarms.vlock->readerIn();
+#endif
+		alarm_container_t::iterator i = alarms.v_alarm.find(alm.name);		//look for alarm just added
+		if (i != alarms.v_alarm.end())
+		{
+			try {
+				i->second.dp_a = new Tango::DeviceProxy(i->second.cmd_dp_a);
+				i->second.dp_a->ping();
+				Tango::CommandInfo info = i->second.dp_a->command_query(i->second.cmd_action_a);
+				if(info.in_type != Tango::DEV_STRING)
+				{
+					ostringstream err;
+					err << "Error: command " << i->second.cmd_name_a << " does not accept a Tango::DevString as input value" << ends;
+					ERROR_STREAM << "Alarm::load(): " << err.str() << endl;
+					set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());					
+				}
+				else
+				{
+					if(info.in_type == Tango::DEV_STRING)
+						i->second.send_arg_a = true;
+					else
+						i->second.send_arg_a = false;
+					DEBUG_STREAM << "Alarm::load(): successfully connected to proxy=" << i->second.cmd_dp_a << " for action=" << i->second.cmd_action_a << endl;
+				}
+			} catch(Tango::DevFailed& e)
+			{
+				ostringstream err;
+				err << alm.name << ": error connecting to device proxy=" << i->second.cmd_dp_a << ", err=" << e.errors[0].desc << ends;
+				WARN_STREAM << "Alarm::load(): " << err.str() << endl;
+				set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());
+			}				
+		}
+#ifndef _RW_LOCK
+		alarms.unlock();
+#else
+		alarms.vlock->readerOut();
+#endif
+	}
+	if(alm.cmd_name_n.length() > 0)
+	{
+#ifndef _RW_LOCK
+		alarms.lock();
+#else
+		alarms.vlock->readerIn();
+#endif
+		alarm_container_t::iterator i = alarms.v_alarm.find(alm.name);		//look for alarm just added
+		if (i != alarms.v_alarm.end())
+		{
+			try {
+				i->second.dp_n = new Tango::DeviceProxy(i->second.cmd_dp_n);
+				i->second.dp_n->ping();
+				Tango::CommandInfo info = i->second.dp_n->command_query(i->second.cmd_action_a);
+				if(info.in_type != Tango::DEV_STRING)
+				{
+					ostringstream err;
+					err << "Error: command " << i->second.cmd_name_n << " does not accept a Tango::DevString as input value" << ends;
+					ERROR_STREAM << "Alarm::load(): " << err.str() << endl;
+					set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());						
+				}
+				else
+				{
+					if(info.in_type == Tango::DEV_STRING)
+						i->second.send_arg_n = true;
+					else
+						i->second.send_arg_n = false;
+					DEBUG_STREAM << "Alarm::load(): successfully connected to proxy=" << i->second.cmd_dp_n << " for action=" << i->second.cmd_action_n << endl;
+				}
+			} catch(Tango::DevFailed& e)
+			{
+				ostringstream err;
+				err << alm.name << ": error connecting to device proxy=" << i->second.cmd_dp_n << ", err=" << e.errors[0].desc << ends;
+				WARN_STREAM << "Alarm::load(): " << err.str() << endl;
+				set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());
+			}				
+		}
+#ifndef _RW_LOCK
+		alarms.unlock();
+#else
+		alarms.vlock->readerOut();
+#endif
+	}	
+
+	//if at least one event was already existing, evaluate formula of just added alarm
+	if(alm.to_be_evaluated)							//TODO: remove this evaluation of the formula that is not necessary
+	{
+		DEBUG_STREAM << "Alarm::load(): Evaluating formula=" << alm.formula << endl;
+		try {    	
+    		double res;
+    		string attr_values;
+    		res = eval_formula(alm.formula_tree, attr_values);
+          	DEBUG_STREAM << "Parsing succeeded of "<< alm.formula << "; result=" << res << endl;
+        	alarms.update(alm.name, gettime(), (int)res, attr_values, alm.grp2str(), alm.msg, alm.formula);		//pass "now" as timestamp in this case
+
+		} catch(std::out_of_range& e)
+		{
+			ostringstream o;
+			o << alm.name << ": in formula array index out of range!" << ends;
+			WARN_STREAM << "Alarm::load(): " << o.str() << endl;
+			set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());				
+		} catch(string & e)
+		{
+			ostringstream o;
+			o << alm.name << ": in formula err=" << e << ends;
+			WARN_STREAM << "Alarm::load(): " << o.str() << endl;
+			set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());				
+		} catch(Tango::DevFailed& e)
+		{
+			ostringstream o;
+			o << alm.name << "error=" << e.errors[0].desc << ends;
+			WARN_STREAM << "Alarm::load(): " << o.str() << endl;
+			set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());				
+		}
+	}
+
+	prepare_alarm_attr();
+	try
+	{
+		if(ds_num == 0)
+		{
+			//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
+			struct timeval now;
+			gettimeofday(&now,NULL);
+			push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
+		}
+		else
+			//attr.set_value(ds, ds_num, 0, false);
+			push_change_event("alarm",ds, ds_num, 0, false);
+	} catch(Tango::DevFailed& e)
+	{
+		ostringstream err;
+		err << "error pushing alarm change event err=" << e.errors[0].desc;
+		INFO_STREAM << __func__<<": " << err.str() << endl;
+	}
+
+	/*----- PROTECTED REGION END -----*/	//	Alarm::load
+}
+//--------------------------------------------------------
+/**
+ *	Command Remove related method
+ *	Description: Remove alarm.
+ *
+ *	@param argin Alarm name
+ */
+//--------------------------------------------------------
+void Alarm::remove(Tango::DevString argin)
+{
+	DEBUG_STREAM << "Alarm::Remove()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(Alarm::remove) ENABLED START -----*/
+	
+	//	Add your own code
+	string s, log_alm_name;
+	s = argin;
+	log_alm_name = argin;
+	bool ret = false;
+	
+	alarmedlock->readerIn();
+	vector<alarm_t>::iterator found = find(alarmed.begin(), alarmed.end(), s);
+	if (found != alarmed.end()) 
+	{
+		ostringstream err;
+		err << s << " is in ALARM status! Acknowledge it before removing." << ends;
+		if((found->stat == S_ALARM) && (found->ack == NOT_ACK))
+		{
+			alarmedlock->readerOut();
+			Tango::Except::throw_exception( \
+				(const char*)"Error removing alarm", \
+				(const char*)err.str().c_str(), \
+				(const char*)"Alarm::remove", Tango::ERR);
+		}
+	}
+	alarmedlock->readerOut();
+	try {
+		ret = remove_alarm(s);
+	} catch (string& err) {
+		Tango::Except::throw_exception( \
+				(const char*)"Error removing alarm", \
+				(const char*)err.c_str(), \
+				(const char*)"Alarm::remove", Tango::ERR);
+	}
+	if (ret) {
+		DEBUG_STREAM << "Alarm::remove(): removing alarm '" \
+								<< s << "'" << endl;
+		while (true) {
+			string::size_type i = s.find_first_of("/.");
+			if (i == string::npos)
+				break;
+			s.replace(i, 1, "_");
+		}
+	}  /* end if */
+	alarms.log_alarm_db(TYPE_LOG_DESC_DIS, gettime(), log_alm_name, "", "", 		//set active to 0
+			"", 0, "", "", "", "", -1);
+	alarmedlock->writerIn();
+	found = find(alarmed.begin(), alarmed.end(), s);	//look again because in the meanwhile lock was not acquired
+	if (found != alarmed.end()) 
+	{
+		alarmed.erase(found);		//remove from alarmed table
+	}
+	alarmedlock->writerOut();
+
+	prepare_alarm_attr();
+	try
+	{
+		if(ds_num == 0)
+		{
+			//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
+			struct timeval now;
+			gettimeofday(&now,NULL);
+			push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
+		}
+		else
+			//attr.set_value(ds, ds_num, 0, false);
+			push_change_event("alarm",ds, ds_num, 0, false);
+	} catch(Tango::DevFailed& e)
+	{
+		ostringstream err;
+		err << "error pushing alarm change event err=" << e.errors[0].desc;
+		INFO_STREAM << __func__<<": " << err.str() << endl;
+	}
+
+	/*----- PROTECTED REGION END -----*/	//	Alarm::remove
+}
+//--------------------------------------------------------
+/**
+ *	Command Configured related method
+ *	Description: Alarms configured
+ *
+ *	@param argin String containing a filter for output, if empty return all alarms
+ *	@returns Alarms configured
+ */
+//--------------------------------------------------------
+Tango::DevVarStringArray *Alarm::configured(Tango::DevString argin)
+{
+	Tango::DevVarStringArray *argout;
+	DEBUG_STREAM << "Alarm::Configured()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(Alarm::configured) ENABLED START -----*/
+	
+	//	Add your own code
+	//	POGO has generated a method core with argout allocation.
+	//	If you would like to use a static reference without copying,
+	//	See "TANGO Device Server Programmer's Manual"
+	//		(chapter : Writing a TANGO DS / Exchanging data)
+	//------------------------------------------------------------
+	argout  = new Tango::DevVarStringArray();
+	//argout->length(1);
+	//(*argout)[0] = CORBA::string_dup("dummy");
+	DEBUG_STREAM << "Alarm::configured(): entering... !" << endl;
+
+	//	Add your own code to control device here
+
+	string filter(argin);
+	size_t found;
+	vector<string> alarm_filtered;
+	ostringstream os1;		
+	os1.clear();
+	/*os1 << headerConfig << "\t" << alarms.v_alarm.size() << ends;
+	alarm_filtered.push_back(os1.str());*/
+
+	alarm_container_t::iterator ai;
+#ifndef _RW_LOCK
+	alarms.lock();
+#else
+	alarms.vlock->readerIn();
+#endif
+	for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++) 
+	{
+		found = 0;
+		if(filter.length() != 0)
+		{
+			found = ai->first.find(filter);
+		}
+		if((filter.length() == 0) || (found != string::npos))
+		{
+			ostringstream os;
+			os.clear();
+			os << ai->second.ts.tv_sec << "\t" << ai->second.name << "\t" << ai->second.formula << "\t" << ai->second.time_threshold << 
+			"\t" << ai->second.lev << "\t" << ai->second.silent_time << "\t" << ai->second.grp2str() << "\t" << ai->second.msg << "\t" <<
+			ai->second.cmd_name_a << ";" << ai->second.cmd_name_n << ends;
+			alarm_filtered.push_back(os.str());
+		}
+	}  /* for */
+#ifndef _RW_LOCK
+	alarms.unlock();
+#else
+	alarms.vlock->readerOut();
+#endif
+	argout->length(alarm_filtered.size());
+	int i = 0;
+	for (vector<string>::iterator it= alarm_filtered.begin(); it != alarm_filtered.end(); it++) 
+	{
+		(*argout)[i] = CORBA::string_dup(it->c_str());
+		i++;
+	}
+
+	/*----- PROTECTED REGION END -----*/	//	Alarm::configured
+	return argout;
+}
+//--------------------------------------------------------
+/**
+ *	Command StopNew related method
+ *	Description: Remove "NEW" field from alarm string (so alarm panel stop sound)
+ *
+ */
+//--------------------------------------------------------
+void Alarm::stop_new()
+{
+	DEBUG_STREAM << "Alarm::StopNew()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(Alarm::stop_new) ENABLED START -----*/
+	
+	//	Add your own code
+	//12-06-08: StopNew command set is_new to 0
+	//	Add your own code to control device here
+	alarm_container_t::iterator ai;
+#ifndef _RW_LOCK
+	alarms.lock();
+#else
+	alarms.vlock->readerIn();
+#endif
+	for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++) {
+		ai->second.is_new = 0;		//set all alarm as no more new
+	}
+#ifndef _RW_LOCK
+	alarms.unlock();
+#else
+	alarms.vlock->readerOut();
+#endif
+
+	prepare_alarm_attr();
+	try
+	{
+		if(ds_num == 0)
+		{
+			//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
+			struct timeval now;
+			gettimeofday(&now,NULL);
+			push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
+		}
+		else
+			//attr.set_value(ds, ds_num, 0, false);
+			push_change_event("alarm",ds, ds_num, 0, false);
+	} catch(Tango::DevFailed& e)
+	{
+		ostringstream err;
+		err << "error pushing alarm change event err=" << e.errors[0].desc;
+		INFO_STREAM << __func__<<": " << err.str() << endl;
+	}
+
+	/*----- PROTECTED REGION END -----*/	//	Alarm::stop_new
+}
+//--------------------------------------------------------
+/**
+ *	Command Silence related method
+ *	Description: Alarm temporarily silence
+ *
+ *	@param argin String array containing the alarms to be silenced
+ */
+//--------------------------------------------------------
+void Alarm::silence(const Tango::DevVarStringArray *argin)
+{
+	DEBUG_STREAM << "Alarm::Silence()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(Alarm::silence) ENABLED START -----*/
+	
+	//	Add your own code
+	vector<string> str;
+	str << (*argin);
+	vector<string>::iterator si;
+
+	for (si = str.begin(); si != str.end(); si++)
+	{
+#ifndef _RW_LOCK
+		alarms.lock();
+#else
+		alarms.vlock->readerIn();
+#endif
+		alarm_container_t::iterator i = alarms.v_alarm.find(*si);
+		if(i != alarms.v_alarm.end())
+		{
+			if(i->second.silenced > 0)
+			{
+				Tango::TimeVal now = gettime();
+				double dnow = now.tv_sec + ((double)now.tv_usec) / 1000000;
+				double dsilent = i->second.ts_time_silenced.tv_sec + ((double)i->second.ts_time_silenced.tv_usec) / 1000000;
+				double dminutes = (dnow - dsilent)/60;
+				//silenced already calculated in alarm_table::update, but here updated for panel also if state not changed:
+				//to see minutes countdown
+				if(dminutes < i->second.silent_time)
+					i->second.silenced = i->second.silent_time - floor(dminutes);
+				else
+					i->second.silenced = 0;
+			}
+			if(i->second.silenced > 0)
+			{
+				ostringstream err;
+				err << "Alarm " << *si << " already silenced for " << i->second.silenced << " more minutes" << ends;
+#ifndef _RW_LOCK
+				alarms.unlock();
+#else
+				alarms.vlock->readerOut();
+#endif
+				Tango::Except::throw_exception( \
+							(const char*)"Alarm already silenced", \
+							err.str(), \
+							(const char*)"Alarm::silence()", Tango::ERR);
+			}
+			if(i->second.silent_time <= 0)
+			{
+				ostringstream err;
+				err << "Alarm " << *si << " cannot be silenced" << ends;
+#ifndef _RW_LOCK
+				alarms.unlock();
+#else
+				alarms.vlock->readerOut();
+#endif
+				Tango::Except::throw_exception( \
+							(const char*)"Alarm cannot be silenced", \
+							err.str(), \
+							(const char*)"Alarm::silence()", Tango::ERR);
+			}
+
+			//load silent time
+			i->second.ts_time_silenced = gettime();
+			i->second.silenced = i->second.silent_time;
+			//search also in alarmed
+			alarmedlock->readerIn();
+			vector<alarm_t>::iterator found = \
+					find(alarmed.begin(), alarmed.end(), *si);
+			if (found != alarmed.end())
+			{
+				//load silent time from alarm table
+				found->silenced = i->second.silent_time;
+				found->ts_time_silenced = i->second.ts_time_silenced;
+			}
+			alarmedlock->readerOut();
+		}
+		//alarms.unlock();
+		if(i == alarms.v_alarm.end())
+		{
+#ifndef _RW_LOCK
+			alarms.unlock();
+#else
+			alarms.vlock->readerOut();
+#endif
+			ostringstream err;
+			err << "Alarm " << *si << " not found" << ends;
+			Tango::Except::throw_exception( \
+						(const char*)"Alarm not found!!", \
+						err.str(), \
+						(const char*)"Alarm::silence()", Tango::ERR);
+		}
+#ifndef _RW_LOCK
+		alarms.unlock();
+#else
+		alarms.vlock->readerOut();
+#endif
+	}
+
+	prepare_alarm_attr();
+	try
+	{
+		if(ds_num == 0)
+		{
+			//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
+			struct timeval now;
+			gettimeofday(&now,NULL);
+			push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
+		}
+		else
+			//attr.set_value(ds, ds_num, 0, false);
+			push_change_event("alarm",ds, ds_num, 0, false);
+	} catch(Tango::DevFailed& e)
+	{
+		ostringstream err;
+		err << "error pushing alarm change event err=" << e.errors[0].desc;
+		INFO_STREAM << __func__<<": " << err.str() << endl;
+	}
+
+	/*----- PROTECTED REGION END -----*/	//	Alarm::silence
+}
+//--------------------------------------------------------
+/**
+ *	Command Modify related method
+ *	Description: Modify an existing alarm.
+ *
+ *	@param argin Alarm entry
+ */
+//--------------------------------------------------------
+void Alarm::modify(Tango::DevString argin)
+{
+	DEBUG_STREAM << "Alarm::Modify()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(Alarm::modify) ENABLED START -----*/
+	
+	//	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.formula.clear();
+	alm.msg.clear();
+	alm.lev.clear();
+	alm.grp=0;
+	alm.to_be_evaluated = false;
+	alm.time_threshold = 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;
+
+#ifndef _ACCESS_NODE_D
+	alm.formula_tree = ast_parse(alarm_string.c_str(), al_gr, space_p);	//parse string s with grammar al_gr, skipping white spaces
+#else
+	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
+#endif
+	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;
+#ifndef _ACCESS_NODE_D
+		o << __func__<<": Parsing Failed, syntax error stopped at " << alm.formula_tree.stop << ends;
+#else
+		o << __func__<<": Parsing Failed, syntax error stopped at " << string(alm.formula_tree.stop, alarm_string.end()) << ends; //TODO
+#endif
+       	DEBUG_STREAM << o.str() << endl;
+       	Tango::Except::throw_exception( \
+				(const char*)"Parsing Failed!", \
+				(const char*)o.str().c_str(), \
+				(const char*)__func__, Tango::ERR);
+    }
+
+
+	//------------------------------
+	//2: if alarm already exist and
+	//   formula is not changed
+	//------------------------------
+#ifndef _RW_LOCK
+	alarms.lock();
+#else
+	alarms.vlock->writerIn();
+#endif
+	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.time_threshold = alm.time_threshold;
+				i->second.silent_time = alm.silent_time;
+				i->second.silenced = alm.silenced;
+				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;
+
+			} else {
+				ostringstream o;
+				o << __func__<<": syntax error in '" << alarm_string << "'" << ends;
+				WARN_STREAM << o.str() << endl;
+#ifndef _RW_LOCK
+				alarms.unlock();
+#else
+				alarms.vlock->writerOut();
+#endif
+				Tango::Except::throw_exception( \
+						(const char*)o.str().c_str(), \
+						(const char*)"", \
+						(const char*)__func__, Tango::ERR);
+			}
+
+
+			alarms.log_alarm_db(TYPE_LOG_DESC_UPDATE, ts, alm.name, "", "",
+					alm.formula, alm.time_threshold, alm.grp2str(), alm.lev, alm.msg, cmd_name_full, alm.silent_time);
+
+			//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" << ends;
+						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 << ends;
+					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" << ends;
+						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 << ends;
+					WARN_STREAM << __func__<<": " << err.str() << endl;
+					set_internal_alarm(INTERNAL_ERROR, gettime(), err.str());
+				}
+			}
+#ifndef _RW_LOCK
+			alarms.unlock();
+#else
+			alarms.vlock->writerOut();
+#endif
+			return;
+		}
+	}
+	else
+	{
+#ifndef _RW_LOCK
+		alarms.unlock();
+#else
+		alarms.vlock->writerOut();
+#endif
+       	ostringstream o;
+       	o << "Alarm '"<<alm.name<<"' not found" << ends;
+       	DEBUG_STREAM << o.str() << endl;
+       	Tango::Except::throw_exception( \
+				(const char*)"Not found", \
+				(const char*)o.str().c_str(), \
+				(const char*)__func__, Tango::ERR);
+	}
+#ifndef _RW_LOCK
+	alarms.unlock();
+#else
+	alarms.vlock->writerOut();
+#endif
+
+	//------------------------------
+	//3: remove (set active=0 on db)
+	//------------------------------
+	remove((Tango::DevString)alm.name.c_str());
+	//------------------------------
+	//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);
+	} catch(Tango::DevFailed& e)
+	{
+		ostringstream err;
+		err << "error pushing alarm change event err=" << e.errors[0].desc;
+		INFO_STREAM << __func__<<": " << err.str() << endl;
+	}
+
+	/*----- PROTECTED REGION END -----*/	//	Alarm::modify
+}
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::add_dynamic_commands()
+ *	Description : Create the dynamic commands if any
+ *                for specified device.
+ */
+//--------------------------------------------------------
+void Alarm::add_dynamic_commands()
+{
+	/*----- PROTECTED REGION ID(Alarm::add_dynamic_commands) ENABLED START -----*/
+	
+	//	Add your own code to create and add dynamic commands if any
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::add_dynamic_commands
+}
+
+/*----- PROTECTED REGION ID(Alarm::namespace_ending) ENABLED START -----*/
+
+//	Additional Methods
+/*
+ * private methods
+ */
+void Alarm::load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn)
+{	
+	DEBUG_STREAM << "Alarm::load_alarm(): Creating Spirit Parser..." << endl;
+	alarm_parse al_gr(alm);    //  Construct Spirit grammar		
+	alm.name.clear();
+	alm.formula.clear();
+	alm.msg.clear();
+	alm.lev.clear();
+	alm.grp=0;
+	alm.to_be_evaluated = false;
+	alm.time_threshold = 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;
+	evn.clear();	
+
+#ifndef _ACCESS_NODE_D	
+	alm.formula_tree = ast_parse(alarm_string.c_str(), al_gr, space_p);	//parse string s with grammar al_gr, skipping white spaces	
+#else	
+	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
+#endif
+	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 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 << ends;
+		DEBUG_STREAM << dbg_msg.str() << endl;	
+	}
+    else
+    {
+       	ostringstream o;
+#ifndef _ACCESS_NODE_D       	
+		o << "Alarm::load_alarm(): Parsing Failed, syntax error stopped at " << alm.formula_tree.stop << ends;
+#else       	
+		o << "Alarm::load_alarm(): Parsing Failed, syntax error stopped at " << string(alm.formula_tree.stop, alarm_string.end()) << ends; //TODO
+#endif		
+       	DEBUG_STREAM << o.str() << endl;
+       	Tango::Except::throw_exception( \
+				(const char*)"Parsing Failed!", \
+				(const char*)o.str().c_str(), \
+				(const char*)"Alarm::load()", Tango::ERR);
+    }	
+	alm.ts = gettime();
+	DEBUG_STREAM << "Alarm::load_alarm(): name     = '" << alm.name << "'" << endl;
+	DEBUG_STREAM << "               formula        = '" << alm.formula << "'" << endl;
+	DEBUG_STREAM << "               time_threshold = '" << alm.time_threshold << "'" << 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;
+	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 << "Alarm::load_alarm(): syntax error in '" << alarm_string << "'" << ends;
+		WARN_STREAM << o.str() << endl;
+	
+		Tango::Except::throw_exception( \
+				(const char*)o.str().c_str(), \
+				(const char*)"", \
+				(const char*)"Alarm::load_alarm()", Tango::ERR);
+	}
+
+	if (alarms.exist(alm.name)) {
+		ostringstream o;
+		o << "Alarm::load_alarm(): alarm '" << alm.name << "' already exist" << ends;
+		WARN_STREAM << o.str() << endl;
+		Tango::Except::throw_exception( \
+				(const char*)o.str().c_str(), \
+				(const char*)o.str().c_str(), \
+				(const char*)"Alarm::load_alarm()", Tango::ERR);
+	}
+}
+void Alarm::init_alarms(map< string,vector<string> > &alarm_events)
+{
+#ifndef _RW_LOCK
+	alarms.lock();
+#else
+	alarms.vlock->readerIn();
+#endif
+	if (alarms.v_alarm.empty() == false) 
+	{
+		for (alarm_container_t::iterator i = alarms.v_alarm.begin(); \
+			i != alarms.v_alarm.end(); i++) 
+		{
+			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 << "Alarm::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 << "Alarm::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 << "Alarm::init_alarms(): found Event= " << found->name << " <- Alarm= " << i->second.name << endl;					
+					//break;		???
+				}  /* if */
+			}	/* for */
+		}
+	}
+#ifndef _RW_LOCK
+	alarms.unlock();
+#else
+	alarms.vlock->readerOut();
+#endif
+}
+void Alarm::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()) {
+			events->push_back(event(*j));
+			j++;
+		}
+	}  /* if */
+}
+void Alarm::add_alarm(alarm_t& a) throw(string&)
+{
+	alarms.push_back(a);
+	DEBUG_STREAM << "Alarm::add_alarm(): added alarm '" \
+							 << a.name << "'" << endl;
+}
+void Alarm::add_event(alarm_t& a, vector<string> &evn) throw(string&)
+{
+	DEBUG_STREAM << "Alarm::add_event(): formula '" << a.formula << "'" << 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()) {
+			/*
+			 * 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 << "Alarm::add_event(): '" << *j << "' found, added " \
+									 << " alarm '"  << a.name << "' to list, valid=" << k->valid << endl;
+#ifndef _RW_LOCK
+			alarms.lock();
+#else
+			alarms.vlock->readerIn();
+#endif
+			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 << "Alarm::add_event():	error inserting event '" << *j << "' in set of alarm '" 
+							<< a.name << "'" << endl;
+			}
+#ifndef _RW_LOCK
+			alarms.unlock();
+#else
+			alarms.vlock->readerOut();
+#endif
+		} 
+		else 
+		{
+			/*
+			 * new event; add to event table
+			 */
+			event e(*j);
+			events->push_back(e);
+			/*
+			 * update per-alarm event list
+			 */
+			DEBUG_STREAM << "Alarm::add_event(): adding '" << *j \
+									 << "' to event list of alarm '" << a.name << "'" << endl;
+#ifndef _RW_LOCK
+			alarms.lock();
+#else
+			alarms.vlock->readerIn();
+#endif
+			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 << "Alarm::add_event():	error inserting event '" << *j << "' in set of alarm '" 
+							<< a.name << "'" << endl;
+			}
+#ifndef _RW_LOCK
+			alarms.unlock();
+#else
+			alarms.vlock->readerOut();
+#endif
+			/*
+			 * now, for the just-added event, subscribe
+			 */
+			k = find(events->v_event.begin(), events->v_event.end(), *j);
+			if (k != events->v_event.end())
+			{
+				k->push_alarm(a.name);
+				try {
+					k->dp = new Tango::DeviceProxy(k->device);
+				} catch(Tango::DevFailed& e)
+				{
+					TangoSys_MemStream out_stream;
+					out_stream << "Failed to connect device proxy=" << k->device << 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
+					throw out_stream.str();
+					/*Tango::Except::re_throw_exception(e,
+						(const char *) "Error writing serial",
+						out_stream.str(),
+						(const char *) "Alarm::add_event()", Tango::ERR);*/
+				}
+				DEBUG_STREAM << "Alarm::add_event(): connected to DeviceProxy: " \
+											 << k->device << endl;
+				//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 << "Alarm::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();
+				}
+			}
+		}
+	} //for (vector<string>::iterator j = evn.begin(); ...
+}
+void Alarm::subscribe_event(alarm_t& a, EventCallBack& ecb, vector<string> &evn) throw(string&)
+{	
+	//now subscribe all events
+	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(k->eid == 0)		//not subscribed yet
+			{
+				try {	
+#if TANGO_VER < 611			
+					k->eid = k->dp->subscribe_event(k->attribute, \
+													Tango::CHANGE_EVENT, \
+													&ecb, k->filter);
+#else
+					k->eid = k->dp->subscribe_event(k->attribute, \
+													Tango::CHANGE_EVENT, \
+													&ecb, k->filter,true);	//stateless subscription (doesn't fail if server not running)
+#endif
+					DEBUG_STREAM << "Alarm::add_event(): subscribed event for '" \
+											 << k->attribute << "' attribute" << endl;											 
+				} catch (...) {
+					ostringstream o;
+					o << "Alarm::add_event(): subscribe_event() failed for '" \
+						<< *j << "'" << ends;
+					WARN_STREAM << o.str() << endl;
+					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 k->dp;
+					k->dp = NULL;					
+					throw o.str();
+				}
+			} 
+		}  // if (k != events->v_event.end())/
+	}  // for 				
+}
+/*
+ * because called asynchronously by alarm evaluating thread
+ * will use an alarm to report errors
+ */
+void Alarm::do_alarm(bei_t& e)
+{
+	bool changed=true;
+	//if (e.name == INTERNAL_ERROR) {
+	if(e.type == TYPE_TANGO_ERR) {	
+		ostringstream o;
+		o << e.msg << endl;
+		WARN_STREAM << "Alarm::do_alarm(): " <<  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 << __FUNCTION__ << " 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 << __FUNCTION__ << " 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!" << ends;
+				WARN_STREAM << "Alarm::do_alarm(): " << o.str() << endl;
+				set_internal_alarm(e.ev_name, gettime(), o.str());
+			}
+		}
+		if(found_ev != events->v_event.end())
+		{
+			found_ev->err_counter++;
+			if(found_ev->err_counter >= errThreshold)
+				set_internal_alarm(e.ev_name, gettime(), o.str(), errThreshold);			
+		}
+		return;
+	}
+	else if(e.type == TYPE_GENERIC_ERR) {	
+		ostringstream o;
+		o << e.msg << endl;
+		WARN_STREAM << "Alarm::do_alarm(): " <<  o.str() << endl;
+		set_internal_alarm(e.ev_name, gettime(), o.str());
+		return;
+	}	
+	DEBUG_STREAM << "Alarm::do_alarm(): arrived event=" << e.ev_name << endl;
+	
+	double 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 << __FUNCTION__ << " 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 << __FUNCTION__ << " 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!" << ends;
+			WARN_STREAM << "Alarm::do_alarm(): " << o.str() << endl;
+			set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());
+		}
+	}
+	if (found != events->v_event.end())
+	{	
+		found->value = e.value;
+		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()) 
+		{    	
+			//alarm_container_t::iterator it = alarms.v_alarm.find(j->first);
+#ifndef _RW_LOCK
+			alarms.lock();
+#else
+			alarms.vlock->readerIn();
+#endif
+			alarm_container_t::iterator it = alarms.v_alarm.find(*j);
+			if(it != alarms.v_alarm.end())
+			{
+				string tmpname=it->first;
+				try {   	
+    				string attr_values;
+    				res = eval_formula(it->second.formula_tree, attr_values);
+          			DEBUG_STREAM << "Alarm::do_alarm(): Evaluation of " << it->second.formula << "; result=" << res << endl;
+#ifndef _RW_LOCK
+          			alarms.unlock();
+#else
+          			alarms.vlock->readerOut();
+#endif
+          			changed = alarms.update(tmpname, found->ts, (int)res, attr_values, it->second.grp2str(), it->second.msg, it->second.formula); 		//update internal structure and log to db
+				} catch(std::out_of_range& e)
+				{
+#ifndef _RW_LOCK
+          			alarms.unlock();
+#else
+          			alarms.vlock->readerOut();
+#endif
+					ostringstream o;
+					o << tmpname << ": in formula array index out of range!" << ends;
+					WARN_STREAM << "Alarm::do_alarm(): " << o.str() << endl;
+					set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());				
+				} catch(string & e)
+				{
+#ifndef _RW_LOCK
+          			alarms.unlock();
+#else
+          			alarms.vlock->readerOut();
+#endif
+					ostringstream o;
+					o << tmpname << ": in formula err=" << e << ends;
+					WARN_STREAM << "Alarm::do_alarm(): " << o.str() << endl;
+					set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());				
+				}
+			}
+			else
+			{
+#ifndef _RW_LOCK
+				alarms.unlock();
+#else
+				alarms.vlock->readerOut();
+#endif
+				ostringstream o;
+				//o << j->first << ": not found formula in alarm table" << ends;
+				o << (*j) << ": not found formula in alarm table" << ends;
+				WARN_STREAM << "Alarm::do_alarm(): " << o.str() << endl;
+				set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());				
+			}
+			j++;
+		}
+
+		//TODO: push_change_event HERE!
+		prepare_alarm_attr();
+		if(!changed)
+			return;
+		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);
+
+	}
+}  /* do_alarm() */
+
+void Alarm::timer_update()
+{
+	bool changed=true;
+	//DEBUG_STREAM << "Alarm::timer_update(): entering..." << endl;
+	try {
+		changed=alarms.timer_update();
+	} catch(string & e)
+	{
+		ostringstream o;
+		o << "Error checking time thresholds and updating alarm status=" << e << ends;
+		WARN_STREAM << "Alarm::timer_update(): " << o.str() << endl;
+		set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());				
+	}
+
+	prepare_alarm_attr();
+	if(!changed)
+		return;
+	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;
+	}
+}
+
+bool Alarm::remove_alarm(string& s) throw(string&)
+{
+#ifndef _RW_LOCK
+	alarms.lock();
+#else
+	alarms.vlock->writerIn();
+#endif
+	alarm_container_t::iterator i = alarms.v_alarm.find(s);
+	if (i != alarms.v_alarm.end()) {	
+		for (set<string>::iterator j = i->second.s_event.begin(); \
+				 j != i->second.s_event.end(); j++) {
+			/*
+		 	 * 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()) {
+				/*
+				 * remove alarm
+				 */			 
+				k->pop_alarm(i->second.name);
+				if (k->m_alarm.empty()) {
+					/*
+					 * no more alarms associated to this event, unsubscribe
+					 * and remove from event table
+					 */
+					DEBUG_STREAM << "Alarm::remove_alarm(): removing event '" \
+							 				<< k->name << "' from event table" << endl;
+					try {
+						k->dp->unsubscribe_event(k->eid);
+					} catch (...) {
+						ostringstream o;
+						o << "unsubscribe_event() failed for " \
+						 	<< k->name << ends;
+						WARN_STREAM << "Alarm::remove_alarm(): " << o.str() << endl;
+#ifndef _RW_LOCK
+						alarms.unlock();
+#else
+						alarms.vlock->writerOut();
+#endif
+						throw o.str();
+						//return false;
+					}
+					delete k->dp;
+					k->dp = NULL;
+					events->v_event.erase(k);
+				}
+			} else {
+				/*
+				 * shouldn't happen!!!
+				 */
+				ostringstream o;
+				o << "event '" << *j \
+					<< "' not found in event table" << ends;
+				WARN_STREAM << "Alarm::remove_alarm(): " << o.str() << endl;
+#ifndef _RW_LOCK
+				alarms.unlock();
+#else
+				alarms.vlock->writerOut();
+#endif
+				throw o.str();
+				//return false;
+			}
+		}  /* for */
+		//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;		
+		/*
+		 * remove this alarm from alarm table
+		 */			
+#ifndef _RW_LOCK
+		alarms.unlock();
+#else
+		alarms.vlock->writerOut();
+#endif
+		alarms.erase(i);
+		return true;
+	}
+#ifndef _RW_LOCK
+	alarms.unlock();
+#else
+	alarms.vlock->writerOut();
+#endif
+	ostringstream o;
+	o << "alarm '" \
+		<< s << "' not found in alarm table" << ends;
+	WARN_STREAM << "Alarm::remove_alarm(): " << o.str() << endl;
+	throw o.str();
+	//return false;
+}  /* remove_alarm() */
+
+
+/*void Alarm::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 << "Alarm::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 << "Alarm::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 << "Alarm::add_to_database(): put_device_attribute_property()" \
+			<< " failed" << ends;
+		ERROR_STREAM << o.str() << endl;
+		throw o.str();
+	}
+}*/
+
+void Alarm::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->counter < count)
+					it->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->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.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 -------------------
+//==============================================================
+double Alarm::eval_formula(tree_parse_info_t tree, string &attr_values)
+{
+    return eval_expression(tree.trees.begin(), attr_values);
+}
+
+double Alarm::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() << ends;
+        	throw err.str(); 
+        }
+        string val_d(i->value.begin(), i->value.end());
+		DEBUG_STREAM << "		node value real = " << val_d << endl;
+        return strtod(val_d.c_str(), 0);
+    }
+    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() << ends;
+        	throw err.str(); 
+        }        		
+        string val_d(i->value.begin(), i->value.end());
+		DEBUG_STREAM << "		node value hex = " << val_d << endl;
+        return strtod(val_d.c_str(), 0);
+    } 
+    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() << ends;
+        	throw err.str(); 
+        }     		
+        string val_st(i->value.begin(), i->value.end());
+#ifndef _ACCESS_NODE_D    
+ 		Tango::DevState st;     
+		if(val_st == "ON")
+        	st = Tango::ON;
+        else if(val_st == "OFF")
+        	st = Tango::OFF;
+       	else if(val_st == "CLOSE")
+        	st = Tango::CLOSE;
+        else if(val_st == "OPEN")
+        	st = Tango::OPEN;
+        else if(val_st == "INSERT")
+        	st = Tango::INSERT;
+        else if(val_st == "EXTRACT")
+        	st = Tango::EXTRACT;
+        else if(val_st == "MOVING")
+        	st = Tango::MOVING;
+        else if(val_st == "STANDBY")
+        	st = Tango::STANDBY;
+        else if(val_st == "FAULT")
+        	st = Tango::FAULT;
+        else if(val_st == "INIT")
+        	st = Tango::INIT;
+        else if(val_st == "RUNNING")
+        	st = Tango::RUNNING;  
+        else if(val_st == "ALARM")
+        	st = Tango::ALARM; 
+        else if(val_st == "DISABLE")
+        	st = Tango::DISABLE; 
+        else if(val_st == "UNKNOWN")
+        	st = Tango::UNKNOWN;               	
+#else
+        double st =  i->value.value();			//get value directly from node saved with access_node_d
+#endif //_ACCESS_NODE_D    	        	        	      	        	        	        	        	        	        	        	        	
+		DEBUG_STREAM << "		node value state : " << val_st << "=" << st << endl;
+        return st;
+    }       
+    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() << ends;
+        	throw err.str(); 
+        }
+        if (*i->value.begin() == '+')
+        	return + eval_expression(i->children.begin(), attr_values);
+        if (*i->value.begin() == '-')
+        	return - eval_expression(i->children.begin(), attr_values);
+        if (*i->value.begin() == '!')
+        	return ! eval_expression(i->children.begin(), attr_values);        	        	
+    }
+    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() << ends;
+        	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" << ends;
+        	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() << ends;
+        	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" << ends;
+        	throw err.str(); 
+        }
+    }
+    else if (i->value.id() == formula_grammar::event_ID)
+    {
+		DEBUG_STREAM << "		node event" << string(i->value.begin(), i->value.end()) << endl;
+		int ind;
+		if(i->children.size() != 2)		
+		{
+        	err <<  "in node event_ID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size() << ends;;
+        	throw err.str(); 
+        }		
+		if((i->children.begin()+1)->value.id() == formula_grammar::indexID)
+			ind = (int)eval_expression(i->children.begin()+1, attr_values);		//array index
+		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()) << ends;;
+        	throw err.str(); 
+        }	
+		return eval_expression(i->children.begin(), attr_values ,ind);
+    }    
+    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() << ends;
+        	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)
+			{
+				err <<  "in node nameID(" << string(i->value.begin(), i->value.end()) << ") value not valid!" << ends;
+        		throw err.str();
+        	}	
+			else if(it->value.empty())
+			{
+				err <<  "in node nameID(" << string(i->value.begin(), i->value.end()) << ") value not initialized!!" << ends;
+        		throw err.str();
+        	}        	
+			ostringstream temp_attr_val;
+			temp_attr_val << it->name << "[" << ev_ind << "]=" <<it->value.at(ev_ind) << ";";
+			attr_values += temp_attr_val.str();
+			DEBUG_STREAM << "		node name -> " << temp_attr_val.str() << endl;
+			return it->value.at(ev_ind);		//throw  std::out_of_range		
+		}
+		else
+		{
+			err <<  "in event: (" << string(i->value.begin(), i->value.end()) << ") not found in event table" << ends;
+        	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() << ends;
+        	throw err.str(); 
+        }			
+        string val_d(i->value.begin(), i->value.end());
+     	DEBUG_STREAM << "		node index = " << val_d << endl;
+        return strtod(val_d.c_str(), 0);
+    }   
+    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() << ends;
+        	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" << ends;
+        	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() << ends;
+        	throw err.str(); 
+        }	 		
+        double val_d1=eval_expression(i->children.begin(), attr_values),
+           	val_d2=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(val_d1);		//transform to long
+    	val_l2 = (long)trunc(val_d2);		//transform to long
+
+	    if((val_l1 != val_d1) || (val_l2 != val_d2))	//if different, lost something with truncf
+    		throw err2;
+    		  
+        if (*i->value.begin() == '&')
+        {          
+            return (double)(val_l1 & val_l2);
+        }
+        else if (*i->value.begin() == '|')
+        {      
+            return (double)(val_l1 | val_l2);
+        }  
+        else if (*i->value.begin() == '^')
+        {         
+            return (double)(val_l1 ^ val_l2);
+        }  
+        else
+        {
+        	err << "in node bitwise_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed" << ends;
+        	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() << ends;
+        	throw err.str(); 
+        }			
+        double val_d1=eval_expression(i->children.begin(), attr_values),
+           	val_d2=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(val_d1);		//transform to long
+    	val_l2 = (long)trunc(val_d2);		//transform to long
+
+	    if((val_l1 != val_d1) || (val_l2 != val_d2))	//if different, lost something with truncf
+    		throw err2;
+    		  
+        if (string(i->value.begin(), i->value.end()) == string("<<"))
+        {          
+            return (double)(val_l1 << val_l2);
+        }
+        else if (string(i->value.begin(), i->value.end()) == string(">>"))
+        {      
+            return (double)(val_l1 >> val_l2);
+        }  
+        else
+        {
+        	err <<  "in node shift_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed" << ends;
+        	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() << ends;
+        	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 equality_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed" << ends;
+        	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() << ends;
+        	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" << ends;
+        	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() << ends;
+        	throw err.str(); 
+        }	
+		return fabs(eval_expression(i->children.begin(), attr_values));			//now handled only abs as function
+    }  
+    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()) << ends;
+        	throw err.str(); 
+        }	
+    }
+    return 0;
+}
+
+void Alarm::find_event_formula(tree_parse_info_t tree, vector<string> & ev)
+{
+    eval_node_event(tree.trees.begin(), ev);
+    return;
+}
+
+void Alarm::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() << ends;
+        	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 Alarm::prepare_alarm_attr()
+{
+	alarm_container_t::iterator ai;
+	vector<alarm_t>::iterator aid;
+#ifndef _RW_LOCK
+	alarms.lock();
+#else
+	alarms.vlock->readerIn();
+#endif
+	for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++) {
+		if (ai->second.stat == S_ALARM) {
+			/*
+			 * 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->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 << __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->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 << __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 */
+	}  /* for */
+#ifndef _RW_LOCK
+	alarms.unlock();
+#else
+	alarms.vlock->readerOut();
+#endif
+
+	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;
+			}
+			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());
+		}
+	}
+	alarmedlock->readerOut();
+	internallock->readerIn();
+	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());
+		}
+	}
+	internallock->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 "<< ends;
+		//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();
+}
+
+
+/*----- PROTECTED REGION END -----*/	//	Alarm::namespace_ending
+} //	namespace
diff --git a/src/Alarm.h b/src/Alarm.h
new file mode 100644
index 0000000..dd9c4d7
--- /dev/null
+++ b/src/Alarm.h
@@ -0,0 +1,337 @@
+/*----- PROTECTED REGION ID(Alarm.h) ENABLED START -----*/
+//=============================================================================
+//
+// file :        Alarm.h
+//
+// description : Include file for the Alarm class
+//
+// project :     alarm
+//
+// 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/>.
+// 
+// $Author:  $
+//
+// $Revision:  $
+// $Date:  $
+//
+// $HeadURL:  $
+//
+//=============================================================================
+//                This file is generated by POGO
+//        (Program Obviously used to Generate tango Object)
+//=============================================================================
+
+
+#ifndef Alarm_H
+#define Alarm_H
+
+#include <tango.h>
+#include <mysql.h>
+
+#include <boost/version.hpp>
+#define _ACCESS_NODE_D 1
+#if BOOST_VERSION  >= 103600
+#define BOOST_VER_1_36_0 1
+#endif
+
+#include "alarm_table.h"
+#include "event_table.h"
+
+#define MAX_ALARMS	1024
+
+#define _USE_ELETTRA_DB_RW
+
+//using namespace Tango;
+
+class alarm_thread;
+class log_thread;
+class update_thread;
+
+
+
+/*----- PROTECTED REGION END -----*/	//	Alarm.h
+
+/**
+ *  Alarm class description:
+ *    Elettra alarm device server
+ */
+
+namespace Alarm_ns
+{
+/*----- PROTECTED REGION ID(Alarm::Additional Class Declarations) ENABLED START -----*/
+
+//	Additional Class Declarations
+
+/*----- PROTECTED REGION END -----*/	//	Alarm::Additional Class Declarations
+
+class Alarm : public TANGO_BASE_CLASS
+{
+
+/*----- PROTECTED REGION ID(Alarm::Data Members) ENABLED START -----*/
+
+//	Add your own data members
+public:
+
+
+/*----- PROTECTED REGION END -----*/	//	Alarm::Data Members
+
+//	Device property data members
+public:
+	//	AlarmStatus:	Persistent storage of the alarms status
+	vector<string>	alarmStatus;
+	//	GroupNames:	Labels for Group mask, first is for mask 0x00
+	vector<string>	groupNames;
+	//	ErrThreshold:	Threshold for Tango error for being internal alarms
+	Tango::DevLong	errThreshold;
+	//	DbHost:	Host of the MySQL db
+	string	dbHost;
+	//	DbUser:	Username for the MySQL db
+	string	dbUser;
+	//	DbPasswd:	Password for the MySQL db
+	string	dbPasswd;
+	//	DbName:	Db name for the MySQL db
+	string	dbName;
+	//	DbPort:	Port of the MySQL db
+	string	dbPort;
+	//	InstanceName:	Name used to associate configured alarm rules to this instance
+	string	instanceName;
+
+//	Attribute data members
+public:
+	Tango::DevString	*attr_alarm_read;
+
+//	Constructors and destructors
+public:
+	/**
+	 * Constructs a newly device object.
+	 *
+	 *	@param cl	Class.
+	 *	@param s 	Device Name
+	 */
+	Alarm(Tango::DeviceClass *cl,string &s);
+	/**
+	 * Constructs a newly device object.
+	 *
+	 *	@param cl	Class.
+	 *	@param s 	Device Name
+	 */
+	Alarm(Tango::DeviceClass *cl,const char *s);
+	/**
+	 * Constructs a newly device object.
+	 *
+	 *	@param cl	Class.
+	 *	@param s 	Device name
+	 *	@param d	Device description.
+	 */
+	Alarm(Tango::DeviceClass *cl,const char *s,const char *d);
+	/**
+	 * The device object destructor.
+	 */
+	~Alarm() {delete_device();};
+
+
+//	Miscellaneous methods
+public:
+	/*
+	 *	will be called at device destruction or at init command.
+	 */
+	void delete_device();
+	/*
+	 *	Initialize the device
+	 */
+	virtual void init_device();
+	/*
+	 *	Read the device properties from database
+	 */
+	void get_device_property();
+	/*
+	 *	Always executed method before execution command method.
+	 */
+	virtual void always_executed_hook();
+
+
+//	Attribute methods
+public:
+	//--------------------------------------------------------
+	/*
+	 *	Method      : Alarm::read_attr_hardware()
+	 *	Description : Hardware acquisition for attributes.
+	 */
+	//--------------------------------------------------------
+	virtual void read_attr_hardware(vector<long> &attr_list);
+
+/**
+ *	Attribute alarm related methods
+ *	Description: 
+ *
+ *	Data type:	Tango::DevString
+ *	Attr type:	Spectrum max = 1024
+ */
+	virtual void read_alarm(Tango::Attribute &attr);
+	virtual bool is_alarm_allowed(Tango::AttReqType type);
+
+
+	//--------------------------------------------------------
+	/**
+	 *	Method      : Alarm::add_dynamic_attributes()
+	 *	Description : Add dynamic attributes if any.
+	 */
+	//--------------------------------------------------------
+	void add_dynamic_attributes();
+
+
+
+
+//	Command related methods
+public:
+	/**
+	 *	Command Ack related method
+	 *	Description: Alarm acknowledge
+	 *
+	 *	@param argin String array containing the alarms to be acknowledged
+	 */
+	virtual void ack(const Tango::DevVarStringArray *argin);
+	virtual bool is_Ack_allowed(const CORBA::Any &any);
+	/**
+	 *	Command Load related method
+	 *	Description: Load a new alarm.
+	 *
+	 *	@param argin Alarm entry
+	 */
+	virtual void load(Tango::DevString argin);
+	virtual bool is_Load_allowed(const CORBA::Any &any);
+	/**
+	 *	Command Remove related method
+	 *	Description: Remove alarm.
+	 *
+	 *	@param argin Alarm name
+	 */
+	virtual void remove(Tango::DevString argin);
+	virtual bool is_Remove_allowed(const CORBA::Any &any);
+	/**
+	 *	Command Configured related method
+	 *	Description: Alarms configured
+	 *
+	 *	@param argin String containing a filter for output, if empty return all alarms
+	 *	@returns Alarms configured
+	 */
+	virtual Tango::DevVarStringArray *configured(Tango::DevString argin);
+	virtual bool is_Configured_allowed(const CORBA::Any &any);
+	/**
+	 *	Command StopNew related method
+	 *	Description: Remove "NEW" field from alarm string (so alarm panel stop sound)
+	 *
+	 */
+	virtual void stop_new();
+	virtual bool is_StopNew_allowed(const CORBA::Any &any);
+	/**
+	 *	Command Silence related method
+	 *	Description: Alarm temporarily silence
+	 *
+	 *	@param argin String array containing the alarms to be silenced
+	 */
+	virtual void silence(const Tango::DevVarStringArray *argin);
+	virtual bool is_Silence_allowed(const CORBA::Any &any);
+	/**
+	 *	Command Modify related method
+	 *	Description: Modify an existing alarm.
+	 *
+	 *	@param argin Alarm entry
+	 */
+	virtual void modify(Tango::DevString argin);
+	virtual bool is_Modify_allowed(const CORBA::Any &any);
+
+
+	//--------------------------------------------------------
+	/**
+	 *	Method      : Alarm::add_dynamic_commands()
+	 *	Description : Add dynamic commands if any.
+	 */
+	//--------------------------------------------------------
+	void add_dynamic_commands();
+
+/*----- PROTECTED REGION ID(Alarm::Additional Method prototypes) ENABLED START -----*/
+
+//	Additional Method prototypes
+friend class alarm_thread;
+
+protected :	
+	
+private:
+	vector<alarm_t> stored;		/* property stored alarms (on exit) */
+	alarm_table alarms;
+	event_table* events;
+//	event_list evlist;				/* producer/consumer events list */		//gcc 4 problem??
+	EventCallBack ecb;				/* callback handles */
+	alarm_thread *almloop;
+	update_thread *updateloop;
+	vector<alarm_t> alarmed;
+	ReadersWritersLock *alarmedlock;
+	vector<alarm_t> internal;
+	ReadersWritersLock *internallock;
+	ReadersWritersLock *dslock;
+	
+	static int instanceCounter;
+	
+	int internal_counter;
+	int ds_num;
+	Tango::DevString ds[MAX_ALARMS];
+	char dss[MAX_ALARMS][10124];
+
+	void init_events(vector<string> &evn);
+	void init_alarms(map< string,vector<string> > &alarm_events);
+	void add_alarm(alarm_t& a) throw(string&);
+	void add_event(alarm_t& a, vector<string> &evn) throw(string&);
+	void subscribe_event(alarm_t& a, EventCallBack& ecb, vector<string> &evn) throw(string&);
+//	void do_alarm(bei_t& e);											//gcc 4 problem??
+	bool remove_alarm(string& s) throw(string&);
+	//void add_to_database(alarm_t& a) throw(string&);
+	void set_internal_alarm(string name, Tango::TimeVal t, string msg, unsigned int count=1);
+	
+	void load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn);
+
+	double eval_formula(tree_parse_info_t tree, string &attr_values);
+	void find_event_formula(tree_parse_info_t tree, vector<string> &);
+	
+	double eval_expression(iter_t const& i, string &attr_values, int ev_ind=0);			//recursive tree node evaluation	
+	void eval_node_event(iter_t const& i, vector<string> & ev);		//recursive tree node evaluation		
+
+	void prepare_alarm_attr();	//for read attribute alarm and push_change_event
+
+public:
+	void do_alarm(bei_t& e);											//public instead of protected for gcc 4 problem??
+	void timer_update();												//public instead of protected for gcc 4 problem??
+	event_list evlist;				/* producer/consumer events list */		//public instead of protected for gcc 4 problem??
+	bool abortflag;
+	
+#ifdef _USE_ELETTRA_DB_RW
+private:
+	string host_rw;
+	long port_rw;
+#endif
+
+/*----- PROTECTED REGION END -----*/	//	Alarm::Additional Method prototypes
+};
+
+/*----- PROTECTED REGION ID(Alarm::Additional Classes Definitions) ENABLED START -----*/
+
+//	Additional Classes Definitions
+
+/*----- PROTECTED REGION END -----*/	//	Alarm::Additional Classes Definitions
+
+}	//	End of namespace
+
+#endif   //	Alarm_H
diff --git a/src/Alarm.xmi b/src/Alarm.xmi
new file mode 100644
index 0000000..e7e5428
--- /dev/null
+++ b/src/Alarm.xmi
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="ASCII"?>
+<pogoDsl:PogoSystem xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:pogoDsl="http://www.esrf.fr/tango/pogo/PogoDsl">
+  <classes name="Alarm" pogoRevision="9.1">
+    <description description="Elettra alarm device server" title="Elettra alarm device server" sourcePath="/home/graziano/workspace/git/alarm/src" language="Cpp" filestogenerate="XMI   file,Code files,Protected Regions" license="GPL" copyright="" hasMandatoryProperty="false" hasConcreteProperty="true" hasAbstractCommand="false" hasAbstractAttribute="false">
+      <inheritances classname="Device_4Impl" sourcePath=""/>
+      <identification contact="at elettra.eu - graziano.scalamera" author="graziano.scalamera" emailDomain="elettra.eu" classFamily="SoftwareSystem" siteSpecific="" platform="Unix Like" bus="Not Applicable" manufacturer="" reference=""/>
+    </description>
+    <deviceProperties name="AlarmStatus" description="Persistent storage of the alarms status">
+      <type xsi:type="pogoDsl:StringVectorType"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </deviceProperties>
+    <deviceProperties name="GroupNames" description="Labels for Group mask, first is for mask 0x00">
+      <type xsi:type="pogoDsl:StringVectorType"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </deviceProperties>
+    <deviceProperties name="ErrThreshold" description="Threshold for Tango error for being internal alarms">
+      <type xsi:type="pogoDsl:IntType"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </deviceProperties>
+    <deviceProperties name="DbHost" description="Host of the MySQL db">
+      <type xsi:type="pogoDsl:StringType"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </deviceProperties>
+    <deviceProperties name="DbUser" description="Username for the MySQL db">
+      <type xsi:type="pogoDsl:StringType"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </deviceProperties>
+    <deviceProperties name="DbPasswd" description="Password for the MySQL db">
+      <type xsi:type="pogoDsl:StringType"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </deviceProperties>
+    <deviceProperties name="DbName" description="Db name for the MySQL db">
+      <type xsi:type="pogoDsl:StringType"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </deviceProperties>
+    <deviceProperties name="DbPort" description="Port of the MySQL db">
+      <type xsi:type="pogoDsl:StringType"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </deviceProperties>
+    <deviceProperties name="InstanceName" description="Name used to associate configured alarm rules to this instance">
+      <type xsi:type="pogoDsl:StringType"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </deviceProperties>
+    <commands name="State" description="This command gets the device state (stored in its &lt;i>device_state&lt;/i> data member) and returns it to the caller." execMethod="dev_state" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="none.">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="State Code">
+        <type xsi:type="pogoDsl:StateType"/>
+      </argout>
+      <status abstract="true" inherited="true" concrete="true" concreteHere="false"/>
+    </commands>
+    <commands name="Status" description="This command gets the device status (stored in its &lt;i>device_status&lt;/i> data member) and returns it to the caller." execMethod="dev_status" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="none.">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="Status description">
+        <type xsi:type="pogoDsl:ConstStringType"/>
+      </argout>
+      <status abstract="true" inherited="true" concrete="true" concreteHere="false"/>
+    </commands>
+    <commands name="Ack" description="Alarm acknowledge" execMethod="ack" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="String array containing the alarms to be acknowledged">
+        <type xsi:type="pogoDsl:StringArrayType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </commands>
+    <commands name="Load" description="Load a new alarm." execMethod="load" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="Alarm entry">
+        <type xsi:type="pogoDsl:StringType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </commands>
+    <commands name="Remove" description="Remove alarm." execMethod="remove" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="Alarm name">
+        <type xsi:type="pogoDsl:StringType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </commands>
+    <commands name="Configured" description="Alarms configured" execMethod="configured" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="String containing a filter for output, if empty return all alarms">
+        <type xsi:type="pogoDsl:StringType"/>
+      </argin>
+      <argout description="Alarms configured">
+        <type xsi:type="pogoDsl:StringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </commands>
+    <commands name="StopNew" description="Remove &quot;NEW&quot; field from alarm string (so alarm panel stop sound)" execMethod="stop_new" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </commands>
+    <commands name="Silence" description="Alarm temporarily silence" execMethod="silence" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="String array containing the alarms to be silenced">
+        <type xsi:type="pogoDsl:StringArrayType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </commands>
+    <commands name="Modify" description="Modify an existing alarm." execMethod="modify" displayLevel="OPERATOR" polledPeriod="0">
+      <argin description="Alarm entry">
+        <type xsi:type="pogoDsl:StringType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </commands>
+    <attributes name="alarm" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="1024" maxY="0">
+      <dataType xsi:type="pogoDsl:StringType"/>
+      <changeEvent fire="false" libCheckCriteria="false"/>
+      <archiveEvent fire="false" libCheckCriteria="false"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </attributes>
+    <preferences docHome="./doc_html" makefileHome="/usr/local/tango-8.1.2.c/share/pogo/preferences"/>
+  </classes>
+</pogoDsl:PogoSystem>
diff --git a/src/AlarmClass.cpp b/src/AlarmClass.cpp
new file mode 100644
index 0000000..e4c2fa1
--- /dev/null
+++ b/src/AlarmClass.cpp
@@ -0,0 +1,918 @@
+/*----- PROTECTED REGION ID(AlarmClass.cpp) ENABLED START -----*/
+static const char *RcsId      = "$Id:  $";
+static const char *TagName    = "$Name:  $";
+static const char *CvsPath    = "$Source:  $";
+static const char *SvnPath    = "$HeadURL:  $";
+static const char *HttpServer = "http://www.esrf.eu/computing/cs/tango/tango_doc/ds_doc/";
+//=============================================================================
+//
+// file :        AlarmClass.cpp
+//
+// description : C++ source for the AlarmClass.
+//               A singleton class derived from DeviceClass.
+//               It implements the command and attribute list
+//               and all properties and methods required
+//               by the Alarm once per process.
+//
+// project :     alarm
+//
+// 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/>.
+// 
+// $Author:  $
+//
+// $Revision:  $
+// $Date:  $
+//
+// $HeadURL:  $
+//
+//=============================================================================
+//                This file is generated by POGO
+//        (Program Obviously used to Generate tango Object)
+//=============================================================================
+
+
+#include <tango.h>
+#include <Alarm.h>
+#include <AlarmClass.h>
+
+/*----- PROTECTED REGION END -----*/	//	AlarmClass.cpp
+
+//-------------------------------------------------------------------
+/**
+ *	Create AlarmClass singleton and
+ *	return it in a C function for Python usage
+ */
+//-------------------------------------------------------------------
+extern "C" {
+#ifdef _TG_WINDOWS_
+
+__declspec(dllexport)
+
+#endif
+
+	Tango::DeviceClass *_create_Alarm_class(const char *name) {
+		return Alarm_ns::AlarmClass::init(name);
+	}
+}
+
+namespace Alarm_ns
+{
+//===================================================================
+//	Initialize pointer for singleton pattern
+//===================================================================
+AlarmClass *AlarmClass::_instance = NULL;
+
+//--------------------------------------------------------
+/**
+ * method : 		AlarmClass::AlarmClass(string &s)
+ * description : 	constructor for the AlarmClass
+ *
+ * @param s	The class name
+ */
+//--------------------------------------------------------
+AlarmClass::AlarmClass(string &s):Tango::DeviceClass(s)
+{
+	cout2 << "Entering AlarmClass constructor" << endl;
+	set_default_property();
+	write_class_property();
+
+	/*----- PROTECTED REGION ID(AlarmClass::constructor) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmClass::constructor
+
+	cout2 << "Leaving AlarmClass constructor" << endl;
+}
+
+//--------------------------------------------------------
+/**
+ * method : 		AlarmClass::~AlarmClass()
+ * description : 	destructor for the AlarmClass
+ */
+//--------------------------------------------------------
+AlarmClass::~AlarmClass()
+{
+	/*----- PROTECTED REGION ID(AlarmClass::destructor) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmClass::destructor
+
+	_instance = NULL;
+}
+
+
+//--------------------------------------------------------
+/**
+ * method : 		AlarmClass::init
+ * description : 	Create the object if not already done.
+ *                  Otherwise, just return a pointer to the object
+ *
+ * @param	name	The class name
+ */
+//--------------------------------------------------------
+AlarmClass *AlarmClass::init(const char *name)
+{
+	if (_instance == NULL)
+	{
+		try
+		{
+			string s(name);
+			_instance = new AlarmClass(s);
+		}
+		catch (bad_alloc &)
+		{
+			throw;
+		}
+	}
+	return _instance;
+}
+
+//--------------------------------------------------------
+/**
+ * method : 		AlarmClass::instance
+ * description : 	Check if object already created,
+ *                  and return a pointer to the object
+ */
+//--------------------------------------------------------
+AlarmClass *AlarmClass::instance()
+{
+	if (_instance == NULL)
+	{
+		cerr << "Class is not initialised !!" << endl;
+		exit(-1);
+	}
+	return _instance;
+}
+
+
+
+//===================================================================
+//	Command execution method calls
+//===================================================================
+//--------------------------------------------------------
+/**
+ * method : 		AckClass::execute()
+ * description : 	method to trigger the execution of the command.
+ *
+ * @param	device	The device on which the command must be executed
+ * @param	in_any	The command input data
+ *
+ *	returns The command output data (packed in the Any object)
+ */
+//--------------------------------------------------------
+CORBA::Any *AckClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
+{
+	cout2 << "AckClass::execute(): arrived" << endl;
+	const Tango::DevVarStringArray *argin;
+	extract(in_any, argin);
+	((static_cast<Alarm *>(device))->ack(argin));
+	return new CORBA::Any();
+}
+
+//--------------------------------------------------------
+/**
+ * method : 		LoadClass::execute()
+ * description : 	method to trigger the execution of the command.
+ *
+ * @param	device	The device on which the command must be executed
+ * @param	in_any	The command input data
+ *
+ *	returns The command output data (packed in the Any object)
+ */
+//--------------------------------------------------------
+CORBA::Any *LoadClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
+{
+	cout2 << "LoadClass::execute(): arrived" << endl;
+	Tango::DevString argin;
+	extract(in_any, argin);
+	((static_cast<Alarm *>(device))->load(argin));
+	return new CORBA::Any();
+}
+
+//--------------------------------------------------------
+/**
+ * method : 		RemoveClass::execute()
+ * description : 	method to trigger the execution of the command.
+ *
+ * @param	device	The device on which the command must be executed
+ * @param	in_any	The command input data
+ *
+ *	returns The command output data (packed in the Any object)
+ */
+//--------------------------------------------------------
+CORBA::Any *RemoveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
+{
+	cout2 << "RemoveClass::execute(): arrived" << endl;
+	Tango::DevString argin;
+	extract(in_any, argin);
+	((static_cast<Alarm *>(device))->remove(argin));
+	return new CORBA::Any();
+}
+
+//--------------------------------------------------------
+/**
+ * method : 		ConfiguredClass::execute()
+ * description : 	method to trigger the execution of the command.
+ *
+ * @param	device	The device on which the command must be executed
+ * @param	in_any	The command input data
+ *
+ *	returns The command output data (packed in the Any object)
+ */
+//--------------------------------------------------------
+CORBA::Any *ConfiguredClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
+{
+	cout2 << "ConfiguredClass::execute(): arrived" << endl;
+	Tango::DevString argin;
+	extract(in_any, argin);
+	return insert((static_cast<Alarm *>(device))->configured(argin));
+}
+
+//--------------------------------------------------------
+/**
+ * method : 		StopNewClass::execute()
+ * description : 	method to trigger the execution of the command.
+ *
+ * @param	device	The device on which the command must be executed
+ * @param	in_any	The command input data
+ *
+ *	returns The command output data (packed in the Any object)
+ */
+//--------------------------------------------------------
+CORBA::Any *StopNewClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any))
+{
+	cout2 << "StopNewClass::execute(): arrived" << endl;
+	((static_cast<Alarm *>(device))->stop_new());
+	return new CORBA::Any();
+}
+
+//--------------------------------------------------------
+/**
+ * method : 		SilenceClass::execute()
+ * description : 	method to trigger the execution of the command.
+ *
+ * @param	device	The device on which the command must be executed
+ * @param	in_any	The command input data
+ *
+ *	returns The command output data (packed in the Any object)
+ */
+//--------------------------------------------------------
+CORBA::Any *SilenceClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
+{
+	cout2 << "SilenceClass::execute(): arrived" << endl;
+	const Tango::DevVarStringArray *argin;
+	extract(in_any, argin);
+	((static_cast<Alarm *>(device))->silence(argin));
+	return new CORBA::Any();
+}
+
+//--------------------------------------------------------
+/**
+ * method : 		ModifyClass::execute()
+ * description : 	method to trigger the execution of the command.
+ *
+ * @param	device	The device on which the command must be executed
+ * @param	in_any	The command input data
+ *
+ *	returns The command output data (packed in the Any object)
+ */
+//--------------------------------------------------------
+CORBA::Any *ModifyClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
+{
+	cout2 << "ModifyClass::execute(): arrived" << endl;
+	Tango::DevString argin;
+	extract(in_any, argin);
+	((static_cast<Alarm *>(device))->modify(argin));
+	return new CORBA::Any();
+}
+
+
+//===================================================================
+//	Properties management
+//===================================================================
+//--------------------------------------------------------
+/**
+ *	Method      : AlarmClass::get_class_property()
+ *	Description : Get the class property for specified name.
+ */
+//--------------------------------------------------------
+Tango::DbDatum AlarmClass::get_class_property(string &prop_name)
+{
+	for (unsigned int i=0 ; i<cl_prop.size() ; i++)
+		if (cl_prop[i].name == prop_name)
+			return cl_prop[i];
+	//	if not found, returns  an empty DbDatum
+	return Tango::DbDatum(prop_name);
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : AlarmClass::get_default_device_property()
+ *	Description : Return the default value for device property.
+ */
+//--------------------------------------------------------
+Tango::DbDatum AlarmClass::get_default_device_property(string &prop_name)
+{
+	for (unsigned int i=0 ; i<dev_def_prop.size() ; i++)
+		if (dev_def_prop[i].name == prop_name)
+			return dev_def_prop[i];
+	//	if not found, return  an empty DbDatum
+	return Tango::DbDatum(prop_name);
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : AlarmClass::get_default_class_property()
+ *	Description : Return the default value for class property.
+ */
+//--------------------------------------------------------
+Tango::DbDatum AlarmClass::get_default_class_property(string &prop_name)
+{
+	for (unsigned int i=0 ; i<cl_def_prop.size() ; i++)
+		if (cl_def_prop[i].name == prop_name)
+			return cl_def_prop[i];
+	//	if not found, return  an empty DbDatum
+	return Tango::DbDatum(prop_name);
+}
+
+
+//--------------------------------------------------------
+/**
+ *	Method      : AlarmClass::set_default_property()
+ *	Description : Set default property (class and device) for wizard.
+ *                For each property, add to wizard property name and description.
+ *                If default value has been set, add it to wizard property and
+ *                store it in a DbDatum.
+ */
+//--------------------------------------------------------
+void AlarmClass::set_default_property()
+{
+	string	prop_name;
+	string	prop_desc;
+	string	prop_def;
+	vector<string>	vect_data;
+
+	//	Set Default Class Properties
+
+	//	Set Default device Properties
+	prop_name = "AlarmStatus";
+	prop_desc = "Persistent storage of the alarms status";
+	prop_def  = "";
+	vect_data.clear();
+	if (prop_def.length()>0)
+	{
+		Tango::DbDatum	data(prop_name);
+		data << vect_data ;
+		dev_def_prop.push_back(data);
+		add_wiz_dev_prop(prop_name, prop_desc,  prop_def);
+	}
+	else
+		add_wiz_dev_prop(prop_name, prop_desc);
+	prop_name = "GroupNames";
+	prop_desc = "Labels for Group mask, first is for mask 0x00";
+	prop_def  = "";
+	vect_data.clear();
+	if (prop_def.length()>0)
+	{
+		Tango::DbDatum	data(prop_name);
+		data << vect_data ;
+		dev_def_prop.push_back(data);
+		add_wiz_dev_prop(prop_name, prop_desc,  prop_def);
+	}
+	else
+		add_wiz_dev_prop(prop_name, prop_desc);
+	prop_name = "ErrThreshold";
+	prop_desc = "Threshold for Tango error for being internal alarms";
+	prop_def  = "";
+	vect_data.clear();
+	if (prop_def.length()>0)
+	{
+		Tango::DbDatum	data(prop_name);
+		data << vect_data ;
+		dev_def_prop.push_back(data);
+		add_wiz_dev_prop(prop_name, prop_desc,  prop_def);
+	}
+	else
+		add_wiz_dev_prop(prop_name, prop_desc);
+	prop_name = "DbHost";
+	prop_desc = "Host of the MySQL db";
+	prop_def  = "";
+	vect_data.clear();
+	if (prop_def.length()>0)
+	{
+		Tango::DbDatum	data(prop_name);
+		data << vect_data ;
+		dev_def_prop.push_back(data);
+		add_wiz_dev_prop(prop_name, prop_desc,  prop_def);
+	}
+	else
+		add_wiz_dev_prop(prop_name, prop_desc);
+	prop_name = "DbUser";
+	prop_desc = "Username for the MySQL db";
+	prop_def  = "";
+	vect_data.clear();
+	if (prop_def.length()>0)
+	{
+		Tango::DbDatum	data(prop_name);
+		data << vect_data ;
+		dev_def_prop.push_back(data);
+		add_wiz_dev_prop(prop_name, prop_desc,  prop_def);
+	}
+	else
+		add_wiz_dev_prop(prop_name, prop_desc);
+	prop_name = "DbPasswd";
+	prop_desc = "Password for the MySQL db";
+	prop_def  = "";
+	vect_data.clear();
+	if (prop_def.length()>0)
+	{
+		Tango::DbDatum	data(prop_name);
+		data << vect_data ;
+		dev_def_prop.push_back(data);
+		add_wiz_dev_prop(prop_name, prop_desc,  prop_def);
+	}
+	else
+		add_wiz_dev_prop(prop_name, prop_desc);
+	prop_name = "DbName";
+	prop_desc = "Db name for the MySQL db";
+	prop_def  = "";
+	vect_data.clear();
+	if (prop_def.length()>0)
+	{
+		Tango::DbDatum	data(prop_name);
+		data << vect_data ;
+		dev_def_prop.push_back(data);
+		add_wiz_dev_prop(prop_name, prop_desc,  prop_def);
+	}
+	else
+		add_wiz_dev_prop(prop_name, prop_desc);
+	prop_name = "DbPort";
+	prop_desc = "Port of the MySQL db";
+	prop_def  = "";
+	vect_data.clear();
+	if (prop_def.length()>0)
+	{
+		Tango::DbDatum	data(prop_name);
+		data << vect_data ;
+		dev_def_prop.push_back(data);
+		add_wiz_dev_prop(prop_name, prop_desc,  prop_def);
+	}
+	else
+		add_wiz_dev_prop(prop_name, prop_desc);
+	prop_name = "InstanceName";
+	prop_desc = "Name used to associate configured alarm rules to this instance";
+	prop_def  = "";
+	vect_data.clear();
+	if (prop_def.length()>0)
+	{
+		Tango::DbDatum	data(prop_name);
+		data << vect_data ;
+		dev_def_prop.push_back(data);
+		add_wiz_dev_prop(prop_name, prop_desc,  prop_def);
+	}
+	else
+		add_wiz_dev_prop(prop_name, prop_desc);
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : AlarmClass::write_class_property()
+ *	Description : Set class description fields as property in database
+ */
+//--------------------------------------------------------
+void AlarmClass::write_class_property()
+{
+	//	First time, check if database used
+	if (Tango::Util::_UseDb == false)
+		return;
+
+	Tango::DbData	data;
+	string	classname = get_name();
+	string	header;
+	string::size_type	start, end;
+
+	//	Put title
+	Tango::DbDatum	title("ProjectTitle");
+	string	str_title("Elettra alarm device server");
+	title << str_title;
+	data.push_back(title);
+
+	//	Put Description
+	Tango::DbDatum	description("Description");
+	vector<string>	str_desc;
+	str_desc.push_back("Elettra alarm device server");
+	description << str_desc;
+	data.push_back(description);
+
+	//	put cvs or svn location
+	string	filename("Alarm");
+	filename += "Class.cpp";
+
+	// check for cvs information
+	string	src_path(CvsPath);
+	start = src_path.find("/");
+	if (start!=string::npos)
+	{
+		end   = src_path.find(filename);
+		if (end>start)
+		{
+			string	strloc = src_path.substr(start, end-start);
+			//	Check if specific repository
+			start = strloc.find("/cvsroot/");
+			if (start!=string::npos && start>0)
+			{
+				string	repository = strloc.substr(0, start);
+				if (repository.find("/segfs/")!=string::npos)
+					strloc = "ESRF:" + strloc.substr(start, strloc.length()-start);
+			}
+			Tango::DbDatum	cvs_loc("cvs_location");
+			cvs_loc << strloc;
+			data.push_back(cvs_loc);
+		}
+	}
+
+	// check for svn information
+	else
+	{
+		string	src_path(SvnPath);
+		start = src_path.find("://");
+		if (start!=string::npos)
+		{
+			end = src_path.find(filename);
+			if (end>start)
+			{
+				header = "$HeadURL: ";
+				start = header.length();
+				string	strloc = src_path.substr(start, (end-start));
+				
+				Tango::DbDatum	svn_loc("svn_location");
+				svn_loc << strloc;
+				data.push_back(svn_loc);
+			}
+		}
+	}
+
+	//	Get CVS or SVN revision tag
+	
+	// CVS tag
+	string	tagname(TagName);
+	header = "$Name: ";
+	start = header.length();
+	string	endstr(" $");
+	
+	end   = tagname.find(endstr);
+	if (end!=string::npos && end>start)
+	{
+		string	strtag = tagname.substr(start, end-start);
+		Tango::DbDatum	cvs_tag("cvs_tag");
+		cvs_tag << strtag;
+		data.push_back(cvs_tag);
+	}
+	
+	// SVN tag
+	string	svnpath(SvnPath);
+	header = "$HeadURL: ";
+	start = header.length();
+	
+	end   = svnpath.find(endstr);
+	if (end!=string::npos && end>start)
+	{
+		string	strloc = svnpath.substr(start, end-start);
+		
+		string tagstr ("/tags/");
+		start = strloc.find(tagstr);
+		if ( start!=string::npos )
+		{
+			start = start + tagstr.length();
+			end   = strloc.find(filename);
+			string	strtag = strloc.substr(start, end-start-1);
+			
+			Tango::DbDatum	svn_tag("svn_tag");
+			svn_tag << strtag;
+			data.push_back(svn_tag);
+		}
+	}
+
+	//	Get URL location
+	string	httpServ(HttpServer);
+	if (httpServ.length()>0)
+	{
+		Tango::DbDatum	db_doc_url("doc_url");
+		db_doc_url << httpServ;
+		data.push_back(db_doc_url);
+	}
+
+	//  Put inheritance
+	Tango::DbDatum	inher_datum("InheritedFrom");
+	vector<string> inheritance;
+	inheritance.push_back("TANGO_BASE_CLASS");
+	inher_datum << inheritance;
+	data.push_back(inher_datum);
+
+	//	Call database and and values
+	get_db_class()->put_property(data);
+}
+
+//===================================================================
+//	Factory methods
+//===================================================================
+
+//--------------------------------------------------------
+/**
+ *	Method      : AlarmClass::device_factory()
+ *	Description : Create the device object(s)
+ *                and store them in the device list
+ */
+//--------------------------------------------------------
+void AlarmClass::device_factory(const Tango::DevVarStringArray *devlist_ptr)
+{
+	/*----- PROTECTED REGION ID(AlarmClass::device_factory_before) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmClass::device_factory_before
+
+	//	Create devices and add it into the device list
+	for (unsigned long i=0 ; i<devlist_ptr->length() ; i++)
+	{
+		cout4 << "Device name : " << (*devlist_ptr)[i].in() << endl;
+		device_list.push_back(new Alarm(this, (*devlist_ptr)[i]));
+	}
+
+	//	Manage dynamic attributes if any
+	erase_dynamic_attributes(devlist_ptr, get_class_attr()->get_attr_list());
+
+	//	Export devices to the outside world
+	for (unsigned long i=1 ; i<=devlist_ptr->length() ; i++)
+	{
+		//	Add dynamic attributes if any
+		Alarm *dev = static_cast<Alarm *>(device_list[device_list.size()-i]);
+		dev->add_dynamic_attributes();
+
+		//	Check before if database used.
+		if ((Tango::Util::_UseDb == true) && (Tango::Util::_FileDb == false))
+			export_device(dev);
+		else
+			export_device(dev, dev->get_name().c_str());
+	}
+
+	/*----- PROTECTED REGION ID(AlarmClass::device_factory_after) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmClass::device_factory_after
+}
+//--------------------------------------------------------
+/**
+ *	Method      : AlarmClass::attribute_factory()
+ *	Description : Create the attribute object(s)
+ *                and store them in the attribute list
+ */
+//--------------------------------------------------------
+void AlarmClass::attribute_factory(vector<Tango::Attr *> &att_list)
+{
+	/*----- PROTECTED REGION ID(AlarmClass::attribute_factory_before) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmClass::attribute_factory_before
+	//	Attribute : alarm
+	alarmAttrib	*alarm = new alarmAttrib();
+	Tango::UserDefaultAttrProp	alarm_prop;
+	//	description	not set for alarm
+	//	label	not set for alarm
+	//	unit	not set for alarm
+	//	standard_unit	not set for alarm
+	//	display_unit	not set for alarm
+	//	format	not set for alarm
+	//	max_value	not set for alarm
+	//	min_value	not set for alarm
+	//	max_alarm	not set for alarm
+	//	min_alarm	not set for alarm
+	//	max_warning	not set for alarm
+	//	min_warning	not set for alarm
+	//	delta_t	not set for alarm
+	//	delta_val	not set for alarm
+	
+	alarm->set_default_properties(alarm_prop);
+	//	Not Polled
+	alarm->set_disp_level(Tango::OPERATOR);
+	//	Not Memorized
+	att_list.push_back(alarm);
+
+
+	//	Create a list of static attributes
+	create_static_attribute_list(get_class_attr()->get_attr_list());
+	/*----- PROTECTED REGION ID(AlarmClass::attribute_factory_after) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmClass::attribute_factory_after
+}
+//--------------------------------------------------------
+/**
+ *	Method      : AlarmClass::pipe_factory()
+ *	Description : Create the pipe object(s)
+ *                and store them in the pipe list
+ */
+//--------------------------------------------------------
+void AlarmClass::pipe_factory()
+{
+	/*----- PROTECTED REGION ID(AlarmClass::pipe_factory_before) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmClass::pipe_factory_before
+	/*----- PROTECTED REGION ID(AlarmClass::pipe_factory_after) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmClass::pipe_factory_after
+}
+//--------------------------------------------------------
+/**
+ *	Method      : AlarmClass::command_factory()
+ *	Description : Create the command object(s)
+ *                and store them in the command list
+ */
+//--------------------------------------------------------
+void AlarmClass::command_factory()
+{
+	/*----- PROTECTED REGION ID(AlarmClass::command_factory_before) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmClass::command_factory_before
+
+
+	//	Command Ack
+	AckClass	*pAckCmd =
+		new AckClass("Ack",
+			Tango::DEVVAR_STRINGARRAY, Tango::DEV_VOID,
+			"String array containing the alarms to be acknowledged",
+			"",
+			Tango::OPERATOR);
+	command_list.push_back(pAckCmd);
+
+	//	Command Load
+	LoadClass	*pLoadCmd =
+		new LoadClass("Load",
+			Tango::DEV_STRING, Tango::DEV_VOID,
+			"Alarm entry",
+			"",
+			Tango::OPERATOR);
+	command_list.push_back(pLoadCmd);
+
+	//	Command Remove
+	RemoveClass	*pRemoveCmd =
+		new RemoveClass("Remove",
+			Tango::DEV_STRING, Tango::DEV_VOID,
+			"Alarm name",
+			"",
+			Tango::OPERATOR);
+	command_list.push_back(pRemoveCmd);
+
+	//	Command Configured
+	ConfiguredClass	*pConfiguredCmd =
+		new ConfiguredClass("Configured",
+			Tango::DEV_STRING, Tango::DEVVAR_STRINGARRAY,
+			"String containing a filter for output, if empty return all alarms",
+			"Alarms configured",
+			Tango::OPERATOR);
+	command_list.push_back(pConfiguredCmd);
+
+	//	Command StopNew
+	StopNewClass	*pStopNewCmd =
+		new StopNewClass("StopNew",
+			Tango::DEV_VOID, Tango::DEV_VOID,
+			"",
+			"",
+			Tango::OPERATOR);
+	command_list.push_back(pStopNewCmd);
+
+	//	Command Silence
+	SilenceClass	*pSilenceCmd =
+		new SilenceClass("Silence",
+			Tango::DEVVAR_STRINGARRAY, Tango::DEV_VOID,
+			"String array containing the alarms to be silenced",
+			"",
+			Tango::OPERATOR);
+	command_list.push_back(pSilenceCmd);
+
+	//	Command Modify
+	ModifyClass	*pModifyCmd =
+		new ModifyClass("Modify",
+			Tango::DEV_STRING, Tango::DEV_VOID,
+			"Alarm entry",
+			"",
+			Tango::OPERATOR);
+	command_list.push_back(pModifyCmd);
+
+	/*----- PROTECTED REGION ID(AlarmClass::command_factory_after) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmClass::command_factory_after
+}
+
+//===================================================================
+//	Dynamic attributes related methods
+//===================================================================
+
+//--------------------------------------------------------
+/**
+ * method : 		AlarmClass::create_static_attribute_list
+ * description : 	Create the a list of static attributes
+ *
+ * @param	att_list	the ceated attribute list
+ */
+//--------------------------------------------------------
+void AlarmClass::create_static_attribute_list(vector<Tango::Attr *> &att_list)
+{
+	for (unsigned long i=0 ; i<att_list.size() ; i++)
+	{
+		string att_name(att_list[i]->get_name());
+		transform(att_name.begin(), att_name.end(), att_name.begin(), ::tolower);
+		defaultAttList.push_back(att_name);
+	}
+
+	cout2 << defaultAttList.size() << " attributes in default list" << endl;
+
+	/*----- PROTECTED REGION ID(AlarmClass::create_static_att_list) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmClass::create_static_att_list
+}
+
+
+//--------------------------------------------------------
+/**
+ * method : 		AlarmClass::erase_dynamic_attributes
+ * description : 	delete the dynamic attributes if any.
+ *
+ * @param	devlist_ptr	the device list pointer
+ * @param	list of all attributes
+ */
+//--------------------------------------------------------
+void AlarmClass::erase_dynamic_attributes(const Tango::DevVarStringArray *devlist_ptr, vector<Tango::Attr *> &att_list)
+{
+	Tango::Util *tg = Tango::Util::instance();
+
+	for (unsigned long i=0 ; i<devlist_ptr->length() ; i++)
+	{
+		Tango::DeviceImpl *dev_impl = tg->get_device_by_name(((string)(*devlist_ptr)[i]).c_str());
+		Alarm *dev = static_cast<Alarm *> (dev_impl);
+
+		vector<Tango::Attribute *> &dev_att_list = dev->get_device_attr()->get_attribute_list();
+		vector<Tango::Attribute *>::iterator ite_att;
+		for (ite_att=dev_att_list.begin() ; ite_att != dev_att_list.end() ; ++ite_att)
+		{
+			string att_name((*ite_att)->get_name_lower());
+			if ((att_name == "state") || (att_name == "status"))
+				continue;
+			vector<string>::iterator ite_str = find(defaultAttList.begin(), defaultAttList.end(), att_name);
+			if (ite_str == defaultAttList.end())
+			{
+				cout2 << att_name << " is a UNWANTED dynamic attribute for device " << (*devlist_ptr)[i] << endl;
+				Tango::Attribute &att = dev->get_device_attr()->get_attr_by_name(att_name.c_str());
+				dev->remove_attribute(att_list[att.get_attr_idx()], true, false);
+				--ite_att;
+			}
+		}
+	}
+	/*----- PROTECTED REGION ID(AlarmClass::erase_dynamic_attributes) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmClass::erase_dynamic_attributes
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : AlarmClass::get_attr_by_name()
+ *	Description : returns Tango::Attr * object found by name
+ */
+//--------------------------------------------------------
+Tango::Attr *AlarmClass::get_attr_object_by_name(vector<Tango::Attr *> &att_list, string attname)
+{
+	vector<Tango::Attr *>::iterator it;
+	for (it=att_list.begin() ; it<att_list.end() ; ++it)
+		if ((*it)->get_name()==attname)
+			return (*it);
+	//	Attr does not exist
+	return NULL;
+}
+
+
+/*----- PROTECTED REGION ID(AlarmClass::Additional Methods) ENABLED START -----*/
+
+/*----- PROTECTED REGION END -----*/	//	AlarmClass::Additional Methods
+} //	namespace
diff --git a/src/AlarmClass.h b/src/AlarmClass.h
new file mode 100644
index 0000000..df66071
--- /dev/null
+++ b/src/AlarmClass.h
@@ -0,0 +1,291 @@
+/*----- PROTECTED REGION ID(AlarmClass.h) ENABLED START -----*/
+//=============================================================================
+//
+// file :        AlarmClass.h
+//
+// description : Include for the Alarm root class.
+//               This class is the singleton class for
+//                the Alarm device class.
+//               It contains all properties and methods which the 
+//               Alarm requires only once e.g. the commands.
+//
+// project :     alarm
+//
+// 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/>.
+// 
+// $Author:  $
+//
+// $Revision:  $
+// $Date:  $
+//
+// $HeadURL:  $
+//
+//=============================================================================
+//                This file is generated by POGO
+//        (Program Obviously used to Generate tango Object)
+//=============================================================================
+
+
+#ifndef AlarmClass_H
+#define AlarmClass_H
+
+#include <tango.h>
+#include <Alarm.h>
+
+/*----- PROTECTED REGION END -----*/	//	AlarmClass.h
+
+
+namespace Alarm_ns
+{
+/*----- PROTECTED REGION ID(AlarmClass::classes for dynamic creation) ENABLED START -----*/
+
+
+/*----- PROTECTED REGION END -----*/	//	AlarmClass::classes for dynamic creation
+
+//=========================================
+//	Define classes for attributes
+//=========================================
+//	Attribute alarm class definition
+class alarmAttrib: public Tango::SpectrumAttr
+{
+public:
+	alarmAttrib():SpectrumAttr("alarm",
+			Tango::DEV_STRING, Tango::READ, 1024) {};
+	~alarmAttrib() {};
+	virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att)
+		{(static_cast<Alarm *>(dev))->read_alarm(att);}
+	virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty)
+		{return (static_cast<Alarm *>(dev))->is_alarm_allowed(ty);}
+};
+
+
+//=========================================
+//	Define classes for commands
+//=========================================
+//	Command Ack class definition
+class AckClass : public Tango::Command
+{
+public:
+	AckClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out,
+				   const char        *in_desc,
+				   const char        *out_desc,
+				   Tango::DispLevel  level)
+	:Command(name,in,out,in_desc,out_desc, level)	{};
+
+	AckClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~AckClass() {};
+	
+	virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any);
+	virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any)
+	{return (static_cast<Alarm *>(dev))->is_Ack_allowed(any);}
+};
+
+//	Command Load class definition
+class LoadClass : public Tango::Command
+{
+public:
+	LoadClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out,
+				   const char        *in_desc,
+				   const char        *out_desc,
+				   Tango::DispLevel  level)
+	:Command(name,in,out,in_desc,out_desc, level)	{};
+
+	LoadClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~LoadClass() {};
+	
+	virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any);
+	virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any)
+	{return (static_cast<Alarm *>(dev))->is_Load_allowed(any);}
+};
+
+//	Command Remove class definition
+class RemoveClass : public Tango::Command
+{
+public:
+	RemoveClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out,
+				   const char        *in_desc,
+				   const char        *out_desc,
+				   Tango::DispLevel  level)
+	:Command(name,in,out,in_desc,out_desc, level)	{};
+
+	RemoveClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~RemoveClass() {};
+	
+	virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any);
+	virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any)
+	{return (static_cast<Alarm *>(dev))->is_Remove_allowed(any);}
+};
+
+//	Command Configured class definition
+class ConfiguredClass : public Tango::Command
+{
+public:
+	ConfiguredClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out,
+				   const char        *in_desc,
+				   const char        *out_desc,
+				   Tango::DispLevel  level)
+	:Command(name,in,out,in_desc,out_desc, level)	{};
+
+	ConfiguredClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~ConfiguredClass() {};
+	
+	virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any);
+	virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any)
+	{return (static_cast<Alarm *>(dev))->is_Configured_allowed(any);}
+};
+
+//	Command StopNew class definition
+class StopNewClass : public Tango::Command
+{
+public:
+	StopNewClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out,
+				   const char        *in_desc,
+				   const char        *out_desc,
+				   Tango::DispLevel  level)
+	:Command(name,in,out,in_desc,out_desc, level)	{};
+
+	StopNewClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~StopNewClass() {};
+	
+	virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any);
+	virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any)
+	{return (static_cast<Alarm *>(dev))->is_StopNew_allowed(any);}
+};
+
+//	Command Silence class definition
+class SilenceClass : public Tango::Command
+{
+public:
+	SilenceClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out,
+				   const char        *in_desc,
+				   const char        *out_desc,
+				   Tango::DispLevel  level)
+	:Command(name,in,out,in_desc,out_desc, level)	{};
+
+	SilenceClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~SilenceClass() {};
+	
+	virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any);
+	virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any)
+	{return (static_cast<Alarm *>(dev))->is_Silence_allowed(any);}
+};
+
+//	Command Modify class definition
+class ModifyClass : public Tango::Command
+{
+public:
+	ModifyClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out,
+				   const char        *in_desc,
+				   const char        *out_desc,
+				   Tango::DispLevel  level)
+	:Command(name,in,out,in_desc,out_desc, level)	{};
+
+	ModifyClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~ModifyClass() {};
+	
+	virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any);
+	virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any)
+	{return (static_cast<Alarm *>(dev))->is_Modify_allowed(any);}
+};
+
+
+/**
+ *	The AlarmClass singleton definition
+ */
+
+#ifdef _TG_WINDOWS_
+class __declspec(dllexport)  AlarmClass : public Tango::DeviceClass
+#else
+class AlarmClass : public Tango::DeviceClass
+#endif
+{
+	/*----- PROTECTED REGION ID(AlarmClass::Additionnal DServer data members) ENABLED START -----*/
+	
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmClass::Additionnal DServer data members
+
+	public:
+		//	write class properties data members
+		Tango::DbData	cl_prop;
+		Tango::DbData	cl_def_prop;
+		Tango::DbData	dev_def_prop;
+	
+		//	Method prototypes
+		static AlarmClass *init(const char *);
+		static AlarmClass *instance();
+		~AlarmClass();
+		Tango::DbDatum	get_class_property(string &);
+		Tango::DbDatum	get_default_device_property(string &);
+		Tango::DbDatum	get_default_class_property(string &);
+	
+	protected:
+		AlarmClass(string &);
+		static AlarmClass *_instance;
+		void command_factory();
+		void attribute_factory(vector<Tango::Attr *> &);
+		void pipe_factory();
+		void write_class_property();
+		void set_default_property();
+		void get_class_property();
+		string get_cvstag();
+		string get_cvsroot();
+	
+	private:
+		void device_factory(const Tango::DevVarStringArray *);
+		void create_static_attribute_list(vector<Tango::Attr *> &);
+		void erase_dynamic_attributes(const Tango::DevVarStringArray *,vector<Tango::Attr *> &);
+		vector<string>	defaultAttList;
+		Tango::Attr *get_attr_object_by_name(vector<Tango::Attr *> &att_list, string attname);
+};
+
+}	//	End of namespace
+
+#endif   //	Alarm_H
diff --git a/src/AlarmStateMachine.cpp b/src/AlarmStateMachine.cpp
new file mode 100644
index 0000000..5f703cc
--- /dev/null
+++ b/src/AlarmStateMachine.cpp
@@ -0,0 +1,186 @@
+/*----- PROTECTED REGION ID(AlarmStateMachine.cpp) ENABLED START -----*/
+static const char *RcsId = "$Id:  $";
+//=============================================================================
+//
+// file :        AlarmStateMachine.cpp
+//
+// description : State machine file for the Alarm class
+//
+// project :     alarm
+//
+// 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/>.
+// 
+// $Author:  $
+//
+// $Revision:  $
+// $Date:  $
+//
+// $HeadURL:  $
+//
+//=============================================================================
+//                This file is generated by POGO
+//        (Program Obviously used to Generate tango Object)
+//=============================================================================
+
+#include <Alarm.h>
+
+/*----- PROTECTED REGION END -----*/	//	Alarm::AlarmStateMachine.cpp
+
+//================================================================
+//  States  |  Description
+//================================================================
+
+
+namespace Alarm_ns
+{
+//=================================================
+//		Attributes Allowed Methods
+//=================================================
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::is_alarm_allowed()
+ *	Description : Execution allowed for alarm attribute
+ */
+//--------------------------------------------------------
+bool Alarm::is_alarm_allowed(TANGO_UNUSED(Tango::AttReqType type))
+{
+
+	//	Not any excluded states for alarm attribute in read access.
+	/*----- PROTECTED REGION ID(Alarm::alarmStateAllowed_READ) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::alarmStateAllowed_READ
+	return true;
+}
+
+
+//=================================================
+//		Commands Allowed Methods
+//=================================================
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::is_Ack_allowed()
+ *	Description : Execution allowed for Ack attribute
+ */
+//--------------------------------------------------------
+bool Alarm::is_Ack_allowed(TANGO_UNUSED(const CORBA::Any &any))
+{
+	//	Not any excluded states for Ack command.
+	/*----- PROTECTED REGION ID(Alarm::AckStateAllowed) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::AckStateAllowed
+	return true;
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::is_Load_allowed()
+ *	Description : Execution allowed for Load attribute
+ */
+//--------------------------------------------------------
+bool Alarm::is_Load_allowed(TANGO_UNUSED(const CORBA::Any &any))
+{
+	//	Not any excluded states for Load command.
+	/*----- PROTECTED REGION ID(Alarm::LoadStateAllowed) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::LoadStateAllowed
+	return true;
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::is_Remove_allowed()
+ *	Description : Execution allowed for Remove attribute
+ */
+//--------------------------------------------------------
+bool Alarm::is_Remove_allowed(TANGO_UNUSED(const CORBA::Any &any))
+{
+	//	Not any excluded states for Remove command.
+	/*----- PROTECTED REGION ID(Alarm::RemoveStateAllowed) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::RemoveStateAllowed
+	return true;
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::is_Configured_allowed()
+ *	Description : Execution allowed for Configured attribute
+ */
+//--------------------------------------------------------
+bool Alarm::is_Configured_allowed(TANGO_UNUSED(const CORBA::Any &any))
+{
+	//	Not any excluded states for Configured command.
+	/*----- PROTECTED REGION ID(Alarm::ConfiguredStateAllowed) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::ConfiguredStateAllowed
+	return true;
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::is_StopNew_allowed()
+ *	Description : Execution allowed for StopNew attribute
+ */
+//--------------------------------------------------------
+bool Alarm::is_StopNew_allowed(TANGO_UNUSED(const CORBA::Any &any))
+{
+	//	Not any excluded states for StopNew command.
+	/*----- PROTECTED REGION ID(Alarm::StopNewStateAllowed) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::StopNewStateAllowed
+	return true;
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::is_Silence_allowed()
+ *	Description : Execution allowed for Silence attribute
+ */
+//--------------------------------------------------------
+bool Alarm::is_Silence_allowed(TANGO_UNUSED(const CORBA::Any &any))
+{
+	//	Not any excluded states for Silence command.
+	/*----- PROTECTED REGION ID(Alarm::SilenceStateAllowed) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::SilenceStateAllowed
+	return true;
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::is_Modify_allowed()
+ *	Description : Execution allowed for Modify attribute
+ */
+//--------------------------------------------------------
+bool Alarm::is_Modify_allowed(TANGO_UNUSED(const CORBA::Any &any))
+{
+	//	Not any excluded states for Modify command.
+	/*----- PROTECTED REGION ID(Alarm::ModifyStateAllowed) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::ModifyStateAllowed
+	return true;
+}
+
+
+/*----- PROTECTED REGION ID(Alarm::AlarmStateAllowed.AdditionalMethods) ENABLED START -----*/
+
+//	Additional Methods
+
+/*----- PROTECTED REGION END -----*/	//	Alarm::AlarmStateAllowed.AdditionalMethods
+
+}	//	End of namespace
diff --git a/src/ClassFactory.cpp b/src/ClassFactory.cpp
new file mode 100644
index 0000000..065b2f9
--- /dev/null
+++ b/src/ClassFactory.cpp
@@ -0,0 +1,49 @@
+/*----- PROTECTED REGION ID(Alarm::ClassFactory.cpp) ENABLED START -----*/
+static const char *RcsId = "$Header: /home/cvsadm/cvsroot/utils/alarm/tango/server/src/ClassFactory.cpp,v 1.2 2008-03-27 09:25:29 graziano Exp $";
+//+=============================================================================
+//
+// file :        ClassFactory.cpp
+//
+// description : C++ source for the class_factory method of the DServer
+//               device class. This method is responsible to create
+//               all class singletin for a device server. It is called
+//               at device server startup
+//
+// project :     TANGO Device Server
+//
+// $Author: graziano $
+//
+// $Revision: 1.2 $
+//
+// copyleft :    Sincrotrone Trieste S.C.p.A. di interesse nazionale
+//                Strada Statale 14 - km 163,5 in AREA Science Park
+//                34012 Basovizza, Trieste ITALY
+//                Tel. +39 040 37581
+//                Fax. +39 040 9380902
+//
+//-=============================================================================
+//
+//  		This file is generated by POGO
+//	(Program Obviously used to Generate tango Object)
+//
+//         (c) - ELETTRA U.O. Controlli
+//=============================================================================
+
+
+#include <tango.h>
+#include <AlarmClass.h>
+
+/**
+ *	Create AlarmClass singleton and store it in DServer object.
+ *
+ * @author	$Author: graziano $
+ * @version	$Revision: 1.2 $ $
+ */
+
+void Tango::DServer::class_factory()
+{
+
+	add_class(Alarm_ns::AlarmClass::init("Alarm"));
+
+}
+/*----- PROTECTED REGION END -----*/	//	Alarm::ClassFactory.cpp
diff --git a/src/alarm-thread.cpp b/src/alarm-thread.cpp
new file mode 100644
index 0000000..57d523b
--- /dev/null
+++ b/src/alarm-thread.cpp
@@ -0,0 +1,90 @@
+/*
+ * alarm-thread.cpp
+ *
+ * $Author: claudio $
+ *
+ * $Revision: 1.7 $
+ *
+ * $Log: alarm-thread.cpp,v $
+ * Revision 1.7  2015-07-21 13:40:59  claudio
+ * minor cleanups
+ *
+ * Revision 1.6  2013-03-06 10:41:11  claudio
+ * commented out debug print statements
+ *
+ * Revision 1.5  2008-07-08 12:11:39  graziano
+ * omni_thread_fatal exception handling
+ *
+ * Revision 1.4  2008/07/07 09:13:12  graziano
+ * omni_thread_fatal exception handling
+ *
+ * Revision 1.3  2008/04/24 06:51:34  graziano
+ * small code cleanings
+ *
+ *
+ *
+ * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
+ *           Strada Statale 14 - km 163,5 in AREA Science Park
+ *           34012 Basovizza, Trieste ITALY
+ */
+
+#include "alarm-thread.h"
+static const char __FILE__rev[] = __FILE__ " $Revision: 1.7 $";
+
+/*
+ * alarm_thread::alarm_thread()
+ */
+alarm_thread::alarm_thread(Alarm_ns::Alarm *p) : p_Alarm(p) 
+{
+	//cout << __FILE__rev << endl;
+}
+
+/*
+ * alarm_thread::~alarm_thread()
+ */
+alarm_thread::~alarm_thread()
+{
+	p_Alarm = NULL;
+}
+
+/*
+ * alarm_thread::run()
+ */
+void alarm_thread::run(void *)
+{
+	while (true) {
+		/*
+		 * pop_front() will wait() on condition variable
+		 */
+		try
+		{
+			bei_t e = p_Alarm->evlist.pop_front();
+			//DEBUG_STREAM << "alarm_thread::run(): woken up!!!! " << e.name << endl;
+			if ((e.ev_name == ALARM_THREAD_EXIT) && \
+				(e.value[0] == ALARM_THREAD_EXIT_VALUE))
+				break;
+			p_Alarm->do_alarm(e);
+		}
+		catch(omni_thread_fatal& ex)
+		{
+			ostringstream err;
+			err << "omni_thread_fatal exception running alarm thread, err=" << ex.error << ends;
+			//WARN_STREAM << "alarm_thread::run(): " << err.str() << endl;	
+			printf("alarm_thread::run(): %s", err.str().c_str());
+		}			
+		catch(Tango::DevFailed& ex)
+		{
+			ostringstream err;
+			err << "exception running alarm thread: '" << ex.errors[0].desc << "'" << ends;
+			//WARN_STREAM << "alarm_thread::run(): " << err.str() << endl;	
+			printf("alarm_thread::run(): %s", err.str().c_str());
+			Tango::Except::print_exception(ex);
+		}		
+		catch(...)
+		{
+			//WARN_STREAM << "alarm_thread::run(): catched unknown exception!!" << endl;
+			printf("alarm_thread::run(): catched unknown exception!!");
+		}		
+	}
+	//cout << "alarm_thread::run(): returning" << endl;
+}  /* alarm_thread::run() */
diff --git a/src/alarm-thread.h b/src/alarm-thread.h
new file mode 100644
index 0000000..221cdab
--- /dev/null
+++ b/src/alarm-thread.h
@@ -0,0 +1,41 @@
+/*
+ * alarm-thread.h
+ *
+ * $Author: graziano $
+ *
+ * $Revision: 1.3 $
+ *
+ * $Log: alarm-thread.h,v $
+ * Revision 1.3  2008-04-23 15:00:57  graziano
+ * small code cleanings
+ *
+ *
+ *
+ * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
+ *           Strada Statale 14 - km 163,5 in AREA Science Park
+ *           34012 Basovizza, Trieste ITALY
+ */
+
+#ifndef ALARM_THREAD_H
+#define ALARM_THREAD_H
+
+#include <omnithread.h>
+#include <tango.h>
+#include <Alarm.h>
+
+#define ALARM_THREAD_EXIT				"alarm_thread_exit"
+#define ALARM_THREAD_EXIT_VALUE	-100
+
+class alarm_thread : public omni_thread {
+	public:
+		alarm_thread(Alarm_ns::Alarm *p);
+		~alarm_thread();
+	protected:
+		void run(void *);
+	private:
+		Alarm_ns::Alarm *p_Alarm;
+};
+
+#endif	/* ALARM_THREAD_H */
+
+/* EOF */
diff --git a/src/alarm_grammar.h b/src/alarm_grammar.h
new file mode 100644
index 0000000..f974699
--- /dev/null
+++ b/src/alarm_grammar.h
@@ -0,0 +1,280 @@
+/*
+ * alarm_grammar.h
+ *
+ * $Author:  $
+ *
+ * $Revision:  $
+ *
+ * $Log: alarm_grammar.h,v $
+ *
+ *
+ * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
+ *           Strada Statale 14 - km 163,5 in AREA Science Park
+ *           34012 Basovizza, Trieste ITALY
+ */
+
+
+#ifndef ALARM_GRAMMAR_H_
+#define ALARM_GRAMMAR_H_
+
+//--------------------------NOTE!!---------------------------------
+//----if a grammar is intended to be used in multithreaded code----
+//----it is required to "#define BOOST_SPIRIT_THREADSAFE" and------
+//----to link against Boost.Threads--------------------------------
+//-----------------------------------------------------------------
+#if BOOST_VERSION  < 103600 
+#ifndef BOOST_SPIRIT_THREADSAFE 
+#define BOOST_SPIRIT_THREADSAFE 
+#endif
+
+#ifndef PHOENIX_THREADSAFE
+#define PHOENIX_THREADSAFE
+#endif
+#endif
+
+#if BOOST_VERSION  < 103600    
+#include <boost/spirit/core.hpp>
+#include <boost/spirit/actor/assign_actor.hpp>			//for assign_a
+#include <boost/spirit/actor/push_back_actor.hpp>		//for push_back_a
+#include <boost/spirit/actor/insert_at_actor.hpp>		//for insert_at_a
+#include <boost/spirit/actor/clear_actor.hpp>			//for clear_a
+#include <boost/spirit/symbols/symbols.hpp>				//for symbol table
+#include <boost/spirit/utility/confix.hpp>				//for confix
+#include <boost/spirit/phoenix/primitives.hpp>			//needed for "var" in group rule
+#include <boost/spirit/phoenix/operators.hpp>			//needed for "var" in group rule
+#include <boost/spirit/phoenix/functions.hpp>
+#else
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_assign_actor.hpp>			//for assign_a
+#include <boost/spirit/include/classic_push_back_actor.hpp>		//for push_back_a
+#include <boost/spirit/include/classic_insert_at_actor.hpp>		//for insert_at_a
+#include <boost/spirit/include/classic_clear_actor.hpp>			//for clear_a
+#include <boost/spirit/include/classic_symbols.hpp>				//for symbol table
+#include <boost/spirit/include/classic_confix.hpp>				//for confix
+#include <boost/spirit/include/phoenix1_primitives.hpp>			//needed for "var" in group rule
+#include <boost/spirit/include/phoenix1_operators.hpp>			//needed for "var" in group rule
+#include <boost/spirit/include/phoenix1_functions.hpp>
+#endif
+
+//#include <boost/spirit/attribute.hpp>					//for closure
+
+//#include <boost/spirit/tree/ast.hpp>					//for ast parse trees (in tree_formula)
+
+#include <iostream>
+#include <string>
+#include <map>
+
+#include "event_table.h"
+#include "formula_grammar.h"
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; 
+#if BOOST_VERSION  < 103600 
+using namespace boost::spirit;
+#else
+using namespace boost::spirit::classic;
+#endif
+using namespace phoenix;								//needed for "var" in group rule
+
+////////////////////////////////////////////////////////////////////////////
+//
+//  Semantic actions for alarm gramamr
+//
+////////////////////////////////////////////////////////////////////////////
+#if 0
+struct push_back_impl
+{
+    template <typename Container, typename Item>
+    struct result
+    {
+        typedef void type;
+    };
+
+    template <typename Container, typename Item>
+    void operator()(Container& c, Item const& item) const
+    {
+        c.push_back(item);
+    }
+};
+
+function<push_back_impl> const push_back = push_back_impl();
+
+struct insert_map_impl
+{
+    template <typename Container, typename Item1, typename Item2>
+    struct result
+    {
+        typedef void type;
+    };
+
+    template <typename Container, typename Item1, typename Item2>
+    void operator()(Container& c, Item1 const& item1, Item2 const& item2) const
+    {
+        c.insert(make_pair(item1, item2));
+    }
+};
+
+function<insert_map_impl> const insert_map = insert_map_impl();
+#endif
+////////////////////////////////////////////////////////////////////////////
+//
+//  alarm grammar
+//
+////////////////////////////////////////////////////////////////////////////
+struct alarm_parse : public grammar<alarm_parse>
+{
+	alarm_t &m_alarm;
+	
+	symbols<unsigned int> sym_grp;
+	
+	alarm_parse(alarm_t &a) \
+		: m_alarm(a) 
+		{
+			//init symbol table with group defined in alarm_t::grp_str
+			map<string,unsigned int>::iterator i = m_alarm.grp_str.begin();
+			while(i != m_alarm.grp_str.end())
+			{
+				sym_grp.add(i->first.c_str(), i->second);
+				i++;
+			}		
+		}   
+   
+    template <typename ScannerT>
+    struct definition
+    {
+        definition(alarm_parse const& self)
+        {
+		//-------BOOST.SPIRIT GLOSSARY-------  
+		// >>			: sequence
+		// |			: union (i.e. alternative)
+		// -			: difference
+		// *			: kleene star (matches 0 or more times)
+		// +			: positive (matches 1 or more times)
+		// !			: optional (matches 0 or 1 time)
+		// str_p		: matches string
+		// ch_p			: matches char
+		// hex_p		: 
+		// alnum_p		: matches alpha-numeric characters
+		// anychar_p	: matches any single character (including the null terminator: '\0')
+		// lexemd_d		: turns off white space skipping
+		// confix		: recognize a sequence of: an opening, an expression and a closing
+		// assign_a		:
+		// push_back_a	:
+    	
+		//std::pair<string, vector<string> > temp;    	
+    	
+            expression
+            	=	discard_node_d
+            		[
+            		name
+            			[
+            				assign_a(self.m_alarm.name)			//save name in alarm_t
+						]
+					]		//discard_node_d					
+            		>> 
+            			root_node_d
+            			[ 
+            			formula	
+            				[
+            					assign_a(self.m_alarm.formula)	//save formula in alarm_t
+            				]
+            			]		//root_node_d
+            			  
+            		>> discard_node_d[!time_threshold]			//save time_threshold in alarm_t (leave it optional)
+            		         				
+            		>> discard_node_d
+            			[
+            			level
+            				[
+            					assign_a(self.m_alarm.lev)		//save level in alarm_t
+            				]
+            			]		//discard_node_d
+
+                	>> discard_node_d[!silent_time]				//save silent_time in alarm_t (leave it optional)
+
+            		>> discard_node_d[group]
+
+            		>> discard_node_d[msg]						//save msg in alarm_t
+
+					>> discard_node_d
+            		[
+            		!name										//leave it optional
+            			[
+            				assign_a(self.m_alarm.cmd_name_a)		//save cmd_name_a in alarm_t
+						]
+					]		//discard_node_d	
+					
+					>> discard_node_d[!ch_p(';')]				//action_a and action_n separed by ';'
+					
+					>> discard_node_d
+            		[
+            		!name										//leave it optional
+            			[
+            				assign_a(self.m_alarm.cmd_name_n)		//save cmd_name_n in alarm_t
+						]
+					]		//discard_node_d
+            	;
+            //------------------------------ALARM NAME--------------------------------------            
+            symbol
+            	=	alnum_p | '.' | '_'  | '-' | '+'				//any alpha numeric char plus '.', '_', '-', '+'
+            	;	
+            name
+            	=	(+symbol) >> '/' >> (+symbol) 
+            		>> '/' >> (+symbol) >> '/' >> (+symbol)
+            	; 
+			//------------------------------LEVEL--------------------------------------	
+			level
+				=	lexeme_d[(+alnum_p)]		//match only possible levels?? (fault, log, ...)
+				;
+			//------------------------------GROUP--------------------------------------	
+			group
+				=	self.sym_grp				//match only group defined in sym_grp symbol table
+					[
+						var(self.m_alarm.grp) |= arg1			//using phoenix::var
+					]
+					>> *(
+						ch_p('|') 
+						>> self.sym_grp			//match only group defined in sym_grp symbol table
+							[
+								var(self.m_alarm.grp) |= arg1	//using phoenix::var
+							]
+						)
+				;
+			//------------------------------MESSAGE--------------------------------------	
+			msg
+				=	ch_p('"') 
+					>> (+(anychar_p - '\"')) 		//one ore more char except '"'
+							[
+								assign_a(self.m_alarm.msg)
+							]					
+					>> '"'
+				;
+			//---------------------------TIME THRESHOLD----------------------------------	
+			time_threshold 
+				=	uint_p
+					[
+						assign_a(self.m_alarm.time_threshold)
+					]
+				;
+			//-----------------------------SILENT TIME------------------------------------
+			silent_time
+				=	int_p
+					[
+						assign_a(self.m_alarm.silent_time)
+					]
+				;
+			         
+        }
+        
+		typedef rule<ScannerT> rule_t;	
+		rule_t expression, event;
+        rule_t symbol, name, val, token, oper, msg, group, level, time_threshold, silent_time;
+		formula_grammar formula;
+		
+		rule_t const&					
+        start() const { return expression; }
+    };
+};
+
+
+#endif /*ALARM_GRAMMAR_H_*/
diff --git a/src/alarm_table.cpp b/src/alarm_table.cpp
new file mode 100644
index 0000000..fa6b4ce
--- /dev/null
+++ b/src/alarm_table.cpp
@@ -0,0 +1,722 @@
+/*
+ * alarm_table.cpp
+ *
+ * $Author: graziano $
+ *
+ * $Revision: 1.5 $
+ *
+ * $Log: alarm_table.cpp,v $
+ *
+ *
+ * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
+ *           Strada Statale 14 - km 163,5 in AREA Science Park
+ *           34012 Basovizza, Trieste ITALY
+ */
+
+#include <sys/time.h>
+#include <tango.h>
+#include "alarm_table.h"
+#include "alarm_grammar.h"
+#include "log_thread.h"
+#include "cmd_thread.h"
+
+#define _ACCESS_NODE_D 1
+
+static const char __FILE__rev[] = __FILE__ " $Revision: 1.5 $";
+
+/*
+ * alarm_t class methods
+ */
+alarm_t::alarm_t()
+{
+	grp=0;
+	counter=0;
+} 
+ 
+bool alarm_t::operator==(const alarm_t &that)
+{
+//	return((stat == that.stat) && (ack == that.ack));
+	//verify if stat not equal but only contained because added *n in internal alarm
+	return((stat.find(that.stat) != std::string::npos) && (ack == that.ack));		
+}
+
+bool alarm_t::operator==(const string &n)
+{
+	return(name == n);
+}
+
+void alarm_t::str2alm(const string &s)
+{
+	istringstream is(s);
+	ostringstream temp_msg;
+	string temp_grp;
+	is >> ts.tv_sec >> ts.tv_usec >> name >> stat >> ack >> counter >> lev >> silent_time >> temp_grp >> msg;		//stop at first white space in msg
+	temp_msg << is.rdbuf();		//read all remaining characters as msg
+	msg += temp_msg.str();
+	str2grp(temp_grp);
+}
+
+string alarm_t::alm2str(void)
+{
+	ostringstream os;
+	os.clear();
+	os << ts.tv_sec << "\t" << ts.tv_usec << "\t" << name << "\t" \
+		 << stat << "\t" << ack << "\t" << counter << "\t" << lev << "\t" << silent_time << "\t" << grp2str() << "\t" << msg << ends;
+	return(os.str());
+}
+
+map<string, unsigned int> alarm_t::grp_str;		//needed here because static
+void alarm_t::init_static_map(vector<string> &group_names)
+{
+	//LOG_STREAM << "alarm_table::init_static_map(vector<string> &group_names): Entering..." << endl;
+	int j=0;
+	vector<string>::iterator i;
+	if(grp_str.size() > 0)
+		return;
+	if(group_names.empty())
+	{
+		//LOG_STREAM << "alarm_table::init_static_map(): inserting: default group " << GR_NONE_NAME << " = " << showbase << hex << GR_NONE << endl;
+		grp_str.insert(make_pair(string(GR_NONE_NAME), GR_NONE));	
+	}	
+	for (i = group_names.begin(); i != group_names.end(); i++)
+	{
+		if((*i) == string(GR_ALL_NAME))
+			continue;
+		if(i == group_names.begin())
+		{
+			//LOG_STREAM << "alarm_table::init_static_map(): inserting: group " << *i << " = " << showbase << hex << GR_NONE << endl;
+			grp_str.insert(make_pair(*i, GR_NONE));
+		}
+		else
+		{
+			//LOG_STREAM << "alarm_table::init_static_map(): inserting: group " << *i << " = " << showbase << hex << int(0x1 << j) << endl;
+			grp_str.insert(make_pair(*i, 0x1 << j));
+			j++;
+		}
+	}
+	//LOG_STREAM << "alarm_table::init_static_map(): inserting: group " << GR_ALL_NAME << " = " << showbase << hex << GR_ALL << endl;
+	grp_str.insert(make_pair(string(GR_ALL_NAME), GR_ALL));
+}
+
+string alarm_t::grp2str(void)
+{
+	map<string, unsigned int>::iterator i = grp_str.begin();
+	bool first=true;
+	string argout;
+	if(grp == GR_ALL)
+		argout = string(GR_ALL_NAME);
+	else if(grp == GR_NONE)
+	{
+		if(i != grp_str.end())
+			argout = i->first;
+		else
+			argout = string(GR_NONE_NAME);		
+	}
+	else
+	{
+		for (; i != grp_str.end(); i++)
+		{
+			if(i->first == string(GR_ALL_NAME))
+				continue;
+			if(grp & i->second)
+			{
+				if(first)
+				{
+					argout = i->first;
+					first = false;
+				}
+				else
+					argout += string("|") + i->first;
+			}
+		}
+	}
+	return argout;
+}
+
+void alarm_t::add_grp_from_str(string &s)
+{
+	map<string, unsigned int>::iterator i = grp_str.find(s);
+	if(i != grp_str.end())
+		grp |= (*i).second;
+}
+
+void alarm_t::str2grp(string &s)
+{
+	for(map<string, unsigned int>::iterator i=grp_str.begin(); i != grp_str.end(); i++)
+		if(s.find(i->first) != string::npos)
+			grp |= i->second;
+}
+
+void alarm_t::insert(const string& s)
+{
+	s_event.insert(s);
+}
+
+void alarm_t::clear()
+{
+	name.clear();
+	formula.clear();
+	msg.clear();
+	lev.clear();
+	grp=0;
+	s_event.clear();
+	to_be_evaluated = false;
+	stat.clear();
+	ack.clear();
+	done = false;
+//	ts = 0;
+}
+
+/*
+ * alarm_table class methods
+ */
+/* typedef std::string::iterator  iterator_t;
+ typedef boost::spirit::node_val_data_factory<unsigned int> factory_t; /////TEMP!!!!!!!!!!!!!!!!!!!
+ typedef boost::spirit::tree_match<iterator_t, factory_t> parse_tree_match_t;     
+typedef boost::spirit::tree_parse_info<iterator_t, factory_t>    tree_parse_info_t;
+*/
+/*
+void alarm_table::init(vector<string>& avs, vector<string> &evn, map< string,vector<string> > &alarm_event)
+{
+	//LOG_STREAM << "alarm_table::init(vector<string>& avs,map< string,vector<string> > &alarm_event): Entering..." << endl;
+	alarm_t tmp_alm;
+	LOG_STREAM << gettime().tv_sec << " " << __FILE__rev << endl;
+	LOG_STREAM << gettime().tv_sec << " alarm_table::init(): Creating Spirit Parser..." << endl;
+	alarm_parse al(tmp_alm);    //  Construct Spirit grammar
+
+	if (avs.empty() == false) {
+		for (vector<string>::iterator i = avs.begin(); \
+				 i != avs.end(); i++) {
+
+			tmp_alm.name.clear();
+			tmp_alm.formula.clear();
+			tmp_alm.msg.clear();
+			tmp_alm.lev.clear();
+			tmp_alm.grp=0;
+#ifndef _ACCESS_NODE_D 			
+			parse_info<> info = parse(i->c_str(), al, space_p);	//parse string i with grammar al, skipping white spaces
+#else			
+			tree_parse_info_t info = ast_parse<factory_t>(i->begin(), i->end(), al, space_p);
+#endif
+			if (info.full)
+			{
+           		LOG_STREAM << gettime().tv_sec << " Parsing succeeded: " << tmp_alm.name << endl;
+				for (vector<string>::iterator i = evn.begin(); i != evn.end(); i++) 
+					LOG_STREAM << gettime().tv_sec << " READ Event! ->" << *i << endl;
+			}	           		
+       		else
+        	{
+#ifndef _ACCESS_NODE_D       	
+				LOG_STREAM << gettime().tv_sec << " Parsing failed, stopped at: " << info.stop << endl;
+#else       	
+				LOG_STREAM << gettime().tv_sec << " Parsing failed, stopped at: " << string(info.stop, i->end()) << ends; //TODO
+#endif            	
+        	}
+
+			if ((tmp_alm.name.empty() == false) && \
+					(tmp_alm.formula.empty() == false) && \
+					((tmp_alm.lev==LEV_LOG)||(tmp_alm.lev==LEV_WARNING)|| \
+					(tmp_alm.lev==LEV_FAULT)||(tmp_alm.lev.empty() == true))) 
+			{
+				tmp_alm.stat = S_NORMAL;
+				tmp_alm.ack = ACK;
+				tmp_alm.done = false;
+				if(tmp_alm.grp == 0)
+					tmp_alm.grp = GR_DEFAULT;
+				if(tmp_alm.lev.empty() == true)
+					tmp_alm.lev = LEV_DEFAULT;
+				push_back(tmp_alm);
+			} else {
+				cerr << gettime().tv_sec << " alarm_table::init(): syntax error in '" << *i \
+						 << "', skipping!" << endl;
+			}
+		}
+	}
+}*/
+
+void alarm_table::push_back(alarm_t &a)
+{
+#ifndef _RW_LOCK
+	this->lock();
+#else
+	vlock->writerIn();
+#endif
+	//v_alarm.push_back(a);
+	v_alarm.insert(make_pair(a.name,a));
+#ifndef _RW_LOCK
+	this->unlock();
+#else
+	vlock->writerOut();
+#endif
+}
+
+void alarm_table::show(vector<string> &al_table_string)
+{
+#ifndef _RW_LOCK
+	this->lock();
+#else
+	vlock->readerIn();
+#endif
+	ostringstream log_msg;
+	string log_str;
+	if (v_alarm.empty() == false) {
+		log_msg << "### alarms table: ###" << ends;
+		al_table_string.push_back(log_msg.str());
+		log_msg.str(string());
+		alarm_container_t::iterator i = v_alarm.begin();
+		unsigned int j = 0;
+		while (i != v_alarm.end()) {
+			log_msg << j << " - name: '" << i->second.name << "'" << ends;
+			al_table_string.push_back(log_msg.str());
+			log_msg.str(string());			
+			log_msg << "    formula: '" << i->second.formula << "'" << ends;
+			al_table_string.push_back(log_msg.str());
+			log_msg.str(string());
+	  		log_msg << "    stat: '" << i->second.stat << "'" << ends;
+	  		al_table_string.push_back(log_msg.str());
+			log_msg.str(string());
+			log_msg << "    ack: '" << i->second.ack << "'" << ends;
+			al_table_string.push_back(log_msg.str());
+			log_msg.str(string());
+			log_msg << "    msg: '" << i->second.msg << "'" << ends;
+			al_table_string.push_back(log_msg.str());
+			log_msg.str(string());
+			log_msg << "    grp: '" << showbase << hex << i->second.grp << "'" << ends;
+			al_table_string.push_back(log_msg.str());
+			log_msg.str(string());
+			log_msg << "    lev: '" << i->second.lev << "'" << ends;
+			al_table_string.push_back(log_msg.str());
+			log_msg.str(string());
+			i++;
+			j++;
+		}
+	}
+#ifndef _RW_LOCK
+	this->unlock();
+#else
+	vlock->readerOut();
+#endif
+}
+
+unsigned int alarm_table::size(void)
+{
+	return(v_alarm.size());
+}
+
+alarm_container_t& alarm_table::get(void)
+{
+	return(v_alarm);
+}
+
+void alarm_table::stored(vector<alarm_t>& a)
+{
+#ifndef _RW_LOCK
+	this->lock();
+#else
+	vlock->readerIn();
+#endif
+	if (a.empty() == false) {
+		for (vector<alarm_t>::iterator i = a.begin(); i != a.end(); i++) 
+		{
+			alarm_container_t::iterator found = v_alarm.find(i->name);
+			if (found != v_alarm.end()) {
+				found->second.ts = i->ts;
+				found->second.stat = i->stat;
+				found->second.ack = i->ack;
+				found->second.done = i->done;
+				found->second.is_new = i->is_new;
+			} else {
+				/*
+			 	 * shouldn't happen!!!
+			   */
+				LOG_STREAM << "alarm_table::stored(): " << i->name \
+					 	 			 << " NOT found in alarm table" << endl;
+			}
+		}  /* for */
+	}  /* if */
+#ifndef _RW_LOCK
+	this->unlock();
+#else
+	vlock->readerOut();
+#endif
+}
+
+bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, int res, string &attr_values, string grp, string msg, string formula)
+{
+	bool ret_changed=false;
+	//Tango::TimeVal now = gettime();
+	TangoSys_MemStream out_stream;
+	alm_log_t a;
+#ifndef _RW_LOCK
+	this->lock();
+#else
+	vlock->readerIn();
+#endif
+	alarm_container_t::iterator found = v_alarm.find(alm_name);
+	if (found != v_alarm.end()) 
+	{
+		if(found->second.silenced > 0)
+		{
+			Tango::TimeVal now = gettime();
+			double dnow = now.tv_sec + ((double)now.tv_usec) / 1000000;
+			double dsilent = found->second.ts_time_silenced.tv_sec + ((double)found->second.ts_time_silenced.tv_usec) / 1000000;
+			double dminutes = (dnow - dsilent)/60;
+			if(dminutes < found->second.silent_time)
+				found->second.silenced = found->second.silent_time - floor(dminutes);
+			else
+				found->second.silenced = 0;
+		}
+
+		bool status_time_threshold;
+		if(found->second.time_threshold > 0)		//if enabled time threshold
+			status_time_threshold = (res) && (found->second.counter >= 1) && ((ts.tv_sec - found->second.time_threshold) > found->second.ts_time_threshold.tv_sec);	//formula gives true and time threshold is passed
+		else
+			status_time_threshold = res;	
+		//if status changed:
+		// - from S_NORMAL to S_ALARM considering also time threshold
+		//or
+		// - from S_ALARM to S_NORMAL		
+		if((status_time_threshold && (found->second.stat == S_NORMAL)) || (!res && (found->second.stat == S_ALARM)))
+		{
+			ret_changed=true;
+			a.type_log = TYPE_LOG_STATUS;
+			a.name = alm_name;
+			a.time_s = ts.tv_sec;		
+			a.time_us = ts.tv_usec;
+			a.status = res ? S_ALARM : S_NORMAL;
+			//a.level = found->second.lev;
+			if(res)
+				found->second.ack = NOT_ACK;	//if changing from NORMAL to ALARM -> NACK
+			a.ack = found->second.ack;
+			a.values = attr_values;
+			//a.grp = found->second.grp2str();
+			//a.msg = res ? found->second.msg : "";
+			logloop->log_alarm_db(a);
+			found->second.ts = ts;	/* store event timestamp into alarm timestamp */ //here update ts only if status changed
+			if(res)
+			{
+				found->second.is_new = 1;		//here set this alarm as new, read attribute set it to 0	//12-06-08: StopNew command set it to 0
+				if(found->second.dp_a && ((ts.tv_sec - startup_complete.tv_sec) > 10))		//action from S_NORMAL to S_ALARM
+				{
+					/*try {
+						long call_id;
+						ostringstream tmp;
+						tmp << alm_name << ";" << attr_values;
+						Tango::DevString str = CORBA::string_dup(tmp.str().c_str());
+						Tango::DeviceData Din;
+						Din << str;
+						CORBA::string_free(str);
+						//found->second.dp_a->ping();
+						cmdloop->mutex_dp->lock();
+						//call_id = found->second.dp_a->command_inout_asynch(found->second.cmd_action_a, Din, true);		//true -> "fire and forget" mode: client do not care at all about the server answer
+						call_id = found->second.dp_a->command_inout_asynch(found->second.cmd_action_a, Din);		//true -> "fire and forget" mode: client do not care at all about the server answer
+						cmdloop->mutex_dp->unlock();
+						LOG_STREAM << "alarm_table::update() executed action: " << found->second.cmd_name_a << " !!!" << endl;
+						cmd_t arg;
+						arg.cmd_id = call_id;
+						arg.dp_add = (long)found->second.dp_a;
+						arg.arg_s = found->second.cmd_name_a;	
+						cmdloop->list.push_back(arg);						
+					} catch(Tango::DevFailed e) 
+					{
+						string err(e.errors[0].desc);
+						if(err.find("is not yet arrived") == string::npos)			//TODO: change this!!
+							out_stream << "Failed to execute action " << found->second.cmd_name_a << ", err=" << e.errors[0].desc << ends;
+						//LOG_STREAM << "alarm_table::update() ERROR: " << out_stream.str() << endl;
+					}*/
+					ostringstream tmp;
+					string tmp_attr_val = attr_values;
+					replace(tmp_attr_val.begin(), tmp_attr_val.end(), ';' , ',');
+					string tmp_msg = msg;
+					replace(tmp_msg.begin(), tmp_msg.end(), ';' , ',');
+					tmp << "name=" << alm_name << ";groups=" << grp << ";msg="<<tmp_msg<<";values="<<tmp_attr_val<<";formula="<<formula;
+					cmd_t arg;
+					arg.cmd_id = CMD_COMMAND;
+					arg.dp_add = (long)found->second.dp_a;
+					arg.arg_s1 = tmp.str();
+					arg.arg_s2 = found->second.cmd_action_a;
+					arg.arg_s3 = found->second.cmd_name_a;
+					arg.arg_b = found->second.send_arg_a;	
+					cmdloop->list.push_back(arg);					
+				}
+			}
+			else
+			{
+				if(found->second.dp_n && ((ts.tv_sec - startup_complete.tv_sec) > 10))		//action from S_ALARM to S_NORMAL 
+				{
+					/*try {
+						long call_id;
+						ostringstream tmp;
+						tmp << alm_name << ";" << attr_values;
+						Tango::DevString str = CORBA::string_dup(tmp.str().c_str());
+						Tango::DeviceData Din;
+						Din << str;
+						CORBA::string_free(str);						
+						//found->second.dp_n->ping();
+						cmdloop->mutex_dp->lock();
+						//call_id = found->second.dp_n->command_inout_asynch(found->second.cmd_action_n, Din, true);		//true -> "fire and forget" mode: client do not care at all about the server answer
+						call_id = found->second.dp_n->command_inout_asynch(found->second.cmd_action_n, Din);				//true -> "fire and forget" mode: client do not care at all about the server answer
+						cmdloop->mutex_dp->unlock();
+						LOG_STREAM << "alarm_table::update() executed action: " << found->second.cmd_name_n << " !!!" << endl;
+						cmd_t arg;
+						arg.cmd_id = call_id;
+						arg.dp_add = (long)found->second.dp_n;
+						arg.arg_s = found->second.cmd_name_n;	
+						cmdloop->list.push_back(arg);						
+					} catch(Tango::DevFailed e) 
+					{
+						string err(e.errors[0].desc);
+						if(err.find("is not yet arrived") == string::npos)			//TODO: change this!!
+							out_stream << "Failed to execute action " << found->second.cmd_name_n << ", err=" << e.errors[0].desc << ends;
+						//LOG_STREAM << "alarm_table::update() ERROR: " << out_stream.str() << endl;
+					}*/
+					ostringstream tmp;
+					string tmp_attr_val = attr_values;
+					replace(tmp_attr_val.begin(), tmp_attr_val.end(), ';' , ',');
+					string tmp_msg = msg;
+					replace(tmp_msg.begin(), tmp_msg.end(), ';' , ',');
+					tmp << "name=" << alm_name << ";groups=" << grp << ";msg="<<tmp_msg<<";values="<<tmp_attr_val<<";formula="<<formula;
+					cmd_t arg;
+					arg.cmd_id = CMD_COMMAND;
+					arg.dp_add = (long)found->second.dp_n;
+					arg.arg_s1 = tmp.str();
+					arg.arg_s2 = found->second.cmd_action_n;
+					arg.arg_s3 = found->second.cmd_name_n;
+					arg.arg_b = found->second.send_arg_n;
+					cmdloop->list.push_back(arg);					
+				}
+			}
+		}
+		if (status_time_threshold) {
+			found->second.stat = S_ALARM;
+			//found->second.ack = NOT_ACK;
+		}
+		if(res) {
+			found->second.counter++;
+		} else {
+			found->second.stat = S_NORMAL;
+			found->second.counter = 0;
+		}
+		if(found->second.counter == 1)
+			found->second.ts_time_threshold = gettime();		//first occurrance of this alarm, now begin to wait for time threshold
+		if(found->second.counter >= 1)
+			found->second.attr_values_time_threshold = attr_values;		//save last attr_values to be used in timer_update if this alarm pass over time threshold
+
+		//found->second.ts = ts;	/* store event timestamp into alarm timestamp */ //here update ts everytime
+	} else {
+		/*
+		 * shouldn't happen!!!!
+		 */
+		out_stream << "couldn't find alarm '" << alm_name << "' in 'alarms' table" << ends;
+		LOG_STREAM << gettime().tv_sec << " alarm_table::update(): " << out_stream.str() << endl;
+	}
+#ifndef _RW_LOCK
+	this->unlock();
+#else
+	vlock->readerOut();
+#endif
+	if(out_stream.str().length() > 0)
+		throw out_stream.str();
+	return ret_changed;
+}
+
+bool alarm_table::timer_update()
+{
+	bool ret_changed=false;
+	Tango::TimeVal ts = gettime();
+	TangoSys_MemStream out_stream;
+	alm_log_t a;
+#ifndef _RW_LOCK
+	this->lock();
+#else
+	vlock->readerIn();
+#endif
+	for(alarm_container_t::iterator i = v_alarm.begin(); i != v_alarm.end(); i++)
+	{		
+		bool status_time_threshold;
+		if(i->second.time_threshold > 0)		//if enabled time threshold
+			status_time_threshold = (i->second.counter >= 1) && ((ts.tv_sec - i->second.time_threshold) > i->second.ts_time_threshold.tv_sec);	//waiting for threshold and time threshold is passed
+		else
+			continue;			//if not enabled time threshold, nothing to do in timer	
+
+		//if status changed from S_NORMAL to S_ALARM considering also time threshold	
+		if(status_time_threshold && (i->second.stat == S_NORMAL))
+		{
+			ret_changed = true;
+			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;
+				if(dminutes < i->second.silent_time)
+					i->second.silenced = i->second.silent_time - floor(dminutes);
+				else
+					i->second.silenced = 0;
+			}
+
+			a.type_log = TYPE_LOG_STATUS;
+			a.name = i->second.name;
+			a.time_s = ts.tv_sec;		
+			a.time_us = ts.tv_usec;
+			a.status = S_ALARM;
+			//a.level = found->second.lev;
+			i->second.ack = NOT_ACK;	//if changing from NORMAL to ALARM -> NACK
+			a.ack = i->second.ack;
+			a.values = i->second.attr_values_time_threshold;
+			logloop->log_alarm_db(a);
+			i->second.ts = ts;	/* store event timestamp into alarm timestamp */ //here update ts only if status changed
+
+			i->second.is_new = 1;		//here set this alarm as new, read attribute set it to 0	//12-06-08: StopNew command set it to 0
+			if(i->second.dp_a && ((ts.tv_sec - startup_complete.tv_sec) > 10))
+			{
+				/*try {
+					long call_id;
+					ostringstream tmp;
+					tmp << i->second.name << ";" << i->second.attr_values_time_threshold;
+					Tango::DevString str = CORBA::string_dup(tmp.str().c_str());
+					Tango::DeviceData Din;
+					Din << str;
+					CORBA::string_free(str);
+					//i->second.dp_a->ping();		
+					cmdloop->mutex_dp->lock();			
+					//call_id = i->second.dp_a->command_inout_asynch(i->second.cmd_action_a, Din, true);		//true -> "fire and forget" mode: client do not care at all about the server answer
+					call_id = i->second.dp_a->command_inout_asynch(i->second.cmd_action_a, Din);		
+					cmdloop->mutex_dp->unlock();
+					LOG_STREAM << gettime().tv_sec << " alarm_table::timer_update() executed action: " << i->second.cmd_name_a << " !!!" << endl;
+					cmd_t arg;
+					arg.cmd_id = call_id;
+					arg.dp_add = (long)i->second.dp_a;
+					arg.arg_s = i->second.cmd_name_a;	
+					cmdloop->list.push_back(arg);					
+				} catch(Tango::DevFailed e) 
+				{
+					string err(e.errors[0].desc);
+					if(err.find("is not yet arrived") == string::npos)			//TODO: change this!!			
+						out_stream << "Failed to execute action " << i->second.cmd_name_a << ", err=" << e.errors[0].desc << ends;
+					//LOG_STREAM << "alarm_table::timer_update() ERROR: " << out_stream.str() << endl;
+				}*/
+				ostringstream tmp;
+				string tmp_attr_val = i->second.attr_values_time_threshold;
+				replace(tmp_attr_val.begin(), tmp_attr_val.end(), ';' , ',');
+				string tmp_msg = i->second.msg;
+				replace(tmp_msg.begin(), tmp_msg.end(), ';' , ',');
+				tmp << "name=" << i->second.name << ";groups=" << i->second.grp2str() << ";msg="<<tmp_msg<<";values="<<tmp_attr_val<<";formula="<<i->second.formula;
+				cmd_t arg;
+				arg.cmd_id = CMD_COMMAND;
+				arg.dp_add = (long)i->second.dp_a;
+				arg.arg_s1 = tmp.str();
+				arg.arg_s2 = i->second.cmd_action_a;
+				arg.arg_s3 = i->second.cmd_name_a;
+				arg.arg_b = i->second.send_arg_a;	
+				cmdloop->list.push_back(arg);
+			}
+		}
+		if (status_time_threshold) {
+			i->second.stat = S_ALARM;
+			//found->second.ack = NOT_ACK;
+		}
+		//found->second.ts = ts;	/* store event timestamp into alarm timestamp */ //here update ts everytime
+	}
+#ifndef _RW_LOCK
+	this->unlock();
+#else
+	vlock->readerOut();
+#endif
+	if(out_stream.str().length() > 0)
+		throw out_stream.str();
+	return ret_changed;
+}
+
+void alarm_table::erase(alarm_container_t::iterator i)
+{
+#ifndef _RW_LOCK
+	this->lock();
+#else
+	vlock->writerIn();
+#endif
+	v_alarm.erase(i);
+#ifndef _RW_LOCK
+	this->unlock();
+#else
+	vlock->writerOut();
+#endif
+}
+
+bool alarm_table::exist(string& s)
+{
+	alarm_container_t::iterator found = v_alarm.find(s);
+	if (found != v_alarm.end())
+		return true;
+	else
+		return false;
+}
+
+#ifdef _RW_LOCK
+void alarm_table::new_rwlock()
+{
+	vlock = new(ReadersWritersLock);
+}
+void alarm_table::del_rwlock()
+{
+	delete vlock;
+}
+#endif
+
+void alarm_table::init_logdb(string dbhost, string dbuser, string dbpw, string dbname, int dbport, string instance_name)
+{
+	logloop = new log_thread(dbhost, dbuser, dbpw, dbname, dbport, instance_name);
+	logloop->start();
+}
+
+void alarm_table::stop_logdb()
+{
+	alm_log_t a;
+	a.name = LOG_THREAD_EXIT;
+	a.time_s = LOG_THREAD_EXIT_TIME;
+	logloop->log_alarm_db(a);
+	//sleep(1);
+	//delete logloop;	
+}
+
+void alarm_table::init_cmdthread()
+{
+	cmdloop = new cmd_thread();
+	cmdloop->start();
+}
+
+void alarm_table::stop_cmdthread()
+{
+	cmd_t arg;
+	//arg.arg_s = CMD_THREAD_EXIT;
+	arg.cmd_id = CMD_THREAD_EXIT;
+	cmdloop->list.push_back(arg);	
+}
+
+void alarm_table::log_alarm_db(unsigned int type, Tango::TimeVal ts, string name, string status, string ack, 
+		string formula, unsigned int time_threshold, string grp, string lev, string msg, string action, int silent_time, vector<string> alm_list)
+{
+	alm_log_t a;
+	a.type_log = type;
+	a.name = name;
+	a.time_s = ts.tv_sec;	
+	a.time_us = ts.tv_usec;
+	a.time_threshold = time_threshold;
+	a.status = status;
+	a.level = lev;
+	a.ack = ack;
+	a.grp = grp;
+	a.msg = msg;
+	a.action = action;
+	a.formula = formula;
+	a.alm_list = alm_list;
+	a.silent_time = silent_time;
+	logloop->log_alarm_db(a);	
+}
+
+void alarm_table::get_alarm_list_db(vector<string> &al_list)
+{
+	logloop->get_alarm_list(al_list);
+}
+
+/* EOF */
diff --git a/src/alarm_table.h b/src/alarm_table.h
new file mode 100644
index 0000000..ee82694
--- /dev/null
+++ b/src/alarm_table.h
@@ -0,0 +1,212 @@
+/*
+ * alarm_table.h
+ *
+ * $Author: graziano $
+ *
+ * $Revision: 1.5 $
+ *
+ * $Log: alarm_table.h,v $
+ *
+ *
+ * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
+ *           Strada Statale 14 - km 163,5 in AREA Science Park
+ *           34012 Basovizza, Trieste ITALY
+ */
+
+#ifndef ALARM_TABLE_H
+#define ALARM_TABLE_H
+
+#define _RW_LOCK
+
+#include <iostream>
+#include <string>
+#include <map>
+
+#include <tango.h>
+
+//spirit defines have to be put befor first inclusion of spirit headers
+#ifndef BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT
+#define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT 2 //tmp scanner_list
+#endif
+
+/*#ifndef BOOST_SPIRIT_THREADSAFE 
+#define BOOST_SPIRIT_THREADSAFE 
+#endif
+
+#ifndef PHOENIX_THREADSAFE
+#define PHOENIX_THREADSAFE
+#endif
+*/	
+//#include "spirit-parser.h"
+//#include <boost/spirit/core.hpp>
+#include <boost/version.hpp>
+#if BOOST_VERSION  < 103600
+#include <boost/spirit/tree/ast.hpp>					//for ast parse trees (in tree_formula)
+#else
+#include <boost/spirit/include/classic_ast.hpp>			//for ast parse trees (in tree_formula)
+#endif
+
+//#include "log_thread.h"
+
+#define LOG_STREAM		cout
+
+using namespace std;
+
+//#define _ACCESS_NODE_D 1
+#if BOOST_VERSION  < 103600
+#ifndef _ACCESS_NODE_D
+typedef char const*         iterator_t;
+typedef boost::spirit::tree_match<iterator_t> parse_tree_match_t;
+typedef boost::spirit::tree_parse_info<>    tree_parse_info_t;
+#else
+typedef std::string::iterator  iterator_t;
+typedef boost::spirit::node_val_data_factory<unsigned int> factory_t;		//want a modified node to contain an unsigned int value
+typedef boost::spirit::tree_match<iterator_t, factory_t> parse_tree_match_t;     
+typedef boost::spirit::tree_parse_info<iterator_t, factory_t>    tree_parse_info_t;   
+#endif
+#else
+#ifndef _ACCESS_NODE_D
+typedef char const*         iterator_t;
+typedef boost::spirit::classic::tree_match<iterator_t> parse_tree_match_t;
+typedef boost::spirit::classic::tree_parse_info<>    tree_parse_info_t;
+#else
+typedef std::string::iterator  iterator_t;
+typedef boost::spirit::classic::node_val_data_factory<unsigned int> factory_t;		//want a modified node to contain an unsigned int value
+typedef boost::spirit::classic::tree_match<iterator_t, factory_t> parse_tree_match_t;     
+typedef boost::spirit::classic::tree_parse_info<iterator_t, factory_t>    tree_parse_info_t;   
+#endif
+#endif
+
+typedef parse_tree_match_t::tree_iterator iter_t;
+
+#define S_NORMAL	"NORMAL"
+#define S_ALARM		"ALARM"
+
+#define NOT_ACK		"NACK"
+#define ACK		"ACK"
+
+#define GR_ALL		0xffffffff
+#define GR_NONE		0x00000000
+#define GR_DEFAULT	GR_NONE			//or GR_ALL??
+//#define MAX_GRP		32
+#define GR_ALL_NAME		"gr_all"
+#define GR_NONE_NAME	"gr_none"
+
+#define LEV_LOG			"log"
+#define LEV_WARNING		"warning"
+#define LEV_FAULT		"fault"
+#define LEV_DEFAULT	LEV_FAULT
+
+class alarm_t;
+class alarm_table;
+class log_thread;
+class cmd_thread;
+
+/*
+ * store the alarm-name/alarm-formula pair
+ */
+class alarm_t {
+	public:
+		string name,
+					 formula;
+		Tango::TimeVal ts;
+		string stat,
+					 ack;
+		unsigned int counter;
+		
+		tree_parse_info_t formula_tree;
+					 
+		static map<string, unsigned int> grp_str;
+
+		bool done;
+		bool to_be_evaluated;
+		string msg;
+		unsigned int grp;
+		string lev;
+		set<string> s_event;
+		int is_new;
+		Tango::TimeVal ts_time_threshold;	//says when it has gone in alarm status for the first time
+		unsigned int time_threshold;		//TODO: seconds, is it enough precision?
+
+		Tango::TimeVal ts_time_silenced;	//says when it has been silenced
+		int silent_time;			//minutes max to be silent
+		int silenced;				//minutes still to be silent
+		string attr_values_time_threshold;	//attr_values of first occurrence of alarm waiting for time threshold
+		string cmd_name_a;					//action to execute: when NORMAL -> ALARM, cmd_name = cmd_dp_a/cmd_action_a
+		string cmd_dp_a;						//device proxy part of cmd_name_a
+		string cmd_action_a;					//action part of cmd_name_a
+		bool send_arg_a;					//send as string argument alarm name and attr values
+		Tango::DeviceProxy *dp_a;
+		string cmd_name_n;					//action to execute: when ALARM -> NORMAL, cmd_name_n = cmd_dp_n/cmd_action_n
+		string cmd_dp_n;						//device proxy part of cmd_name_n
+		string cmd_action_n;					//action part of cmd_name_n
+		bool send_arg_n;					//send as string argument alarm name and attr values
+		Tango::DeviceProxy *dp_n;
+		/*
+		 * methods
+		 */
+		alarm_t();							//constructor
+		void init_static_map(vector<string> &group_names);
+		bool operator==(const alarm_t& that);
+		bool operator==(const string& n);
+		void str2alm(const string &s);
+		string alm2str(void);
+		string grp2str(void);
+		void add_grp_from_str(string &s);
+		void str2grp(string &s);
+		void insert(const string& s);
+		void clear();
+		
+	protected:
+	private:
+		
+};
+
+typedef map<string,alarm_t> alarm_container_t;	
+#ifndef _RW_LOCK
+class alarm_table  : public omni_mutex {
+#else
+class alarm_table {
+#endif
+	public:
+		alarm_table() {}
+		~alarm_table() {}
+
+		//void init(vector<string>& avs);
+		//void init(vector<string>& avs, vector<string> &evn, map< string,vector<string> > &alarm_event);		
+		void push_back(alarm_t& a);
+		void show(vector<string> &al_table_string);
+		unsigned int size(void);
+		alarm_container_t& get(void);
+		void stored(vector<alarm_t>& a);
+		bool update(const string& alm_name, Tango::TimeVal ts, int res, string &attr_values, string grp, string msg, string formula);
+		bool timer_update();
+		void erase(alarm_container_t::iterator i);
+		bool exist(string& s);
+		//vector<alarm_t> v_alarm;
+		alarm_container_t v_alarm;
+#ifdef _RW_LOCK
+		ReadersWritersLock *vlock;
+		void new_rwlock();
+		void del_rwlock();
+#endif
+		
+
+		void init_logdb(string dbhost, string dbuser, string dbpw, string dbname, int dbport, string instance_name);
+		void stop_logdb();
+		void log_alarm_db(unsigned int type, Tango::TimeVal ts, string name, string status, string ack,
+				 string formula, unsigned int time_threshold, string grp, string lev, string msg, string action, int silent_time, vector<string> alm_list=vector<string>());
+		void get_alarm_list_db(vector<string> &al_list);
+		void init_cmdthread();
+		void stop_cmdthread();
+		Tango::TimeVal startup_complete;			//to disable action execution at startup		
+	
+	protected:
+	private:
+		
+		log_thread *logloop;
+		cmd_thread *cmdloop;		
+};
+
+
+#endif	/* ALARM_TABLE_H */
diff --git a/src/cmd_thread.cpp b/src/cmd_thread.cpp
new file mode 100644
index 0000000..21db6bc
--- /dev/null
+++ b/src/cmd_thread.cpp
@@ -0,0 +1,288 @@
+/*
+ * cmd_thread.cpp
+ *
+ * $Author: claudio $
+ *
+ * $Revision: 1.3 $
+ *
+ * $Log: cmd_thread.cpp,v $
+ * Revision 1.3  2015-07-21 13:40:59  claudio
+ * minor cleanups
+ *
+ * Revision 1.2  2008-11-17 13:13:21  graziano
+ * command action can be: without arguments or with string argument
+ *
+ * Revision 1.1  2008/11/10 10:53:31  graziano
+ * thread for execution of commands
+ *
+ *
+ *
+ *
+ *
+ * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
+ *           Strada Statale 14 - km 163,5 in AREA Science Park
+ *           34012 Basovizza, Trieste ITALY
+ */
+
+#include "cmd_thread.h"
+static const char __FILE__rev[] = __FILE__ " $Revision: 1.3 $";
+
+/*
+ * cmd_thread::cmd_thread()
+ */
+cmd_thread::cmd_thread() 
+{
+	cout << __FILE__rev << endl;
+	cout << gettime().tv_sec << " cmd_thread::cmd_thread(): constructor... !" << endl;	
+	//mutex_dp = new omni_mutex::omni_mutex();
+}
+
+/*
+ * cmd_thread::~cmd_thread()
+ */
+cmd_thread::~cmd_thread()
+{
+	cout << gettime().tv_sec << " cmd_thread::~cmd_thread(): delete device entering..." << endl;
+	//delete mutex_dp;	
+}
+
+/*
+ * cmd_thread::run()
+ */
+void cmd_thread::run(void *)
+{
+	long call_id;
+	while (true) {
+		/*
+		 * pop_front() will wait() on condition variable
+		 */
+		try
+		{
+			cmd_t cmd = list.pop_front();
+			switch(cmd.cmd_id)
+			{
+				case CMD_THREAD_EXIT:
+					cout << gettime().tv_sec << " cmd_thread::run(): received command THREAD_EXIT -> exiting..." << endl;				
+				return;
+				
+				case CMD_COMMAND:
+				{
+					try {
+						cout << gettime().tv_sec << " cmd_thread::run(): COMMAND ... action=" << cmd.arg_s3 << endl;
+						dp = (Tango::DeviceProxy *)cmd.dp_add;
+						if(cmd.arg_b)
+						{
+							Tango::DevString str = CORBA::string_dup(cmd.arg_s1.c_str());
+							Tango::DeviceData Din;
+							Din << str;
+							CORBA::string_free(str);
+							//found->second.dp_a->ping();
+							//call_id = dp->command_inout_asynch(cmd.arg_s2, Din, true);		//true -> "fire and forget" mode: client do not care at all about the server answer
+							call_id = dp->command_inout_asynch(cmd.arg_s2, Din);		//true -> "fire and forget" mode: client do not care at all about the server answer
+						}
+						else
+							call_id = dp->command_inout_asynch(cmd.arg_s2);
+						cout << gettime().tv_sec <<  " cmd_thread::run() executed action: " << cmd.arg_s3 << " !!! call_id=" << call_id << endl;
+						/*cmd_t arg;
+						arg.cmd_id = CMD_RESPONSE;
+						arg.call_id = call_id;
+						arg.dp_add = cmd.dp_add;
+						arg.arg_s1 = cmd.arg_s1;
+						arg.arg_s2 = cmd.arg_s2;
+						arg.arg_s3 = cmd.arg_s3;	
+						cmdloop->list.push_back(arg);*/
+						cmd.cmd_id = CMD_RESPONSE;			//if no exception till now push in list request of response
+						cmd.call_id = call_id;				//if no exception till now push in list request of response
+						list.push_back(cmd);		//if no exception till now push in list request of response
+					} catch(Tango::DevFailed e) 
+					{
+						TangoSys_MemStream out_stream;
+						string err(e.errors[0].desc);
+						if(err.find("is not yet arrived") == string::npos)			//TODO: change this!!
+						{
+							out_stream << "Failed to execute action " << cmd.arg_s3 << ", err=" << e.errors[0].desc << ends;
+							cout << gettime().tv_sec <<  " cmd_thread::run() ERROR: " << out_stream.str() << endl;
+						}
+						else
+						{
+							cout << gettime().tv_sec <<  " cmd_thread::run() exception 'is not yet arrived': pushing request of response, call_id=" << call_id << endl;
+							cmd.cmd_id = CMD_RESPONSE;			//if no exception till now push in list request of response
+							cmd.call_id = call_id;				//if no exception till now push in list request of response
+							list.push_back(cmd);		//if no exception till now push in list request of response						
+						}
+						
+					}					
+				}	
+				break;
+				
+				case CMD_RESPONSE:
+				{
+					//cout << gettime().tv_sec << " cmd_thread::run(): RESPONSE WAKE UP... action=" << cmd.arg_s3 << " call_id=" << cmd.call_id << endl;
+					Tango::DeviceData resp;
+					dp = (Tango::DeviceProxy *)cmd.dp_add;
+					try {
+						resp = dp->command_inout_reply(cmd.call_id);
+						cout << gettime().tv_sec << " cmd_thread::run() RECEIVED response to action " << cmd.arg_s3 << endl;
+					} catch(Tango::DevFailed e) 
+					{
+						TangoSys_MemStream out_stream;
+						out_stream << "EXCEPTION executing action " << cmd.arg_s3 << ", err=" << e.errors[0].desc << ends;
+						
+						if(out_stream.str().find("is not yet arrived") != string::npos)			//TODO: change this!!
+						{
+							
+							list.push_back(cmd);				//if exception "not yet arrived" push in list another request of response		
+							omni_thread::sleep(0,300000000);	//0.3 s
+						}
+						else
+						{
+							cout << gettime().tv_sec << " cmd_thread::run() " <<  out_stream.str() << endl;
+							Tango::Except::print_exception(e);
+						}
+					}				
+				}
+				break;		
+			}
+/*			if(cmd.arg_s == CMD_THREAD_EXIT)
+			{
+				cout << gettime().tv_sec << " cmd_thread::run(): received command THREAD_EXIT -> exiting..." << endl;				
+				return;
+			}
+			else
+			{
+				cout << gettime().tv_sec << " cmd_thread::run(): WAKE UP... action=" << cmd.arg_s << endl;
+				Tango::DeviceData resp;
+				dp = (Tango::DeviceProxy *)cmd.dp_add;
+				try {
+					mutex_dp->lock();
+					resp = dp->command_inout_reply(cmd.cmd_id);
+					mutex_dp->unlock();
+					cout << gettime().tv_sec << " cmd_thread::run() received response to action " << cmd.arg_s << endl;
+				} catch(Tango::DevFailed e) 
+				{
+					TangoSys_MemStream out_stream;
+					out_stream << "EXCEPTION executing action " << cmd.arg_s << ", err=" << e.errors[0].desc << ends;
+					
+					if(out_stream.str().find("is not yet arrived") != string::npos)			//TODO: change this!!
+					{
+						
+						list.push_back(cmd);
+						omni_thread::sleep(0,300000000);	//0.2 s
+					}
+					else
+						cout << gettime().tv_sec << " cmd_thread::run() " <<  out_stream.str() << endl;
+				}
+			}*/
+			
+		}
+		catch(omni_thread_fatal& ex)
+		{
+			ostringstream err;
+			err << "omni_thread_fatal exception running command thread, err=" << ex.error << ends;
+			//WARN_STREAM << "alarm_thread::run(): " << err.str() << endl;	
+			printf("cmd_thread::run(): %s", err.str().c_str());			
+		}			
+		catch(Tango::DevFailed& ex)
+		{
+			ostringstream err;
+			err << "exception running command thread: '" << ex.errors[0].desc << "'" << ends;
+			//WARN_STREAM << "alarm_thread::run(): " << err.str() << endl;	
+			printf("cmd_thread::run(): %s", err.str().c_str());			
+			Tango::Except::print_exception(ex);
+		}		
+		catch(...)
+		{
+			//WARN_STREAM << "alarm_thread::run(): catched unknown exception!!" << endl;
+			printf("cmd_thread::run(): catched unknown exception!!");
+		}		
+	}
+	//cout << "alarm_thread::run(): returning" << endl;
+}  /* cmd_thread::run() */
+
+/*
+ * cmd_list class methods
+ */
+void cmd_list::push_back(cmd_t& cmd)
+{
+	this->lock();
+
+	//cout << "event_list::push_back: " << e.name << " value=" << e.value[0] << endl;
+	try{
+		l_cmd.push_back(cmd);		
+		empty.signal();
+	}
+	catch(omni_thread_fatal& ex)
+	{
+		ostringstream err;
+		err << "omni_thread_fatal exception signaling omni_condition, err=" << ex.error << ends;
+		//WARN_STREAM << "event_list::push_back(): " << err.str() << endl;	
+		printf("cmd_list::push_back(): %s", err.str().c_str());
+	}			
+	catch(Tango::DevFailed& ex)
+	{
+		ostringstream err;
+		err << "exception  signaling omni_condition: '" << ex.errors[0].desc << "'" << ends;
+		//WARN_STREAM << "event_list::push_back(): " << err.str() << endl;	
+		printf("cmd_list::push_back: %s", err.str().c_str());
+		Tango::Except::print_exception(ex);	
+	}		
+	catch(...)
+	{
+		printf("cmd_list::push_back(): catched unknown exception  signaling omni_condition!!");	
+	}	
+	this->unlock();
+}
+
+const cmd_t cmd_list::pop_front(void)
+{
+	this->lock();
+	//omni_mutex_lock l((omni_mutex)this);	//call automatically unlock on destructor and on exception
+	try{
+		while (l_cmd.empty() == true)
+			empty.wait();					//wait release mutex while is waiting, then reacquire when signaled
+	}
+	catch(omni_thread_fatal& ex)
+	{
+		ostringstream err;
+		err << "omni_thread_fatal exception waiting on omni_condition, err=" << ex.error << ends;
+		printf("cmd_list::pop_front(): %s", err.str().c_str());
+		this->unlock();
+		sleep(1);
+		cmd_t c;
+		return c;
+	}			
+	catch(Tango::DevFailed& ex)
+	{
+		ostringstream err;
+		err << "exception  waiting on omni_condition: '" << ex.errors[0].desc << "'" << ends;	
+		printf("cmd_list::pop_front: %s", err.str().c_str());
+		Tango::Except::print_exception(ex);
+		this->unlock();
+		sleep(1);
+		cmd_t c;
+		return c;		
+	}		
+	catch(...)
+	{
+		printf("cmd_list::pop_front(): catched unknown exception  waiting on omni_condition!!");
+		this->unlock();
+		sleep(1);
+		cmd_t c;
+		return c;		
+	}			
+	/*const*/ cmd_t cmd;
+
+	cmd = *(l_cmd.begin());
+	//cout << "event_list::pop_front: " << e.name << " value=" << e.value[0] << endl; 
+	l_cmd.pop_front();
+
+	this->unlock();
+	return cmd;
+}
+
+void cmd_list::clear(void)
+{
+	//this->lock();
+	l_cmd.clear();
+	//this->unlock();
+}
diff --git a/src/cmd_thread.h b/src/cmd_thread.h
new file mode 100644
index 0000000..4405122
--- /dev/null
+++ b/src/cmd_thread.h
@@ -0,0 +1,85 @@
+/*
+ *cmd_thread.h
+ *
+ * $Author: graziano $
+ *
+ * $Revision: 1.2 $
+ *
+ * $Log: cmd_thread.h,v $
+ * Revision 1.2  2008-11-17 13:10:36  graziano
+ * command action can be: without arguments or with string argument
+ *
+ * Revision 1.1  2008/11/10 10:53:31  graziano
+ * thread for execution of commands
+ *
+ * Revision 1.2  2008/10/07 14:03:07  graziano
+ * added handling of multi axis groups and spindle groups
+ *
+ * Revision 1.1  2008/09/30 09:46:32  graziano
+ * first version
+ *
+ * Revision 1.3  2008/04/23 15:00:57  graziano
+ * small code cleanings
+ *
+ *
+ *
+ * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
+ *           Strada Statale 14 - km 163,5 in AREA Science Park
+ *           34012 Basovizza, Trieste ITALY
+ */
+
+#ifndef CMD_THREAD_H
+#define CMD_THREAD_H
+
+#ifndef _LOGA
+#define _LOGA	1
+#endif		// _LOGA
+
+//#define CMD_THREAD_EXIT	"EXIT"
+#define CMD_COMMAND		1
+#define CMD_RESPONSE	2
+#define CMD_THREAD_EXIT	3
+
+#include <omnithread.h>
+#include <tango.h>
+#include "Alarm.h"
+
+struct cmd_t
+{
+	short cmd_id;
+	long call_id;
+	string arg_s1;
+	string arg_s2;
+	string arg_s3;
+	bool arg_b;
+	long dp_add;
+};
+
+class cmd_list : public omni_mutex {
+	public:
+		cmd_list(void): empty(this) {}
+		~cmd_list(void) {}
+		void push_back(cmd_t& cmd);
+		const cmd_t pop_front(void);
+		void clear(void);
+	protected:
+		list<cmd_t> l_cmd;
+	private:
+		omni_condition empty;
+};
+
+class cmd_thread : public omni_thread{
+	public:
+		cmd_thread();
+		~cmd_thread();
+		cmd_list list;
+		//omni_mutex::omni_mutex *mutex_dp;
+	protected:
+		void run(void *);
+	private:
+		Tango::DeviceProxy *dp;
+};
+
+#endif	/* CMD_THREAD_H */
+
+/* EOF */
diff --git a/src/event_table.cpp b/src/event_table.cpp
new file mode 100644
index 0000000..846e5cb
--- /dev/null
+++ b/src/event_table.cpp
@@ -0,0 +1,549 @@
+/*
+ * event_table.cpp
+ *
+ * $Author: graziano $
+ *
+ * $Revision: 1.5 $
+ *
+ * $Log: event_table.cpp,v $
+ *
+ *
+ * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
+ *           Strada Statale 14 - km 163,5 in AREA Science Park
+ *           34012 Basovizza, Trieste ITALY
+ */
+
+#include <sys/time.h>
+#include <tango.h>
+#include "event_table.h"
+
+static const char __FILE__rev[] = __FILE__ " $Revision: 1.5 $";
+
+/*
+ * event_list class methods
+ */
+void event_list::push_back(bei_t& e)
+{
+	this->lock();
+
+	try{
+		l_event.push_back(e);		
+		empty.signal();
+	}
+	catch(omni_thread_fatal& ex)
+	{
+		ostringstream err;
+		err << "omni_thread_fatal exception signaling omni_condition, err=" << ex.error << ends;
+		//WARN_STREAM << "event_list::push_back(): " << err.str() << endl;	
+		printf("event_list::push_back(): %s", err.str().c_str());
+	}			
+	catch(Tango::DevFailed& ex)
+	{
+		ostringstream err;
+		err << "exception  signaling omni_condition: '" << ex.errors[0].desc << "'" << ends;
+		//WARN_STREAM << "event_list::push_back(): " << err.str() << endl;	
+		printf("event_list::push_back: %s", err.str().c_str());
+		Tango::Except::print_exception(ex);	
+	}		
+	catch(...)
+	{
+		//WARN_STREAM << "event_list::push_back(): catched unknown exception!!" << endl;
+		printf("event_list::push_back(): catched unknown exception  signaling omni_condition!!");	
+	}	
+	this->unlock();
+}
+
+const bei_t event_list::pop_front(void)
+{
+	this->lock();
+	//omni_mutex_lock l((omni_mutex)this);	//call automatically unlock on destructor and on exception
+	try{
+		while (l_event.empty() == true)
+			empty.wait();					//wait release mutex while is waiting, then reacquire when signaled
+	}
+	catch(omni_thread_fatal& ex)
+	{
+		ostringstream err;
+		err << "omni_thread_fatal exception waiting on omni_condition, err=" << ex.error << ends;
+		//WARN_STREAM << "event_list::pop_front(): " << err.str() << endl;	
+		printf("event_list::pop_front(): %s", err.str().c_str());
+		bei_t e;
+		this->unlock();
+		sleep(1);
+		return(e);
+	}			
+	catch(Tango::DevFailed& ex)
+	{
+		ostringstream err;
+		err << "exception  waiting on omni_condition: '" << ex.errors[0].desc << "'" << ends;
+		//WARN_STREAM << "event_list::pop_front(): " << err.str() << endl;	
+		printf("event_list::pop_front: %s", err.str().c_str());
+		Tango::Except::print_exception(ex);
+		bei_t e;
+		this->unlock();
+		sleep(1);
+		return(e);		
+	}		
+	catch(...)
+	{
+		//WARN_STREAM << "event_list::pop_front(): catched unknown exception!!" << endl;
+		printf("event_list::pop_front(): catched unknown exception  waiting on omni_condition!!");
+		bei_t e;
+		this->unlock();
+		sleep(1);
+		return(e);		
+	}			
+	/*const*/ bei_t e;
+
+	e = *(l_event.begin());
+
+	l_event.pop_front();
+
+	this->unlock();
+	return(e);
+}
+
+void event_list::clear(void)
+{
+	//this->lock();
+	l_event.clear();
+	//this->unlock();
+}
+
+list<bei_t> event_list::show(void)
+{
+	list<bei_t> el;
+	
+	this->lock();
+	el = l_event;
+	this->unlock();
+	return(el);
+}
+
+
+/*
+ * event class methods
+ */
+event::event(string& s, value_t& v, Tango::TimeVal& t) : \
+						 name(s), value(v), ts(t)
+{
+	const char *c = name.c_str();
+	int j = 0;
+	int num_slashes=3;	//not FQDN
+	if(name.find("tango://") != string::npos)	//FQDN!!
+		num_slashes = 6;
+	while (*c) {
+		if (*c == '/')
+			j++;
+		if (j < num_slashes)
+			device.push_back(*c);
+		else if (*c != '/')
+			attribute.push_back(*c);
+		c++;
+	}
+	type = -1;
+	eid = 0;
+	err_counter = 0;
+	valid = false;
+}
+
+event::event(string& s) : name(s)
+{
+	const char *c = name.c_str();
+	int j = 0;
+	int num_slashes=3;	//not FQDN
+	if(name.find("tango://") != string::npos)	//FQDN!!
+		num_slashes = 6;
+	while (*c) {
+		if (*c == '/')
+			j++;
+		if (j < num_slashes)
+			device.push_back(*c);
+		else if (*c != '/')
+			attribute.push_back(*c);
+		c++;
+	}
+	type = -1;
+	eid = 0;
+	err_counter = 0;
+	valid = false;	
+}
+
+void event::push_alarm(string& n)
+{
+	m_alarm.push_back(n);
+}
+
+void event::pop_alarm(string& n)
+{
+	vector<string>::iterator it = find(m_alarm.begin(), m_alarm.end(), n);
+	m_alarm.erase(it);
+	
+}
+
+bool event::operator==(const event& e)
+{
+	return(name == e.name);
+}
+
+bool event::operator==(const string& s)
+{
+	return(name == s);
+}
+
+/*
+ * event_table class methods
+ */
+void event_table::push_back(event e)
+{
+	v_event.push_back(e);
+}
+
+void event_table::show(void)
+{
+	DEBUG_STREAM << "events found:" << endl;
+	if (v_event.empty() == false) {
+		vector<event>::iterator i = v_event.begin();
+		while (i != v_event.end()) {
+			DEBUG_STREAM << "\t" << i->name << endl;
+			i++;
+		}
+	}
+}
+
+unsigned int event_table::size(void)
+{
+	return(v_event.size());
+}
+
+void event_table::init_proxy(void)	throw(vector<string> &)
+{
+	vector<string> proxy_error;
+	if (v_event.empty() == false) {
+		for (vector<event>::iterator i = v_event.begin(); \
+				 i != v_event.end(); i++) 
+		{
+			try	{
+				i->dp = new Tango::DeviceProxy(i->device);
+			} catch(Tango::DevFailed& e)
+			{
+				ostringstream o;
+				o << "new DeviceProxy() failed for " \
+					<< i->device << ends;
+				ERROR_STREAM << o.str() << endl;
+				//throw o.str();
+				proxy_error.push_back(o.str());
+			}
+		}
+	}
+	if(!proxy_error.empty())
+		throw proxy_error;	
+}
+
+void event_table::free_proxy(void)
+{
+	if (v_event.empty() == false) {
+		for (vector<event>::iterator i = v_event.begin(); \
+				 i != v_event.end(); i++) {
+			try{
+				delete i->dp;
+				DEBUG_STREAM << gettime().tv_sec << " event_table::free_proxy(): deleted proxy " << i->device << endl;
+			} catch(...)
+			{
+				ERROR_STREAM << "event_table::free_proxy: exception deleting proxy of event: " << i->name << endl;
+			}
+		}
+	}
+}
+
+void event_table::subscribe(EventCallBack& ecb) throw(vector<string> &)//throw(string&)
+{
+	vector<string> subscribe_error;
+	if (v_event.empty() == false) {
+		for (vector<event>::iterator i = v_event.begin(); \
+				 i != v_event.end(); i++) {
+			try {
+				i->eid = i->dp->subscribe_event(i->attribute, \
+												Tango::CHANGE_EVENT, \
+												&ecb, i->filter);
+			} catch (...) {
+				ostringstream o;
+				o << "subscribe_event() failed for " \
+					<< i->name << ends;
+				ERROR_STREAM << o.str() << endl;
+				//throw o.str();
+				subscribe_error.push_back(o.str());
+			}
+		}
+	}
+	if(!subscribe_error.empty())
+		throw subscribe_error;
+}
+
+void event_table::unsubscribe(void) throw(string&)
+{
+	ostringstream o;
+	if (v_event.empty() == false) {
+		for (vector<event>::iterator i = v_event.begin(); \
+				 i != v_event.end(); i++) {
+			try {
+				i->dp->unsubscribe_event(i->eid);
+				DEBUG_STREAM << gettime().tv_sec << " event_table::unsubscribe(): unsubscribed " << i->name << endl;
+			} catch (Tango::DevFailed& e) {
+				o << " unsubscribe_event() failed for "	<< i->name << " err=" << e.errors[0].desc;
+				ERROR_STREAM << gettime().tv_sec << " event_table::unsubscribe(): " << o.str() << endl;
+				//throw o.str();
+			} catch (...) {
+				o << " unsubscribe_event() failed for " \
+					<< i->name;
+				ERROR_STREAM << gettime().tv_sec << " event_table::unsubscribe(): " << o.str() << endl;
+				//throw o.str();
+			}
+		}
+	}
+	if(o.str().length() > 0)
+		throw o.str();
+}
+
+void event_table::update_events(bei_t &e) throw(string&)
+{
+	//LOG_STREAM << "event_table::update_events(bei_t &e): Entering..." << endl ;
+	vector<event>::iterator found = \
+			find(v_event.begin(), v_event.end(), e.ev_name);
+
+	if (found == 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);
+				//LOG_STREAM << __FUNCTION__ << " event "<< e.ev_name << " not found, trying without domain: " << ev_name_str_no_domain << endl;
+				found = \
+							find(v_event.begin(), v_event.end(), ev_name_str_no_domain);
+			}
+			if (found == v_event.end() && pos_slash != string::npos)
+			{
+				ev_name_str = ev_name_str.substr(pos_slash + 1);//remove FQDN
+				//LOG_STREAM << __FUNCTION__ << " event "<< e.ev_name << " not found, trying without fqdn: " << ev_name_str << endl;
+				found = \
+							find(v_event.begin(), v_event.end(), ev_name_str);
+			}
+		}
+		if (found == v_event.end())
+		{
+			/*
+			 * shouldn't happen!!!
+			 */
+			ostringstream o;
+			o << "event_table::update_events(): event '" \
+				<< e.ev_name << "' not found! error=" << e.msg << ends;
+				ERROR_STREAM << o.str() << endl;
+			//cerr << o.str() << endl;
+			throw o.str();
+		}
+	}
+
+	if (found != v_event.end())
+	{
+		found->value = e.value;
+		found->ts = e.ts;
+		found->type = e.type;
+	}
+}
+
+
+/*
+ * EventCallBack class methods
+ */
+EventCallBack::EventCallBack(void)
+{
+	e_ptr = NULL;
+}
+
+EventCallBack::~EventCallBack(void)
+{
+	e_ptr = NULL;
+}
+
+void EventCallBack::push_event(Tango::EventData* ev)
+{
+	string temp_name;	
+	bei_t e;
+	
+	try {
+		if (!ev->err) {
+			
+#if 0//TANGO_VER >= 711
+ 			string ev_name_str(ev->attr_name);
+ 			string::size_type pos = ev_name_str.find("tango://");
+ 			if (pos != string::npos)
+ 			{
+ 				pos = ev_name_str.find('/',8);
+ 				ev_name_str = ev_name_str.substr(pos + 1);
+ 			}
+ 			e.ev_name = ev_name_str.c_str();
+#else			
+			e.ev_name = ev->attr_name;
+#endif
+			e.ts = ev->attr_value->time;
+			extract_values(ev->attr_value, e.value, e.type);
+		} else {
+#if 0//TANGO_VER >= 711
+ 			string ev_name_str(ev->attr_name);
+ 			string::size_type pos = ev_name_str.find("tango://");
+ 			if (pos != string::npos)
+ 			{
+ 				pos = ev_name_str.find('/',8);
+ 				ev_name_str = ev_name_str.substr(pos + 1);
+ 			}
+ 			temp_name = ev_name_str.c_str() + string(".") + ev->event;
+#else
+			temp_name = ev->attr_name + string(".") + ev->event;		//TODO: BUG IN TANGO: part of attr_name after first dot continues in field event
+#endif
+			size_t pos_change = temp_name.find(".change");
+			if(pos_change != string::npos)
+			{
+				temp_name = temp_name.substr(0,pos_change);
+			}
+			ostringstream o;
+			o << "Tango error for '" << temp_name << "'=" << ev->errors[0].desc.in() << ends;			
+			e.ev_name = temp_name;
+			e.type = TYPE_TANGO_ERR;
+			//e.ev_name = INTERNAL_ERROR;
+			//e.type = -1;
+			e.msg = o.str();
+		}
+	} 
+	catch (string &err) {
+		e.msg = err + " for event '" + ev->attr_name + "'";
+		e.ev_name = ev->attr_name;
+		e.type = TYPE_GENERIC_ERR;
+		//e.value.i = 0;
+		e.ts = gettime();
+		//cerr << o.str() << endl;		
+	} catch(Tango::DevFailed& Terr)
+	{
+		ostringstream o;
+		o << "Event exception for'" \
+			<< ev->attr_name << "' error=" << Terr.errors[0].desc << ends;
+		e.ev_name = ev->attr_name;
+		e.type = TYPE_GENERIC_ERR;
+		//e.value.i = 0;
+		e.ts = gettime();
+		e.msg = o.str();
+		//cerr << o.str() << endl;		
+	}	
+	catch (...) {
+		ostringstream o;
+		o << "Generic Event exception for'" \
+			<< ev->attr_name << "'" << ends;
+		e.ev_name = ev->attr_name;
+		e.type = TYPE_GENERIC_ERR;
+		//e.value.i = 0;
+		e.ts = gettime();
+		e.msg = o.str();
+		//cerr << o.str() << endl;		
+	}
+	e_ptr->push_back(e);
+}  /* push_event() */
+
+void EventCallBack::extract_values(Tango::DeviceAttribute *attr_value, vector<double> &val, int &type)
+{
+	Tango::DevState stval;
+	vector<Tango::DevState> v_st;
+#if TANGO_VER >= 600
+	vector<Tango::DevULong> v_ulo;
+#endif
+	vector<Tango::DevUChar> v_uch;
+	vector<Tango::DevShort> v_sh;
+	vector<Tango::DevUShort> v_ush;
+	vector<Tango::DevLong> v_lo;
+	vector<Tango::DevDouble> v_do;
+	vector<Tango::DevFloat> v_fl;
+	vector<Tango::DevBoolean> v_bo;
+
+	if (attr_value->get_type() == Tango::DEV_UCHAR) {
+		*(attr_value) >> v_uch;
+		for(vector<Tango::DevUChar>::iterator it = v_uch.begin(); it != v_uch.end(); it++)
+			val.push_back((double)(*it));		//convert all to double
+		type = Tango::DEV_UCHAR;		
+	} else if (attr_value->get_type() == Tango::DEV_SHORT) {
+		*(attr_value) >> v_sh;
+		for(vector<Tango::DevShort>::iterator  it = v_sh.begin(); it != v_sh.end(); it++)
+			val.push_back((double)(*it));		//convert all to double				
+		type = Tango::DEV_SHORT;
+	} else if (attr_value->get_type() == Tango::DEV_USHORT) {
+		*(attr_value) >> v_ush;
+		for(vector<Tango::DevUShort>::iterator  it = v_ush.begin(); it != v_ush.end(); it++)
+			val.push_back((double)(*it));		//convert all to double						
+		type = Tango::DEV_USHORT;			
+	} else if (attr_value->get_type() == Tango::DEV_LONG) {
+		*(attr_value) >> v_lo;
+		for(vector<Tango::DevLong>::iterator  it = v_lo.begin(); it != v_lo.end(); it++)
+			val.push_back((double)(*it));		//convert all to double						
+		type = Tango::DEV_LONG;
+	} else if (attr_value->get_type() == Tango::DEV_STATE) {
+		//*(attr_value) >> v_st;		//doesn't work in tango 5
+		*(attr_value) >> stval;
+		v_st.push_back(stval);
+		for(vector<Tango::DevState>::iterator it = v_st.begin(); it != v_st.end(); it++)
+			val.push_back((double)(*it));		//convert all to double
+		type = Tango::DEV_STATE;
+#if TANGO_VER >= 600	
+	} else if (attr_value->get_type() == Tango::DEV_ULONG) {
+		*(attr_value) >> v_ulo;
+		for(vector<Tango::DevULong>::iterator  it = v_ulo.begin(); it != v_ulo.end(); it++)
+			val.push_back((double)(*it));		//convert all to double						
+		type = Tango::DEV_ULONG;
+#endif  //TANGO_VER >= 600								
+	} else if (attr_value->get_type() == Tango::DEV_DOUBLE) {
+		*(attr_value) >> v_do;
+		for(vector<Tango::DevDouble>::iterator  it = v_do.begin(); it != v_do.end(); it++)
+			val.push_back((double)(*it));		//convert all to double						
+		type = Tango::DEV_DOUBLE;
+	} else if (attr_value->get_type() == Tango::DEV_FLOAT) {
+		*(attr_value) >> v_fl;
+		for(vector<Tango::DevFloat>::iterator  it = v_fl.begin(); it != v_fl.end(); it++)
+			val.push_back((double)(*it));		//convert all to double						
+		type = Tango::DEV_FLOAT;
+	} else if (attr_value->get_type() == Tango::DEV_BOOLEAN) {
+		*(attr_value) >> v_bo;
+		for(vector<Tango::DevBoolean>::iterator  it = v_bo.begin(); it != v_bo.end(); it++)
+			val.push_back((double)(*it));		//convert all to double		
+		type = Tango::DEV_BOOLEAN;
+	}
+	else {
+		ostringstream o;
+		o << "unknown type" << ends;
+		throw o.str();
+	}	
+}
+
+void EventCallBack::init(event_list* e)
+{
+	e_ptr = e;
+}
+
+
+Tango::TimeVal gettime(void)
+{
+	struct timeval tv;
+	struct timezone tz;
+	Tango::TimeVal t;
+	
+	gettimeofday(&tv, &tz);
+	t.tv_sec = tv.tv_sec;
+	t.tv_usec = tv.tv_usec;
+	t.tv_nsec = 0;
+	return t;
+}
+
+/* EOF */
diff --git a/src/event_table.h b/src/event_table.h
new file mode 100644
index 0000000..395c9ec
--- /dev/null
+++ b/src/event_table.h
@@ -0,0 +1,144 @@
+/*
+ * event_table.h
+ *
+ * $Author: graziano $
+ *
+ * $Revision: 1.2 $
+ *
+ * $Log: event_table.h,v $
+ *
+ *
+ * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
+ *           Strada Statale 14 - km 163,5 in AREA Science Park
+ *           34012 Basovizza, Trieste ITALY
+ */
+
+#ifndef EVENT_TABLE_H
+#define EVENT_TABLE_H
+
+#include <iostream>
+#include <string>
+#include <map>
+
+#include <tango.h>
+
+
+using namespace std;
+
+#define INTERNAL_ERROR	"internal_error"
+#define TYPE_TANGO_ERR		-2
+#define TYPE_GENERIC_ERR	-3		
+
+class event;
+class event_list;
+class event_table;
+class EventCallBack;
+
+typedef vector<Tango::DevDouble> value_t;
+
+/*
+ * basic event type
+ */
+class event {
+	public:
+		string name,					/* event name */
+					 device,				/* device name */
+					 attribute;			/* attribute name */
+		value_t value;				/* event value */
+		Tango::TimeVal ts;		/* event timestamp */
+		int type,							/* attribute data type */
+				counter,					/* molteplicita' */
+				err_counter;					/* molteplicita' errore */				
+		//map<string, string> m_alarm;
+		vector<string> m_alarm;
+		bool valid;
+		
+		Tango::DeviceProxy *dp;
+		unsigned int eid;
+		vector<string> filter;
+		/*
+		 * methods
+		 */
+		event(string& s, value_t& v, Tango::TimeVal& t);
+		event(string& s);
+		event() {}
+		~event() {}
+		void push_alarm(string& n);
+		void pop_alarm(string& n);
+//		bool event::operator==(const event& e);		//TODO: gcc 4 problem??
+		bool operator==(const event& e);
+//		bool event::operator==(const string& s);	//TODO: gcc 4 problem??
+		bool operator==(const string& s);
+	protected:
+	private:
+};
+
+typedef struct basic_event_info_s {
+	string ev_name;
+	value_t value;
+	int type;
+	Tango::TimeVal ts;
+	string msg;
+} bei_t;
+	
+/*
+ * here the event callback handler will store the relevant
+ * events info coming from subscribed events for the
+ * processing thread
+ */
+class event_list : public omni_mutex {
+	public:
+		event_list(void): full(this), empty(this) {}
+		~event_list(void) {}
+		void push_back(bei_t& e);
+		const bei_t pop_front(void);
+		void clear(void);
+		list<bei_t> show(void);
+	protected:
+		list<bei_t> l_event;
+	private:
+		omni_condition full,
+									 empty;
+};
+
+/*
+ * store all the events
+ */
+class event_table : public event , Tango::LogAdapter {
+	public:
+		event_table(Tango::DeviceImpl *s):Tango::LogAdapter(s) {}
+		~event_table(void) {}
+		void push_back(event e);
+		void show(void);
+		unsigned int size(void);
+		void init_proxy(void)  throw(vector<string> &);
+		void free_proxy(void);
+		void subscribe(EventCallBack& ecb) throw(vector<string> &);//throw(string&);
+		void unsubscribe(void) throw(string&);
+		void update_events(bei_t& e) throw(string&);
+		vector<event> v_event;
+	protected:
+	private:
+};  /* class event_table */
+
+
+/*
+ * event callback
+ */
+class EventCallBack : public Tango::CallBack {
+	public:
+		EventCallBack(void);
+		~EventCallBack(void);
+		void push_event(Tango::EventData* ev);
+		void init(event_list* e);
+		void extract_values(Tango::DeviceAttribute *attr_value, vector<double> &val, int &type);
+	private:
+		event_list* e_ptr;
+};
+
+/*
+ * utility function
+ */
+Tango::TimeVal gettime(void);
+
+#endif	/* EVENT_TABLE_H */
diff --git a/src/formula_grammar.h b/src/formula_grammar.h
new file mode 100644
index 0000000..f3bc90a
--- /dev/null
+++ b/src/formula_grammar.h
@@ -0,0 +1,291 @@
+/*
+ * formula_grammar.h
+ *
+ * $Author: graziano $
+ *
+ * $Revision: 1.5 $ 
+ *
+ * $Log: formula_grammar.h,v $
+ *
+ *
+ * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
+ *           Strada Statale 14 - km 163,5 in AREA Science Park
+ *           34012 Basovizza, Trieste ITALY
+ */
+#ifndef FORMULA_GRAMMAR_H_
+#define FORMULA_GRAMMAR_H_
+
+
+//#define BOOST_SPIRIT_NO_TREE_NODE_COLLAPSING  //test trying to have node also if formula of type (ev/ev/ev/ev) 27/02/2008
+
+#if BOOST_VERSION  < 103600  
+#ifndef BOOST_SPIRIT_THREADSAFE 
+#define BOOST_SPIRIT_THREADSAFE 
+#endif
+#endif
+
+#if BOOST_VERSION  < 103600     
+#include <boost/spirit/core.hpp>
+#include <boost/spirit/tree/ast.hpp>
+using namespace boost::spirit;
+#else
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_ast.hpp>
+using namespace boost::spirit::classic;	
+#endif
+				//for ast parse trees (in tree_formula)
+//#include <boost/spirit/symbols/symbols.hpp>				//for symbol table
+
+using namespace std;  
+
+
+
+#ifdef _ACCESS_NODE_D
+/*typedef char const*                    iterator_t;       
+typedef node_val_data_factory<unsigned int>    factory_t;
+typedef tree_match<iterator_t, factory_t>        parse_tree_match_t;   
+typedef tree_parse_info<iterator_t, factory_t>    tree_parse_t;   
+typedef parse_tree_match_t::tree_iterator        iter_t;*/
+typedef node_val_data<iterator_t, unsigned int>    node_t;
+typedef tree_node<node_t>                tree_node_t;
+
+/*static unsigned int stat_tmp;
+static void Save_Stat (unsigned int val)
+{
+	stat_tmp = val;
+}
+
+static void Assign_Stat (tree_node_t & node, const iterator_t & begin, const iterator_t & end)
+{
+	node.value.value(stat_tmp);
+}*/
+
+unsigned int stat_tmp;
+struct Save_Stat
+{   
+	void operator () (unsigned int val) const
+	{
+		stat_tmp = val;
+	}
+};
+
+struct Assign_Stat 
+{  
+	void operator () (tree_node_t & node, const iterator_t & begin, const iterator_t & end) const
+	{
+		node.value.value(stat_tmp);
+	}
+};
+
+#endif //_ACCESS_NODE_D
+struct formula_grammar : public grammar<formula_grammar>
+{
+    static const int val_rID = 1;
+    static const int val_hID = 2; 
+    static const int val_stID = 3;    
+    static const int event_ID = 4;
+    static const int nameID = 5;
+    static const int indexID = 6; 
+    static const int funcID = 7;
+    static const int logical_exprID = 8;
+    static const int bitwise_exprID = 9;
+    static const int equality_exprID = 10;
+    static const int compare_exprID = 11;
+    static const int add_exprID = 12;
+    static const int mult_exprID = 13;
+    static const int expr_atomID = 14;
+    static const int shift_exprID = 15;
+    static const int unary_exprID = 16;
+    
+    symbols<unsigned int> tango_states;           
+    
+	formula_grammar() 
+	{
+		tango_states.add("ON", (unsigned int)Tango::ON);
+		tango_states.add("OFF", (unsigned int)Tango::OFF);
+		tango_states.add("CLOSE", (unsigned int)Tango::CLOSE);
+		tango_states.add("OPEN", (unsigned int)Tango::OPEN);
+		tango_states.add("INSERT", (unsigned int)Tango::INSERT);
+		tango_states.add("EXTRACT", (unsigned int)Tango::EXTRACT);
+		tango_states.add("MOVING", (unsigned int)Tango::MOVING);
+		tango_states.add("STANDBY", (unsigned int)Tango::STANDBY);
+		tango_states.add("FAULT", (unsigned int)Tango::FAULT);
+		tango_states.add("INIT", (unsigned int)Tango::INIT);
+		tango_states.add("RUNNING", (unsigned int)Tango::RUNNING);
+		tango_states.add("ALARM", (unsigned int)Tango::ALARM);
+		tango_states.add("DISABLE", (unsigned int)Tango::DISABLE);
+		tango_states.add("UNKNOWN", (unsigned int)Tango::UNKNOWN);
+	}   
+   
+    template <typename ScannerT>
+    struct definition
+    {
+        
+/*        typedef
+            scanner<
+                typename ScannerT::iterator_t,
+                scanner_policies<
+                    typename ScannerT::iteration_policy_t,
+                    ast_match_policy<
+                        typename ScannerT::match_policy_t::iterator_t,
+                        typename ScannerT::match_policy_t::factory_t
+                    >,
+                    typename ScannerT::action_policy_t
+                >
+            > ast_scanner;*/  
+
+		//typedef scanner_list< ScannerT, phrase_scanner_t > scanners; //try using multiple scanners
+
+        definition(formula_grammar const& self)
+        {      
+            symbol
+            	=	(alnum_p | '.' | '_' | '-' | '+')				//any alpha numeric char plus '.', '_', '-', '+'
+            	;
+            //------------------------------ALARM NAME--------------------------------------	
+            name
+#if BOOST_VERSION  < 103600              
+            	=	token_node_d[
+#else            	
+            	=	reduced_node_d[
+#endif
+            			lexeme_d[							//needed to ignore "space_p" (skip white spaces) evaluating name
+            				!("tango://" >> (+symbol) >> ':' >> uint_p >> "/")	//eventually match FQDN
+            				>> (+symbol) >> '/' >> (+symbol)
+            				>> '/' >> (+symbol) >> '/' >> (+symbol)
+            			]
+            		]
+//            	=	repeat_p(3)[(+symbol) >> ch_p('/')] >> (+symbol) 
+            	; 
+            index
+            	= 	inner_node_d[ch_p('[') >> uint_p >> ch_p(']')]
+            	;
+            //------------------------------FORMULA--------------------------------------	   
+			val_r
+#if BOOST_VERSION  < 103600              
+				=	leaf_node_d[real_p]
+#else            	
+            	=	reduced_node_d[real_p]
+#endif				
+				;
+			val_h
+#if BOOST_VERSION  < 103600  		
+				=	token_node_d[(str_p("0x") >> hex_p)]		//token_node_d here to create only one node with all chars
+#else            	
+            	=	reduced_node_d[(str_p("0x") >> hex_p)]		//token_node_d here to create only one node with all chars
+#endif					
+				;
+			val_st
+				=
+#ifndef _ACCESS_NODE_D				
+					token_node_d[self.tango_states]				//match only group defined in sym_grp symbol table				            	   
+#else				
+					//access_node_d[self.tango_states[&Save_Stat]][&Assign_Stat]	//save Tango::state value in node
+					access_node_d[self.tango_states[Save_Stat()]][Assign_Stat()]	//save Tango::state value in node
+#endif //_ACCESS_NODE_D					
+            	;
+
+			event_
+				=	name
+					>> !(index)
+				;				
+				
+			top = logical_expr
+				;	
+
+            logical_expr
+                = 	bitwise_expr
+                 	>> *(	(root_node_d[str_p("&&")] >> bitwise_expr)
+                 		|	(root_node_d[str_p("||")] >> bitwise_expr)
+                 		)
+                 ;
+
+            bitwise_expr
+                = 	equality_expr
+                	 >> *(	(root_node_d[ch_p('&')] >> equality_expr)
+                	 	| 	(root_node_d[ch_p('|')] >> equality_expr) 
+                	 	| 	(root_node_d[ch_p('^')] >> equality_expr)
+                	 	)
+                ;
+                
+            equality_expr
+                = 	compare_expr
+                	>> *(	(root_node_d[str_p("==")] >> compare_expr)
+                		| 	(root_node_d[str_p("!=")] >> compare_expr)
+                		)
+				;
+
+            compare_expr
+                = 	shift_expr
+                 	>> *(	(root_node_d[str_p("<=")] >> add_expr) 
+                 		| 	(root_node_d[str_p(">=")] >> add_expr) 
+                 		|	(root_node_d[ch_p('<')] >> add_expr) 
+                 		| 	(root_node_d[ch_p('>')] >> add_expr) 
+                 		)
+                 ;
+			shift_expr
+                = 	add_expr
+                	>> *(	(root_node_d[str_p("<<")] >> add_expr)
+                		| 	(root_node_d[str_p(">>")] >> add_expr)
+                		)
+                ;
+            add_expr
+                = 	mult_expr
+                	>> *(	(root_node_d[ch_p('+')] >> mult_expr)
+                		|	(root_node_d[ch_p('-')] >> mult_expr)
+                		)
+                ;
+            mult_expr
+                = 	expr_atom 
+                	>> *(	(root_node_d[ch_p('*')] >> expr_atom)
+                		| 	(root_node_d[ch_p('/')] >> expr_atom)
+                		)
+                ;
+            function
+            	=	root_node_d[str_p("abs")] >> (inner_node_d[ch_p('(') >> logical_expr >> ')'])
+            	;
+            unary_expr
+            	=	(	(root_node_d[ch_p('+')] >> expr_atom)
+            		 |	(root_node_d[ch_p('-')] >> expr_atom)
+            		 |	(root_node_d[ch_p('!')] >> expr_atom)
+            		)
+            	;
+            expr_atom
+                =	//val_h | val_r	              
+					event_
+                	| unary_expr					
+					| val_h | val_r | val_st
+               		| function										     
+                	//| (inner_node_d[ch_p('(') >> logical_expr >> ')'])
+                	| (discard_node_d[ch_p('(')] >> logical_expr >> discard_node_d[ch_p(')')])
+                	| unary_expr
+
+                ;
+        }
+        
+        rule<ScannerT> top;
+        //rule<ScannerT> symbol;
+        rule<typename lexeme_scanner<ScannerT>::type> symbol;					//neede to use lexeme_d in rule name
+        rule<ScannerT, parser_context<>, parser_tag<val_rID> > val_r;
+        rule<ScannerT, parser_context<>, parser_tag<val_hID> > val_h;
+        rule<ScannerT, parser_context<>, parser_tag<val_stID> > val_st;        
+        rule<ScannerT, parser_context<>, parser_tag<event_ID> > event_;
+        rule<ScannerT, parser_context<>, parser_tag<logical_exprID> > logical_expr;
+        rule<ScannerT, parser_context<>, parser_tag<bitwise_exprID> > bitwise_expr;
+        rule<ScannerT, parser_context<>, parser_tag<shift_exprID> > shift_expr;
+        rule<ScannerT, parser_context<>, parser_tag<equality_exprID> > equality_expr;
+        rule<ScannerT, parser_context<>, parser_tag<compare_exprID> > compare_expr;
+        rule<ScannerT, parser_context<>, parser_tag<add_exprID> > add_expr;
+        rule<ScannerT, parser_context<>, parser_tag<mult_exprID> > mult_expr;
+		rule<ScannerT, parser_context<>, parser_tag<unary_exprID> > unary_expr;        
+        rule<ScannerT, parser_context<>, parser_tag<expr_atomID> > expr_atom;
+        rule<ScannerT, parser_context<>, parser_tag<funcID> > function;
+		rule<ScannerT, parser_context<>, parser_tag<nameID> > name;
+		rule<ScannerT, parser_context<>, parser_tag<indexID> > index;
+
+        rule<ScannerT> const&
+        start() const { return top; }      
+        
+    };
+};
+
+#endif /*FORMULA_GRAMMAR_H_*/
diff --git a/src/log_thread.cpp b/src/log_thread.cpp
new file mode 100644
index 0000000..21ac238
--- /dev/null
+++ b/src/log_thread.cpp
@@ -0,0 +1,510 @@
+/*
+ * log_thread.cpp
+ *
+ * $Author: graziano $
+ *
+ * $Revision: 1.7 $
+ *
+ * $Log: log_thread.cpp,v $
+ *
+ *
+ * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
+ *           Strada Statale 14 - km 163,5 in AREA Science Park
+ *           34012 Basovizza, Trieste ITALY
+ */
+
+#include "log_thread.h"
+//#define _DEBUG_LOG_THREAD 0
+//#define _DEBUG_LOG_THREAD 1
+
+static const char __FILE__rev[] = __FILE__ " $Revision: 1.7 $";
+
+/*
+ * log_thread::log_thread()
+ */
+log_thread::log_thread(string dbhost, string dbuser, string dbpw, string dbname, int dbport, string instance_name/*, Alarm_ns::Alarm *p*/)/*: Tango::LogAdapter(p)*/
+{
+	//p_Alarm = p;
+	m_dbhost = dbhost;
+	m_dbuser = dbuser;
+	m_dbpw = dbpw;
+	m_dbname = dbname;
+	m_dbport = dbport;
+	m_instance_name = instance_name;
+	
+	//cout << __FILE__rev << endl;
+
+	ostringstream err;
+	if(!mysql_init(&log_db))
+	{
+		err << "mysql_init failed for log DB" << ends;
+		throw err.str();
+	}
+	my_bool my_auto_reconnect=1;
+	if(mysql_options(&log_db,MYSQL_OPT_RECONNECT,&my_auto_reconnect) !=0)
+	{
+		err << "mysql auto reconnection error for log DB: " << mysql_error(&log_db) << ends;;
+		throw err.str();
+	}
+
+	if(!mysql_real_connect(&log_db, m_dbhost.c_str(), m_dbuser.c_str(), m_dbpw.c_str(), m_dbname.c_str(), m_dbport, NULL, 0))
+	{
+		err << "mysql_real_connect failed for log DB" << ends;
+		throw err.str();
+	}
+}
+
+/*
+ * log_thread::~log_thread()
+ */
+log_thread::~log_thread()
+{
+	//p_Alarm = NULL;
+	mysql_close(&log_db);
+}
+
+/*
+ * log_thread::run()
+ */
+void log_thread::run(void *)
+{
+	while (true) {
+		/*
+		 * pop_front() will wait() on condition variable
+		 */
+		 try
+		 {
+			alm_log_t a = al_list.pop_front();
+			if ((a.name == LOG_THREAD_EXIT) && \
+					(a.time_s == LOG_THREAD_EXIT_TIME))
+				break;
+
+			write_db(a);
+		}
+		catch(omni_thread_fatal& ex)
+		{
+			ostringstream err;
+			err << "omni_thread_fatal exception running log thread, err=" << ex.error << ends;
+			//WARN_STREAM << "alarm_thread::run(): " << err.str() << endl;	
+			printf("log_thread::run(): %s", err.str().c_str());
+		}			
+		catch(Tango::DevFailed& ex)
+		{
+			ostringstream err;
+			err << "exception running log thread: '" << ex.errors[0].desc << "'" << ends;
+			//WARN_STREAM << "alarm_thread::run(): " << err.str() << endl;	
+			printf("log_thread::run(): %s", err.str().c_str());
+			Tango::Except::print_exception(ex);
+		}		
+		catch(...)
+		{
+			//WARN_STREAM << "alarm_thread::run(): catched unknown exception!!" << endl;
+			printf("log_thread::run(): catched unknown exception!!");
+		}		
+	}
+}  /* alarm_thread::run() */
+
+void log_thread::log_alarm_db(alm_log_t& a)
+{
+	al_list.push_back(a);
+}
+
+void log_thread::write_db(alm_log_t& a)
+{
+	ostringstream query_str;
+	ostringstream err_msg;
+	
+	char *values_escaped = new char [2 * a.values.length() + 1];
+	char *name_escaped = new char [2 * a.name.length() + 1];
+	char *formula_escaped = new char [2 * a.formula.length() + 1];
+	char *grp_escaped = new char [2 * a.grp.length() + 1];
+	char *msg_escaped = new char [2 * a.msg.length() + 1];
+	char *level_escaped = new char [2 * a.level.length() + 1];
+	char *action_escaped = new char [2 * a.action.length() + 1];
+	char *instance_escaped = new char [2 * m_instance_name.length() + 1];
+	mysql_real_escape_string(&log_db, values_escaped, a.values.c_str(), a.values.length());
+	mysql_real_escape_string(&log_db, name_escaped, a.name.c_str(), a.name.length());
+	mysql_real_escape_string(&log_db, formula_escaped, a.formula.c_str(), a.formula.length());
+	mysql_real_escape_string(&log_db, grp_escaped, a.grp.c_str(), a.grp.length());	
+	mysql_real_escape_string(&log_db, msg_escaped, a.msg.c_str(), a.msg.length());	
+	mysql_real_escape_string(&log_db, level_escaped, a.level.c_str(), a.level.length());
+	mysql_real_escape_string(&log_db, action_escaped, a.action.c_str(), a.action.length());
+	mysql_real_escape_string(&log_db, instance_escaped, m_instance_name.c_str(), m_instance_name.length());
+	
+	char *tmp_name_escaped;
+	ostringstream tmp_names;
+	for(vector<string>::iterator it=a.alm_list.begin(); it!=a.alm_list.end(); it++)
+	{
+		tmp_name_escaped = new char [2 * it->length() + 1];
+		mysql_real_escape_string(&log_db, tmp_name_escaped, it->c_str(), it->length());
+		tmp_names << " AND " << DESC_COL_NAME << "!='" << tmp_name_escaped << "'";
+		delete [] tmp_name_escaped;
+	}
+			
+	switch (a.type_log)
+	{
+		case TYPE_LOG_STATUS:
+		//example: 
+		//INSERT INTO alarms 
+		//		(time_sec, time_usec, status, ack, id_description, attr_values) 
+		//		SELECT 1234567890, 123456, 'ALARM', 'NACK', id_description, 'ev/ev/ev/ev2=1.;' 	//take id_description
+		//			FROM description 															//from description
+		//			WHERE name='al/al/al/al' AND active=1 AND instance='alarm_1';				//where this alarm is active
+			if((a.status.size() == 0) || (a.ack.size() == 0) || (strlen(name_escaped) == 0))
+			{
+				err_msg << "log_thread::write_db(): ERROR some mandatory values adding alarm status are empty: status=" << 
+						a.status << " ack=" << a.ack << " name=" << name_escaped << ends;
+				break;
+			}
+			query_str << 
+				"INSERT INTO " << m_dbname << "." << STAT_TABLE_NAME <<
+					" (" << STAT_COL_TIME_S << "," << STAT_COL_TIME_U << "," <<		
+						STAT_COL_STATUS << "," << STAT_COL_ACK << "," <<
+						STAT_COL_DESC_ID <<	"," << STAT_COL_VALUES <<		
+					") SELECT " << a.time_s << "," << a.time_us << ",'" <<				
+						a.status << "','" << a.ack << "'," << 
+						DESC_COL_ID << ",'" << values_escaped << "'" <<								
+						" FROM " << DESC_TABLE_NAME <<
+						" WHERE " << DESC_COL_NAME << "='" << name_escaped << "'" <<
+							" AND " << DESC_COL_ACTIVE << "=" << ALARM_ACTIVE <<
+							" AND " << DESC_COL_INSTANCE << "='" << instance_escaped << "'" <<
+				ends;
+			break;
+		case TYPE_LOG_DESC_ADD:
+		//example: 
+		//INSERT INTO description 
+		//		(name, active, time_sec, formula, time_threashold, level, grp, msg, action, instance) 
+		//		SELECT 'al/al/al/al', 'alarm_1', 1, 1234567890, '(ev/ev/ev/evn < 1.2)', 'log', 'gr_none', 'msg'
+		//			FROM description 
+		//			WHERE name='al/al/al/al' AND active=1 AND instance='alarm_1'	//look if exists an alarm with the same name and active
+		//			HAVING count(*) = 0;											//insert only if it does not  exist 
+			if((strlen(name_escaped) == 0) || (strlen(instance_escaped) == 0) || (strlen(formula_escaped) == 0) || (strlen(level_escaped) == 0) ||
+				 (strlen(grp_escaped) == 0) || (strlen(msg_escaped) == 0))
+			{
+				err_msg << "log_thread::write_db(): ERROR some mandatory values adding alarm description are empty: name=" << 
+					name_escaped << " instance=" << instance_escaped << " formula=" << formula_escaped << " level=" << level_escaped << " grp=" << grp_escaped << 
+					" msg=" << msg_escaped << ends;
+				break;
+			}			
+			query_str << 
+				"INSERT INTO " << m_dbname << "." << DESC_TABLE_NAME <<
+					" (" << DESC_COL_NAME << "," << DESC_COL_ACTIVE << "," <<		
+						DESC_COL_TIME_S << "," << DESC_COL_FORMULA << "," << 
+						DESC_COL_TIME_THRESHOLD << "," << DESC_COL_LEVEL << "," << 
+						DESC_COL_GRP << "," << DESC_COL_MSG << "," << 
+						DESC_COL_ACTION << "," << DESC_COL_INSTANCE << "," <<
+						DESC_COL_SILENT_TIME <<
+					") SELECT '" << name_escaped << "'," << ALARM_ACTIVE << "," <<
+						a.time_s << ",'" << formula_escaped << "','" <<				
+					 	a.time_threshold << "','" << level_escaped << "','" << 
+					 	grp_escaped << "','" <<	msg_escaped << "','" <<	
+					 	action_escaped << "','" <<instance_escaped << "','" <<
+					 	a.silent_time << "'" <<
+						" FROM " << DESC_TABLE_NAME <<
+						" WHERE " << DESC_COL_NAME << "='" << name_escaped << "'" << 
+							" AND " << DESC_COL_ACTIVE << "=" << ALARM_ACTIVE <<
+							" AND " << DESC_COL_INSTANCE << "='" << instance_escaped << "'" <<
+						" HAVING COUNT(*) = 0" << 
+				ends;
+			break;
+		case TYPE_LOG_DESC_DIS:
+		//example: 
+		//UPDATE description 								
+		//		SET active=0 													//set active to 0
+		//		WHERE name='al/al/al/al' AND active=1 AND instance='alarm_1';	//in alarm specified that is active
+			if(strlen(name_escaped) == 0 || strlen(instance_escaped) == 0)
+			{
+				err_msg << "log_thread::write_db(): ERROR some mandatory values setting non-active alarm are empty: name=" << 
+					name_escaped << " instance=" << instance_escaped << ends;
+				break;
+			}		
+			query_str << 
+				"UPDATE " << m_dbname << "." << DESC_TABLE_NAME <<
+					" SET " << DESC_COL_ACTIVE << "=" << ALARM_REMOVED <<		
+					" WHERE " << DESC_COL_NAME << "='" << name_escaped << "'" << 
+							" AND " << DESC_COL_ACTIVE << "=" << ALARM_ACTIVE <<
+							" AND " << DESC_COL_INSTANCE << "='" << instance_escaped << "'" <<
+				ends;
+			break;	
+		case TYPE_LOG_DESC_REM:
+		//example: 
+		//DELETE FROM description 								
+		//		WHERE name='al/al/al/al' AND active=1 AND instance='alarm_1';	//in alarm specified that is active
+			if(strlen(name_escaped) == 0 || strlen(instance_escaped) == 0)
+			{
+				err_msg << "log_thread::write_db(): ERROR some mandatory values removing alarm are empty: name=" << 
+					name_escaped << " instance=" << instance_escaped<< ends;
+				break;
+			}			
+			query_str << 
+				"DELETE FROM " << m_dbname << "." << DESC_TABLE_NAME <<
+					" WHERE " << DESC_COL_NAME << "='" << name_escaped << "'" << 
+							" AND " << DESC_COL_ACTIVE << "=" << ALARM_ACTIVE <<
+							" AND " << DESC_COL_INSTANCE << "='" << instance_escaped << "'" <<
+				ends;
+			break;	
+		case TYPE_LOG_DESC_SYNC:
+		//example:
+		//UPDATE description 
+		//		SET active=0 
+		//		WHERE name='al/al/al/al' 					//disable this alarm
+		//			AND active=1 							//if it is active and
+		//			AND instance='alarm_1'					//for this alarm instance and
+		//			AND (formula!='(ev/ev/ev/ev > 1)'		//or formula is changed
+		//				OR time_threashold!=5				//or time_threshold is changed		
+		//				OR level!='log' 					//or level is changed
+		//				OR grp!='gr_none' 					//or grp is changed
+		//				OR msg!='message');					//or msg is changed
+		//				OR action!='act/act/act/act');		//or action is changed		
+			query_str << 
+				"UPDATE " << m_dbname << "." << DESC_TABLE_NAME <<
+					" SET " << DESC_COL_ACTIVE << "=" << ALARM_REMOVED <<		
+					" WHERE " << DESC_COL_NAME << "='" << name_escaped << "'" << 
+							" AND " << DESC_COL_ACTIVE << "=" << ALARM_ACTIVE <<
+							" AND " << DESC_COL_INSTANCE << "='" << instance_escaped << "'" <<
+							" AND (" << DESC_COL_FORMULA << "!='" << formula_escaped << "'" <<
+									" OR " << DESC_COL_TIME_THRESHOLD << "!='" << a.time_threshold << "'" <<							
+									" OR " << DESC_COL_LEVEL << "!='" << level_escaped << "'" <<
+									" OR " << DESC_COL_GRP << "!='" << grp_escaped << "'" <<
+									" OR " << DESC_COL_MSG << "!='" << msg_escaped << "'" <<
+									" OR " << DESC_COL_ACTION << "!='" << action_escaped << "'" <<									
+							")" <<
+				ends;
+			break;
+		case TYPE_LOG_DESC_UPD_OLD:
+		//example:
+		//UPDATE description 
+		//		SET active=0 
+		//		WHERE name!='al1/al1/al1/al1' 					//disable every alarm not in this list
+		//			AND name !='al2/al2/al2/al2'
+		//			AND name !=...
+		//			AND active=1 								//if it is active
+		//			AND instance='alarm_1'
+			query_str << 
+				"UPDATE " << m_dbname << "." << DESC_TABLE_NAME <<
+					" SET " << DESC_COL_ACTIVE << "=" << ALARM_REMOVED <<		
+					" WHERE " << DESC_COL_ACTIVE << "=" << ALARM_ACTIVE << 
+						" AND " << DESC_COL_INSTANCE << "='" << instance_escaped << "'" <<
+						tmp_names.str() <<
+				ends;
+			break;
+		case TYPE_LOG_DESC_UPDATE:
+		//example:
+		//UPDATE description
+		//		SET time_sec=1234567890, time_threashold=1, level='log', grp='gr_none', msg='msg'
+		//		WHERE name='al1/al1/al1/al1' 					//
+		//			AND active=1 								//
+		//			AND instance='alarm_1'
+			query_str <<
+				"UPDATE " << m_dbname << "." << DESC_TABLE_NAME <<
+					" SET " << DESC_COL_TIME_S << "=" << a.time_s <<
+					" , " << DESC_COL_TIME_THRESHOLD << "=" << a.time_threshold <<
+					" , " << DESC_COL_LEVEL << "='" << level_escaped << "'" <<
+					" , " << DESC_COL_GRP << "='" << grp_escaped << "'" <<
+					" , " << DESC_COL_MSG << "='" << msg_escaped << "'" <<
+					" , " << DESC_COL_ACTION << "='" << action_escaped << "'" <<
+					" , " << DESC_COL_SILENT_TIME << "='" << a.silent_time << "'" <<
+					" WHERE " << DESC_COL_NAME << "='" << name_escaped << "'" <<
+						" AND " << DESC_COL_ACTIVE << "=" << ALARM_ACTIVE <<
+						" AND " << DESC_COL_INSTANCE << "='" << instance_escaped << "'" <<
+				ends;
+			break;		
+	}				
+	delete [] values_escaped;
+	delete [] name_escaped; 	
+	delete [] formula_escaped; 	
+	delete [] grp_escaped; 	
+	delete [] msg_escaped; 	 
+	delete [] level_escaped;
+	delete [] action_escaped;	
+	delete [] instance_escaped;
+	if(err_msg.str().size() != 0)
+	{
+		cout << err_msg.str();
+		return;
+	} 		
+	if(mysql_query(&log_db, query_str.str().c_str()))
+	{
+		err_msg << " log_thread::write_db(): ERROR in query=" << query_str.str() << endl;
+		//cout << err_msg.str();
+		//throw err_msg.str();
+	}
+
+	if(err_msg.str().size() != 0)
+	{
+		cout << gettime().tv_sec << err_msg.str();
+		return;
+	} 
+	int num_rows = mysql_affected_rows(&log_db);
+#ifdef _DEBUG_LOG_THREAD	
+	cout << gettime().tv_sec << " log_thread::write_db(): Affected rows=" << num_rows << " in query=" << query_str.str() << endl;	
+#else
+	if(((a.type_log == TYPE_LOG_STATUS) || (a.type_log == TYPE_LOG_DESC_DIS)) && (num_rows != 1))
+		cout << gettime().tv_sec << " log_thread::write_db(): Error num_rows=" << num_rows << " in query=" << query_str.str() << endl;			
+#endif
+}
+
+void log_thread::get_alarm_list(vector<string> &al_list)
+{
+	ostringstream query_str;
+	ostringstream err_msg;
+	MYSQL_RES *res;
+	MYSQL_ROW row;
+	
+	char *instance_escaped = new char [2 * m_instance_name.length() + 1];
+	mysql_real_escape_string(&log_db, instance_escaped, m_instance_name.c_str(), m_instance_name.length());	
+//	unsigned int num_fields;
+//	unsigned int i;	
+	
+	//example:
+	//SELECT description 
+	//		CONCAT('\t',name,'\t',formula, 
+	//			'\t',IFNULL(time_threshold,0),'\t',level,
+	//			'\t',grp,'\t','\"',IFNULL(msg,''),'\"',
+	//			'\t',IFNULL(action,''))
+	//		FROM alarm.description
+	//		WHERE active=1
+	//			AND instance='alarm_1'
+	query_str << 
+		"SELECT" <<
+			" CONCAT('\t', " << DESC_COL_NAME << ",'\t'," << DESC_COL_FORMULA <<
+				",'\t'," << "IFNULL(" << DESC_COL_TIME_THRESHOLD << ",0)" << ",'\t'," << DESC_COL_LEVEL <<
+				",'\t'," << "IFNULL(" << DESC_COL_SILENT_TIME << ",-1)" <<
+				",'\t'," << DESC_COL_GRP <<	",'\t','\"'," << "IFNULL(" << DESC_COL_MSG << ",'')" <<
+				",'\"','\t'," << "IFNULL(" << DESC_COL_ACTION << ",';')" << ")" <<
+			" FROM " << m_dbname << "." << DESC_TABLE_NAME <<
+			" WHERE " << DESC_COL_ACTIVE << "=" << ALARM_ACTIVE <<
+				" AND " << DESC_COL_INSTANCE << "='" << instance_escaped << "'" <<
+		ends;
+	delete [] instance_escaped;		
+	if(mysql_query(&log_db, query_str.str().c_str()))
+	{
+		err_msg << "log_thread::get_alarm_list(): ERROR in query=" << query_str.str() << endl;
+		//cout << err_msg.str();
+		throw err_msg.str();
+	}	
+//#define _DEBUG_LOG_THREAD 1
+#ifdef _DEBUG_LOG_THREAD	
+	else
+		cout << gettime().tv_sec << " log_thread::get_alarm_list(): Success with query=" << query_str.str() << endl;
+#endif 		//_DEBUG_LOG_THREAD	
+	
+	res = mysql_use_result(&log_db);
+	if(res == NULL)
+	{
+		if(*mysql_error(&log_db))
+			err_msg << "log_thread::get_alarm_list(): ERROR while retrieving result, err=" << mysql_error(&log_db) << endl;
+		else
+			err_msg << "log_thread::get_alarm_list(): ERROR while retrieving result" << endl;
+		//cout << err_msg.str();
+		throw err_msg.str();
+	}
+	//num_fields = mysql_num_fields(res);
+	while ((row = mysql_fetch_row(res)))
+	{
+		al_list.push_back(row[0]);
+
+#ifdef _DEBUG_LOG_THREAD	
+		cout << gettime().tv_sec << " log_thread::get_alarm_list(): Retrieved line: " << row[0] << endl;
+#endif 		//_DEBUG_LOG_THREAD		
+	}	
+	mysql_free_result(res);
+}
+/*
+ * alarm_list class methods
+ */
+void alarm_list::push_back(alm_log_t& a)
+{
+	this->lock();
+	try{
+		l_alarm.push_back(a);		
+		empty.signal();
+	}
+	catch(omni_thread_fatal& ex)
+	{
+		ostringstream err;
+		err << "omni_thread_fatal exception signaling omni_condition, err=" << ex.error << ends;
+		//WARN_STREAM << "alarm_list::push_back(): " << err.str() << endl;	
+		printf("alarm_list::push_back(): %s", err.str().c_str());
+	}			
+	catch(Tango::DevFailed& ex)
+	{
+		ostringstream err;
+		err << "exception  signaling omni_condition: '" << ex.errors[0].desc << "'" << ends;
+		//WARN_STREAM << "alarm_list::push_back(): " << err.str() << endl;	
+		printf("alarm_list::push_back: %s", err.str().c_str());
+		Tango::Except::print_exception(ex);	
+	}		
+	catch(...)
+	{
+		//WARN_STREAM << "alarm_list::push_back(): catched unknown exception!!" << endl;
+		printf("alarm_list::push_back(): catched unknown exception  signaling omni_condition!!");	
+	}			
+	this->unlock();
+}
+
+const alm_log_t alarm_list::pop_front(void)
+{
+	this->lock();
+	//omni_mutex_lock l((omni_mutex)this);	//call automatically unlock on destructor and on exception
+	try{
+		while (l_alarm.empty() == true)
+			empty.wait();					//wait release mutex while is waiting, then reacquire when signaled
+	}
+	catch(omni_thread_fatal& ex)
+	{
+		ostringstream err;
+		err << "omni_thread_fatal exception waiting on omni_condition, err=" << ex.error << ends;
+		//WARN_STREAM << "alarm_list::pop_front(): " << err.str() << endl;	
+		printf("alarm_list::pop_front(): %s", err.str().c_str());
+		alm_log_t a;
+		this->unlock();
+		sleep(1);
+		return(a);
+	}			
+	catch(Tango::DevFailed& ex)
+	{
+		ostringstream err;
+		err << "exception  waiting on omni_condition: '" << ex.errors[0].desc << "'" << ends;
+		//WARN_STREAM << "alarm_list::pop_front(): " << err.str() << endl;	
+		printf("alarm_list::pop_front: %s", err.str().c_str());
+		Tango::Except::print_exception(ex);
+		alm_log_t a;
+		this->unlock();
+		sleep(1);
+		return(a);		
+	}		
+	catch(...)
+	{
+		//WARN_STREAM << "alarm_list::pop_front(): catched unknown exception!!" << endl;
+		printf("alarm_list::pop_front(): catched unknown exception  waiting on omni_condition!!");
+		alm_log_t a;
+		this->unlock();
+		sleep(1);
+		return(a);		
+	}			
+	/*const*/ alm_log_t a;
+
+	a = *(l_alarm.begin());
+	l_alarm.pop_front();
+
+	this->unlock();
+	return(a);
+}
+
+void alarm_list::clear(void)
+{
+	//this->lock();
+	l_alarm.clear();
+	//this->unlock();
+}
+
+list<alm_log_t> alarm_list::show(void)
+{
+	list<alm_log_t> al;
+	
+	this->lock();
+	al = l_alarm;
+	this->unlock();
+	return(al);
+}
diff --git a/src/log_thread.h b/src/log_thread.h
new file mode 100644
index 0000000..17ab492
--- /dev/null
+++ b/src/log_thread.h
@@ -0,0 +1,133 @@
+/*
+ * log_thread.h
+ *
+ * $Author: graziano $
+ *
+ * $Revision: 1.4 $
+ *
+ * $Log: log_thread.h,v $
+ *
+ *
+ * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
+ *           Strada Statale 14 - km 163,5 in AREA Science Park
+ *           34012 Basovizza, Trieste ITALY
+ */
+
+#ifndef LOG_THREAD_H
+#define LOG_THREAD_H
+
+#include <omnithread.h>
+#include <tango.h>
+#include <Alarm.h>
+#include <mysql.h>
+
+#define LOG_THREAD_EXIT				"log_thread_exit"
+#define LOG_THREAD_EXIT_TIME		1
+
+//############# DB ############
+//#define LOG_DB_NAME			"alarm"
+//######## ALARM_DESC ########
+#define DESC_TABLE_NAME			"description"
+#define DESC_COL_ID				"id_description"
+#define DESC_COL_NAME			"name"
+#define DESC_COL_INSTANCE		"instance"
+#define DESC_COL_ACTIVE			"active"
+#define DESC_COL_TIME_S			"time_sec"
+#define DESC_COL_FORMULA		"formula"
+#define DESC_COL_SILENT_TIME	"silent_time"
+#define DESC_COL_TIME_THRESHOLD	"time_threshold"
+#define DESC_COL_LEVEL			"level"
+#define DESC_COL_GRP			"grp"
+#define DESC_COL_MSG			"msg"
+#define DESC_COL_ACTION			"action"
+//######## ALARM_STATUS #######
+#define STAT_TABLE_NAME		"alarms"
+#define STAT_COL_ID			"id_alarms"
+#define STAT_COL_TIME_S		"time_sec"
+#define STAT_COL_TIME_U		"time_usec"
+#define STAT_COL_STATUS		"status"
+#define STAT_COL_ACK		"ack"
+#define STAT_COL_DESC_ID	DESC_COL_ID
+#define STAT_COL_VALUES		"attr_values"
+
+
+#define TYPE_LOG_STATUS			1
+#define TYPE_LOG_DESC_ADD		2
+#define TYPE_LOG_DESC_DIS		3
+#define TYPE_LOG_DESC_REM		4
+#define TYPE_LOG_DESC_SYNC		5
+#define TYPE_LOG_DESC_UPD_OLD	6
+#define TYPE_LOG_DESC_UPDATE	7
+
+#define ALARM_ACTIVE		1
+#define ALARM_REMOVED		0
+
+
+typedef struct {
+	unsigned int type_log;
+	unsigned int time_s;
+	unsigned int time_us;
+	unsigned int time_threshold;
+	int silent_time;
+	string name;
+	string status;
+	string ack;
+	string level;
+	string grp;
+	string msg;
+	string formula;
+	string action;
+	string values;
+	vector<string> alm_list;
+} alm_log_t;
+
+/*
+ * here Alarm insert data to log, log_thread process data
+ * and store in db
+ */
+class alarm_list : public omni_mutex {
+	public:
+		alarm_list(void): full(this), empty(this) {}
+		~alarm_list(void) {}
+		void push_back(alm_log_t& a);
+		const alm_log_t pop_front(void);
+		void clear(void);
+		list<alm_log_t> show(void);
+	protected:
+		list<alm_log_t> l_alarm;
+	private:
+		omni_condition full,
+					empty;
+};
+
+
+class log_thread : public omni_thread/*, public Tango::LogAdapter*/ 
+{
+	public:
+		log_thread(string dbhost, string dbuser, string dbpw, string dbname, int dbport, string instance_name/*, Alarm_ns::Alarm *p*/);
+		~log_thread();
+		
+		void log_alarm_db(alm_log_t& a);
+		void get_alarm_list(vector<string> &al_list);		
+		
+	protected:
+		void run(void *);
+	private:
+		//Alarm_ns::Alarm *p_Alarm;
+		MYSQL log_db;
+		
+		alarm_list al_list;	
+		
+		string m_dbhost;
+		string m_dbuser;
+		string m_dbpw;
+		string m_dbname;
+		int m_dbport;
+		string m_instance_name;
+		
+		void write_db(alm_log_t& a);
+};
+
+#endif	/* LOG_THREAD_H */
+
+/* EOF */
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..3a94797
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,88 @@
+/*----- PROTECTED REGION ID(Alarm::main.cpp) ENABLED START -----*/
+static const char *RcsId = "$Id:  $";
+//=============================================================================
+//
+// file :        main.cpp
+//
+// description : C++ source for the Alarm device server main.
+//               The main rule is to initialise (and create) the Tango
+//               system and to create the DServerClass singleton.
+//               The main should be the same for every Tango device server.
+//
+// project :     alarm
+//
+// 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/>.
+// 
+// $Author:  $
+//
+// $Revision:  $
+// $Date:  $
+//
+// $HeadURL:  $
+//
+//=============================================================================
+//                This file is generated by POGO
+//        (Program Obviously used to Generate tango Object)
+//=============================================================================
+
+
+#include <tango.h>
+
+
+int main(int argc,char *argv[])
+{
+
+	Tango::Util *tg;
+	try
+	{
+		// Initialise the device server
+		//----------------------------------------
+		tg = Tango::Util::init(argc,argv);
+
+		/*
+		 * serialize all calls
+		 * BY_DEVICE, BY_CLASS, BY_PROCESS
+		 */
+		//tg->set_serial_model(Tango::BY_PROCESS);
+		
+		// Create the device server singleton 
+		//	which will create everything
+		//----------------------------------------
+		tg->server_init(false);
+
+		// Run the endless loop
+		//----------------------------------------
+		cout << "Ready to accept request" << endl;
+		tg->server_run();
+	}
+	catch (bad_alloc)
+	{
+		cout << "Can't allocate memory to store device object !!!" << endl;
+		cout << "Exiting" << endl;
+	}
+	catch (CORBA::Exception &e)
+	{
+		Tango::Except::print_exception(e);
+		
+		cout << "Received a CORBA_Exception" << endl;
+		cout << "Exiting" << endl;
+	}
+	tg->server_cleanup();
+	return(0);
+}
+
+
+/*----- PROTECTED REGION END -----*/	//	Alarm::main.cpp
diff --git a/src/update-thread.cpp b/src/update-thread.cpp
new file mode 100644
index 0000000..313913e
--- /dev/null
+++ b/src/update-thread.cpp
@@ -0,0 +1,65 @@
+/*
+ * update-thread.cpp
+ *
+ * $Author: claudio $
+ *
+ * $Revision: 1.2 $
+ *
+ * $Log: update-thread.cpp,v $
+ * Revision 1.2  2013-03-06 10:38:43  claudio
+ * commented out debug print statements
+ *
+ * Revision 1.1  2008-11-10 10:54:09  graziano
+ * thread for update of alarms with time threshold > 0
+ *
+ *
+ *
+ *
+ * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
+ *           Strada Statale 14 - km 163,5 in AREA Science Park
+ *           34012 Basovizza, Trieste ITALY
+ */
+
+#include "update-thread.h"
+static const char __FILE__rev[] = __FILE__ " $Revision: 1.2 $";
+
+/*
+ * alarm_thread::alarm_thread()
+ */
+update_thread::update_thread(Alarm_ns::Alarm *p) : p_Alarm(p) 
+{
+	//cout << __FILE__rev << endl;
+}
+
+/*
+ * alarm_thread::~alarm_thread()
+ */
+update_thread::~update_thread()
+{
+	p_Alarm = NULL;
+}
+
+/*
+ * alarm_thread::run()
+ */
+void update_thread::run(void *)
+{
+	//printf("update_thread::run(): running...\n");
+	unsigned int pausasec, pausanano;
+	pausasec=1;
+	pausanano = 100000000;		//0.1 sec
+	omni_thread::sleep(pausasec,pausanano);
+	while (!p_Alarm->abortflag) {
+		try
+		{
+			omni_thread::sleep(pausasec,pausanano);
+			p_Alarm->timer_update();
+			//printf("update_thread::run(): TIMER!!\n");
+		}		
+		catch(...)
+		{
+			printf("update_thread::run(): catched unknown exception!!\n");
+		}		
+	}
+	//cout << "update_thread::run(): exiting!" << endl;
+}  /* update_thread::run() */
diff --git a/src/update-thread.h b/src/update-thread.h
new file mode 100644
index 0000000..ebf7102
--- /dev/null
+++ b/src/update-thread.h
@@ -0,0 +1,39 @@
+/*
+ * alarm-thread.h
+ *
+ * $Author: graziano $
+ *
+ * $Revision: 1.1 $
+ *
+ * $Log: update-thread.h,v $
+ * Revision 1.1  2008-11-10 10:54:09  graziano
+ * thread for update of alarms with time threshold > 0
+ *
+ *
+ *
+ *
+ * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
+ *           Strada Statale 14 - km 163,5 in AREA Science Park
+ *           34012 Basovizza, Trieste ITALY
+ */
+
+#ifndef UPDATE_THREAD_H
+#define UPDATE_THREAD_H
+
+#include <omnithread.h>
+#include <tango.h>
+#include <Alarm.h>
+
+class update_thread : public omni_thread {
+	public:
+		update_thread(Alarm_ns::Alarm *p);
+		~update_thread();
+	protected:
+		void run(void *);
+	private:
+		Alarm_ns::Alarm *p_Alarm;
+};
+
+#endif	/* UPDATE_THREAD_H */
+
+/* EOF */
-- 
GitLab