Allow separate stacks registration through services operation
[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   * Number of scopes registered
229   */
230   int scopes() const { return a_scopes.size(); }
231
232   /**
233   * Enable all the counters registered in this module (enabled by default at constructor).
234   * Usually managed at PROCCESS implementation
235   */
236   void enableCounters(void) throw();
237
238   /**
239   * Disable all the counters registered in this module (enabled by default at constructor).
240   * Usually managed at PROCCESS implementation
241   */
242   void disableCounters(void) throw();
243
244   /**
245   * Enable all the alarms registered in this module (enabled by default at constructor).
246   * Usually managed at PROCCESS implementation
247   */
248   void enableAlarms(void) throw();
249
250   /**
251   * Disable all the alarms registered in this module (enabled by default at constructor).
252   * Usually managed at PROCCESS implementation
253   */
254   void disableAlarms(void) throw();
255
256   /**
257     Getter for counters enabled
258   */
259   bool countersEnabled() const throw() { return a_counters_enabled; }
260
261   /**
262     Getter for alarms enabled
263   */
264   bool alarmsEnabled() const throw() { return a_alarms_enabled; }
265
266   /**
267   * Show own module alarm preffix (enabled by default at constructor).
268   * Usually managed at PROCCESS implementation
269   */
270   void enableAlarmsPreffix(void) throw();
271
272   /**
273   * Show own module alarm suffix (enabled by default at constructor).
274   * Usually managed at PROCCESS implementation
275   */
276   void enableAlarmsSuffix(void) throw();
277
278   /**
279   * Hide own module alarm preffix (enabled by default at constructor).
280   * Usually managed at PROCCESS implementation
281   */
282   void disableAlarmsPreffix(void) throw();
283
284   /**
285   * Hide own module alarm suffix (enabled by default at constructor).
286   * Usually managed at PROCCESS implementation
287   */
288   void disableAlarmsSuffix(void) throw();
289
290   /**
291   * Sets the operations handler. By default, all modules will use the default anna::oam::Handler.
292   * This method will be used only when a different behaviour is needed, for example for the project
293   * specific events.
294   *
295   * Used ONLY at PROCCESS implementation (initial tasks)
296   *
297   * @param handler Handler used for OAM operations (registering and launch). NULL is ignored
298   */
299   void setHandler(Handler *handler) throw() { if(handler) a_handler = handler; }
300
301   /**
302   * Counter scope registration. Usually, only one scope id will be registered, but multicontext applications
303   * could manage scope clones where all the counters are REPLICATED in order to manage separate sub-facilities.
304   * Multicontext applications must invoke N times to this method, and then register the common counters.
305   * Each context must activate with 'setActiveCounterScope()', the correct scope id.
306   * After invocation, provided scope id will be activated.
307   * Used ONLY at PROCCESS implementation (initial tasks)
308   *
309   * @param scopeId Counter scope id. It must be non negative (0 is usually reserved for core platform counters).
310   * @param description Counter scope id description. If missing, module description will be set, but is
311   * a good idea add different names between replicated scopes, i.e.: 'Main OAM Module - Context X', etc.
312   * better than 'Main OAM Module' for all of them. Also, you can use the same description for all scopes
313   * (that is the case of default assignment).
314   */
315   void initializeCounterScope(const int & scopeId, const std::string & description = "") throw(anna::RuntimeException);
316
317
318   /**
319   * Multicontext application could decide the correct scope id in order to sure right sub-module counting.
320   * Applications that only initializes one scope (which becomes active after that), don't need to use this method.
321   * Used ONLY at PROCCESS implementation (normal tasks)
322   *
323   * @param scopeId Counter scope id which becomes active.
324   */
325   void setActiveCounterScope(const int & scopeId) throw();
326
327
328   /**
329   * Gets the current activated counter scope
330   *
331   * @return Activated counter scope
332   */
333   const anna::oam::CounterScope* getActiveCounterScope() const throw() { return a_active_counter_scope; }
334
335   /**
336   * Child oam module classes should define descriptions for each enum type. A good practice would be the use of
337   * 'anna_declare_enum' macro in order to define names for enum types. This is an oam-internal description which
338   * should be redefined at application layer during registering. Returns undefined by default.
339   *
340   * @param type Counter enum-identification within the own context/module
341   *
342   * @return Default alarm description
343   */
344   virtual std::string getDefaultInternalAlarmDescription(const int & type) const throw();
345
346   /**
347   * Child oam module classes should define descriptions for each enum type. A good practice would be the use of
348   * 'anna_declare_enum' macro in order to define names for enum types. This is an oam-internal description which
349   * should be redefined at application layer during registering. Returns undefined by default.
350   *
351   * @param type Counter enum-identification within the own context/module
352   *
353   * @return Default counter description
354   */
355   virtual std::string getDefaultInternalCounterDescription(const int & type) const throw();
356
357
358   /**
359   * Counter registration providing the specific documentacion codes.
360   * To guarantee clone operations, no scope initialization will be possible after use of this method.
361   * Used ONLY at PROCCESS implementation (initial tasks)
362   *
363   * @param type Counter enum-identification added within the module (defined enum type on @Singleton child class)
364   * @param description Counter description added within the module. If empty string is provided, default description
365   * for non-registered will be searched (#getDefaultInternalCounterDescription).
366   * @param offset Counter offset over (1000 * scope id). Offset has 0-999 range.
367   */
368   void registerCounter(const int &type, const std::string &description, const int &offset) throw(anna::RuntimeException);
369
370
371   /**
372   * Alarm registration providing the specific process codes useful for manage any kind of alarm generation: external id
373   * (which could be a database unique idenfier), dynamic variables used during text parsing to allow advanced manipulation,
374   * and activation/cancellation codes (which could be used at a certain management system node).
375   *
376   * @param type Alarm enum-identification added within the module (defined enum type on @Singleton child class)
377   * @param description Alarm description added within the module. If empty string is provided, default description
378   * for non-registered will be searched (#getDefaultInternalAlarmDescription).
379   * @param externalId External text identification.
380   * @param dynamicVariablesCSL Comma-separated list of dynamic variable names (same order than launched with #activateAlarm and #cancelAlarm).
381   * @param activationId Alarm activation identifier
382   * @param cancellationId Alarm cancellation identifier. If missing, the alarm will interpreted as non-transferable
383   */
384   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);
385
386
387   /**
388      Gets the OAM module name
389
390      @param OAM module name
391   */
392   const char *getName() const throw() { return a_name.c_str(); }
393
394
395   /**
396      Gets counter data for type provided. NULL if not found.
397
398      @param type Alarm enum-identification within the own context/module.
399   */
400   const counter_data_t *counter(const int &type) const throw() {
401     const_counter_iterator it = counter_find(type);
402     return ((it != counter_end()) ? (&(*it).second) : NULL);
403   }
404
405   /**
406      Gets alarm data for type provided. NULL if not found.
407
408      @param type Counter enum-identification within the own context/module.
409   */
410   const alarm_data_t *alarm(const int &type) const throw() {
411     const_alarm_iterator it = alarm_find(type);
412     return ((it != alarm_end()) ? (&(*it).second) : NULL);
413   }
414
415
416   /**
417   * Notifies counter increase with certain amount within the ativated scope
418   * Used at MODULE implementation (library or proccess itself)
419   *
420   * @param type Counter enum-identification within the own context/module
421   * @param amount Units increased. Default is 1
422   */
423   void count(const int & type, const int & amount = 1) throw(anna::RuntimeException);
424
425
426   /**
427   * Reset all counters accumulated amount (analysis purposes)
428   * Usually managed at PROCCESS implementation
429   *
430   * @param scopeId Restrict reset to provided scope id. If missing, all scopes will be affected.
431   *
432   * @return Number of affected counters which have been reset (only those which have non-zero accumulated count).
433   */
434   int resetCounters(const int & scopeId = -1) throw();
435
436
437   /**
438   * Sets the instance for the class which will save the counters information.
439   * @counterRecorder Provided instance
440   * @warning It should be invoked periodically as a common solution
441   */
442   void setCounterRecorder(CounterRecorder* counterRecorder) throw() { a_counterRecorder = counterRecorder; }
443
444   /**
445   * Dumps the modified counters from last invocation to this method.
446   * A counter recorder should have been assigned by mean setCounterRecorder(), which
447   * will have the specific behaviour. This procedure is oriented to have physical storage
448   * for counters information.
449   */
450   void recordCounters() throw(anna::RuntimeException);
451
452
453   /**
454   * Activates alarm with dynamic-composed text parsed with provided data (...).
455   * Used at MODULE implementation (library or proccess itself)
456   *
457   * @param alarmType Alarm enum-identification within the own context/module
458   * @param ... Optional parsing data for dynamic-composed text.
459   */
460   void activateAlarm(int type, ...) const throw(anna::RuntimeException);
461
462
463   /**
464   * Send transferable alarm cancellation, with dynamic-composed text parsed with provided data (...)
465   * Used at MODULE implementation (library or proccess itself)
466   *
467   * @param alarmType Alarm enum-identification within the own context/module
468   * @param ... Optional parsing data for dynamic-composed text.
469   */
470   void cancelAlarm(int type, ...) const throw(anna::RuntimeException);
471
472
473   /**
474   * Class string representation
475   * Usually managed at PROCCESS implementation
476   *
477   * @return String with class content
478   */
479   virtual std::string asString(void) const throw();
480
481
482   /**
483   * Class XML representation
484   * Usually managed at PROCCESS implementation
485   *
486   * @return XML with class content
487   */
488   virtual anna::xml::Node* asXML(anna::xml::Node* parent) const throw();
489
490
491 protected:
492
493   /**
494   * Module alarm preffix components used to add aditional information over alarm text.
495   * Oam modules push-back this additional components to global 'Configuration' preffix components.
496   * To disable, use 'disableAlarmsPreffix()'.
497   * Note that preffix components string should be multilanguage texts if alarm texts are based on
498   * language-context traslations.
499   * Used at MODULE implementation (library or proccess itself)
500   *
501   * @param components Alarm preffix components defined by oam module. Empty on default implementation.
502   */
503   virtual void readAlarmPreffixComponents(std::vector<std::string> & components) const throw() {;}
504
505
506   /**
507   * Module alarm suffix components used to add aditional information over alarm text.
508   * Oam modules push-back this additional components to global 'Configuration' suffix components.
509   * To disable, use 'disableAlarmsSuffix()'.
510   * Note that suffix components string should be multilanguage texts if alarm texts are based on
511   * language-context traslations.
512   * Used at MODULE implementation (library or proccess itself)
513   *
514   * @param components Alarm suffix components defined by oam module. Empty on default implementation.
515   */
516   virtual void readAlarmSuffixComponents(std::vector<std::string> & components) const throw() {;}
517
518
519   friend class RecordingGuard;
520 };
521
522 }
523 }
524
525 #endif
526