First commit
[anna.git] / source / core / oam / CounterScope.cpp
1 // ANNA - Anna is Not 'N' Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // https://bitbucket.org/testillano/anna
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 #include <string>
38
39 #include <anna/core/tracing/Logger.hpp>
40
41 #include <anna/xml/Node.hpp>
42 #include <anna/xml/Attribute.hpp>
43
44 #include <anna/timex/Engine.hpp>
45
46 #include <anna/core/oam/CounterManager.hpp>
47 #include <anna/core/oam/CounterScope.hpp>
48 #include <anna/core/oam/Counter.hpp>
49
50 using namespace std;
51 using namespace anna;
52
53 #define test_range(index) \
54    if (index < 0 || index >= MaxCounter) { \
55       string msg (asString ()); \
56       msg += functions::asText (" | Index: ", index); \
57       msg += functions::asText (" | Out of range [0, MaxCounter): ", index); \
58       throw RuntimeException (msg, __FILE__, __LINE__); \
59    }
60
61 #define test_instance(index) \
62    if (a_counters [index] == NULL) { \
63       string msg (asString ()); \
64       msg += functions::asText (" | CounterId: ", index); \
65       msg += " | Counter Id is not defined"; \
66       throw RuntimeException (msg, __FILE__, __LINE__); \
67    }
68
69
70 oam::CounterScope::~CounterScope() {
71   for(int i = 0; i < MaxCounter; i ++) {
72     if(a_counters [i] != NULL)
73       delete a_counters [i];
74   }
75 }
76
77 void oam::CounterScope::create(const int counter, const char* name)
78 throw(RuntimeException) {
79   test_range(counter);
80
81   if(a_counters [counter] != NULL) {
82     string msg("Counter '");
83     msg += name;
84     msg += "' (";
85     msg += functions::asString(counter);
86     msg += ") already registered as ";
87     msg += a_counters [counter]->asString();
88     throw RuntimeException(msg, ANNA_FILE_LOCATION);
89   }
90
91   a_counters [counter] = new Counter(*this, counter, name);
92   LOGDEBUG(
93     string msg("Creation | ");
94     msg += asString();
95     msg += " | ";
96     msg += a_counters [counter]->asString();
97     Logger::write(Logger::Debug, msg, ANNA_FILE_LOCATION)
98   );
99 }
100
101 oam::Counter::type_t oam::CounterScope::increment(const int counter, const oam::Counter::type_t value)
102 throw(RuntimeException) {
103   test_range(counter);
104   test_instance(counter);
105   a_counters [counter]->a_value += value;
106   a_counters [counter]->a_accValue += value;
107   LOGINFORMATION(a_counters [counter]->debug());
108   a_counterManager.activateTimer();
109   return a_counters [counter]->a_value;
110 }
111
112 oam::Counter::type_t oam::CounterScope::assign(const int counter, const oam::Counter::type_t value)
113 throw(RuntimeException) {
114   test_range(counter);
115   test_instance(counter);
116   a_counters [counter]->a_value = value;
117   a_counters [counter]->a_accValue = value;
118   LOGINFORMATION(a_counters [counter]->debug());
119   a_counterManager.activateTimer();
120   return value;
121 }
122
123 oam::Counter::type_t oam::CounterScope::getValue(const int counter) const
124 throw(RuntimeException) {
125   test_range(counter);
126   test_instance(counter);
127   return a_counters [counter]->a_value;
128 }
129
130 Unsigned64 oam::CounterScope::getAccValue(const int counter) const
131 throw(RuntimeException) {
132   test_range(counter);
133   test_instance(counter);
134   return a_counters [counter]->a_accValue;
135 }
136
137 int oam::CounterScope::resetAccValues() throw(RuntimeException) {
138   int result = 0; // affected counters
139
140   for(int ii = 0; ii < MaxCounter; ii ++)
141     if(a_counters [ii])
142       result += (a_counters [ii]->resetAcc()) ? 1 : 0;
143
144   return result;
145 }
146
147 const oam::Counter* oam::CounterScope::getCounter(const int counter) const
148 throw(RuntimeException) {
149   test_range(counter);
150   test_instance(counter);
151   return a_counters [counter];
152 }
153
154 string oam::CounterScope::asString() const
155 throw() {
156   string result("oam::CounterScope { Id: ");
157   result += functions::asString(a_id);
158   result += " | Name: ";
159   result += a_name;
160   return result += " }";
161 }
162
163 xml::Node* oam::CounterScope::asXML(xml::Node* parent) const
164 throw(RuntimeException) {
165   xml::Node* result = parent->createChild("Scope");
166   xml::Node* counter;
167
168   for(int ii = 0; ii < MaxCounter; ii ++) {
169     if(a_counters [ii] == NULL)
170       continue;
171
172     counter = result->createChild("Counter");
173     counter->createAttribute("Id", ii);
174     counter->createAttribute("Name", a_counters [ii]->getName());
175     counter->createAttribute("Value", a_counters [ii]->getValue());
176     counter->createAttribute("AccValue", a_counters [ii]->getAccumulatedValue());
177   }
178
179   return result;
180 }
181
182 /*
183 [0x7fbfffea90]: timex::Engine | Callers: timex::Engine::activate [2],timex::Engine::tick [69]
184    [0x79bf60, 2]: oam::CounterManager | Callers: MyInterface::receive [4],anna::oam::CounterManager::record [2]
185       [0x7fbfffea90, 2]: timex::Engine | Callers: timex::Engine::activate [2],timex::Engine::tick [69]
186       ------ Loop detected [ Level=2 | Loop: 3 ] -------
187 */
188 oam::CounterScope::Safe::Safe(timex::Engine* ttcc, oam::CounterScope& counterScope, const char* whatis) :
189   a_counterScope(counterScope) {
190   if(ttcc != NULL)
191     a_guards [0] = new Guard(ttcc, "timex::Engine from oam::CounterScope::Safe::Safe");
192   else
193     a_guards [0] = NULL;
194
195   a_guards [1] = new Guard(counterScope, whatis);
196 }
197
198 oam::CounterScope::Safe::~Safe()
199 throw() {
200   delete a_guards [1];
201   delete a_guards [0];
202 }
203