ANNA Suite  2020b
Multipurpose development suite for Telco applications
Context.hpp
Go to the documentation of this file.
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 #ifndef anna_timex_Context_hpp
10 #define anna_timex_Context_hpp
11 
12 #include <string>
13 #include <map>
14 
15 #include <anna/core/functions.hpp>
17 #include <anna/core/mt/Guard.hpp>
19 
20 #include <anna/xml/Node.hpp>
21 #include <anna/xml/Attribute.hpp>
22 
23 #include <anna/timex/Engine.hpp>
26 
28 
29 namespace anna {
30 
31 namespace timex {
32 
48 template <typename Tid> class Context : public timex::TimeEventObserver {
49 public:
62  Transaction* open(const Tid& tid, const int classType = 0)
63  noexcept(false) {
64  Transaction* result = NULL;
65  {
66  Guard guard(a_mutex, "timex::Context::open");
67  transaction_iterator ii = a_transactions.find(tid);
68 
69  if(ii != a_transactions.end()) {
70  std::string msg(transaction(ii)->asString());
71  msg += " | Already in progress";
73  }
74 
75  if((result = createTransaction(classType)) == NULL) {
76  std::string msg("timex::Context::createTransaction returned NULL | ClassType: ");
77  msg += functions::asString(classType);
79  }
80 
81  result->setTimeout(a_timeout);
82  result->setObserver(this);
83  result->setControlPoint();
84  result->setId(anna_ptrnumber_cast(result));
85  // Copia en el contexto de la transacción la clave usada.
86  // Se usará para poder buscar por clave a la hora de liberar la transacción.
87  std::pair <transaction_iterator, bool> rr = a_transactions.insert(value_type(tid, result));
88  result->setContext((void*) &rr.first->first);
89  }
90 
91  try {
92  a_timeController.activate(result);
93  } catch(RuntimeException&) {
94  releaseTransaction(result);
95  throw;
96  }
97 
99  std::string msg("timex::Context::open | ");
100  msg += result->asString();
102  );
103  return result;
104  }
105 
113  noexcept(false) {
114  Guard guard(a_mutex, "timex::Context::find");
115  transaction_iterator ii = a_transactions.find(tid);
116  Transaction* result = (ii != a_transactions.end()) ? transaction(ii) : NULL;
117 
118  if(result == NULL) {
119  if(emode == Exception::Mode::Throw) {
120  std::string msg("Transaction: ");
121  msg += identifierAsString(tid);
122  msg += " | Tid not found";
125  std::string msg("Transaction: ");
126  msg += identifierAsString(tid);
127  msg += " | Tid not found";
129  }
130  }
131 
132  return result;
133  }
134 
140  const Tid& getIdentifier(const Transaction* transaction) const
141  noexcept(false) {
142  if(transaction == NULL)
143  throw RuntimeException("timex::Context::getIdentifier | Can not work with NULL transaction", ANNA_FILE_LOCATION);
144 
145  const void* context = transaction->getContext();
146 
147  if(context == NULL) {
148  std::string msg("timex::Context::getIdentifier | ");
149  msg += transaction->asString();
150  msg += " | Can not work with NULL context";
152  }
153 
154  return contextAsIdentifier(context);
155  }
156 
161  void close(Transaction* transaction)
162  {
163  if(transaction == NULL)
164  return;
165 
167  std::string msg("timex::Context::close | ");
168  msg += transaction->asString();
170  );
171 
172  try {
173  a_timeController.cancel(transaction);
174  } catch(RuntimeException& ex) {
175  ex.trace();
176  }
177  }
178 
184  virtual xml::Node* asXML(xml::Node* parent) const
185  {
186  xml::Node* result = parent->createChild("timex.Context");
187  result->createAttribute("Size", a_transactions.size());
188  result->createAttribute("AvgSize", (a_counter == 0) ? 0 : a_accSize / a_counter);
189  result->createChild("Timeout")->createAttribute("Millisecond", a_timeout.getValue());
190  result->createChild("AvgResponseTime")->createAttribute("Millisecond", (a_counter == 0) ? 0 : a_accDelay / a_counter);
191  return result;
192  }
193 
202  static const Context* getInstance(const Transaction* transaction)
203  noexcept(false) {
204  if(transaction == NULL)
205  throw RuntimeException("timex::Context::getInstance | Can not work with NULL transaction", ANNA_FILE_LOCATION);
206 
207  return reinterpret_cast <const Context*>(transaction->getObserver());
208  }
209 
210 protected:
220  Context(const char* observerName, timex::Engine& timeController, const Millisecond& timeout) :
221  TimeEventObserver(observerName),
222  a_timeController(timeController),
223  a_timeout(timeout) {
224  a_counter = a_accDelay = a_accSize = 0;
225  }
226 
234  virtual Transaction* createTransaction(const int classType) = 0;
235 
241  virtual void releaseTransaction(Transaction* transaction) = 0;
242 
249  virtual std::string identifierAsString(const Tid& tid) const = 0;
250 
256  virtual const Tid& contextAsIdentifier(const void* tid) const = 0;
257 
258 private:
259  typedef typename std::map <Tid, Transaction*> transaction_container;
260  typedef typename transaction_container::iterator transaction_iterator;
261  typedef typename transaction_container::value_type value_type;
262 
263  Engine& a_timeController;
264  transaction_container a_transactions;
265  Mutex a_mutex;
266  Millisecond a_timeout;
267  unsigned int a_counter;
268  unsigned int a_accDelay;
269  unsigned int a_accSize;
270 
271  /* Método re-implementado de timex::TimeEventObserver */
272  void release(timex::TimeEvent* event)
273  {
274  Transaction* tt = static_cast <Transaction*>(event);
275  Guard guard(a_mutex, "timex::Context::release");
276  // Calcula la duración media de las transaciones de este contexto.
277  const Millisecond &delay = tt->getDelay();
278  const int size = a_transactions.size();
279 
280  /* Si desborda el acumulador de tiempo ... */
281  if(++ a_counter == 0 || (a_accDelay + delay) < a_accDelay || (a_accSize + size) < a_accSize) {
282  a_counter = 1;
283  a_accDelay = 0;
284  a_accSize = 0;
285  }
286 
287  const Tid& tid(contextAsIdentifier(tt->getContext()));
288 
289  if(a_transactions.erase(tid) == 0) {
290  std::string msg("Transaction: ");
291  msg += identifierAsString(tid);
292  msg += " | Tid can not be erased from map";
294  }
295 
296  releaseTransaction(tt);
297  a_accDelay += delay;
298  a_accSize += a_transactions.size();
299  }
300 
301  static Transaction* transaction(transaction_iterator ii) { return ii->second; }
302 };
303 
304 }
305 }
306 
307 #endif
308 
309 
virtual Transaction * createTransaction(const int classType)=0
Definition: Exception.hpp:26
#define anna_ptrnumber_cast(pointer)
Definition: defines.hpp:118
Definition: Millisecond.hpp:24
xml::Attribute * createAttribute(const char *name, const char *value, const Namespace *_namespace=NULL)
Definition: Exception.hpp:26
static void information(const std::string &text, const char *fromFile, const int fromLine)
Definition: Logger.hpp:316
void setId(const Id id)
Definition: TimeEvent.hpp:69
Definition: Transaction.hpp:34
virtual std::string asString() const
Definition: Transaction.hpp:84
_v
Definition: Exception.hpp:26
Node * createChild(const char *name)
Transaction * open(const Tid &tid, const int classType=0) noexcept(false)
Definition: Context.hpp:62
#define LOGINFORMATION(a)
Definition: defines.hpp:62
Millisecond getDelay() const
Definition: Meter.hpp:98
Definition: Node.hpp:56
void setContext(void *context)
Definition: Transaction.hpp:78
void trace() const
static std::string asString(const int number)
void setObserver(TimeEventObserver *observer)
Definition: TimeEvent.hpp:85
void cancel(TimeEvent *timeEvent) noexcept(false)
static void warning(const std::string &text, const char *fromFile, const int fromLine)
Definition: Logger.hpp:338
virtual void releaseTransaction(Transaction *transaction)=0
void activate(TimeEvent *timeEvent) noexcept(false)
void * getContext()
Definition: Transaction.hpp:66
const Tid & getIdentifier(const Transaction *transaction) const noexcept(false)
Definition: Context.hpp:140
Definition: TimeEvent.hpp:26
Definition: Logger.hpp:41
void setTimeout(const Millisecond &timeout)
Definition: TimeEvent.hpp:75
const TimeEventObserver * getObserver() const
Definition: TimeEvent.hpp:61
virtual xml::Node * asXML(xml::Node *parent) const
Definition: Context.hpp:184
virtual std::string identifierAsString(const Tid &tid) const =0
type_t getValue() const
Definition: Millisecond.hpp:120
Millisecond setControlPoint()
Definition: Meter.hpp:62
Definition: TimeEventObserver.hpp:33
void close(Transaction *transaction)
Definition: Context.hpp:161
Definition: app.hpp:12
Definition: Guard.hpp:35
#define ANNA_FILE_LOCATION
Definition: defines.hpp:23
Transaction * find(const Tid &tid, const Exception::Mode::_v emode=Exception::Mode::Throw) noexcept(false)
Definition: Context.hpp:112
Definition: Engine.hpp:62
Definition: Mutex.hpp:41
std::string asString() const
Definition: TimeEventObserver.hpp:45
static const Context * getInstance(const Transaction *transaction) noexcept(false)
Definition: Context.hpp:202
Definition: RuntimeException.hpp:23
Context(const char *observerName, timex::Engine &timeController, const Millisecond &timeout)
Definition: Context.hpp:220
virtual const Tid & contextAsIdentifier(const void *tid) const =0
Definition: Context.hpp:48
static bool isActive(const Level level)
Definition: Logger.hpp:169