Newer
Older

Graziano Scalamera
committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/*
* 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
//#define _USE_BOOST_LOCK
#ifdef _USE_BOOST_LOCK
#include <boost/thread/shared_mutex.hpp>
#endif

Graziano Scalamera
committed
//#include "log_thread.h"
#define LOG_STREAM cout
using namespace std;

Graziano Scalamera
committed
#if BOOST_VERSION < 103600
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;
#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
typedef parse_tree_match_t::tree_iterator iter_t;
#define S_NORMAL "NORMAL"
#define S_ALARM "ALARM"

Graziano Scalamera
committed
#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
#define LEV_LOWEST "lowest"
#define LEV_LOW "low"
#define LEV_MEDIUM "medium"
#define LEV_HIGH "high"
#define LEV_HIGHEST "highest"
#define LEV_DEFAULT LEV_HIGH

Graziano Scalamera
committed
class alarm_t;
class alarm_table;
class log_thread;
class cmd_thread;
#ifdef _USE_BOOST_LOCK
struct rwlock_t
{
string name;
rwlock_t(string n){name=n;};
rwlock_t(){name=string("RWLOCK");};
boost::shared_mutex mut;
void readerIn(){cout<<name<<": " << __func__<<endl;mut.lock_shared();}
void readerOut(){cout<<name<<": " << __func__<<endl;mut.unlock_shared();}
void writerIn(){cout<<name<<": " << __func__<<endl;mut.lock();}
void writerOut(){cout<<name<<": " << __func__<<endl;mut.unlock();}
};
#endif
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
struct formula_res_t
{
formula_res_t(){value=0;quality=Tango::ATTR_VALID;ex_reason=string("");ex_desc=string("");ex_origin=string("");}
double value;
int quality;
Tango::DevErrorList errors; //TODO: error stack
string ex_reason;
string ex_desc;
string ex_origin;
int combine_quality(int quality1, int quality2)
{
int res;
if(quality1 == Tango::ATTR_INVALID || quality2 == Tango::ATTR_INVALID)
res = Tango::ATTR_INVALID;
else if(quality1 == Tango::ATTR_ALARM || quality2 == Tango::ATTR_ALARM)
res = Tango::ATTR_ALARM;
else if(quality1 == Tango::ATTR_WARNING || quality2 == Tango::ATTR_WARNING)
res = Tango::ATTR_WARNING;
else if(quality1 == Tango::ATTR_CHANGING || quality2 == Tango::ATTR_CHANGING)
res = Tango::ATTR_CHANGING;
else
res = (quality1 > quality2) ? quality1 : quality2; //TODO: decide priority in enum AttrQuality { ATTR_VALID, ATTR_INVALID, ATTR_ALARM, ATTR_CHANGING, ATTR_WARNING /*, __max_AttrQuality=0xffffffff */ };
return res;
}
string combine_exception(string ex_1, string ex_2)
{
if(ex_1.length() > 0)
return ex_1;
else
return ex_2;
}
formula_res_t operator==(const formula_res_t& e)
{
formula_res_t res;
res.value = value == e.value;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
return res;
}
formula_res_t operator!=(const formula_res_t& e)
{
formula_res_t res;
res.value = value != e.value;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
return res;
}
formula_res_t operator<=(const formula_res_t& e)
{
formula_res_t res;
res.value = value <= e.value;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
return res;
}
formula_res_t operator>=(const formula_res_t& e)
{
formula_res_t res;
res.value = value >= e.value;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
return res;
}
formula_res_t operator<(const formula_res_t& e)
{
formula_res_t res;
res.value = value < e.value;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
return res;
}
formula_res_t operator>(const formula_res_t& e)
{
formula_res_t res;
res.value = value > e.value;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
return res;
}
formula_res_t operator||(const formula_res_t& e)
{
formula_res_t res;
res.value = value || e.value;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
return res;
}
formula_res_t operator&&(const formula_res_t& e)
{
formula_res_t res;
res.value = value && e.value;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
return res;
}
formula_res_t operator+(const formula_res_t& e)
{
formula_res_t res;
res.value = value + e.value;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
return res;
}
formula_res_t operator-(const formula_res_t& e)
{
formula_res_t res;
res.value = value - e.value;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
return res;
}
formula_res_t operator*(const formula_res_t& e)
{
formula_res_t res;
res.value = value * e.value;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
return res;
}
formula_res_t operator/(const formula_res_t& e)
{
formula_res_t res;
res.value = value / e.value;
res.quality = combine_quality(quality, e.quality);
res.ex_reason = combine_exception(ex_reason, e.ex_reason);
res.ex_desc = combine_exception(ex_desc, e.ex_desc);
res.ex_origin = combine_exception(ex_origin, e.ex_origin);
return res;
}
/*string operator<<(const formula_res_t& e)
{
stringstream res;
res << "value="<<e.value<<" quality="<<e.quality<<" EX reason="<<e.ex_reason<<" desc="<<e.ex_desc<<" origin="<<e.ex_origin;
return res.str();
}*/
};

Graziano Scalamera
committed
/*
* store the alarm-name/alarm-formula pair
*/
class alarm_t {
public:
string name,
formula;
string attr_name;
string attr_name_formula;
Tango::DevEnum *attr_value;
Tango::DevString *attr_value_formula;
int quality;
string ex_reason;
string ex_desc;
string ex_origin;

Graziano Scalamera
committed
Tango::TimeVal ts;
string stat{S_NORMAL},
ack{ACK};
bool enabled{true};
bool shelved{false};
#ifdef _CNT_ATOMIC
atomic_uint on_counter= {0};
atomic_uint off_counter= {0};
atomic_uint err_counter= {0};
#else
unsigned int on_counter= {0};
unsigned int off_counter= {0};
unsigned int err_counter= {0};
#endif
unsigned int freq_counter{0};

Graziano Scalamera
committed
tree_parse_info_t formula_tree;
static map<string, unsigned int> grp_str;
bool done;
bool to_be_evaluated;
string msg;

Graziano Scalamera
committed
string lev;
set<string> s_event;
int is_new;
Tango::TimeVal ts_on_delay; //says when it has gone in alarm status for the first time
unsigned int on_delay{0}; //TODO: seconds, is it enough precision?
Tango::TimeVal ts_off_delay; //says when it returned normal status
unsigned int off_delay{0}; //TODO: seconds, is it enough precision?
Tango::TimeVal ts_err_delay; //says when it has gone in error status for the first time

Graziano Scalamera
committed
Tango::TimeVal ts_time_silenced; //says when it has been silenced
int silent_time{-1}; //minutes max to be silent

Graziano Scalamera
committed
int silenced; //minutes still to be silent
string attr_values_delay; //attr_values of first occurrence of alarm waiting for on or off delay
string cmd_name_a{""}; //action to execute: when NORMAL -> ALARM, cmd_name = cmd_dp_a/cmd_action_a

Graziano Scalamera
committed
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

Graziano Scalamera
committed
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() noexcept {}; //constructor
#ifdef _CNT_ATOMIC
alarm_t& operator=(const alarm_t& rhs) { on_counter = rhs.on_counter.load(); off_counter = rhs.off_counter.load(); err_counter = rhs.err_counter.load(); return *this; }
alarm_t(const alarm_t& rhs) { on_counter = rhs.on_counter.load(); off_counter = rhs.off_counter.load(); err_counter = rhs.err_counter.load();}
#endif

Graziano Scalamera
committed
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();

Graziano Scalamera
committed
protected:
private:
};
typedef map<string,alarm_t> alarm_container_t;
class alarm_table {
public:
alarm_table() {}
void set_dev(Tango::DeviceImpl* devImpl) {mydev=devImpl;}

Graziano Scalamera
committed
//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, formula_res_t res, string &attr_values, string grp, string msg, string formula);

Graziano Scalamera
committed
bool timer_update();
void erase(alarm_container_t::iterator i);
bool exist(string& s);
unsigned int to_be_evaluated_num();
vector<string> to_be_evaluated_list();

Graziano Scalamera
committed
//vector<alarm_t> v_alarm;
alarm_container_t v_alarm;

Graziano Scalamera
committed
ReadersWritersLock *vlock;
#else
rwlock_t *vlock;
#endif

Graziano Scalamera
committed
void new_rwlock();
void del_rwlock();
void save_alarm_conf_db(const string &att_name, const string &name, const string &status, const string &ack, bool enabled,
const string &formula, unsigned int on_delay, unsigned int off_delay, const string &grp, const string &url, const string &lev, const string &msg, const string &cmd_a, const string &cmd_n, int silent_time);
void delete_alarm_conf_db(string att_name);
void get_alarm_list_db(vector<string> &al_list, map<string, string> &saved_alarms, ReadersWritersLock *savedlock);

Graziano Scalamera
committed
void init_cmdthread();
void stop_cmdthread();
Tango::TimeVal startup_complete; //to disable action execution at startup
void set_err_delay(unsigned int delay){err_delay=delay;};

Graziano Scalamera
committed
protected:
private:
Tango::DeviceImpl* mydev;

Graziano Scalamera
committed
log_thread *logloop;
cmd_thread *cmdloop;
unsigned int err_delay;

Graziano Scalamera
committed
};
#endif /* ALARM_TABLE_H */