44a235f99272d4253f5851f4171608090179db14
[anna.git] / source / diameter.comm / ApplicationMessageOamModule.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 // Standard
10 #include <algorithm>
11
12 // Project
13 #include <anna/diameter.comm/ApplicationMessageOamModule.hpp>
14 #include <anna/core/mt/Guard.hpp>
15 #include <anna/core/functions.hpp>
16 #include <anna/core/oam/CounterScope.hpp>
17 #include <anna/diameter/stack/Engine.hpp>
18
19
20 anna_assign_enum(anna::diameter::comm::ApplicationMessageOamModule::Counter) = { \
21     "Request_SentOK_AsClient", \
22     "Request_SentNOK_AsClient", \
23     "Answer_SentOK_AsClient", \
24     "Answer_SentNOK_AsClient", \
25     "Request_Received_AsClient", \
26     "Answer_Received_AsClient", \
27     "Answer_UnknownReceived_AsClient", \
28
29     "Request_SentOK_AsServer", \
30     "Request_SentNOK_AsServer", \
31     "Answer_SentOK_AsServer", \
32     "Answer_SentNOK_AsServer", \
33     "Request_Received_AsServer", \
34     "Answer_Received_AsServer", \
35     "Answer_UnknownReceived_AsServer", \
36     NULL /* list end indicator */
37 };
38
39 void anna::diameter::comm::ApplicationMessageOamModule::createStackCounterScope(int scopeId, unsigned int stackId) throw(anna::RuntimeException) {
40
41   initializeCounterScope(scopeId, anna::functions::asString("Application Message Events for stack id %lu", stackId));
42
43   // Better to be enabled by application in order to be more conscious of the native disabled nature of this special oam module
44   //if (!countersEnabled()) enableCounters();
45   //enableAlarms(); not yet implemented
46
47   a_stackMap[stackId] = scopeId;
48 }
49
50 void anna::diameter::comm::ApplicationMessageOamModule::count (int messageCode, unsigned int stackId, const int & type, const int & amount) throw(anna::RuntimeException) {
51
52   // Optimization:
53   // Checkings
54   if(!countersEnabled()) {
55     LOGDEBUG
56     (
57       std::string msg = "Count operation ignored over module '";
58       msg += getName();
59       msg += "': counters are disabled";
60       anna::Logger::debug(msg, ANNA_FILE_LOCATION);
61     );
62     return;
63   }
64
65   anna::Guard guard(a_mutex, "ApplicationMessageOamModule::count"); // counter scope switch
66
67   std::map<unsigned int /* stack id */, int /* scope id */>::const_iterator stackMap_it = a_stackMap.find(stackId);
68
69   if (stackMap_it == a_stackMap.end()) {
70     LOGDEBUG(anna::Logger::debug(anna::functions::asString("Unregistered stack id %lu", stackId), ANNA_FILE_LOCATION));
71     return;
72   }
73
74   // Select counter scope 
75   setActiveCounterScope(stackMap_it->second);
76  
77   std::map<int /* message code */, int /* base offset */>::const_iterator messageMap_it = a_messageMap.find(messageCode);
78   int baseOffset = messageMap_it->second;
79      
80   if (messageMap_it == a_messageMap.end()) {
81     int capacity = anna::oam::CounterScope::MaxCounter / getCounterTypes();
82     if (a_messageMap.size() > capacity) {
83       LOGDEBUG(anna::Logger::debug(anna::functions::asString("No more holes to register new application message counters in the scope (up to %d message codes)", capacity), ANNA_FILE_LOCATION));
84       return;
85     }
86     baseOffset = getCounterTypes() * a_messageMap.size(); // N counter types for each message code
87     a_messageMap[messageCode] = baseOffset;
88
89     // Counter name:
90     std::string counterNamePrefix = anna::functions::asString("ApplicationMessageCode_%d", messageCode); // default
91     anna::diameter::stack::Engine &stackEngine = anna::diameter::stack::Engine::instantiate();
92     const anna::diameter::stack::Dictionary *dictionary = stackEngine.getDictionary(stackId);
93     if (dictionary) {
94       anna::diameter::CommandId cidR(messageCode, true /* request */);
95       anna::diameter::CommandId cidA(messageCode, false /* answer */);
96       const anna::diameter::stack::Command *commandR = dictionary->getCommand(cidR);
97       const anna::diameter::stack::Command *commandA = dictionary->getCommand(cidA);
98       if (commandR && commandA) {
99         std::string string1 = commandR->getName();
100         std::string string2 = commandA->getName();
101         std::string intersection; // non-standard names will be also intersected: XXR and XXA gives XX
102         std::set_intersection(string1.begin(), string1.end(), string2.begin(), string2.end(), std::back_inserter(intersection));
103         counterNamePrefix = intersection;
104         // Special case:
105         if (counterNamePrefix == "") counterNamePrefix = string1 + "#" + string2;
106       }
107     } 
108
109     if (counterNamePrefix[counterNamePrefix.size() - 1] != '-') counterNamePrefix += "-";
110     for (int offset = 0; offset < getCounterTypes(); offset++)
111       registerCounter(baseOffset + offset, counterNamePrefix + getDefaultInternalCounterDescription(offset), baseOffset + offset);
112   }
113
114   // Count
115   Module::count(baseOffset + type, amount);
116 }
117