Fix local server for multiple applications
[anna.git] / 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   if(a_counters.size() != 0)  // any counter have been registered
233     throw anna::RuntimeException("After use of counter registration can't initialize more scope ids!. Do initializations firstly", ANNA_FILE_LOCATION);
234
235   // Scope range: 0 - 99
236   if(scopeId < 0 || scopeId >= MaxScope) {
237     std::string msg = "Scope Id must be in range [0 - ";
238     msg += anna::functions::asString(MaxScope - 1); // 99
239     msg += "]";
240     throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
241   }
242
243   // Check module scopes:
244   if(getScope(scopeId)) {
245     std::string msg = "Scope Id '";
246     msg += anna::functions::asString(scopeId);
247     msg += "' has already been registered in this module!";
248     throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
249   }
250
251   // Create scope:
252   bool missingScopeDescription = (description == "");
253   LOGWARNING(
254
255   if(missingScopeDescription && a_scopes.size() != 0) {
256   anna::Logger::warning("This is not the first initialized scope. Perhaps you should provide specific description better than general module name ...", ANNA_FILE_LOCATION);
257   }
258   );
259   const char * c_description = (missingScopeDescription ? getName() : description.c_str());
260   a_active_counter_scope = new CounterScope(scopeId, c_description);
261   a_scopes[scopeId] = a_active_counter_scope;
262 }
263
264
265 //------------------------------------------------------------------------------
266 //---------------------------------------------- Module::setActiveCounterScope()
267 //------------------------------------------------------------------------------
268 void anna::oam::Module::setActiveCounterScope(const int & scopeId) throw() {
269   anna::oam::CounterScope *scope = getScope(scopeId);
270
271   if(!scope) {
272     anna::Logger::error(anna::functions::asString("Provided scope id '%d' can't be activated, because you must initialize it first", scopeId), ANNA_FILE_LOCATION);
273     return;
274   }
275
276   a_active_counter_scope = scope;
277 }
278
279
280 //------------------------------------------------------------------------------
281 //---------------------------------------------------- Module::registerCounter()
282 //------------------------------------------------------------------------------
283 void anna::oam::Module::registerCounter(const int & type, const std::string & description, const int & offset) throw(anna::RuntimeException) {
284   // Handler-specific
285   a_handler->registerCounter(this, type, description, offset);
286
287   // Order of use:
288   if(a_scopes.size() == 0)  // at least one scope must be initialized
289     throw anna::RuntimeException("Before counter registration, at least one counter scope must be initialized at oam module", ANNA_FILE_LOCATION);
290
291   // Check type existence:
292   const_counter_iterator counter_it = counter_find(type);
293
294   if(counter_it != counter_end()) {
295     std::string msg = "There is a former counter registered with enum value (counter type) = ";
296     msg += anna::functions::asString(type);
297     throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
298   }
299
300   // If description is empty, get the default defined
301   std::string _description = ((description != "") ? description : getDefaultInternalCounterDescription(type));
302   counter_data_t aux;
303   aux.Offset = offset;
304   aux.Description = _description;
305   // Register for all initialized scopes:
306
307   for(scope_iterator scope_it = scope_begin(); scope_it != scope_end(); scope_it++) {
308     int scopeId = (*scope_it).first;
309     anna::oam::CounterScope * counterScope = scope(scope_it);
310     counterScope->create(offset, _description.c_str());
311     LOGDEBUG
312     (
313       std::string msg = "Added counter '";
314       msg += _description;
315       msg += "' over scope '";
316       msg += counterScope->getName();
317       msg += "': ScopeId/Offset [RealCounterId] = ";
318       msg += anna::functions::asString(scopeId); msg += "/";
319       msg += anna::functions::asString(offset); msg += " [";
320       msg += anna::functions::asString((scopeId * anna::oam::CounterScope::MaxCounter) + offset); msg += "]";
321       anna::Logger::debug(msg, ANNA_FILE_LOCATION);
322     );
323   }
324
325   a_counters[type] = aux;
326 }
327
328
329
330 //------------------------------------------------------------------------------
331 //------------------------------------------------------ Module::registerAlarm()
332 //------------------------------------------------------------------------------
333 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) {
334   // Handler-specific
335   a_handler->registerAlarm(this, type, description, externalId, dynamicVariablesCSL, activationId, cancellationId);
336   // Check type existence:
337   const_alarm_iterator alarm_it = alarm_find(type);
338
339   if(alarm_it != alarm_end()) {
340     std::string msg = "There is a former alarm registered with enum value (alarm type) = ";
341     msg += anna::functions::asString(type);
342     throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
343   }
344
345   // If description is empty, get the default defined
346   std::string _description = ((description != "") ? description : getDefaultInternalAlarmDescription(type));
347   alarm_data_t aux;
348   aux.ExternalId = externalId;
349   aux.DynamicVariablesCSL = dynamicVariablesCSL;
350   aux.ActivationId = activationId;
351   aux.CancellationId = cancellationId;
352   aux.Description = _description;
353   a_alarms[type] = aux;
354   LOGDEBUG
355   (
356     std::string msg = "Added alarm '";
357     msg += _description;
358     msg += "': externalId[dynamicVariablesCSL]/activationId";
359
360     if(cancellationId != -1) msg += "/cancellationId";
361     msg += " = ";
362     msg += anna::functions::asString(externalId); msg += "[";
363     msg += anna::functions::asString(dynamicVariablesCSL); msg += "]/";
364     msg += anna::functions::asString(activationId);
365   if(cancellationId != -1) {
366     msg += "/";
367     msg += anna::functions::asString(cancellationId);
368     }
369   anna::Logger::debug(msg, ANNA_FILE_LOCATION);
370   );
371 }
372
373
374 //------------------------------------------------------------------------------
375 //------------------------------------------------------ Module::activateAlarm()
376 //------------------------------------------------------------------------------
377 void anna::oam::Module::alarmEvent(bool activation, const int & type, va_list argList) const throw() {
378   // Preffix/Suffix and separator:
379   std::string userPreffix, userSuffix; char separator;
380   getAlarmPreffixSuffixAndZoneSeparator(userPreffix, userSuffix, separator);
381   const char *preffix = ((userPreffix != "") ? userPreffix.c_str() : NULL);
382   const char *suffix = ((userSuffix != "") ? userSuffix.c_str() : NULL);
383   va_list ap;
384   va_copy(ap, argList); // http://julipedia.meroh.net/2011/09/using-vacopy-to-safely-pass-ap.html
385   a_handler->alarmEvent(this, preffix, suffix, separator, activation, type, ap);
386   va_end(ap);
387 }
388
389
390 //------------------------------------------------------------------------------
391 //------------------------------------------------------ Module::activateAlarm()
392 //------------------------------------------------------------------------------
393 void anna::oam::Module::activateAlarm(int type, ...) const throw(anna::RuntimeException) {
394 //   LOGMETHOD(anna::TraceMethod tttm("anna::oam::Module", "activateAlarm", ANNA_FILE_LOCATION));
395
396   // Checkings
397   if(!a_alarms_enabled) {
398     LOGDEBUG
399     (
400       std::string msg = "Alarm activation ignored over module '";
401       msg += getName();
402       msg += "': alarms are disabled";
403       anna::Logger::debug(msg, ANNA_FILE_LOCATION);
404     );
405     return;
406   }
407
408   // User alarm event
409   va_list argList;
410   va_start(argList, type);
411   alarmEvent(true, type, argList);
412   va_end(argList);
413 }
414
415
416 //------------------------------------------------------------------------------
417 //-------------------------------------------------------- Module::cancelAlarm()
418 //------------------------------------------------------------------------------
419 void anna::oam::Module::cancelAlarm(int type, ...) const throw(anna::RuntimeException) {
420 //   LOGMETHOD(anna::TraceMethod tttm("anna::oam::Module", "cancelAlarm", ANNA_FILE_LOCATION));
421
422   // Checkings
423   if(!a_alarms_enabled) {
424     LOGDEBUG
425     (
426       std::string msg = "Alarm cancellation ignored over module '";
427       msg += getName();
428       msg += "': alarms are disabled";
429       anna::Logger::debug(msg, ANNA_FILE_LOCATION);
430     );
431     return;
432   }
433
434   // User alarm event
435   va_list argList;
436   va_start(argList, type);
437   alarmEvent(false, type, argList);
438   va_end(argList);
439 }
440
441
442 //------------------------------------------------------------------------------
443 //-------------------------------------------------------------- Module::count()
444 //------------------------------------------------------------------------------
445 void anna::oam::Module::count(const int & type, const int & amount) throw(anna::RuntimeException) {
446 //   LOGMETHOD(anna::TraceMethod tttm("anna::oam::Module", "count", ANNA_FILE_LOCATION));
447
448   // Checkings
449   if(!a_counters_enabled) {
450     LOGDEBUG
451     (
452       std::string msg = "Count operation ignored over module '";
453       msg += getName();
454       msg += "': counters are disabled";
455       anna::Logger::debug(msg, ANNA_FILE_LOCATION);
456     );
457     return;
458   }
459
460   a_handler->counterEvent(this, type, amount);
461 }
462
463
464 //------------------------------------------------------------------------------
465 //------------------------------------------------------ Module::resetCounters()
466 //------------------------------------------------------------------------------
467 int anna::oam::Module::resetCounters(const int & scopeId) throw() {
468   LOGMETHOD(anna::TraceMethod tttm("anna::oam::Module", "resetCounters", ANNA_FILE_LOCATION));
469   int result = 0; // affected number
470
471   for(scope_iterator scope_it = scope_begin(); scope_it != scope_end(); scope_it++)
472     result += scope(scope_it)->resetAccValues();
473
474   return result;
475 }
476
477
478 //------------------------------------------------------------------------------
479 //------------------------------------- Module::RecordingGuard::RecordingGuard()
480 //------------------------------------------------------------------------------
481 anna::oam::Module::RecordingGuard::RecordingGuard(anna::oam::Module* module) :
482   a_module(module) {                                                
483   module->a_counterRecording = true;                                               
484 }                                                                                   
485                                                                                     
486
487 //------------------------------------------------------------------------------
488 //------------------------------------ Module::RecordingGuard::~RecordingGuard()
489 //------------------------------------------------------------------------------
490 anna::oam::Module::RecordingGuard::~RecordingGuard() {                            
491   a_module->a_counterRecording = false;                                            
492 }                                                                                   
493
494
495 //------------------------------------------------------------------------------
496 //----------------------------------------------------- Module::recordCounters()
497 //------------------------------------------------------------------------------
498 void anna::oam::Module::recordCounters() throw(anna::RuntimeException) {
499   LOGMETHOD(anna::TraceMethod tttm("anna::oam::Module", "recordCounters", ANNA_FILE_LOCATION));
500
501   if(a_counterRecorder == NULL)
502     throw RuntimeException("anna::oam::Module has no counter recorder associated", ANNA_FILE_LOCATION);
503
504   LOGDEBUG(
505     std::string msg("Recording counters | ");
506     msg += a_counterRecorder->asString();
507     anna::Logger::write(Logger::Debug, msg, ANNA_FILE_LOCATION)
508   );
509   RecordingGuard guard(this);
510
511   a_counterRecorder->open();
512   CounterScope* cscope = NULL;
513
514   try {
515     for(scope_iterator scope_it = scope_begin(); scope_it != scope_end(); scope_it++) {
516       cscope = scope(scope_it);
517       if(cscope == NULL) continue;
518
519       Guard csGuard(cscope, "oam::CounterScope from oam::Module::record");
520
521       for(int icounter = 0; icounter < CounterScope::MaxCounter; icounter ++) {
522         Counter* counter = cscope->a_counters [icounter];
523
524         if(counter == NULL)
525           continue;
526
527         if(counter->getValue() == 0)
528           continue;
529
530         a_counterRecorder->apply(*counter);
531         counter->reset();
532       }
533     }
534
535     a_counterRecorder->close();
536   } catch(anna::RuntimeException&) {
537     a_counterRecorder->close();
538     throw;
539   }
540 }
541
542 //------------------------------------------------------------------------------
543 //----------------------------------------------------------- Module::asString()
544 //------------------------------------------------------------------------------
545 std::string anna::oam::Module::asString(void) const throw() {
546   std::string trace;
547   trace = "Module name: '";
548   trace += getName();
549   trace += "'";
550   trace += "\n\nCOUNTERS"; trace += "\n--------";
551   trace += "\nScoped counters "; trace += a_counters_enabled ? "Enabled" : "Disabled";
552   trace += "\nCounter Scopes: "; trace += anna::functions::asString(a_scopes.size());
553
554   for(const_scope_iterator scope_it = scope_begin(); scope_it != scope_end(); scope_it++) {
555     trace += "\n\nCounter Scope:";
556     int scopeId = (*scope_it).first;
557     trace += " Id: "; trace += anna::functions::asString(scopeId);
558     trace += " | Description: '"; trace += scope(scope_it)->getName(); trace += "'";
559     trace += "\nRegistered counters:\n";
560     counter_data_t * ptrCounterData;
561
562     for(const_counter_iterator cnt_it = counter_begin(); cnt_it != counter_end(); cnt_it++) {
563       ptrCounterData = (counter_data_t *) & ((*cnt_it).second);
564       // Counter:
565       trace += "\n\tType: "; trace += anna::functions::asString((*cnt_it).first);
566       trace += " | Description: '"; trace += ptrCounterData->Description; trace += "'";
567       int offset = ptrCounterData->Offset;
568       int realId = (1000 * scopeId) + offset;
569       trace += " | ScopeId/Offset: "; trace += anna::functions::asString(scopeId); trace += "/"; trace += anna::functions::asString(offset);
570       trace += " | RealId: "; trace += anna::functions::asString(realId);
571       unsigned long long int accValue = scope(scope_it)->getAccValue(offset);
572
573       if(accValue != 0ULL) {
574         trace += " | AccumulatedAmount: ";
575         trace += anna::functions::asString("%llu", accValue);
576       }
577     }
578   }
579
580   trace += "\n\nALARMS"; trace += "\n------";
581   trace += "\nScoped alarms "; trace += a_alarms_enabled ? "Enabled" : "Disabled";
582   trace += "\nPreffix alarm components: "; trace += a_alarms_preffix_enabled ? "Shown" : "Hidden";
583   trace += "\nSuffix alarm components: "; trace += a_alarms_suffix_enabled ? "Shown" : "Hidden";
584   trace += "\nRegistered alarms:\n";
585
586   for(const_alarm_iterator alrm_it = alarm_begin(); alrm_it != alarm_end(); alrm_it++) {
587     int cancellationId = (*alrm_it).second.CancellationId;
588     bool transferable = (cancellationId != -1);
589     trace += "\n\tType: "; trace += anna::functions::asString((*alrm_it).first);
590     trace += " | Description: '"; trace += (*alrm_it).second.Description;
591     trace += transferable ? "' [transferable alarm]" : "'";
592     trace += " | DatabaseId: "; trace += anna::functions::asString((*alrm_it).second.ExternalId);
593     trace += " | dynamicVariablesCSL: "; trace += (*alrm_it).second.DynamicVariablesCSL;
594     trace += " | ActivationId: "; trace += anna::functions::asString((*alrm_it).second.ActivationId);
595
596     if(transferable) { trace += " | CancellationId: "; trace += anna::functions::asString(cancellationId); }
597   }
598
599   return (trace);
600 }
601
602
603
604 //------------------------------------------------------------------------------
605 //-------------------------------------------------------------- Module::asXML()
606 //------------------------------------------------------------------------------
607 anna::xml::Node* anna::oam::Module::asXML(anna::xml::Node* parent) const throw() {
608   anna::xml::Node* result = parent->createChild("oam.Module");
609   result->createAttribute("Name", getName());
610   result->createAttribute("Counters", a_counters_enabled ? "Enabled" : "Disabled");
611   anna::xml::Node* registeredCounterScopes = result->createChild("RegisteredCounterScopes");
612
613   for(const_scope_iterator scope_it = scope_begin(); scope_it != scope_end(); scope_it++) {
614     // Scope:
615     anna::xml::Node* scopeNode = registeredCounterScopes->createChild("Scope");
616     int scopeId = (*scope_it).first;
617     scopeNode->createAttribute("Id", anna::functions::asString(scopeId));
618     scopeNode->createAttribute("Description", scope(scope_it)->getName());
619     // Counters:
620     anna::xml::Node* registeredCounters = scopeNode->createChild("RegisteredCounters");
621     counter_data_t * ptrCounterData;
622
623     for(const_counter_iterator cnt_it = counter_begin(); cnt_it != counter_end(); cnt_it++) {
624       ptrCounterData = (counter_data_t *) & ((*cnt_it).second);
625       // Counter:
626       anna::xml::Node* counter = registeredCounters->createChild("Counter");
627       counter->createAttribute("Type", anna::functions::asString((*cnt_it).first));
628       counter->createAttribute("Description", ptrCounterData->Description);
629       int offset = ptrCounterData->Offset;
630       int realId = (1000 * scopeId) + offset;
631       counter->createAttribute("ScopeId", anna::functions::asString(scopeId));
632       counter->createAttribute("Offset", anna::functions::asString(offset));
633       counter->createAttribute("RealId", anna::functions::asString(realId));
634       unsigned long long int accValue = scope(scope_it)->getAccValue(offset);
635
636       if(accValue != 0ULL)
637         counter->createAttribute("AccumulatedAmount", anna::functions::asString("%llu", accValue));
638     }
639   }
640
641   result->createAttribute("Alarms", a_alarms_enabled ? "Enabled" : "Disabled");
642   result->createAttribute("PreffixAlarmComponents", a_alarms_preffix_enabled ? "Shown" : "Hidden");
643   result->createAttribute("SuffixAlarmComponents", a_alarms_suffix_enabled ? "Shown" : "Hidden");
644   anna::xml::Node* registeredAlarms = result->createChild("RegisteredAlarms");
645
646   for(const_alarm_iterator alrm_it = alarm_begin(); alrm_it != alarm_end(); alrm_it++) {
647     anna::xml::Node* alarm;
648     int cancellationId = (*alrm_it).second.CancellationId;
649     bool transferable = (cancellationId != -1);
650     alarm  = registeredAlarms->createChild("Alarm");
651     alarm->createAttribute("Type", anna::functions::asString((*alrm_it).first));
652     std::string desc = (*alrm_it).second.Description; desc += " ["; desc += transferable ? "transferable]" : "non transferable]";
653     alarm->createAttribute("Description", desc);
654     alarm->createAttribute("DatabaseId", anna::functions::asString((*alrm_it).second.ExternalId));
655     alarm->createAttribute("DynamicVariablesCSL", (*alrm_it).second.DynamicVariablesCSL);
656     alarm->createAttribute("ActivationId", anna::functions::asString((*alrm_it).second.ActivationId));
657
658     if(transferable) alarm->createAttribute("CancellationId", anna::functions::asString(cancellationId));
659   }
660
661   return result;
662 }
663