Allow separate stacks registration through services operation
[anna.git] / source / core / oam / Module.cpp
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 // Local
10 #include <anna/core/oam/Module.hpp>
11 #include <anna/core/functions.hpp>
12 #include <anna/core/oam/Configuration.hpp>
13 #include <anna/core/oam/CounterScope.hpp>
14 #include <anna/core/oam/CounterRecorder.hpp>
15
16 #include <anna/core/tracing/Logger.hpp>
17 #include <anna/core/tracing/TraceWriter.hpp>
18 #include <anna/core/tracing/TraceMethod.hpp>
19 #include <anna/core/functions.hpp>
20 #include <anna/xml/xml.hpp>
21
22 // Standard
23 #include <cstdarg>
24
25
26 #define UNDEFINED_EVENT_DESCRIPTION "<undefined>"
27
28
29 //******************************************************************************
30 //----------------------------------------------------------------------- Module
31 //******************************************************************************
32
33 //------------------------------------------------------------------------------
34 //-------------------------------------------------------------- Module::~Module
35 //------------------------------------------------------------------------------
36 anna::oam::Module::~Module() {
37   for(scope_iterator scope_it = scope_begin(); scope_it != scope_end(); scope_it++)
38     delete (scope(scope_it));
39 }
40
41
42 //------------------------------------------------------------------------------
43 //----------------------------------------------------------- Module::getScope()
44 //------------------------------------------------------------------------------
45 anna::oam::CounterScope *anna::oam::Module::getScope(const int &id) throw() {
46   scope_iterator it = scope_find(id);
47   return ((it != scope_end()) ? scope(it) : NULL);
48 }
49
50 ////------------------------------------------------------------------------------
51 ////------------------------------------------------------- Module::alarm_remove()
52 ////------------------------------------------------------------------------------
53 //bool anna::oam::Module::alarm_remove(const int &key) throw() {
54 //   alarm_iterator it = alarm_find(key);
55 //   if (it != alarm_end()) {
56 //      a_alarms.erase(key);
57 //      return true;
58 //   }
59 //
60 //   return false;
61 //}
62 //
63 ////------------------------------------------------------------------------------
64 ////----------------------------------------------------- Module::counter_remove()
65 ////------------------------------------------------------------------------------
66 //bool anna::oam::Module::counter_remove(const int &key) throw() {
67 //   counter_iterator it = counter_find(key);
68 //   if (it != counter_end()) {
69 //      a_counters.erase(key);
70 //      return true;
71 //   }
72 //
73 //   return false;
74 //}
75
76
77 // public:
78
79
80 //------------------------------------------------------------------------------
81 //----------------------------------------------------- Module::enableCounters()
82 //------------------------------------------------------------------------------
83 void anna::oam::Module::enableCounters(void) throw() {
84   a_counters_enabled = true;
85   LOGDEBUG(anna::Logger::debug("Scoped counters ENABLED", ANNA_FILE_LOCATION));
86 }
87
88
89 //------------------------------------------------------------------------------
90 //---------------------------------------------------- Module::disableCounters()
91 //------------------------------------------------------------------------------
92 void anna::oam::Module::disableCounters(void) throw() {
93   a_counters_enabled = false;
94   LOGDEBUG(anna::Logger::debug("Scoped counters DISABLED", ANNA_FILE_LOCATION));
95 }
96
97
98 //------------------------------------------------------------------------------
99 //------------------------------------------------------- Module::enableAlarms()
100 //------------------------------------------------------------------------------
101 void anna::oam::Module::enableAlarms(void) throw() {
102   a_alarms_enabled = true;
103   LOGDEBUG(anna::Logger::debug("Scoped alarms ENABLED", ANNA_FILE_LOCATION));
104 }
105
106
107 //------------------------------------------------------------------------------
108 //------------------------------------------------------ Module::disableAlarms()
109 //------------------------------------------------------------------------------
110 void anna::oam::Module::disableAlarms(void) throw() {
111   a_alarms_enabled = false;
112   LOGDEBUG(anna::Logger::debug("Scoped alarms DISABLED", ANNA_FILE_LOCATION));
113 }
114
115
116 //------------------------------------------------------------------------------
117 //------------------------------------------------ Module::enableAlarmsPreffix()
118 //------------------------------------------------------------------------------
119 void anna::oam::Module::enableAlarmsPreffix(void) throw() {
120   a_alarms_preffix_enabled = true;
121   LOGDEBUG(anna::Logger::debug("Alarm preffix module components SHOWN", ANNA_FILE_LOCATION));
122 }
123
124
125 //------------------------------------------------------------------------------
126 //------------------------------------------------- Module::enableAlarmsSuffix()
127 //------------------------------------------------------------------------------
128 void anna::oam::Module::enableAlarmsSuffix(void) throw() {
129   a_alarms_suffix_enabled = true;
130   LOGDEBUG(anna::Logger::debug("Alarm suffix module components SHOWN", ANNA_FILE_LOCATION));
131 }
132
133
134 //------------------------------------------------------------------------------
135 //----------------------------------------------- Module::disableAlarmsPreffix()
136 //------------------------------------------------------------------------------
137 void anna::oam::Module::disableAlarmsPreffix(void) throw() {
138   a_alarms_preffix_enabled = false;
139   LOGDEBUG(anna::Logger::debug("Alarm preffix module components HIDDEN", ANNA_FILE_LOCATION));
140 }
141
142
143 //------------------------------------------------------------------------------
144 //------------------------------------------------ Module::disableAlarmsSuffix()
145 //------------------------------------------------------------------------------
146 void anna::oam::Module::disableAlarmsSuffix(void) throw() {
147   a_alarms_suffix_enabled = false;
148   LOGDEBUG(anna::Logger::debug("Alarm suffix module components HIDDEN", ANNA_FILE_LOCATION));
149 }
150
151
152 //------------------------------------------------------------------------------
153 //--------------------------------- Module::getDefaultInternalAlarmDescription()
154 //------------------------------------------------------------------------------
155 std::string anna::oam::Module::getDefaultInternalAlarmDescription(const int & type) const throw() {
156   return UNDEFINED_EVENT_DESCRIPTION;
157 }
158
159
160 //------------------------------------------------------------------------------
161 //------------------------------- Module::getDefaultInternalCounterDescription()
162 //------------------------------------------------------------------------------
163 std::string anna::oam::Module::getDefaultInternalCounterDescription(const int & type) const throw() {
164   return UNDEFINED_EVENT_DESCRIPTION;
165 }
166
167
168 //------------------------------------------------------------------------------
169 //---------------------------------------------- Module::alarmComponentsToText()
170 //------------------------------------------------------------------------------
171 std::string anna::oam::Module::alarmComponentsToText(const std::vector<std::string> & components, const std::string & psL, const std::string & psS, const std::string & psR) const throw() {
172   if(components.size() == 0) return ("");
173
174   std::vector<std::string>::const_iterator it_min(components.begin());
175   std::vector<std::string>::const_iterator it_max(components.end());
176   std::vector<std::string>::const_iterator it, it_last = it_max - 1;
177   std::string result = psL;
178
179   for(it = it_min; it != it_last; it++) { result += (*it); result += psS; }
180
181   result += (*it_last);
182   result += psR;
183   return (result);
184 }
185
186
187 //------------------------------------------------------------------------------
188 //------------------------------ Module::getAlarmPreffixSuffixAndZoneSeparator()
189 //------------------------------------------------------------------------------
190 void anna::oam::Module::getAlarmPreffixSuffixAndZoneSeparator(std::string & preffix, std::string & suffix, char & zS) const throw() {
191   Configuration &conf = Configuration::instantiate();
192   const std::vector<std::string> * globalPreffixComponents = conf.getAlarmPreffixComponents();
193   const std::vector<std::string> * globalSuffixComponents = conf.getAlarmSuffixComponents();
194   std::vector<std::string> preffixComponents, suffixComponents, compsAux;
195
196   if(globalPreffixComponents) preffixComponents = *globalPreffixComponents;
197
198   if(globalSuffixComponents) suffixComponents = *globalSuffixComponents;
199
200   if(a_alarms_preffix_enabled) {
201     // Read from virtual and append to global configuration ones:
202     readAlarmPreffixComponents(compsAux);
203
204     if(compsAux.size() != 0) preffixComponents.insert(preffixComponents.begin(), compsAux.begin(), compsAux.end());
205   }
206
207   if(a_alarms_suffix_enabled) {
208     // Read from virtual and append to global configuration ones:
209     compsAux.clear();
210     readAlarmSuffixComponents(compsAux);
211
212     if(compsAux.size() != 0) suffixComponents.insert(suffixComponents.begin(), compsAux.begin(), compsAux.end());
213   }
214
215   // Build final preffix and suffix from its components:
216   std::string psL, psS, psR;
217   conf.getAlarmTextDelimiters(zS, psL, psS, psR);
218   preffix = alarmComponentsToText(preffixComponents, psL, psS, psR);
219   suffix = alarmComponentsToText(suffixComponents, psL, psS, psR);
220 }
221
222
223
224
225 //------------------------------------------------------------------------------
226 //--------------------------------------------- Module::initializeCounterScope()
227 //------------------------------------------------------------------------------
228 void anna::oam::Module::initializeCounterScope(const int & scopeId, const std::string & description) throw(anna::RuntimeException) {
229   LOGMETHOD(anna::TraceMethod tttm("anna::oam::Module", "initializeCounterScope", ANNA_FILE_LOCATION));
230
231   // Order of use:
232   // https://redmine.teslayout.com/issues/48
233   //if(a_counters.size() != 0)  // any counter have been registered
234   //  throw anna::RuntimeException("After use of counter registration can't initialize more scope ids!. Do initializations firstly", ANNA_FILE_LOCATION);
235
236   // Scope range: 0 - 99
237   if(scopeId < 0 || scopeId >= MaxScope) {
238     std::string msg = "Scope Id must be in range [0 - ";
239     msg += anna::functions::asString(MaxScope - 1); // 99
240     msg += "]";
241     throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
242   }
243
244   // Check module scopes:
245   if(getScope(scopeId)) {
246     std::string msg = "Scope Id '";
247     msg += anna::functions::asString(scopeId);
248     msg += "' has already been registered in this module!";
249     throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
250   }
251
252   // Create scope:
253   bool missingScopeDescription = (description == "");
254   LOGWARNING(
255
256   if(missingScopeDescription && a_scopes.size() != 0) {
257   anna::Logger::warning("This is not the first initialized scope. Perhaps you should provide specific description better than general module name ...", ANNA_FILE_LOCATION);
258   }
259   );
260   const char * c_description = (missingScopeDescription ? getName() : description.c_str());
261   a_active_counter_scope = new CounterScope(scopeId, c_description);
262   a_scopes[scopeId] = a_active_counter_scope;
263 }
264
265
266 //------------------------------------------------------------------------------
267 //---------------------------------------------- Module::setActiveCounterScope()
268 //------------------------------------------------------------------------------
269 void anna::oam::Module::setActiveCounterScope(const int & scopeId) throw() {
270   anna::oam::CounterScope *scope = getScope(scopeId);
271
272   if(!scope) {
273     anna::Logger::error(anna::functions::asString("Provided scope id '%d' can't be activated, because you must initialize it first", scopeId), ANNA_FILE_LOCATION);
274     return;
275   }
276
277   a_active_counter_scope = scope;
278 }
279
280
281 //------------------------------------------------------------------------------
282 //---------------------------------------------------- Module::registerCounter()
283 //------------------------------------------------------------------------------
284 void anna::oam::Module::registerCounter(const int & type, const std::string & description, const int & offset) throw(anna::RuntimeException) {
285   // Handler-specific
286   a_handler->registerCounter(this, type, description, offset);
287
288   // Order of use:
289   if(a_scopes.size() == 0)  // at least one scope must be initialized
290     throw anna::RuntimeException("Before counter registration, at least one counter scope must be initialized at oam module", ANNA_FILE_LOCATION);
291
292   // Check type existence:
293   const_counter_iterator counter_it = counter_find(type);
294
295   if(counter_it != counter_end()) {
296     std::string msg = "There is a former counter registered with enum value (counter type) = ";
297     msg += anna::functions::asString(type);
298     throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
299   }
300
301   // If description is empty, get the default defined
302   std::string _description = ((description != "") ? description : getDefaultInternalCounterDescription(type));
303   counter_data_t aux;
304   aux.Offset = offset;
305   aux.Description = _description;
306   // Register for all initialized scopes:
307
308   for(scope_iterator scope_it = scope_begin(); scope_it != scope_end(); scope_it++) {
309     int scopeId = (*scope_it).first;
310     anna::oam::CounterScope * counterScope = scope(scope_it);
311     counterScope->create(offset, _description.c_str());
312     LOGDEBUG
313     (
314       std::string msg = "Added counter '";
315       msg += _description;
316       msg += "' over scope '";
317       msg += counterScope->getName();
318       msg += "': ScopeId/Offset [RealCounterId] = ";
319       msg += anna::functions::asString(scopeId); msg += "/";
320       msg += anna::functions::asString(offset); msg += " [";
321       msg += anna::functions::asString((scopeId * anna::oam::CounterScope::MaxCounter) + offset); msg += "]";
322       anna::Logger::debug(msg, ANNA_FILE_LOCATION);
323     );
324   }
325
326   a_counters[type] = aux;
327 }
328
329
330
331 //------------------------------------------------------------------------------
332 //------------------------------------------------------ Module::registerAlarm()
333 //------------------------------------------------------------------------------
334 void anna::oam::Module::registerAlarm(const int & type, const std::string &description, const int & externalId, const std::string & dynamicVariablesCSL, const int & activationId, const int & cancellationId) throw(anna::RuntimeException) {
335   // Handler-specific
336   a_handler->registerAlarm(this, type, description, externalId, dynamicVariablesCSL, activationId, cancellationId);
337   // Check type existence:
338   const_alarm_iterator alarm_it = alarm_find(type);
339
340   if(alarm_it != alarm_end()) {
341     std::string msg = "There is a former alarm registered with enum value (alarm type) = ";
342     msg += anna::functions::asString(type);
343     throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
344   }
345
346   // If description is empty, get the default defined
347   std::string _description = ((description != "") ? description : getDefaultInternalAlarmDescription(type));
348   alarm_data_t aux;
349   aux.ExternalId = externalId;
350   aux.DynamicVariablesCSL = dynamicVariablesCSL;
351   aux.ActivationId = activationId;
352   aux.CancellationId = cancellationId;
353   aux.Description = _description;
354   a_alarms[type] = aux;
355   LOGDEBUG
356   (
357     std::string msg = "Added alarm '";
358     msg += _description;
359     msg += "': externalId[dynamicVariablesCSL]/activationId";
360
361     if(cancellationId != -1) msg += "/cancellationId";
362     msg += " = ";
363     msg += anna::functions::asString(externalId); msg += "[";
364     msg += anna::functions::asString(dynamicVariablesCSL); msg += "]/";
365     msg += anna::functions::asString(activationId);
366   if(cancellationId != -1) {
367     msg += "/";
368     msg += anna::functions::asString(cancellationId);
369     }
370   anna::Logger::debug(msg, ANNA_FILE_LOCATION);
371   );
372 }
373
374
375 //------------------------------------------------------------------------------
376 //------------------------------------------------------ Module::activateAlarm()
377 //------------------------------------------------------------------------------
378 void anna::oam::Module::alarmEvent(bool activation, const int & type, va_list argList) const throw() {
379   // Preffix/Suffix and separator:
380   std::string userPreffix, userSuffix; char separator;
381   getAlarmPreffixSuffixAndZoneSeparator(userPreffix, userSuffix, separator);
382   const char *preffix = ((userPreffix != "") ? userPreffix.c_str() : NULL);
383   const char *suffix = ((userSuffix != "") ? userSuffix.c_str() : NULL);
384   va_list ap;
385   va_copy(ap, argList); // http://julipedia.meroh.net/2011/09/using-vacopy-to-safely-pass-ap.html
386   a_handler->alarmEvent(this, preffix, suffix, separator, activation, type, ap);
387   va_end(ap);
388 }
389
390
391 //------------------------------------------------------------------------------
392 //------------------------------------------------------ Module::activateAlarm()
393 //------------------------------------------------------------------------------
394 void anna::oam::Module::activateAlarm(int type, ...) const throw(anna::RuntimeException) {
395 //   LOGMETHOD(anna::TraceMethod tttm("anna::oam::Module", "activateAlarm", ANNA_FILE_LOCATION));
396
397   // Checkings
398   if(!a_alarms_enabled) {
399     LOGDEBUG
400     (
401       std::string msg = "Alarm activation ignored over module '";
402       msg += getName();
403       msg += "': alarms are disabled";
404       anna::Logger::debug(msg, ANNA_FILE_LOCATION);
405     );
406     return;
407   }
408
409   // User alarm event
410   va_list argList;
411   va_start(argList, type);
412   alarmEvent(true, type, argList);
413   va_end(argList);
414 }
415
416
417 //------------------------------------------------------------------------------
418 //-------------------------------------------------------- Module::cancelAlarm()
419 //------------------------------------------------------------------------------
420 void anna::oam::Module::cancelAlarm(int type, ...) const throw(anna::RuntimeException) {
421 //   LOGMETHOD(anna::TraceMethod tttm("anna::oam::Module", "cancelAlarm", ANNA_FILE_LOCATION));
422
423   // Checkings
424   if(!a_alarms_enabled) {
425     LOGDEBUG
426     (
427       std::string msg = "Alarm cancellation ignored over module '";
428       msg += getName();
429       msg += "': alarms are disabled";
430       anna::Logger::debug(msg, ANNA_FILE_LOCATION);
431     );
432     return;
433   }
434
435   // User alarm event
436   va_list argList;
437   va_start(argList, type);
438   alarmEvent(false, type, argList);
439   va_end(argList);
440 }
441
442
443 //------------------------------------------------------------------------------
444 //-------------------------------------------------------------- Module::count()
445 //------------------------------------------------------------------------------
446 void anna::oam::Module::count(const int & type, const int & amount) throw(anna::RuntimeException) {
447 //   LOGMETHOD(anna::TraceMethod tttm("anna::oam::Module", "count", ANNA_FILE_LOCATION));
448
449   // Checkings
450   if(!a_counters_enabled) {
451     LOGDEBUG
452     (
453       std::string msg = "Count operation ignored over module '";
454       msg += getName();
455       msg += "': counters are disabled";
456       anna::Logger::debug(msg, ANNA_FILE_LOCATION);
457     );
458     return;
459   }
460
461   a_handler->counterEvent(this, type, amount);
462 }
463
464
465 //------------------------------------------------------------------------------
466 //------------------------------------------------------ Module::resetCounters()
467 //------------------------------------------------------------------------------
468 int anna::oam::Module::resetCounters(const int & scopeId) throw() {
469   LOGMETHOD(anna::TraceMethod tttm("anna::oam::Module", "resetCounters", ANNA_FILE_LOCATION));
470   int result = 0; // affected number
471
472   for(scope_iterator scope_it = scope_begin(); scope_it != scope_end(); scope_it++)
473     result += scope(scope_it)->resetAccValues();
474
475   return result;
476 }
477
478
479 //------------------------------------------------------------------------------
480 //------------------------------------- Module::RecordingGuard::RecordingGuard()
481 //------------------------------------------------------------------------------
482 anna::oam::Module::RecordingGuard::RecordingGuard(anna::oam::Module* module) :
483   a_module(module) {
484   module->a_counterRecording = true;
485 }
486
487
488 //------------------------------------------------------------------------------
489 //------------------------------------ Module::RecordingGuard::~RecordingGuard()
490 //------------------------------------------------------------------------------
491 anna::oam::Module::RecordingGuard::~RecordingGuard() {
492   a_module->a_counterRecording = false;
493 }
494
495
496 //------------------------------------------------------------------------------
497 //----------------------------------------------------- Module::recordCounters()
498 //------------------------------------------------------------------------------
499 void anna::oam::Module::recordCounters() throw(anna::RuntimeException) {
500   LOGMETHOD(anna::TraceMethod tttm("anna::oam::Module", "recordCounters", ANNA_FILE_LOCATION));
501
502   if(a_counterRecorder == NULL)
503     throw RuntimeException("anna::oam::Module has no counter recorder associated", ANNA_FILE_LOCATION);
504
505   LOGDEBUG(
506     std::string msg("Recording counters | ");
507     msg += a_counterRecorder->asString();
508     anna::Logger::write(Logger::Debug, msg, ANNA_FILE_LOCATION)
509   );
510   RecordingGuard guard(this);
511
512   a_counterRecorder->open();
513   CounterScope* cscope = NULL;
514
515   try {
516     for(scope_iterator scope_it = scope_begin(); scope_it != scope_end(); scope_it++) {
517       cscope = scope(scope_it);
518       if(cscope == NULL) continue;
519
520       Guard csGuard(cscope, "oam::CounterScope from oam::Module::record");
521
522       for(int icounter = 0; icounter < CounterScope::MaxCounter; icounter ++) {
523         Counter* counter = cscope->a_counters [icounter];
524
525         if(counter == NULL)
526           continue;
527
528         if(counter->getValue() == 0)
529           continue;
530
531         a_counterRecorder->apply(*counter);
532         counter->reset();
533       }
534     }
535
536     a_counterRecorder->close();
537   } catch(anna::RuntimeException&) {
538     a_counterRecorder->close();
539     throw;
540   }
541 }
542
543 //------------------------------------------------------------------------------
544 //----------------------------------------------------------- Module::asString()
545 //------------------------------------------------------------------------------
546 std::string anna::oam::Module::asString(void) const throw() {
547   std::string trace;
548   trace = "Module name: '";
549   trace += getName();
550   trace += "'";
551   trace += "\n\nCOUNTERS"; trace += "\n--------";
552   trace += "\nScoped counters "; trace += a_counters_enabled ? "Enabled" : "Disabled";
553   trace += "\nCounter Scopes: "; trace += anna::functions::asString(a_scopes.size());
554
555   for(const_scope_iterator scope_it = scope_begin(); scope_it != scope_end(); scope_it++) {
556     trace += "\n\nCounter Scope:";
557     int scopeId = (*scope_it).first;
558     trace += " Id: "; trace += anna::functions::asString(scopeId);
559     trace += " | Description: '"; trace += scope(scope_it)->getName(); trace += "'";
560     trace += "\nRegistered counters:\n";
561     counter_data_t * ptrCounterData;
562
563     for(const_counter_iterator cnt_it = counter_begin(); cnt_it != counter_end(); cnt_it++) {
564       ptrCounterData = (counter_data_t *) & ((*cnt_it).second);
565
566       // Counter registered ?
567       int offset = ptrCounterData->Offset;
568       unsigned long long int accValue = 0ULL;
569       try {
570         const anna::oam::CounterScope *csAux = scope(scope_it);
571         accValue = csAux->getAccValue(offset);
572       } catch(anna::RuntimeException &ex) {
573         ex.trace();
574         continue;
575       }
576
577       // Counter:
578       trace += "\n\tType: "; trace += anna::functions::asString((*cnt_it).first);
579       trace += " | Description: '"; trace += ptrCounterData->Description; trace += "'";
580       int realId = (1000 * scopeId) + offset;
581       trace += " | ScopeId/Offset: "; trace += anna::functions::asString(scopeId); trace += "/"; trace += anna::functions::asString(offset);
582       trace += " | RealId: "; trace += anna::functions::asString(realId);
583       accValue = scope(scope_it)->getAccValue(offset);
584
585       if(accValue != 0ULL) {
586         trace += " | AccumulatedAmount: ";
587         trace += anna::functions::asString("%llu", accValue);
588       }
589     }
590   }
591
592   trace += "\n\nALARMS"; trace += "\n------";
593   trace += "\nScoped alarms "; trace += a_alarms_enabled ? "Enabled" : "Disabled";
594   trace += "\nPreffix alarm components: "; trace += a_alarms_preffix_enabled ? "Shown" : "Hidden";
595   trace += "\nSuffix alarm components: "; trace += a_alarms_suffix_enabled ? "Shown" : "Hidden";
596   trace += "\nRegistered alarms:\n";
597
598   for(const_alarm_iterator alrm_it = alarm_begin(); alrm_it != alarm_end(); alrm_it++) {
599     int cancellationId = (*alrm_it).second.CancellationId;
600     bool transferable = (cancellationId != -1);
601     trace += "\n\tType: "; trace += anna::functions::asString((*alrm_it).first);
602     trace += " | Description: '"; trace += (*alrm_it).second.Description;
603     trace += transferable ? "' [transferable alarm]" : "'";
604     trace += " | DatabaseId: "; trace += anna::functions::asString((*alrm_it).second.ExternalId);
605     trace += " | dynamicVariablesCSL: "; trace += (*alrm_it).second.DynamicVariablesCSL;
606     trace += " | ActivationId: "; trace += anna::functions::asString((*alrm_it).second.ActivationId);
607
608     if(transferable) { trace += " | CancellationId: "; trace += anna::functions::asString(cancellationId); }
609   }
610
611   return (trace);
612 }
613
614
615
616 //------------------------------------------------------------------------------
617 //-------------------------------------------------------------- Module::asXML()
618 //------------------------------------------------------------------------------
619 anna::xml::Node* anna::oam::Module::asXML(anna::xml::Node* parent) const throw() {
620   anna::xml::Node* result = parent->createChild("oam.Module");
621   result->createAttribute("Name", getName());
622   result->createAttribute("Counters", a_counters_enabled ? "Enabled" : "Disabled");
623   anna::xml::Node* registeredCounterScopes = result->createChild("RegisteredCounterScopes");
624
625   for(const_scope_iterator scope_it = scope_begin(); scope_it != scope_end(); scope_it++) {
626     // Scope:
627     anna::xml::Node* scopeNode = registeredCounterScopes->createChild("Scope");
628     int scopeId = (*scope_it).first;
629     scopeNode->createAttribute("Id", anna::functions::asString(scopeId));
630     scopeNode->createAttribute("Description", scope(scope_it)->getName());
631     // Counters:
632     anna::xml::Node* registeredCounters = scopeNode->createChild("RegisteredCounters");
633     counter_data_t * ptrCounterData;
634
635     for(const_counter_iterator cnt_it = counter_begin(); cnt_it != counter_end(); cnt_it++) {
636       ptrCounterData = (counter_data_t *) & ((*cnt_it).second);
637
638       // Counter registered ?
639       int offset = ptrCounterData->Offset;
640       unsigned long long int accValue = 0ULL;
641       try {
642         const anna::oam::CounterScope *csAux = scope(scope_it);
643         accValue = csAux->getAccValue(offset);
644       } catch(anna::RuntimeException &ex) {
645         ex.trace();
646         continue;
647       }
648
649       // Counter:
650       anna::xml::Node* counter = registeredCounters->createChild("Counter");
651       counter->createAttribute("Type", anna::functions::asString((*cnt_it).first));
652       counter->createAttribute("Description", ptrCounterData->Description);
653       int realId = (1000 * scopeId) + offset;
654       counter->createAttribute("ScopeId", anna::functions::asString(scopeId));
655       counter->createAttribute("Offset", anna::functions::asString(offset));
656       counter->createAttribute("RealId", anna::functions::asString(realId));
657
658       if(accValue != 0ULL)
659         counter->createAttribute("AccumulatedAmount", anna::functions::asString("%llu", accValue));
660     }
661   }
662
663   result->createAttribute("Alarms", a_alarms_enabled ? "Enabled" : "Disabled");
664   result->createAttribute("PreffixAlarmComponents", a_alarms_preffix_enabled ? "Shown" : "Hidden");
665   result->createAttribute("SuffixAlarmComponents", a_alarms_suffix_enabled ? "Shown" : "Hidden");
666   anna::xml::Node* registeredAlarms = result->createChild("RegisteredAlarms");
667
668   for(const_alarm_iterator alrm_it = alarm_begin(); alrm_it != alarm_end(); alrm_it++) {
669     anna::xml::Node* alarm;
670     int cancellationId = (*alrm_it).second.CancellationId;
671     bool transferable = (cancellationId != -1);
672     alarm  = registeredAlarms->createChild("Alarm");
673     alarm->createAttribute("Type", anna::functions::asString((*alrm_it).first));
674     std::string desc = (*alrm_it).second.Description; desc += " ["; desc += transferable ? "transferable]" : "non transferable]";
675     alarm->createAttribute("Description", desc);
676     alarm->createAttribute("DatabaseId", anna::functions::asString((*alrm_it).second.ExternalId));
677     alarm->createAttribute("DynamicVariablesCSL", (*alrm_it).second.DynamicVariablesCSL);
678     alarm->createAttribute("ActivationId", anna::functions::asString((*alrm_it).second.ActivationId));
679
680     if(transferable) alarm->createAttribute("CancellationId", anna::functions::asString(cancellationId));
681   }
682
683   return result;
684 }
685