533eaad700882e393097dbba017ab7fd3fff288d
[anna.git] / include / anna / core / oam / Module.hpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 #ifndef anna_core_oam_Module_hpp
10 #define anna_core_oam_Module_hpp
11
12
13 // STL
14 #include <string>
15 #include <vector>
16 #include <map>
17
18 #include <anna/core/RuntimeException.hpp>
19
20 #include <anna/core/oam/defines.hpp>
21 #include <anna/core/oam/Handler.hpp>
22
23 #include <cstdarg>
24
25
26 namespace anna {
27 namespace xml {
28 class Node;
29 }
30 namespace oam {
31 class CounterScope;
32 class CounterRecorder;
33 }
34 }
35
36
37 namespace anna {
38
39 namespace oam {
40
41 class Handler;
42
43 /**
44 * Class used to implement context-module-alarms/counters. Each process module (within library or process itself) must
45 * inherit from this, defining specific-alarm/counters codes (better public enum type) which will be managed within each
46 * module (usually through a management singleton class). This allow code reusability regarding alarm/counter conditions
47 * usually badly managed with API return codes instead of self-governing alarms shared and reusabled by any API client,
48 * or counters with fixed-inflexible values. It is posible to manage more than one oam module per library or proccess,
49 * simply defining more children classes, but the normal way is to use only one.
50 *
51 * <pre>
52 *
53 * Example of use:
54 *
55 *  class OamModule : public anna::oam::Module, public anna::Singleton <OamModule>
56 *  {
57 *              struct Counter
58 *              {
59 *                 enum _v // types
60 *                 {
61 *                    None = -1,
62 *                    ErrorLDAP
63 *                 };
64 *
65 *                 anna_declare_enum(Counter);
66 *              };
67 *
68 *              struct Alarm
69 *              {
70 *                 enum _v // types
71 *                 {
72 *                    None = -1,
73 *                    ErrorOnNode__s__WithSessionId__d__
74 *                 };
75 *
76 *                 anna_declare_enum(Alarm);
77 *              };
78 *
79 *        OamModule() : anna::oam::Module ("Main Proccess 'HTE_CLDAP' OAM module") {;};
80 *
81 *        friend class anna::Singleton <OamModule>;
82 *  };
83 *
84 * Normally, we will use one scope per module (library/proccess) but we could define many oam modules per subsystem functionality.
85 * For example, libanna.diameter.b have oam modules for comm.db and codec.db. Also, macros as 'anna_declare_enum' are useful to
86 * define default descriptions for counter and alarm types.
87 *
88 *
89 * == REGISTRATION for all the linked scopes ==
90 *
91 * anna::<project>::oam::Handler *projectHandler = new anna::<project>::oam::Handler(); // handler for project alarms
92 *
93 * OamModule & oam_proc = OamModule::instantiate();
94 * <library_namespace>::OamModule & oam_lib = <library_namespace>::OamModule::instantiate();
95 * oam_proc.setHandler(projectHandler);
96 * oam_proc.initializeCounterScope (1);
97 * oam_proc.registerCounter (OamModule::Counter::ErrorLDAP, "ErrorLDAP", 0);
98 * oam_proc.registerAlarm (OamModule::Alarm::ErrorOnNode__s__WithSessionId__d__, "Error on node", 1, "nodeName,errorCode", anna::oam::MSAlarmId::NODE_ERROR);
99 *
100 * oam_lib.setHandler(projectHandler);
101 * oam_lib.initializeCounterScope (2); // different scope for different modules (normal way)
102 * oam_lib.registerCounter (<library_namespace>::OamModule::Counter::<type>, "counter description", 0);
103 * oam_lib.registerAlarm (<library_namespace>::OamModule::Alarm::<type>, "alarm description", 2, <dynamic variable names CSL>, anna::oam::MSAlarmId::<type>);
104 *
105 * -> LAUNCH for all local scopes (library launches will be done at library code):
106 * oam_proc.count (OamModule::Counter::ErrorLDAP);
107 * oam_proc.activateAlarm (OamModule::Alarm::ErrorOnNode__s__WithSessionId__d__, "my node", a_session_id);
108 *
109 *
110 * == MULTI-CONTEXT APPLICATIONS ==
111 *
112 * Suppose two contexts, one with scopes 1 and 4 for process and library respectively, and
113 * the other defined by 2 and 5:
114 *
115 * oam_proc.initializeCounterScope (1, "Main OAM Module - Context A");
116 * oam_proc.initializeCounterScope (2, "Main OAM Module - Context B");
117 * Counters registration ...
118 *
119 * oam_lib.initializeCounterScope (4, "Encoder OAM Module - Context A");
120 * oam_lib.initializeCounterScope (5, "Encoder OAM Module - Context B");
121 * Counters registration ...
122 *
123 * Application must switch between these scope ids to distinguise the contexts:
124 *
125 * Context A:
126 * oam_proc.setActiveCounterScope(1);
127 * oam_lib.setActiveCounterScope(4);
128 *
129 * Context B:
130 * oam_proc.setActiveCounterScope(2);
131 * oam_lib.setActiveCounterScope(5);
132 *
133 * </pre>
134 */
135 class Module {
136
137   Handler a_defaultHandler;        // default OAM handler
138   Handler *a_handler;              // Handler reference
139   std::string a_name;         // module description
140
141   bool a_counters_enabled;         // Enable/Disable registered counters over this module (default is 'false')
142   bool a_alarms_enabled;           // Enable/Disable registered alarms over this module (default is 'false')
143
144   // GENERIC COUNTERS
145   anna::oam::CounterScope* a_active_counter_scope; // Current scope for counters generation
146   typedef std::map <int, anna::oam::CounterScope*> scope_container;
147   scope_container a_scopes; // Module can manage N scope clones (usually, there is only one registered scope: mono-context applications)
148   typedef std::map < int /*type*/, counter_data_t > counter_container;
149   counter_container a_counters;
150
151   // GENERIC ALARMS
152   typedef std::map < int /*type*/, alarm_data_t > alarm_container;
153   alarm_container a_alarms;
154   void alarmEvent(bool activation, const int & type, va_list argList) const throw();
155
156   // dynamic modifications over alarm text
157   bool a_alarms_preffix_enabled;   // Show own module alarm preffix
158   bool a_alarms_suffix_enabled;    // Show own module alarm suffix
159   std::string alarmComponentsToText(const std::vector<std::string> & components, const std::string & psL, const std::string & psS, const std::string & psR) const throw();
160
161   // Counters
162   typedef scope_container::iterator scope_iterator;
163   typedef scope_container::const_iterator const_scope_iterator;
164   scope_iterator scope_find(const int &key) throw() { return a_scopes.find(key); }
165   scope_iterator scope_begin() throw() { return a_scopes.begin(); }
166   scope_iterator scope_end() throw() { return a_scopes.end(); }
167   static anna::oam::CounterScope* scope(scope_iterator ii) throw() { return ii->second; }
168   const_scope_iterator scope_begin() const throw() { return a_scopes.begin(); }
169   const_scope_iterator scope_end() const throw() { return a_scopes.end(); }
170   static const anna::oam::CounterScope* scope(const_scope_iterator ii) throw() { return ii->second; }
171   anna::oam::CounterScope *getScope(const int &id) throw();
172   typedef counter_container::iterator counter_iterator;
173   typedef counter_container::const_iterator const_counter_iterator;
174 //   bool counter_remove(const int &key) throw();
175   const_counter_iterator counter_find(const int &key) const throw() { return a_counters.find(key); }
176   const_counter_iterator counter_begin() const throw() { return a_counters.begin(); }
177   const_counter_iterator counter_end() const throw() { return a_counters.end(); }
178   counter_iterator counter_find(const int &key) throw() { return a_counters.find(key); }
179   counter_iterator counter_begin() throw() { return a_counters.begin(); }
180   counter_iterator counter_end() throw() { return a_counters.end(); }
181   CounterRecorder* a_counterRecorder;
182   bool a_counterRecording;
183
184   class RecordingGuard {
185     public:
186       RecordingGuard(Module*);
187       ~RecordingGuard();
188     private:
189       Module *a_module;
190   };
191
192   // Alarms
193   typedef alarm_container::iterator alarm_iterator;
194   typedef alarm_container::const_iterator const_alarm_iterator;
195 //   bool alarm_remove(const int &key) throw();
196   const_alarm_iterator alarm_find(const int &key) const throw() { return a_alarms.find(key); }
197   const_alarm_iterator alarm_begin() const throw() { return a_alarms.begin(); }
198   const_alarm_iterator alarm_end() const throw() { return a_alarms.end(); }
199   alarm_iterator alarm_find(const int &key) throw() { return a_alarms.find(key); }
200   alarm_iterator alarm_begin() throw() { return a_alarms.begin(); }
201   alarm_iterator alarm_end() throw() { return a_alarms.end(); }
202   void getAlarmPreffixSuffixAndZoneSeparator(std::string & preffix, std::string & suffix, char & zS) const throw();
203
204 public:
205
206   static const int MaxScope = 1000; /**< Numero maximo de ambitos */
207
208
209   /** Constructor
210       @param name Logical name for the class (better use fullNaming format including namespace resolution)
211    */
212   Module(const std::string &name) :
213     a_handler(&a_defaultHandler),
214     a_name(name),
215     a_counters_enabled(false),
216     a_alarms_enabled(false),
217     a_alarms_preffix_enabled(true),
218     a_alarms_suffix_enabled(true),
219     a_counterRecorder(NULL),
220     a_counterRecording(false) {;}
221
222   /**
223    * Destructor
224    */
225   virtual ~Module();
226
227
228   /**
229   * Enable all the counters registered in this module (enabled by default at constructor).
230   * Usually managed at PROCCESS implementation
231   */
232   void enableCounters(void) throw();
233
234   /**
235   * Disable all the counters registered in this module (enabled by default at constructor).
236   * Usually managed at PROCCESS implementation
237   */
238   void disableCounters(void) throw();
239
240   /**
241   * Enable all the alarms registered in this module (enabled by default at constructor).
242   * Usually managed at PROCCESS implementation
243   */
244   void enableAlarms(void) throw();
245
246   /**
247   * Disable all the alarms registered in this module (enabled by default at constructor).
248   * Usually managed at PROCCESS implementation
249   */
250   void disableAlarms(void) throw();
251
252   /**
253     Getter for counters enabled
254   */
255   bool countersEnabled() const throw() { return a_counters_enabled; }
256
257   /**
258     Getter for alarms enabled
259   */
260   bool alarmsEnabled() const throw() { return a_alarms_enabled; }
261
262   /**
263   * Show own module alarm preffix (enabled by default at constructor).
264   * Usually managed at PROCCESS implementation
265   */
266   void enableAlarmsPreffix(void) throw();
267
268   /**
269   * Show own module alarm suffix (enabled by default at constructor).
270   * Usually managed at PROCCESS implementation
271   */
272   void enableAlarmsSuffix(void) throw();
273
274   /**
275   * Hide own module alarm preffix (enabled by default at constructor).
276   * Usually managed at PROCCESS implementation
277   */
278   void disableAlarmsPreffix(void) throw();
279
280   /**
281   * Hide own module alarm suffix (enabled by default at constructor).
282   * Usually managed at PROCCESS implementation
283   */
284   void disableAlarmsSuffix(void) throw();
285
286   /**
287   * Sets the operations handler. By default, all modules will use the default anna::oam::Handler.
288   * This method will be used only when a different behaviour is needed, for example for the project
289   * specific events.
290   *
291   * Used ONLY at PROCCESS implementation (initial tasks)
292   *
293   * @param handler Handler used for OAM operations (registering and launch). NULL is ignored
294   */
295   void setHandler(Handler *handler) throw() { if(handler) a_handler = handler; }
296
297   /**
298   * Counter scope registration. Usually, only one scope id will be registered, but multicontext applications
299   * could manage scope clones where all the counters are REPLICATED in order to manage separate sub-facilities.
300   * Multicontext applications must invoke N times to this method, and then register the common counters.
301   * Each context must activate with 'setActiveCounterScope()', the correct scope id.
302   * After invocation, provided scope id will be activated.
303   * Used ONLY at PROCCESS implementation (initial tasks)
304   *
305   * @param scopeId Counter scope id. It must be non negative (0 is usually reserved for core platform counters).
306   * @param description Counter scope id description. If missing, module description will be set, but is
307   * a good idea add different names between replicated scopes, i.e.: 'Main OAM Module - Context X', etc.
308   * better than 'Main OAM Module' for all of them. Also, you can use the same description for all scopes
309   * (that is the case of default assignment).
310   */
311   void initializeCounterScope(const int & scopeId, const std::string & description = "") throw(anna::RuntimeException);
312
313
314   /**
315   * Multicontext application could decide the correct scope id in order to sure right sub-module counting.
316   * Applications that only initializes one scope (which becomes active after that), don't need to use this method.
317   * Used ONLY at PROCCESS implementation (normal tasks)
318   *
319   * @param scopeId Counter scope id which becomes active.
320   */
321   void setActiveCounterScope(const int & scopeId) throw();
322
323
324   /**
325   * Gets the current activated counter scope
326   *
327   * @return Activated counter scope
328   */
329   const anna::oam::CounterScope* getActiveCounterScope() const throw() { return a_active_counter_scope; }
330
331   /**
332   * Child oam module classes should define descriptions for each enum type. A good practice would be the use of
333   * 'anna_declare_enum' macro in order to define names for enum types. This is an oam-internal description which
334   * should be redefined at application layer during registering. Returns undefined by default.
335   *
336   * @param type Counter enum-identification within the own context/module
337   *
338   * @return Default alarm description
339   */
340   virtual std::string getDefaultInternalAlarmDescription(const int & type) const throw();
341
342   /**
343   * Child oam module classes should define descriptions for each enum type. A good practice would be the use of
344   * 'anna_declare_enum' macro in order to define names for enum types. This is an oam-internal description which
345   * should be redefined at application layer during registering. Returns undefined by default.
346   *
347   * @param type Counter enum-identification within the own context/module
348   *
349   * @return Default counter description
350   */
351   virtual std::string getDefaultInternalCounterDescription(const int & type) const throw();
352
353
354   /**
355   * Counter registration providing the specific documentacion codes.
356   * To guarantee clone operations, no scope initialization will be possible after use of this method.
357   * Used ONLY at PROCCESS implementation (initial tasks)
358   *
359   * @param type Counter enum-identification added within the module (defined enum type on @Singleton child class)
360   * @param description Counter description added within the module. If empty string is provided, default description
361   * for non-registered will be searched (#getDefaultInternalCounterDescription).
362   * @param offset Counter offset over (1000 * scope id). Offset has 0-999 range.
363   */
364   void registerCounter(const int &type, const std::string &description, const int &offset) throw(anna::RuntimeException);
365
366
367   /**
368   * Alarm registration providing the specific process codes useful for manage any kind of alarm generation: external id
369   * (which could be a database unique idenfier), dynamic variables used during text parsing to allow advanced manipulation,
370   * and activation/cancellation codes (which could be used at a certain management system node).
371   *
372   * @param type Alarm enum-identification added within the module (defined enum type on @Singleton child class)
373   * @param description Alarm description added within the module. If empty string is provided, default description
374   * for non-registered will be searched (#getDefaultInternalAlarmDescription).
375   * @param externalId External text identification.
376   * @param dynamicVariablesCSL Comma-separated list of dynamic variable names (same order than launched with #activateAlarm and #cancelAlarm).
377   * @param activationId Alarm activation identifier
378   * @param cancellationId Alarm cancellation identifier. If missing, the alarm will interpreted as non-transferable
379   */
380   void registerAlarm(const int &type, const std::string &description, const int &externalId, const std::string &dynamicVariablesCSL, const int &activationId, const int &cancellationId = -1) throw(anna::RuntimeException);
381
382
383   /**
384      Gets the OAM module name
385
386      @param OAM module name
387   */
388   const char *getName() const throw() { return a_name.c_str(); }
389
390
391   /**
392      Gets counter data for type provided. NULL if not found.
393
394      @param type Alarm enum-identification within the own context/module.
395   */
396   const counter_data_t *counter(const int &type) const throw() {
397     const_counter_iterator it = counter_find(type);
398     return ((it != counter_end()) ? (&(*it).second) : NULL);
399   }
400
401   /**
402      Gets alarm data for type provided. NULL if not found.
403
404      @param type Counter enum-identification within the own context/module.
405   */
406   const alarm_data_t *alarm(const int &type) const throw() {
407     const_alarm_iterator it = alarm_find(type);
408     return ((it != alarm_end()) ? (&(*it).second) : NULL);
409   }
410
411
412   /**
413   * Notifies counter increase with certain amount within the ativated scope
414   * Used at MODULE implementation (library or proccess itself)
415   *
416   * @param type Counter enum-identification within the own context/module
417   * @param amount Units increased. Default is 1
418   */
419   void count(const int & type, const int & amount = 1) throw(anna::RuntimeException);
420
421
422   /**
423   * Reset all counters accumulated amount (analysis purposes)
424   * Usually managed at PROCCESS implementation
425   *
426   * @param scopeId Restrict reset to provided scope id. If missing, all scopes will be affected.
427   *
428   * @return Number of affected counters which have been reset (only those which have non-zero accumulated count).
429   */
430   int resetCounters(const int & scopeId = -1) throw();
431
432
433   /**
434   * Sets the instance for the class which will save the counters information.
435   * @counterRecorder Provided instance
436   * @warning It should be invoked periodically as a common solution
437   */
438   void setCounterRecorder(CounterRecorder* counterRecorder) throw() { a_counterRecorder = counterRecorder; }
439
440   /**
441   * Dumps the modified counters from last invocation to this method.
442   * A counter recorder should have been assigned by mean setCounterRecorder(), which
443   * will have the specific behaviour. This procedure is oriented to have physical storage
444   * for counters information.
445   */
446   void recordCounters() throw(anna::RuntimeException);
447
448
449   /**
450   * Activates alarm with dynamic-composed text parsed with provided data (...).
451   * Used at MODULE implementation (library or proccess itself)
452   *
453   * @param alarmType Alarm enum-identification within the own context/module
454   * @param ... Optional parsing data for dynamic-composed text.
455   */
456   void activateAlarm(int type, ...) const throw(anna::RuntimeException);
457
458
459   /**
460   * Send transferable alarm cancellation, with dynamic-composed text parsed with provided data (...)
461   * Used at MODULE implementation (library or proccess itself)
462   *
463   * @param alarmType Alarm enum-identification within the own context/module
464   * @param ... Optional parsing data for dynamic-composed text.
465   */
466   void cancelAlarm(int type, ...) const throw(anna::RuntimeException);
467
468
469   /**
470   * Class string representation
471   * Usually managed at PROCCESS implementation
472   *
473   * @return String with class content
474   */
475   virtual std::string asString(void) const throw();
476
477
478   /**
479   * Class XML representation
480   * Usually managed at PROCCESS implementation
481   *
482   * @return XML with class content
483   */
484   virtual anna::xml::Node* asXML(anna::xml::Node* parent) const throw();
485
486
487 protected:
488
489   /**
490   * Module alarm preffix components used to add aditional information over alarm text.
491   * Oam modules push-back this additional components to global 'Configuration' preffix components.
492   * To disable, use 'disableAlarmsPreffix()'.
493   * Note that preffix components string should be multilanguage texts if alarm texts are based on
494   * language-context traslations.
495   * Used at MODULE implementation (library or proccess itself)
496   *
497   * @param components Alarm preffix components defined by oam module. Empty on default implementation.
498   */
499   virtual void readAlarmPreffixComponents(std::vector<std::string> & components) const throw() {;}
500
501
502   /**
503   * Module alarm suffix components used to add aditional information over alarm text.
504   * Oam modules push-back this additional components to global 'Configuration' suffix components.
505   * To disable, use 'disableAlarmsSuffix()'.
506   * Note that suffix components string should be multilanguage texts if alarm texts are based on
507   * language-context traslations.
508   * Used at MODULE implementation (library or proccess itself)
509   *
510   * @param components Alarm suffix components defined by oam module. Empty on default implementation.
511   */
512   virtual void readAlarmSuffixComponents(std::vector<std::string> & components) const throw() {;}
513
514
515   friend class RecordingGuard;
516 };
517
518 }
519 }
520
521 #endif
522