// STL
#include <string>
#include <vector>
+#include <map>
+// Project
#include <anna/config/defines.hpp>
-#include <anna/statistics/Accumulator.hpp>
#include <anna/diameter.comm/ServerSession.hpp>
+#include <anna/diameter/defines.hpp>
+#include <anna/diameter.comm/MessageStatistics.hpp>
namespace anna {
Engine *a_engine;
// Statistics
- int a_processing_time__StatisticConceptId; // request from local server (dpr's, etc.)
- int a_received_message_size__StatisticConceptId;
- anna::statistics::Accumulator *a_statisticsAccumulator;
+ MessageStatistics a_messageStatistics;
void initializeStatisticResources() throw();
void resetStatistics() throw();
anna::xml::Node* asXML(anna::xml::Node* parent) const throw();
// Statistics
- void updateProcessingTimeStatisticConcept(const double &value) throw();
- void updateReceivedMessageSizeStatisticConcept(const double &value) throw();
- int getProcessingTimeStatisticConcept() const throw() { return a_processing_time__StatisticConceptId; }
- int getReceivedMessageSizeStatisticConcept() const throw() { return a_received_message_size__StatisticConceptId; }
+ void updateProcessingTimeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw();
+ void updateReceivedMessageSizeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw();
+// int getProcessingTimeStatisticConcept() const throw() { return a_processing_time__StatisticConceptId; }
+// int getReceivedMessageSizeStatisticConcept() const throw() { return a_received_message_size__StatisticConceptId; }
protected:
--- /dev/null
+// ANNA - Anna is Not Nothingness Anymore //
+// //
+// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
+// //
+// See project site at http://redmine.teslayout.com/projects/anna-suite //
+// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
+
+
+#ifndef anna_diameter_comm_MessageStatistics_hpp
+#define anna_diameter_comm_MessageStatistics_hpp
+
+// Standard
+#include <algorithm>
+#include <string>
+#include <map>
+
+// Project
+#include <anna/diameter/defines.hpp>
+#include <anna/statistics/Accumulator.hpp>
+
+namespace anna {
+
+namespace xml {
+ class Node;
+}
+
+namespace diameter {
+
+namespace comm {
+
+
+
+class MessageStatistics {
+
+ public:
+ MessageStatistics() {;}
+ ~MessageStatistics() {;}
+
+ struct ConceptType { enum _v { SentRequestProcessingTime, ReceivedMessageSize }; };
+
+ void initialize(const std::string &name) throw(anna::RuntimeException);
+ void process(const ConceptType::_v &conceptType, const anna::diameter::CommandId &cid, const double & value) throw(anna::RuntimeException);
+ anna::statistics::Accumulator *getAccumulator() const throw() { return a_accumulator; }
+
+ private:
+ anna::statistics::Accumulator *a_accumulator;
+ typedef std::pair<anna::diameter::CommandId, ConceptType::_v> ConceptId;
+ typedef std::map<ConceptId, int /* engine concept id */> concepts_map_t;
+ typedef std::map<ConceptId, int /* engine concept id */>::const_iterator concepts_map_it;
+ concepts_map_t a_concepts;
+};
+
+}
+}
+}
+
+#endif
// STL
#include <string>
#include <vector>
+#include <map>
+// Project
#include <anna/core/util/Millisecond.hpp>
#include <anna/core/RuntimeException.hpp>
-
#include <anna/diameter/defines.hpp>
#include <anna/config/defines.hpp>
#include <anna/diameter.comm/ClassCode.hpp>
-#include <anna/statistics/Accumulator.hpp>
+#include <anna/diameter.comm/MessageStatistics.hpp>
+
+
namespace anna {
Engine *a_engine;
// Statistics
- int a_processing_time__StatisticConceptId;
- int a_received_message_size__StatisticConceptId;
- anna::statistics::Accumulator *a_statisticsAccumulator;
+ MessageStatistics a_messageStatistics;
void initializeStatisticResources() throw();
void resetStatistics() throw();
// Statistics
- void updateProcessingTimeStatisticConcept(const double &value) throw();
- void updateReceivedMessageSizeStatisticConcept(const double &value) throw();
- int getProcessingTimeStatisticConcept() const throw() { return a_processing_time__StatisticConceptId; }
- int getReceivedMessageSizeStatisticConcept() const throw() { return a_received_message_size__StatisticConceptId; }
+ void updateProcessingTimeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw();
+ void updateReceivedMessageSizeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw();
+// int getProcessingTimeStatisticConcept() const throw() { return a_processing_time__StatisticConceptId; }
+// int getReceivedMessageSizeStatisticConcept() const throw() { return a_received_message_size__StatisticConceptId; }
protected:
/** Generic AVP */
static const AvpId AVPID__AVP(0, 0);
+/** Reserved Generic COMMAND */
+//static const AvpId COMMANDID__COMMAND(0, 0);
+
/**
* Vendors
* http://www.iana.org/assignments/enterprise-numbers
* @short Contains statistical sample information
*/
class Accumulator {
+
+ std::string a_name;
+
+ void initialize(const int & conceptId) throw();
+ _concept_data_t * getConcept(const int & conceptId) const throw(anna::RuntimeException);
+ // Gets the data structure for a existing concept Id.
+ // Initializes and returns the new data structure for a new stored concept Id which is valid (exists for the engine).
+ // Launch exception if concept id is not a valid concept registered at Engine.
+
+ /*mutable */_concept_data_map_t a_concept_data_map;
+
+ std::string floatFormat(const int & numberOfDecimals) const throw();
+
+ double getStandardDeviation(const _concept_data_t * conceptData) const throw(anna::RuntimeException);
+ double getBesselStandardDeviation(const _concept_data_t * conceptData) const throw(anna::RuntimeException);
+
+
public:
/**
/**
* Destructor.
*/
- ~Accumulator();
+ ~Accumulator() {;}
+
+
+ /**
+ * Sets the accumulator name
+ *
+ * @param name Name provided
+ */
+ void setName(const std::string &name) throw() { a_name = name; }
/**
* Adds a new statistic concept through the accumulator, to ease the concept name creation,
* (is more intuitive 850 msecs than 0,850 secs). Then, it is @em true by default.
* This is useful to advice better representation for some indicators like minimum/maximum
* within integer samples.
+ * @param conceptNameFormat Format to register the complete concept name. Will be parsed using (in order) the provided
+ * description, and the accumulator name: '<concept description> [<accumulator name>]' by default.
*
* @return Assigned concept identification number (sequence)
*/
- int addConcept(const std::string & description, const std::string & unit, const bool & integerNatureSample = true) throw();
-
+ int addConcept(const std::string & description, const std::string & unit, const bool & integerNatureSample = true, const char *conceptNameFormat = "%s [%s]") throw();
/**
- * Process new value for the sample.
+ * Process new value for the sample regarding a concept identifier previously registered through the engine.
*
* @param conceptId statistical concept processed
* @param value Value for processed item
// Gets
+ /**
+ * Gets the accumulator name
+ *
+ * @result Accumulator name
+ */
+ const std::string &getName() const throw() { return a_name; }
+
/**
* Gets current sample size for any concept id
*
* @return XML with class content
*/
anna::xml::Node* asXML(anna::xml::Node* parent, const int & numberOfDecimals = 2) const throw();
-
-
-private:
-
- std::string a_name;
-
- void initialize(const int & conceptId) throw();
- _concept_data_t * getConcept(const int & conceptId) const throw(anna::RuntimeException);
- // Return NULL if no data is found for the concept Id
- // Launch exception if concept id is not a valid concept registered at Engine
-
- /*mutable */_concept_data_map_t a_concept_data_map;
-
- std::string floatFormat(const int & numberOfDecimals) const throw();
-
- double getStandardDeviation(const _concept_data_t * conceptData) const throw(anna::RuntimeException);
- double getBesselStandardDeviation(const _concept_data_t * conceptData) const throw(anna::RuntimeException);
};
}
#include <anna/core/Singleton.hpp>
#include <anna/core/util/Millisecond.hpp>
+#include <anna/core/RuntimeException.hpp>
#include <anna/core/mt/Mutex.hpp>
// Standard
#include <string>
-#include <vector>
#include <map>
// Local
namespace statistics {
+class Accumulator;
+
+
typedef struct {
std::string SampleFile; // Sample file to optional writtings
typedef std::map <int, _concept_identification_t>::const_iterator _concept_identification_map_iter;
typedef std::map <int, _concept_identification_t>::iterator _concept_identification_map_nc_iter;
-typedef std::vector <Accumulator*> _accumulator_vector_t;
-typedef std::vector <Accumulator*>::const_iterator _accumulator_vector_it;
+typedef std::map <std::string, Accumulator*> _accumulator_map_t;
+typedef std::map <std::string, Accumulator*>::const_iterator _accumulator_map_it;
+typedef std::map <std::string, Accumulator*>::iterator _accumulator_map_nc_it;
/**
*/
bool enabled(void) const throw() { return (a_enabled); }
+
/**
- * There is an advantage creating Accumulators over the engine: the #asXML method will show all the controlled information
- * easily. Anyway, you could allocate this class objects without using this. Then, this is a helper to create accumulators
- * and centralize their reports.
- *
- * @param name Accumulator name
- *
- * @return New allocated accumulator, to be used by the client
- */
- Accumulator *createAccumulator(const std::string &name) throw();
+ * Creates a statistic accumulator
+ *
+ * @param name Accumulator name
+ *
+ * \return The accumulator created or exception when already exists for the provided name.
+ */
+ Accumulator *createAccumulator(const std::string &name) throw(anna::RuntimeException);
+
+ /**
+ * Returns accumulator instance identified by name.
+ *
+ * \param name Accumulator name
+ *
+ * \return The accumulator instance identified by name provided, NULL if not found
+ */
+ Accumulator* getAccumulator(const std::string &name) throw();
+
+
/**
* Class string representation
Engine(); // private constructor
_concept_identification_map_t a_concept_identification_map;
- _accumulator_vector_t a_accumulators; // you could create accumulators regardless the engine, but this is easier and asXML will show all the information easily
+ _accumulator_map_t a_accumulators; // you could create accumulators regardless the engine, but this is easier and asXML will show all the information easily
bool a_enabled;
int a_sequence_concept_id;
anna::Mutex a_mutex; // for logSample
/**
* Constructor.
*/
- Meter(const std::string & description);
+ Meter(const std::string & name);
/**
* Destructor.
}
}
);
+
// Main counters:
OamModule &oamModule = OamModule::instantiate();
oamModule.count(isRequest ? OamModule::Counter::RequestReceived : OamModule::Counter::AnswerReceived);
oamModule.count(isRequest ? OamModule::Counter::RequestReceivedOnClientSession : OamModule::Counter::AnswerReceivedOnClientSession);
// Statistic (size)
- a_parent->updateReceivedMessageSizeStatisticConcept(message.getSize()); // only on reception (application could manage sent sizes)
+ a_parent->updateReceivedMessageSizeStatisticConcept(message.getSize(), cid); // only on reception (application could manage sent sizes)
if(isRequest) {
/////////////////////////////
anna::Millisecond current = (anna::Millisecond)anna::functions::millisecond();
anna::Millisecond request = response->getRequest()->getRequestTimestampMs();
anna::Millisecond timeToAnswerMs = current - request;
- a_parent->updateProcessingTimeStatisticConcept(timeToAnswerMs);
- LOGDEBUG
- (
- std::string msg = "This diameter request context lasted ";
- msg += anna::functions::asString(timeToAnswerMs);
- msg += " milliseconds at diameter server (included network time)";
- anna::Logger::debug(msg, ANNA_FILE_LOCATION);
- );
+ a_parent->updateProcessingTimeStatisticConcept(timeToAnswerMs, cid);
+ //LOGDEBUG
+ //(
+ // std::string msg = "This diameter request context lasted ";
+ // msg += anna::functions::asString(timeToAnswerMs);
+ // msg += " milliseconds at diameter server (included network time)";
+ // anna::Logger::debug(msg, ANNA_FILE_LOCATION);
+ //);
// Progress origin for tracking purposes on asyncronous boxes with both diameter interfaces (entities and clients)
Message * requestMessage = const_cast<Message*>(response->getRequest());
requestMessage->setRequestServerSessionKey(response->getRequest()->getRequestServerSessionKey()); // -1 means unkown/unset
#include <anna/comm/Network.hpp>
#include <anna/comm/Host.hpp>
#include <anna/comm/ClientSocket.hpp>
-
#include <anna/diameter.comm/Transport.hpp>
#include <anna/diameter.comm/Engine.hpp>
#include <anna/diameter.comm/Entity.hpp>
a_category(0),
a_lock(false),
a_available(false),
- a_lastUsedResource(NULL),
- a_statisticsAccumulator(NULL) {}
+ a_lastUsedResource(NULL) {}
void LocalServer::initializeStatisticResources() throw() {
accName += "' and origin-host '";
accName += a_engine ? a_engine->getOriginHost() : "unknown"; // it should be known (createServer)
accName += "'";
- a_statisticsAccumulator = anna::statistics::Engine::instantiate().createAccumulator(accName);
- a_processing_time__StatisticConceptId = a_statisticsAccumulator->addConcept("Diameter requests processing time at clients connected to", "ms", true/* integer values */);
- a_received_message_size__StatisticConceptId = a_statisticsAccumulator->addConcept("Diameter message sizes received from clients connected to", "bytes", true/* integer values */);
+ a_messageStatistics.initialize(accName);
}
void LocalServer::resetStatistics() throw() {
- a_statisticsAccumulator->reset();
+ a_messageStatistics.getAccumulator()->reset();
}
-void LocalServer::updateProcessingTimeStatisticConcept(const double &value) throw() {
- a_statisticsAccumulator->process(a_processing_time__StatisticConceptId, value);
- LOGDEBUG(anna::Logger::debug(a_statisticsAccumulator->asString(), ANNA_FILE_LOCATION));
+void LocalServer::updateProcessingTimeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw() {
+ a_messageStatistics.process(MessageStatistics::ConceptType::SentRequestProcessingTime, cid, value);
+ LOGDEBUG(anna::Logger::debug(a_messageStatistics.getAccumulator()->asString(), ANNA_FILE_LOCATION));
}
-void LocalServer::updateReceivedMessageSizeStatisticConcept(const double &value) throw() {
- a_statisticsAccumulator->process(a_received_message_size__StatisticConceptId, value);
- //LOGDEBUG(anna::Logger::debug(a_statisticsAccumulator->asString(), ANNA_FILE_LOCATION));
+void LocalServer::updateReceivedMessageSizeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw() {
+ a_messageStatistics.process(MessageStatistics::ConceptType::ReceivedMessageSize, cid, value);
+ LOGDEBUG(anna::Logger::debug(a_messageStatistics.getAccumulator()->asString(), ANNA_FILE_LOCATION));
}
-
ServerSession* LocalServer::allocateServerSession() throw() { return a_serverSessionsRecycler.create(); }
void LocalServer::releaseServerSession(ServerSession *serverSession) throw() { a_serverSessionsRecycler.release(serverSession); }
}
void LocalServer::setMaxConnections(int maxConnections) throw(anna::RuntimeException) {
- LOGMETHOD(anna::TraceMethod tttm("diameter::comm::LocalServer", "setMaxConnections", ANNA_FILE_LOCATION));
+ LOGMETHOD(anna::TraceMethod tttm("anna::diameter::comm::LocalServer", "setMaxConnections", ANNA_FILE_LOCATION));
// Negative & initial
if(maxConnections < 0) {
result += " | Last Outgoing Activity Time: ";
result += a_lastOutgoingActivityTime.asString();
// result += "\n";
-// result += a_statisticsAccumulator->asString();
+// result += a_messageStatistics.getAccumulator()->asString();
// ServerSessions only in xml
return result += " }";
}
result->createAttribute("LastIncomingActivityTime", a_lastIncomingActivityTime.asString());
result->createAttribute("LastOutgoingActivityTime", a_lastOutgoingActivityTime.asString());
// Statistics
- anna::xml::Node* stats = result->createChild("Statistics");
- a_statisticsAccumulator->asXML(stats);
+ anna::xml::Node* stats = result->createChild("MessageStatistics");
+ a_messageStatistics.getAccumulator()->asXML(stats);
anna::xml::Node* serverSessions = result->createChild("ServerSessions"); // LocalServer.ServerSessions
for(const_serverSession_iterator it = serverSession_begin(); it != serverSession_end(); it++)
--- /dev/null
+// ANNA - Anna is Not Nothingness Anymore //
+// //
+// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
+// //
+// See project site at http://redmine.teslayout.com/projects/anna-suite //
+// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
+
+// Standard
+#include <string>
+
+// Project
+#include <anna/diameter.comm/MessageStatistics.hpp>
+#include <anna/statistics/Engine.hpp>
+#include <anna/diameter/functions.hpp>
+#include <anna/diameter/helpers/defines.hpp>
+#include <anna/diameter/codec/Message.hpp>
+#include <anna/diameter/codec/Engine.hpp>
+#include <anna/diameter/codec/EngineManager.hpp>
+
+
+void anna::diameter::comm::MessageStatistics::initialize(const std::string &name) throw(anna::RuntimeException) {
+ a_accumulator = anna::statistics::Engine::instantiate().createAccumulator(name);
+}
+
+
+void anna::diameter::comm::MessageStatistics::process(const ConceptType::_v &conceptType, const anna::diameter::CommandId &cid, const double & value) throw(anna::RuntimeException) {
+
+ // Development issue:
+// if (!a_accumulator) {
+// LOGWARNING(anna::Logger::warning("Cannot process uninitialized 'MessageStatistics' instance", ANNA_FILE_LOCATION));
+// return;
+// }
+
+ // retrieve the concept id for the pair:
+ ConceptId conceptId(cid, conceptType);
+ int engine_concept_id = 0;
+ concepts_map_it it = a_concepts.find(conceptId);
+ if (it != a_concepts.end()) { // found
+ engine_concept_id = it->second;
+ }
+ else { // register a new concept id
+ std::string description;
+ if(conceptType == ConceptType::SentRequestProcessingTime) {
+ description = anna::functions::asString("Processing time for outgoing requests (code = %d)", cid.first);
+ }
+ else if (conceptType == ConceptType::ReceivedMessageSize) {
+ description = "Message size for received messages ";
+ description += anna::diameter::functions::commandIdAsPairString(cid);
+ }
+
+ engine_concept_id = a_accumulator->addConcept(description, "ms", true/* integer values */);
+ a_concepts[conceptId] = engine_concept_id;
+ }
+
+ a_accumulator->process(engine_concept_id, value);
+}
+
a_maxClientSessions = 1; // mono client connection
a_lastIncomingActivityTime = (anna::Millisecond)0;
a_lastOutgoingActivityTime = (anna::Millisecond)0;
- a_statisticsAccumulator = NULL;
a_lastUsedResource = NULL;
}
accName += "' and origin-host '";
accName += a_engine ? a_engine->getOriginHost() : "unknown"; // it should be known (createServer)
accName += "'";
- a_statisticsAccumulator = anna::statistics::Engine::instantiate().createAccumulator(accName);
- a_processing_time__StatisticConceptId = a_statisticsAccumulator->addConcept("Diameter requests processing time at", "ms", true/* integer values */);
- a_received_message_size__StatisticConceptId = a_statisticsAccumulator->addConcept("Diameter message sizes received from", "bytes", true/* integer values */);
+ a_messageStatistics.initialize(accName);
}
void Server::resetStatistics() throw() {
- a_statisticsAccumulator->reset();
+ a_messageStatistics.getAccumulator()->reset();
}
-void Server::updateProcessingTimeStatisticConcept(const double &value) throw() {
- a_statisticsAccumulator->process(a_processing_time__StatisticConceptId, value);
- LOGDEBUG(anna::Logger::debug(a_statisticsAccumulator->asString(), ANNA_FILE_LOCATION));
+void Server::updateProcessingTimeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw() {
+ a_messageStatistics.process(MessageStatistics::ConceptType::SentRequestProcessingTime, cid, value);
+ LOGDEBUG(anna::Logger::debug(a_messageStatistics.getAccumulator()->asString(), ANNA_FILE_LOCATION));
}
-void Server::updateReceivedMessageSizeStatisticConcept(const double &value) throw() {
- a_statisticsAccumulator->process(a_received_message_size__StatisticConceptId, value);
- //LOGDEBUG(anna::Logger::debug(a_statisticsAccumulator->asString(), ANNA_FILE_LOCATION));
+void Server::updateReceivedMessageSizeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw() {
+ a_messageStatistics.process(MessageStatistics::ConceptType::ReceivedMessageSize, cid, value);
+ LOGDEBUG(anna::Logger::debug(a_messageStatistics.getAccumulator()->asString(), ANNA_FILE_LOCATION));
}
result += " | Hidden: ";
result += (hidden() ? "yes" : "no");
result += "\n";
- result += a_statisticsAccumulator->asString();
+ result += a_messageStatistics.getAccumulator()->asString();
for(std::vector<ClientSession*>::const_iterator it = begin(); it != end(); it++) {
result += "\n";
result->createAttribute("Hidden", hidden() ? "yes" : "no");
// Statistics
anna::xml::Node* stats = result->createChild("Statistics");
- a_statisticsAccumulator->asXML(stats);
+ a_messageStatistics.getAccumulator()->asXML(stats);
anna::xml::Node* clientSessions = result->createChild("Server.ClientSessions");
for(std::vector<ClientSession*>::const_iterator it = begin(); it != end(); it++)
oamModule.count(isRequest ? OamModule::Counter::RequestReceived : OamModule::Counter::AnswerReceived);
oamModule.count(isRequest ? OamModule::Counter::RequestReceivedOnServerSession : OamModule::Counter::AnswerReceivedOnServerSession);
// Statistic (size)
- a_parent->updateReceivedMessageSizeStatisticConcept(message.getSize()); // only on reception (application could manage sent sizes)
+ a_parent->updateReceivedMessageSizeStatisticConcept(message.getSize(), cid); // only on reception (application could manage sent sizes)
if(isRequest) {
// Si recibo un request, el message solo tiene fiable el DataBlock. Como por defecto se construye como ApplicationMessage,
anna::Millisecond current = (anna::Millisecond)anna::functions::millisecond();
anna::Millisecond request = response->getRequest()->getRequestTimestampMs();
anna::Millisecond timeToAnswerMs = current - request;
- a_parent->updateProcessingTimeStatisticConcept(timeToAnswerMs);
- LOGDEBUG
- (
- std::string msg = "This diameter request context lasted ";
- msg += anna::functions::asString(timeToAnswerMs);
- msg += " milliseconds at diameter client (included network time)";
- anna::Logger::debug(msg, ANNA_FILE_LOCATION);
- );
+ a_parent->updateProcessingTimeStatisticConcept(timeToAnswerMs, cid);
+ //LOGDEBUG
+ //(
+ // std::string msg = "This diameter request context lasted ";
+ // msg += anna::functions::asString(timeToAnswerMs);
+ // msg += " milliseconds at diameter client (included network time)";
+ // anna::Logger::debug(msg, ANNA_FILE_LOCATION);
+ //);
// Progress origin for tracking purposes on asyncronous boxes with both diameter interfaces (entities and clients)
Message * requestMessage = const_cast<Message*>(response->getRequest());
requestMessage->setRequestClientSessionKey(response->getRequest()->getRequestClientSessionKey()); // "" means unkown/unset
using namespace anna::time;
-//******************************************************************************
-//------------------------------------------------------------------------------
-//-------------------------------------------------- Accumulator::~Accumulator()
-//------------------------------------------------------------------------------
-Accumulator::~Accumulator() {
-// LOGMETHOD (TraceMethod tttm ("anna::statistics::Accumulator", "Destructor", ANNA_FILE_LOCATION));
- // TODO: anna::statistics::Engine::instantiate().releaseAccumulator(a_name);
-}
-
// Private functions:
//------------------------------------------------------------------------------
//---------------------------------------------------- Accumulator::addConcept()
//------------------------------------------------------------------------------
-int Accumulator::addConcept(const std::string & description, const std::string & unit, const bool & integerNatureSample) throw() {
- std::string conceptName = description;
- conceptName += ": ";
- conceptName += a_name;
+int Accumulator::addConcept(const std::string & description, const std::string & unit, const bool & integerNatureSample, const char *conceptNameFormat) throw() {
+ std::string conceptName = anna::functions::asString(conceptNameFormat, description.c_str(), a_name.c_str());
return anna::statistics::Engine::instantiate().addConcept(conceptName, unit, integerNatureSample);
}
//------------------------------------------------------------------------------
//---------------------------------------------------- Accumulator::getConcept()
//------------------------------------------------------------------------------
-_concept_data_t * Accumulator::getConcept(const int & conceptId) const throw(anna::RuntimeException) {
+_concept_data_t *Accumulator::getConcept(const int & conceptId) const throw(anna::RuntimeException) {
_concept_data_map_iter it = a_concept_data_map.find(conceptId);
if(it == a_concept_data_map.end()) { // not found
Accumulator * nc_this = const_cast<Accumulator *>(this);
nc_this->initialize(conceptId);
- // (la otra posibilidad era hacer mutable el mapa e inicializar poniendo el contenido de 'initialize()')
it = a_concept_data_map.find(conceptId);
}
}
-
-
-
//------------------------------------------------------------------------------
//------------------------------------------ Accumulator::getStandardDeviation()
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Accumulator::reset(const int & conceptId) throw(anna::RuntimeException) {
// LOGMETHOD (TraceMethod tttm ("anna::statistics::Accumulator", "reset", ANNA_FILE_LOCATION));
- _concept_data_t *ptr_auxConceptData = getConcept(conceptId);
- //if (ptr_auxConceptData == NULL) return; // Not possible: getConcept initializes it if not found.
+ _concept_data_t *ptr_auxConceptData = getConcept(conceptId); // will initialize if didn't associated to this accumulator,
+ // exception if engine knows nothing about such concept id.
+ //if (ptr_auxConceptData == NULL) return; // Not possible: getConcept initializes it if not found or exception was launched
+ // previously if the engine don't know the concept id.
ptr_auxConceptData->reset();
}
//------------------------------------------------------------ Engine::~Engine()
//------------------------------------------------------------------------------
Engine::~Engine() {
- for (_accumulator_vector_it it = a_accumulators.begin(); it != a_accumulators.end(); it++)
- delete (*it);
+ for (_accumulator_map_it it = a_accumulators.begin(); it != a_accumulators.end(); it++)
+ delete (it->second);
}
//------------------------------------------------------------------------------
-//----------------------------------------------------------- Engine::asString()
+//-------------------------------------------------- Engine::createAccumulator()
//------------------------------------------------------------------------------
-Accumulator *Engine::createAccumulator(const std::string &name) throw() {
- Accumulator *result;
+Accumulator *Engine::createAccumulator(const std::string &name) throw(anna::RuntimeException) {
+ Accumulator *result = getAccumulator(name);
+
+ if (result)
+ throw anna::RuntimeException(anna::functions::asString("Cannot register another accumulator with the same name: %s", name.c_str()), ANNA_FILE_LOCATION);
result = new Accumulator(name);
- a_accumulators.push_back(result);
+ a_accumulators[name] = result;
+ return result;
+}
+
+Accumulator* Engine::getAccumulator(const std::string &name) throw() {
+ Accumulator *result = NULL;
+
+ _accumulator_map_nc_it it = a_accumulators.find(name);
+ if (it != a_accumulators.end())
+ result = it->second;
+
return result;
}
// Accumulators:
trace += "\nNumber of accumulators= "; trace += anna::functions::asString(a_accumulators.size());
- for (_accumulator_vector_it it = a_accumulators.begin(); it != a_accumulators.end(); it++) {
+ for (_accumulator_map_it it = a_accumulators.begin(); it != a_accumulators.end(); it++) {
trace += "\n";
- trace += (*it)->asString();
+ trace += it->second->asString();
}
return (trace);
// Accumulators:
anna::xml::Node* accumulators = result->createChild("anna.statistics.Accumulators");
accumulators->createAttribute("RegisteredAccumulators", a_accumulators.size());
- for (_accumulator_vector_it it = a_accumulators.begin(); it != a_accumulators.end(); it++)
- (*it)->asXML(accumulators);
+ for (_accumulator_map_it it = a_accumulators.begin(); it != a_accumulators.end(); it++)
+ it->second->asXML(accumulators);
return result;
}
//------------------------------------------------------------------------------
// Default Constructor
-Meter::Meter(const std::string & description) : a_accumulator(description) {
+Meter::Meter(const std::string & name) : a_accumulator(name) {
Engine& statsEngine = Engine::instantiate();
- a_single_accumulator_concept_id = statsEngine.addConcept(description, "ms", true);
+ a_single_accumulator_concept_id = statsEngine.addConcept(name, "ms", true);
}