test
[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, int resultCode, 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   int scopeId = monoStackScopeId();
68   if (scopeId == -1) {
69     std::map<unsigned int /* stack id */, int /* scope id */>::const_iterator stackMap_it = a_stackMap.find(stackId);
70
71     if (stackMap_it == a_stackMap.end()) {
72       LOGDEBUG(anna::Logger::debug(anna::functions::asString("Unregistered stack id %lu", stackId), ANNA_FILE_LOCATION));
73       return;
74     }
75
76     scopeId = stackMap_it->second;
77   }
78
79   // Select counter scope 
80   setActiveCounterScope(scopeId);
81
82   // Build event id: <message code>_<result code>
83   std::string eventId = anna::functions::asString("%d_%d", messageCode, resultCode); 
84
85   std::map<std::string /* event id */, int /* base offset */>::const_iterator eventMap_it = a_eventMap.find(eventId);
86   int baseOffset;
87      
88   if (eventMap_it == a_eventMap.end()) {
89     int capacity = anna::oam::CounterScope::MaxCounter / getCounterTypes();
90     if (a_eventMap.size() > capacity) {
91       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));
92       return;
93     }
94     baseOffset = getCounterTypes() * a_eventMap.size(); // N counter types for each message code / rc
95     a_eventMap[eventId] = baseOffset;
96
97     // Counter name:
98     std::string counterNamePrefix = anna::functions::asString("ApplicationMessageCode_%d", messageCode); // default
99     anna::diameter::stack::Engine &stackEngine = anna::diameter::stack::Engine::instantiate();
100     const anna::diameter::stack::Dictionary *dictionary = stackEngine.getDictionary(stackId);
101     if (dictionary) {
102       anna::diameter::CommandId cidR(messageCode, true /* request */);
103       anna::diameter::CommandId cidA(messageCode, false /* answer */);
104       const anna::diameter::stack::Command *commandR = dictionary->getCommand(cidR);
105       const anna::diameter::stack::Command *commandA = dictionary->getCommand(cidA);
106       if (commandR && commandA) {
107         std::string string1 = commandR->getName();
108         std::string string2 = commandA->getName();
109         std::string intersection; // non-standard names will be also intersected: XXR and XXA gives XX
110         std::set_intersection(string1.begin(), string1.end(), string2.begin(), string2.end(), std::back_inserter(intersection));
111         counterNamePrefix = intersection;
112         // Special case:
113         if (counterNamePrefix == "") counterNamePrefix = string1 + "#" + string2;
114       }
115     } 
116
117     if (counterNamePrefix[counterNamePrefix.size() - 1] != '-') counterNamePrefix += "-";
118     std::string counterName;
119     /*
120     for (int offset = 0; offset < getCounterTypes(); offset++) {
121       counterName = counterNamePrefix + getDefaultInternalCounterDescription(offset);
122       if (resultCode != -1) counterName += anna::functions::asString("-ResultCode_%d", resultCode);
123       registerCounter(baseOffset + offset, counterName, baseOffset + offset);
124     }
125     */
126     // Register only affected one:
127     int offset = baseOffset + type;
128     counterName = counterNamePrefix + getDefaultInternalCounterDescription(type);
129     if (resultCode != -1) counterName += anna::functions::asString("-ResultCode_%d", resultCode);
130     registerCounter(offset, counterName, offset);
131     
132   }
133   else {
134     baseOffset = eventMap_it->second;
135   }
136
137   // Count
138   Module::count(baseOffset + type, amount);
139 }
140