From f30388c4342e928139ca789b32f74bae4fdc7075 Mon Sep 17 00:00:00 2001
From: gscalamera <graziano.scalamera@elettra.eu>
Date: Fri, 10 Mar 2017 09:32:46 +0100
Subject: [PATCH] Support for key=value configuration string

---
 src/Alarm.cpp       |  12 ++---
 src/alarm_grammar.h | 116 ++++++++++++++++++++++++++++----------------
 src/alarm_table.cpp |  66 +++++++++++++++----------
 src/alarm_table.h   |   2 +-
 4 files changed, 122 insertions(+), 74 deletions(-)

diff --git a/src/Alarm.cpp b/src/Alarm.cpp
index 7c66d61..bd604ab 100644
--- a/src/Alarm.cpp
+++ b/src/Alarm.cpp
@@ -1479,7 +1479,7 @@ void Alarm::load(Tango::DevString argin)
 			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
 
 	alarms.save_alarm_conf_db(alm.attr_name, 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
+			alm.formula, alm.time_threshold, alm.grp2str(), alm.lev, alm.msg, alm.cmd_name_a, alm.cmd_name_n, alm.silent_time);	//but if it fails remove it from table
 
 
 
@@ -1762,9 +1762,9 @@ Tango::DevVarStringArray *Alarm::configured(Tango::DevString argin)
 		{
 			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;
+			os << ai->second.ts.tv_sec << "\t" << ai->second.name << "\t" /*TODO<< KEY(FORMULA_KEY)*/ << ai->second.formula << "\t" << KEY(DELAY_KEY) << ai->second.time_threshold <<
+			"\t" << KEY(LEVEL_KEY) << ai->second.lev << "\t" << KEY(SILENT_TIME_KEY) << ai->second.silent_time << "\t" << KEY(GROUP_KEY) << ai->second.grp2str() << "\t" << KEY(MESSAGE_KEY) << ai->second.msg << "\t" <<
+			KEY(ON_COMMAND_KEY) << ai->second.cmd_name_a << "\t" << KEY(OFF_COMMAND_KEY) << ai->second.cmd_name_n << ends;
 			alarm_filtered.push_back(os.str());
 		}
 	}  /* for */
@@ -2052,7 +2052,7 @@ void Alarm::modify(Tango::DevString argin)
     else
     {
        	ostringstream o;
-		o << __func__<<": Parsing Failed, syntax error stopped at " << string(alm.formula_tree.stop, alarm_string.end()) << ends; //TODO
+		o << __func__<<": Parsing Failed, parsed up to '" << string(alarm_string.begin(), alm.formula_tree.stop) << "' not parsed '" << string(alm.formula_tree.stop, alarm_string.end()) << "'" << ends; //TODO
        	DEBUG_STREAM << o.str() << endl;
        	Tango::Except::throw_exception( \
 				(const char*)"Parsing Failed!", \
@@ -2365,7 +2365,7 @@ void Alarm::load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn)
     else
     {
        	ostringstream o;
-		o << "Alarm::load_alarm(): Parsing Failed, syntax error stopped at " << string(alm.formula_tree.stop, alarm_string.end()) << ends; //TODO
+		o << "Alarm::load_alarm(): Parsing Failed, '" << string(alarm_string.begin(), alm.formula_tree.stop) << "' parsed ok, BUT '" << string(alm.formula_tree.stop, alarm_string.end()) << "' not parsed" << ends; //TODO
        	DEBUG_STREAM << o.str() << endl;
        	Tango::Except::throw_exception( \
 				(const char*)"Parsing Failed!", \
diff --git a/src/alarm_grammar.h b/src/alarm_grammar.h
index f974699..0b2a578 100644
--- a/src/alarm_grammar.h
+++ b/src/alarm_grammar.h
@@ -67,6 +67,17 @@
 #include "event_table.h"
 #include "formula_grammar.h"
 
+#define NAME_KEY			"name"
+#define FORMULA_KEY			"formula"
+#define DELAY_KEY			"time_threshold"
+#define LEVEL_KEY			"level"
+#define SILENT_TIME_KEY		"silent_time"
+#define GROUP_KEY			"group"
+#define MESSAGE_KEY			"message"
+#define ON_COMMAND_KEY		"on_command"
+#define OFF_COMMAND_KEY		"off_command"
+#define KEY(S_VAL)  		S_VAL "="
+
 ////////////////////////////////////////////////////////////////////////////
 using namespace std; 
 #if BOOST_VERSION  < 103600 
@@ -179,56 +190,47 @@ struct alarm_parse : public grammar<alarm_parse>
             					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[option])
+			;
 
-            		>> discard_node_d[msg]						//save msg in alarm_t
+            option
+				=	discard_node_d[time_threshold] |
+					discard_node_d[level] |
+					discard_node_d[silent_time] |
+					discard_node_d[group] |
+					discard_node_d[msg] |
+					discard_node_d[on_command] |
+					discard_node_d[off_command]
+			;
 
-					>> 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 '.', '_', '-', '+'
             	;	
+            symbol_attr_name
+            	=	alnum_p | '_'									//any alpha numeric char plus '_'
+            	;
             name
             	=	(+symbol) >> '/' >> (+symbol) 
-            		>> '/' >> (+symbol) >> '/' >> (+symbol)
+            		>> '/' >> (+symbol) >> '/' >> (+symbol_attr_name)
+            	;
+            name_alm
+            	=	(+symbol_attr_name)
             	; 
 			//------------------------------LEVEL--------------------------------------	
 			level
-				=	lexeme_d[(+alnum_p)]		//match only possible levels?? (fault, log, ...)
+				=	discard_node_d[str_p(KEY(LEVEL_KEY))] >>
+					//lexeme_d[(+alnum_p)]		//match only possible levels?? (fault, log, ...)
+					//(+(alnum_p-'\t'))
+					(str_p("fault") | str_p("warning") | str_p("log"))
+					[
+						assign_a(self.m_alarm.lev)		//save level in alarm_t
+					]
 				;
 			//------------------------------GROUP--------------------------------------	
 			group
-				=	self.sym_grp				//match only group defined in sym_grp symbol table
+				=	discard_node_d[str_p(KEY(GROUP_KEY))] >>
+					self.sym_grp				//match only group defined in sym_grp symbol table
 					[
 						var(self.m_alarm.grp) |= arg1			//using phoenix::var
 					]
@@ -242,7 +244,8 @@ struct alarm_parse : public grammar<alarm_parse>
 				;
 			//------------------------------MESSAGE--------------------------------------	
 			msg
-				=	ch_p('"') 
+				=	discard_node_d[str_p(KEY(MESSAGE_KEY))] >>
+					ch_p('"')
 					>> (+(anychar_p - '\"')) 		//one ore more char except '"'
 							[
 								assign_a(self.m_alarm.msg)
@@ -251,24 +254,53 @@ struct alarm_parse : public grammar<alarm_parse>
 				;
 			//---------------------------TIME THRESHOLD----------------------------------	
 			time_threshold 
-				=	uint_p
+				=	discard_node_d[str_p(KEY(DELAY_KEY))] >>
+					(uint_p
 					[
 						assign_a(self.m_alarm.time_threshold)
 					]
+					| epsilon_p)
 				;
 			//-----------------------------SILENT TIME------------------------------------
 			silent_time
-				=	int_p
+				= discard_node_d[str_p(KEY(SILENT_TIME_KEY))] >>
+					(int_p
 					[
 						assign_a(self.m_alarm.silent_time)
 					]
+					| epsilon_p)
+				;
+			//-----------------------------ON COMMAND------------------------------------
+			on_command
+				= discard_node_d[str_p(KEY(ON_COMMAND_KEY))] >>
+						(discard_node_d
+						[
+							name
+							[
+								assign_a(self.m_alarm.cmd_name_a)		//save cmd_name_a in alarm_t
+							]
+						]		//discard_node_d
+						| epsilon_p)
+				;
+			//-----------------------------OFF COMMAND------------------------------------
+			off_command
+				= discard_node_d[str_p(KEY(OFF_COMMAND_KEY))] >>
+						(discard_node_d
+						[
+							name
+							[
+								assign_a(self.m_alarm.cmd_name_n)		//save cmd_name_a in alarm_t
+							]
+						]		//discard_node_d
+						| epsilon_p)
 				;
-			         
         }
         
 		typedef rule<ScannerT> rule_t;	
-		rule_t expression, event;
-        rule_t symbol, name, val, token, oper, msg, group, level, time_threshold, silent_time;
+		rule_t expression, event, option;
+        rule<typename lexeme_scanner<ScannerT>::type> symbol;					//needed to use lexeme_d in rule name
+        rule<typename lexeme_scanner<ScannerT>::type> symbol_attr_name;		//needed to use lexeme_d in rule name
+        rule_t name, name_alm, val, token, oper, msg, group, level, time_threshold, silent_time, on_command, off_command;
 		formula_grammar formula;
 		
 		rule_t const&					
diff --git a/src/alarm_table.cpp b/src/alarm_table.cpp
index dcbc199..5798630 100644
--- a/src/alarm_table.cpp
+++ b/src/alarm_table.cpp
@@ -32,6 +32,10 @@ alarm_t::alarm_t()
 	counter=0;
 	stat = S_NORMAL;
 	ack = ACK;
+	time_threshold = 0;
+	silent_time = -1;
+	cmd_name_a=string("");
+	cmd_name_n=string("");
 } 
  
 bool alarm_t::operator==(const alarm_t &that)
@@ -779,21 +783,22 @@ void alarm_table::log_alarm_db(unsigned int type, Tango::TimeVal ts, string name
 }
 
 void alarm_table::save_alarm_conf_db(string att_name, 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)
+		string formula, unsigned int time_threshold, string grp, string lev, string msg, string cmd_a, string cmd_n, int silent_time, vector<string> alm_list)
 {
 	// We want to put properties for attribute "att_name"
 	Tango::DbDatum dbd_att_name(att_name);
-	Tango::DbDatum dbd_name("name");
-	Tango::DbDatum dbd_formula("formula");
-	Tango::DbDatum dbd_time_threshold("time_threshold");
-	Tango::DbDatum dbd_level("level");
-	Tango::DbDatum dbd_silence_time("silence_time");	//TODO: silent_time
-	Tango::DbDatum dbd_group("group");
-	Tango::DbDatum dbd_message("message");
-	Tango::DbDatum dbd_command("command");	//TODO: action
+	Tango::DbDatum dbd_name(NAME_KEY);
+	Tango::DbDatum dbd_formula(FORMULA_KEY);
+	Tango::DbDatum dbd_time_threshold(DELAY_KEY);
+	Tango::DbDatum dbd_level(LEVEL_KEY);
+	Tango::DbDatum dbd_silence_time(SILENT_TIME_KEY);	//TODO: silent_time
+	Tango::DbDatum dbd_group(GROUP_KEY);
+	Tango::DbDatum dbd_message(MESSAGE_KEY);
+	Tango::DbDatum dbd_oncommand(ON_COMMAND_KEY);	//TODO: action
+	Tango::DbDatum dbd_offcommand(OFF_COMMAND_KEY);	//TODO: action
 
 	Tango::DbData db_data;
-	dbd_att_name << 8;                               // Eigth properties for attribute "att_name"
+	dbd_att_name << 9;                               // Eigth properties for attribute "att_name"
 	dbd_name << name;
 	dbd_formula << formula;
 	dbd_time_threshold << time_threshold;
@@ -801,7 +806,8 @@ void alarm_table::save_alarm_conf_db(string att_name, Tango::TimeVal ts, string
 	dbd_silence_time << silent_time;
 	dbd_group << grp;
 	dbd_message << msg;
-	dbd_command << action;
+	dbd_oncommand << cmd_a;
+	dbd_offcommand << cmd_n;
 
 	db_data.push_back(dbd_att_name);
 	db_data.push_back(dbd_name);
@@ -811,7 +817,8 @@ void alarm_table::save_alarm_conf_db(string att_name, Tango::TimeVal ts, string
 	db_data.push_back(dbd_silence_time);
 	db_data.push_back(dbd_group);
 	db_data.push_back(dbd_message);
-	db_data.push_back(dbd_command);
+	db_data.push_back(dbd_oncommand);
+	db_data.push_back(dbd_offcommand);
 
 	string dev_name(mydev->get_name());
 
@@ -858,27 +865,30 @@ void alarm_table::get_alarm_list_db(vector<string> &al_list)
 		string alm_silence_time("-1");
 		string alm_group;
 		string alm_message;
-		string alm_command(";");
+		string alm_on_command("");
+		string alm_off_command("");
 		for (long k=0;k < nb_prop;k++)
 		{
 			string &prop_name = db_data[i].name;
 
-			if (prop_name == "name")
+			if (prop_name == NAME_KEY)
 				db_data[i] >> alm_name;
-			else if (prop_name == "formula")
+			else if (prop_name == FORMULA_KEY)
 				db_data[i] >> alm_formula;
-			else if (prop_name == "time_threshold")
+			else if (prop_name == DELAY_KEY)
 				db_data[i] >> alm_time_threshold;
-			else if (prop_name == "level")
+			else if (prop_name == LEVEL_KEY)
 				db_data[i] >> alm_level;
-			else if (prop_name == "silence_time")
+			else if (prop_name == SILENT_TIME_KEY)
 				db_data[i] >> alm_silence_time;
-			else if (prop_name == "group")
+			else if (prop_name == GROUP_KEY)
 				db_data[i] >> alm_group;
-			else if (prop_name == "message")
+			else if (prop_name == MESSAGE_KEY)
 				db_data[i] >> alm_message;
-			else if (prop_name == "command")
-				db_data[i] >> alm_command;
+			else if (prop_name == ON_COMMAND_KEY)
+				db_data[i] >> alm_on_command;
+			else if (prop_name == OFF_COMMAND_KEY)
+				db_data[i] >> alm_off_command;
 			else
 			{
 				cout << "att_name="<<att_name<<" UNKWNOWN prop_name="<<prop_name<<endl;
@@ -888,12 +898,18 @@ void alarm_table::get_alarm_list_db(vector<string> &al_list)
 			i++;
 		}
 		stringstream alm;
-		alm << alm_name << "\t" << alm_formula << "\t" << alm_time_threshold << "\t" << alm_level <<
-				"\t" << alm_silence_time << "\t" << alm_group << "\t\"" << alm_message <<	"\"\t" << alm_command;
+		alm << alm_name << "\t" <<
+				/*TODO: KEY(FORMULA_KEY)<<*/alm_formula << "\t" <<
+				KEY(DELAY_KEY)<<alm_time_threshold << "\t" <<
+				KEY(LEVEL_KEY)<< alm_level << "\t" <<
+				KEY(SILENT_TIME_KEY)<<alm_silence_time << "\t" <<
+				KEY(GROUP_KEY)<< alm_group << "\t" <<
+				KEY(MESSAGE_KEY)<< "\""  << alm_message <<	"\"\t" <<
+				KEY(ON_COMMAND_KEY)<< alm_on_command << "\t" <<
+				KEY(OFF_COMMAND_KEY)<< alm_off_command;
 		al_list.push_back(alm.str());
 	}
 
-
 #if 0
 
 	db_dev->get_attribute_property(db_data);
diff --git a/src/alarm_table.h b/src/alarm_table.h
index 0bdf7b0..062648d 100644
--- a/src/alarm_table.h
+++ b/src/alarm_table.h
@@ -356,7 +356,7 @@ class alarm_table {
 		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 save_alarm_conf_db(string att_name, 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>());
+				 string formula, unsigned int time_threshold, string grp, string lev, string msg, string cmd_a, string cmd_n, int silent_time, vector<string> alm_list=vector<string>());
 		void get_alarm_list_db(vector<string> &al_list);
 		void init_cmdthread();
 		void stop_cmdthread();
-- 
GitLab