mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 21:45:37 +00:00
[#891,!592] make StatsMgr thread safe
This commit is contained in:
@@ -7,39 +7,111 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <stats/context.h>
|
||||
#include <util/multi_threading_mgr.h>
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
using namespace isc::data;
|
||||
using namespace isc::util;
|
||||
|
||||
namespace isc {
|
||||
namespace stats {
|
||||
|
||||
ObservationPtr StatContext::get(const std::string& name) const {
|
||||
std::map<std::string, ObservationPtr>::const_iterator obs = stats_.find(name);
|
||||
if (obs == stats_.end()) {
|
||||
return (ObservationPtr());
|
||||
} else {
|
||||
return (obs->second);
|
||||
}
|
||||
ObservationPtr result;
|
||||
auto lambda = [&]() {
|
||||
auto obs = stats_.find(name);
|
||||
if (obs != stats_.end()) {
|
||||
result = obs->second;
|
||||
}
|
||||
};
|
||||
MultiThreadingMgr::call(mutex_, lambda);
|
||||
return (result);
|
||||
}
|
||||
|
||||
void StatContext::add(const ObservationPtr& obs) {
|
||||
std::map<std::string, ObservationPtr>::iterator existing = stats_.find(obs->getName());
|
||||
if (existing == stats_.end()) {
|
||||
stats_.insert(make_pair(obs->getName() ,obs));
|
||||
} else {
|
||||
isc_throw(DuplicateStat, "Statistic named " << obs->getName()
|
||||
<< " already exists.");
|
||||
}
|
||||
|
||||
auto lambda = [&]() {
|
||||
auto existing = stats_.find(obs->getName());
|
||||
if (existing == stats_.end()) {
|
||||
stats_.insert(make_pair(obs->getName() ,obs));
|
||||
} else {
|
||||
isc_throw(DuplicateStat, "Statistic named " << obs->getName()
|
||||
<< " already exists.");
|
||||
}
|
||||
};
|
||||
MultiThreadingMgr::call(mutex_, lambda);
|
||||
}
|
||||
|
||||
bool StatContext::del(const std::string& name) {
|
||||
std::map<std::string, ObservationPtr>::iterator obs = stats_.find(name);
|
||||
if (obs == stats_.end()) {
|
||||
return (false);
|
||||
} else {
|
||||
stats_.erase(obs);
|
||||
return (true);
|
||||
}
|
||||
bool result = false;
|
||||
auto lambda = [&]() {
|
||||
auto obs = stats_.find(name);
|
||||
if (obs != stats_.end()) {
|
||||
stats_.erase(obs);
|
||||
result = true;
|
||||
}
|
||||
};
|
||||
MultiThreadingMgr::call(mutex_, lambda);
|
||||
return (result);
|
||||
}
|
||||
|
||||
size_t StatContext::size() {
|
||||
size_t size;
|
||||
MultiThreadingMgr::call(mutex_, [&]() {size = stats_.size();});
|
||||
return (size);
|
||||
}
|
||||
|
||||
void StatContext::clear() {
|
||||
MultiThreadingMgr::call(mutex_, [&]() {stats_.clear();});
|
||||
}
|
||||
|
||||
void StatContext::reset() {
|
||||
auto lambda = [&]() {
|
||||
// Let's iterate over all stored statistics...
|
||||
for (auto s : stats_) {
|
||||
// ... and reset each statistic.
|
||||
s.second->reset();
|
||||
}
|
||||
};
|
||||
MultiThreadingMgr::call(mutex_, lambda);
|
||||
}
|
||||
|
||||
ConstElementPtr
|
||||
StatContext::getAll() const {
|
||||
ElementPtr map = isc::data::Element::createMap(); // a map
|
||||
auto lambda = [&]() {
|
||||
// Let's iterate over all stored statistics...
|
||||
for (auto s : stats_) {
|
||||
// ... and add each of them to the map.
|
||||
map->set(s.first, s.second->getJSON());
|
||||
}
|
||||
};
|
||||
MultiThreadingMgr::call(mutex_, lambda);
|
||||
return (map);
|
||||
}
|
||||
|
||||
void
|
||||
StatContext::setMaxSampleAgeAll(const StatsDuration& duration) {
|
||||
auto lambda = [&]() {
|
||||
// Let's iterate over all stored statistics...
|
||||
for (auto s : stats_) {
|
||||
// ... and set duration limit for each statistic.
|
||||
s.second->setMaxSampleAge(duration);
|
||||
}
|
||||
};
|
||||
MultiThreadingMgr::call(mutex_, lambda);
|
||||
}
|
||||
|
||||
void
|
||||
StatContext::setMaxSampleCountAll(uint32_t max_samples) {
|
||||
auto lambda = [&]() {
|
||||
// Let's iterate over all stored statistics...
|
||||
for (auto s : stats_) {
|
||||
// ... and set count limit for each statistic.
|
||||
s.second->setMaxSampleCount(max_samples);
|
||||
}
|
||||
};
|
||||
MultiThreadingMgr::call(mutex_, lambda);
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <stats/observation.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
namespace isc {
|
||||
@@ -28,7 +29,7 @@ public:
|
||||
/// all statistics related to a given subnet or all statistics related to a
|
||||
/// given network interface.
|
||||
struct StatContext {
|
||||
public:
|
||||
public:
|
||||
|
||||
/// @brief attempts to get an observation
|
||||
/// @param name name of the statistic
|
||||
@@ -45,14 +46,23 @@ struct StatContext {
|
||||
/// @return true if successful, false if no such statistic was found
|
||||
bool del(const std::string& name);
|
||||
|
||||
size_t size();
|
||||
|
||||
void clear();
|
||||
|
||||
void reset();
|
||||
|
||||
void setMaxSampleAgeAll(const StatsDuration& duration);
|
||||
|
||||
void setMaxSampleCountAll(uint32_t max_samples);
|
||||
|
||||
isc::data::ConstElementPtr getAll() const;
|
||||
|
||||
private:
|
||||
/// @brief Statistics container
|
||||
///
|
||||
/// It is public to allow various operations that require iterating over
|
||||
/// all elements. In particular, two operations (setting all stats to 0;
|
||||
/// reporting all stats) will take advantage of this. Alternatively, we
|
||||
/// could make it protected and then return a pointer to it, but that
|
||||
/// would defeat the purpose of the hermetization in the first place.
|
||||
std::map<std::string, ObservationPtr> stats_;
|
||||
|
||||
mutable std::mutex mutex_;
|
||||
};
|
||||
|
||||
/// @brief Pointer to the statistics context
|
||||
|
@@ -11,183 +11,220 @@
|
||||
#include <cc/data.h>
|
||||
#include <cc/command_interpreter.h>
|
||||
#include <util/boost_time_utils.h>
|
||||
#include <util/multi_threading_mgr.h>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace isc::data;
|
||||
using namespace isc::config;
|
||||
using namespace isc::util;
|
||||
|
||||
namespace isc {
|
||||
namespace stats {
|
||||
|
||||
StatsMgr& StatsMgr::instance() {
|
||||
StatsMgr&
|
||||
StatsMgr::instance() {
|
||||
static StatsMgr stats_mgr;
|
||||
return (stats_mgr);
|
||||
}
|
||||
|
||||
StatsMgr::StatsMgr() :
|
||||
global_(new StatContext()) {
|
||||
|
||||
}
|
||||
|
||||
void StatsMgr::setValue(const std::string& name, const int64_t value) {
|
||||
setValueInternal(name, value);
|
||||
void
|
||||
StatsMgr::setValue(const string& name, const int64_t value) {
|
||||
MultiThreadingMgr::call(mutex_, [&]() {setValueInternal(name, value);});
|
||||
}
|
||||
|
||||
void StatsMgr::setValue(const std::string& name, const double value) {
|
||||
setValueInternal(name, value);
|
||||
void
|
||||
StatsMgr::setValue(const string& name, const double value) {
|
||||
MultiThreadingMgr::call(mutex_, [&]() {setValueInternal(name, value);});
|
||||
}
|
||||
|
||||
void StatsMgr::setValue(const std::string& name, const StatsDuration& value) {
|
||||
setValueInternal(name, value);
|
||||
}
|
||||
void StatsMgr::setValue(const std::string& name, const std::string& value) {
|
||||
setValueInternal(name, value);
|
||||
void
|
||||
StatsMgr::setValue(const string& name, const StatsDuration& value) {
|
||||
MultiThreadingMgr::call(mutex_, [&]() {setValueInternal(name, value);});
|
||||
}
|
||||
|
||||
void StatsMgr::addValue(const std::string& name, const int64_t value) {
|
||||
addValueInternal(name, value);
|
||||
void
|
||||
StatsMgr::setValue(const string& name, const string& value) {
|
||||
MultiThreadingMgr::call(mutex_, [&]() {setValueInternal(name, value);});
|
||||
}
|
||||
|
||||
void StatsMgr::addValue(const std::string& name, const double value) {
|
||||
addValueInternal(name, value);
|
||||
void
|
||||
StatsMgr::addValue(const string& name, const int64_t value) {
|
||||
MultiThreadingMgr::call(mutex_, [&]() {addValueInternal(name, value);});
|
||||
}
|
||||
|
||||
void StatsMgr::addValue(const std::string& name, const StatsDuration& value) {
|
||||
addValueInternal(name, value);
|
||||
void
|
||||
StatsMgr::addValue(const string& name, const double value) {
|
||||
MultiThreadingMgr::call(mutex_, [&]() {addValueInternal(name, value);});
|
||||
}
|
||||
|
||||
void StatsMgr::addValue(const std::string& name, const std::string& value) {
|
||||
addValueInternal(name, value);
|
||||
void
|
||||
StatsMgr::addValue(const string& name, const StatsDuration& value) {
|
||||
MultiThreadingMgr::call(mutex_, [&]() {addValueInternal(name, value);});
|
||||
}
|
||||
|
||||
ObservationPtr StatsMgr::getObservation(const std::string& name) const {
|
||||
void
|
||||
StatsMgr::addValue(const string& name, const string& value) {
|
||||
MultiThreadingMgr::call(mutex_, [&]() {addValueInternal(name, value);});
|
||||
}
|
||||
|
||||
ObservationPtr
|
||||
StatsMgr::getObservation(const string& name) const {
|
||||
ObservationPtr result;
|
||||
MultiThreadingMgr::call(mutex_, [&]() {result = getObservationInternal(name);});
|
||||
return (result);
|
||||
}
|
||||
|
||||
ObservationPtr
|
||||
StatsMgr::getObservationInternal(const string& name) const {
|
||||
/// @todo: Implement contexts.
|
||||
// Currently we keep everything in a global context.
|
||||
return (global_->get(name));
|
||||
}
|
||||
|
||||
void StatsMgr::addObservation(const ObservationPtr& stat) {
|
||||
void
|
||||
StatsMgr::addObservation(const ObservationPtr& stat) {
|
||||
MultiThreadingMgr::call(mutex_, [&]() {addObservationInternal(stat);});
|
||||
}
|
||||
|
||||
void
|
||||
StatsMgr::addObservationInternal(const ObservationPtr& stat) {
|
||||
/// @todo: Implement contexts.
|
||||
// Currently we keep everything in a global context.
|
||||
return (global_->add(stat));
|
||||
}
|
||||
|
||||
bool StatsMgr::deleteObservation(const std::string& name) {
|
||||
bool
|
||||
StatsMgr::deleteObservation(const string& name) {
|
||||
bool result;
|
||||
MultiThreadingMgr::call(mutex_, [&]() {result = deleteObservationInternal(name);});
|
||||
return (result);
|
||||
}
|
||||
|
||||
bool
|
||||
StatsMgr::deleteObservationInternal(const string& name) {
|
||||
/// @todo: Implement contexts.
|
||||
// Currently we keep everything in a global context.
|
||||
return (global_->del(name));
|
||||
}
|
||||
|
||||
bool StatsMgr::setMaxSampleAge(const std::string& name,
|
||||
const StatsDuration& duration) {
|
||||
ObservationPtr obs = getObservation(name);
|
||||
if (obs) {
|
||||
obs->setMaxSampleAge(duration);
|
||||
return (true);
|
||||
} else {
|
||||
return (false);
|
||||
}
|
||||
bool
|
||||
StatsMgr::setMaxSampleAge(const string& name, const StatsDuration& duration) {
|
||||
bool result = false;
|
||||
auto lambda = [&]() {
|
||||
ObservationPtr obs = getObservationInternal(name);
|
||||
if (obs) {
|
||||
obs->setMaxSampleAge(duration);
|
||||
result = true;
|
||||
}
|
||||
};
|
||||
MultiThreadingMgr::call(mutex_, lambda);
|
||||
return (result);
|
||||
}
|
||||
|
||||
bool StatsMgr::setMaxSampleCount(const std::string& name,
|
||||
uint32_t max_samples) {
|
||||
ObservationPtr obs = getObservation(name);
|
||||
if (obs) {
|
||||
obs->setMaxSampleCount(max_samples);
|
||||
return (true);
|
||||
} else {
|
||||
return (false);
|
||||
}
|
||||
bool
|
||||
StatsMgr::setMaxSampleCount(const string& name, uint32_t max_samples) {
|
||||
bool result = false;
|
||||
auto lambda = [&]() {
|
||||
ObservationPtr obs = getObservationInternal(name);
|
||||
if (obs) {
|
||||
obs->setMaxSampleCount(max_samples);
|
||||
result = true;
|
||||
}
|
||||
};
|
||||
MultiThreadingMgr::call(mutex_, lambda);
|
||||
return (result);
|
||||
}
|
||||
|
||||
void StatsMgr::setMaxSampleAgeAll(const StatsDuration& duration) {
|
||||
// Let's iterate over all stored statistics...
|
||||
for (std::map<std::string, ObservationPtr>::iterator s = global_->stats_.begin();
|
||||
s != global_->stats_.end(); ++s) {
|
||||
|
||||
// ... and set duration limit for each statistic.
|
||||
s->second->setMaxSampleAge(duration);
|
||||
}
|
||||
void
|
||||
StatsMgr::setMaxSampleAgeAll(const StatsDuration& duration) {
|
||||
MultiThreadingMgr::call(mutex_, [&]() {global_->setMaxSampleAgeAll(duration);});
|
||||
}
|
||||
|
||||
void StatsMgr::setMaxSampleCountAll(uint32_t max_samples) {
|
||||
// Let's iterate over all stored statistics...
|
||||
for (std::map<std::string, ObservationPtr>::iterator s = global_->stats_.begin();
|
||||
s != global_->stats_.end(); ++s) {
|
||||
|
||||
// ... and set count limit for each statistic.
|
||||
s->second->setMaxSampleCount(max_samples);
|
||||
}
|
||||
void
|
||||
StatsMgr::setMaxSampleCountAll(uint32_t max_samples) {
|
||||
MultiThreadingMgr::call(mutex_, [&]() {global_->setMaxSampleCountAll(max_samples);});
|
||||
}
|
||||
|
||||
bool StatsMgr::reset(const std::string& name) {
|
||||
ObservationPtr obs = getObservation(name);
|
||||
if (obs) {
|
||||
obs->reset();
|
||||
return (true);
|
||||
} else {
|
||||
return (false);
|
||||
}
|
||||
bool
|
||||
StatsMgr::reset(const string& name) {
|
||||
bool result = false;
|
||||
auto lambda = [&]() {
|
||||
ObservationPtr obs = getObservationInternal(name);
|
||||
if (obs) {
|
||||
obs->reset();
|
||||
result = true;
|
||||
}
|
||||
};
|
||||
MultiThreadingMgr::call(mutex_, lambda);
|
||||
return (result);
|
||||
}
|
||||
|
||||
bool StatsMgr::del(const std::string& name) {
|
||||
return (global_->del(name));
|
||||
bool
|
||||
StatsMgr::del(const string& name) {
|
||||
bool result;
|
||||
MultiThreadingMgr::call(mutex_, [&]() {result = global_->del(name);});
|
||||
return (result);
|
||||
}
|
||||
|
||||
void StatsMgr::removeAll() {
|
||||
global_->stats_.clear();
|
||||
void
|
||||
StatsMgr::removeAll() {
|
||||
MultiThreadingMgr::call(mutex_, [&]() {global_->clear();});
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr StatsMgr::get(const std::string& name) const {
|
||||
ConstElementPtr
|
||||
StatsMgr::get(const string& name) const {
|
||||
isc::data::ElementPtr response = isc::data::Element::createMap(); // a map
|
||||
ObservationPtr obs = getObservation(name);
|
||||
if (obs) {
|
||||
response->set(name, obs->getJSON()); // that contains observations
|
||||
}
|
||||
auto lambda = [&]() {
|
||||
ObservationPtr obs = getObservationInternal(name);
|
||||
if (obs) {
|
||||
response->set(name, obs->getJSON()); // that contains observations
|
||||
}
|
||||
};
|
||||
MultiThreadingMgr::call(mutex_, lambda);
|
||||
return (response);
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr StatsMgr::getAll() const {
|
||||
isc::data::ElementPtr map = isc::data::Element::createMap(); // a map
|
||||
|
||||
// Let's iterate over all stored statistics...
|
||||
for (std::map<std::string, ObservationPtr>::iterator s = global_->stats_.begin();
|
||||
s != global_->stats_.end(); ++s) {
|
||||
|
||||
// ... and add each of them to the map.
|
||||
map->set(s->first, s->second->getJSON());
|
||||
}
|
||||
return (map);
|
||||
ConstElementPtr
|
||||
StatsMgr::getAll() const {
|
||||
ConstElementPtr result;
|
||||
MultiThreadingMgr::call(mutex_, [&]() {result = global_->getAll();});
|
||||
return (result);
|
||||
}
|
||||
|
||||
void StatsMgr::resetAll() {
|
||||
// Let's iterate over all stored statistics...
|
||||
for (std::map<std::string, ObservationPtr>::iterator s = global_->stats_.begin();
|
||||
s != global_->stats_.end(); ++s) {
|
||||
|
||||
// ... and reset each statistic.
|
||||
s->second->reset();
|
||||
}
|
||||
void
|
||||
StatsMgr::resetAll() {
|
||||
MultiThreadingMgr::call(mutex_, [&]() {global_->reset();});
|
||||
}
|
||||
|
||||
size_t StatsMgr::getSize(const std::string& name) const {
|
||||
ObservationPtr obs = getObservation(name);
|
||||
size_t
|
||||
StatsMgr::getSize(const string& name) const {
|
||||
size_t size = 0;
|
||||
if (obs) {
|
||||
size = obs->getSize();
|
||||
}
|
||||
auto lambda = [&]() {
|
||||
ObservationPtr obs = getObservationInternal(name);
|
||||
if (obs) {
|
||||
size = obs->getSize();
|
||||
}
|
||||
};
|
||||
MultiThreadingMgr::call(mutex_, lambda);
|
||||
return (size);
|
||||
}
|
||||
|
||||
size_t StatsMgr::count() const {
|
||||
return (global_->stats_.size());
|
||||
size_t
|
||||
StatsMgr::count() const {
|
||||
size_t result;
|
||||
MultiThreadingMgr::call(mutex_, [&]() {result = global_->size();});
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
StatsMgr::statisticSetMaxSampleAgeHandler(const std::string& /*name*/,
|
||||
const isc::data::ConstElementPtr& params) {
|
||||
std::string name, error;
|
||||
ConstElementPtr
|
||||
StatsMgr::statisticSetMaxSampleAgeHandler(const string& /*name*/,
|
||||
const ConstElementPtr& params) {
|
||||
string name, error;
|
||||
StatsDuration duration;
|
||||
if (!StatsMgr::getStatName(params, name, error)) {
|
||||
return (createAnswer(CONTROL_RESULT_ERROR, error));
|
||||
@@ -204,10 +241,10 @@ StatsMgr::statisticSetMaxSampleAgeHandler(const std::string& /*name*/,
|
||||
}
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
StatsMgr::statisticSetMaxSampleCountHandler(const std::string& /*name*/,
|
||||
const isc::data::ConstElementPtr& params) {
|
||||
std::string name, error;
|
||||
ConstElementPtr
|
||||
StatsMgr::statisticSetMaxSampleCountHandler(const string& /*name*/,
|
||||
const ConstElementPtr& params) {
|
||||
string name, error;
|
||||
uint32_t max_samples;
|
||||
if (!StatsMgr::getStatName(params, name, error)) {
|
||||
return (createAnswer(CONTROL_RESULT_ERROR, error));
|
||||
@@ -224,10 +261,10 @@ StatsMgr::statisticSetMaxSampleCountHandler(const std::string& /*name*/,
|
||||
}
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
StatsMgr::statisticGetHandler(const std::string& /*name*/,
|
||||
const isc::data::ConstElementPtr& params) {
|
||||
std::string name, error;
|
||||
ConstElementPtr
|
||||
StatsMgr::statisticGetHandler(const string& /*name*/,
|
||||
const ConstElementPtr& params) {
|
||||
string name, error;
|
||||
if (!StatsMgr::getStatName(params, name, error)) {
|
||||
return (createAnswer(CONTROL_RESULT_ERROR, error));
|
||||
}
|
||||
@@ -235,14 +272,13 @@ StatsMgr::statisticGetHandler(const std::string& /*name*/,
|
||||
StatsMgr::instance().get(name)));
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
StatsMgr::statisticResetHandler(const std::string& /*name*/,
|
||||
const isc::data::ConstElementPtr& params) {
|
||||
std::string name, error;
|
||||
ConstElementPtr
|
||||
StatsMgr::statisticResetHandler(const string& /*name*/,
|
||||
const ConstElementPtr& params) {
|
||||
string name, error;
|
||||
if (!StatsMgr::getStatName(params, name, error)) {
|
||||
return (createAnswer(CONTROL_RESULT_ERROR, error));
|
||||
}
|
||||
|
||||
if (StatsMgr::instance().reset(name)) {
|
||||
return (createAnswer(CONTROL_RESULT_SUCCESS,
|
||||
"Statistic '" + name + "' reset."));
|
||||
@@ -252,10 +288,10 @@ StatsMgr::statisticResetHandler(const std::string& /*name*/,
|
||||
}
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
StatsMgr::statisticRemoveHandler(const std::string& /*name*/,
|
||||
const isc::data::ConstElementPtr& params) {
|
||||
std::string name, error;
|
||||
ConstElementPtr
|
||||
StatsMgr::statisticRemoveHandler(const string& /*name*/,
|
||||
const ConstElementPtr& params) {
|
||||
string name, error;
|
||||
if (!StatsMgr::getStatName(params, name, error)) {
|
||||
return (createAnswer(CONTROL_RESULT_ERROR, error));
|
||||
}
|
||||
@@ -269,33 +305,33 @@ StatsMgr::statisticRemoveHandler(const std::string& /*name*/,
|
||||
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
StatsMgr::statisticRemoveAllHandler(const std::string& /*name*/,
|
||||
const isc::data::ConstElementPtr& /*params*/) {
|
||||
ConstElementPtr
|
||||
StatsMgr::statisticRemoveAllHandler(const string& /*name*/,
|
||||
const ConstElementPtr& /*params*/) {
|
||||
StatsMgr::instance().removeAll();
|
||||
return (createAnswer(CONTROL_RESULT_SUCCESS,
|
||||
"All statistics removed."));
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
StatsMgr::statisticGetAllHandler(const std::string& /*name*/,
|
||||
const isc::data::ConstElementPtr& /*params*/) {
|
||||
ConstElementPtr
|
||||
StatsMgr::statisticGetAllHandler(const string& /*name*/,
|
||||
const ConstElementPtr& /*params*/) {
|
||||
ConstElementPtr all_stats = StatsMgr::instance().getAll();
|
||||
return (createAnswer(CONTROL_RESULT_SUCCESS, all_stats));
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
StatsMgr::statisticResetAllHandler(const std::string& /*name*/,
|
||||
const isc::data::ConstElementPtr& /*params*/) {
|
||||
ConstElementPtr
|
||||
StatsMgr::statisticResetAllHandler(const string& /*name*/,
|
||||
const ConstElementPtr& /*params*/) {
|
||||
StatsMgr::instance().resetAll();
|
||||
return (createAnswer(CONTROL_RESULT_SUCCESS,
|
||||
"All statistics reset to neutral values."));
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
StatsMgr::statisticSetMaxSampleAgeAllHandler(const std::string& /*name*/,
|
||||
const isc::data::ConstElementPtr& params) {
|
||||
std::string error;
|
||||
ConstElementPtr
|
||||
StatsMgr::statisticSetMaxSampleAgeAllHandler(const string& /*name*/,
|
||||
const ConstElementPtr& params) {
|
||||
string error;
|
||||
StatsDuration duration;
|
||||
if (!StatsMgr::getStatDuration(params, duration, error)) {
|
||||
return (createAnswer(CONTROL_RESULT_ERROR, error));
|
||||
@@ -305,10 +341,10 @@ StatsMgr::statisticSetMaxSampleAgeAllHandler(const std::string& /*name*/,
|
||||
"All statistics duration limit are set."));
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
StatsMgr::statisticSetMaxSampleCountAllHandler(const std::string& /*name*/,
|
||||
const isc::data::ConstElementPtr& params) {
|
||||
std::string error;
|
||||
ConstElementPtr
|
||||
StatsMgr::statisticSetMaxSampleCountAllHandler(const string& /*name*/,
|
||||
const ConstElementPtr& params) {
|
||||
string error;
|
||||
uint32_t max_samples;
|
||||
if (!StatsMgr::getStatMaxSamples(params, max_samples, error)) {
|
||||
return (createAnswer(CONTROL_RESULT_ERROR, error));
|
||||
@@ -319,9 +355,9 @@ StatsMgr::statisticSetMaxSampleCountAllHandler(const std::string& /*name*/,
|
||||
}
|
||||
|
||||
bool
|
||||
StatsMgr::getStatName(const isc::data::ConstElementPtr& params,
|
||||
std::string& name,
|
||||
std::string& reason) {
|
||||
StatsMgr::getStatName(const ConstElementPtr& params,
|
||||
string& name,
|
||||
string& reason) {
|
||||
if (!params) {
|
||||
reason = "Missing mandatory 'name' parameter.";
|
||||
return (false);
|
||||
@@ -335,15 +371,14 @@ StatsMgr::getStatName(const isc::data::ConstElementPtr& params,
|
||||
reason = "'name' parameter expected to be a string.";
|
||||
return (false);
|
||||
}
|
||||
|
||||
name = stat_name->stringValue();
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool
|
||||
StatsMgr::getStatDuration(const isc::data::ConstElementPtr& params,
|
||||
StatsMgr::getStatDuration(const ConstElementPtr& params,
|
||||
StatsDuration& duration,
|
||||
std::string& reason) {
|
||||
string& reason) {
|
||||
if (!params) {
|
||||
reason = "Missing mandatory 'duration' parameter.";
|
||||
return (false);
|
||||
@@ -353,24 +388,20 @@ StatsMgr::getStatDuration(const isc::data::ConstElementPtr& params,
|
||||
reason = "Missing mandatory 'duration' parameter.";
|
||||
return (false);
|
||||
}
|
||||
|
||||
int64_t time_duration = stat_duration->intValue();
|
||||
|
||||
int64_t hours = time_duration / 3600;
|
||||
time_duration -= hours * 3600;
|
||||
|
||||
int64_t minutes = time_duration / 60;
|
||||
time_duration -= minutes * 60;
|
||||
|
||||
int64_t seconds = time_duration;
|
||||
duration = boost::posix_time::time_duration(hours, minutes, seconds, 0);
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool
|
||||
StatsMgr::getStatMaxSamples(const isc::data::ConstElementPtr& params,
|
||||
StatsMgr::getStatMaxSamples(const ConstElementPtr& params,
|
||||
uint32_t& max_samples,
|
||||
std::string& reason) {
|
||||
string& reason) {
|
||||
if (!params) {
|
||||
reason = "Missing mandatory 'max-samples' parameter.";
|
||||
return (false);
|
||||
@@ -384,7 +415,6 @@ StatsMgr::getStatMaxSamples(const isc::data::ConstElementPtr& params,
|
||||
reason = "'max-samples' parameter expected to be an integer.";
|
||||
return (false);
|
||||
}
|
||||
|
||||
max_samples = stat_max_samples->intValue();
|
||||
return (true);
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
@@ -224,6 +225,8 @@ class StatsMgr : public boost::noncopyable {
|
||||
/// @return Pointer to the Observation object
|
||||
ObservationPtr getObservation(const std::string& name) const;
|
||||
|
||||
ObservationPtr getObservationInternal(const std::string& name) const;
|
||||
|
||||
/// @brief Generates statistic name in a given context
|
||||
///
|
||||
/// Example:
|
||||
@@ -447,14 +450,13 @@ private:
|
||||
/// @throw InvalidStatType is statistic exists and has a different type.
|
||||
template<typename DataType>
|
||||
void setValueInternal(const std::string& name, DataType value) {
|
||||
|
||||
// If we want to log each observation, here would be the best place for it.
|
||||
ObservationPtr stat = getObservation(name);
|
||||
ObservationPtr stat = getObservationInternal(name);
|
||||
if (stat) {
|
||||
stat->setValue(value);
|
||||
} else {
|
||||
stat.reset(new Observation(name, value));
|
||||
addObservation(stat);
|
||||
addObservationInternal(stat);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,14 +474,13 @@ private:
|
||||
/// @throw InvalidStatType is statistic exists and has a different type.
|
||||
template<typename DataType>
|
||||
void addValueInternal(const std::string& name, DataType value) {
|
||||
|
||||
// If we want to log each observation, here would be the best place for it.
|
||||
ObservationPtr existing = getObservation(name);
|
||||
ObservationPtr existing = getObservationInternal(name);
|
||||
if (!existing) {
|
||||
// We tried to add to a non-existing statistic. We can recover from
|
||||
// that. Simply add the new incremental value as a new statistic and
|
||||
// we're done.
|
||||
setValue(name, value);
|
||||
setValueInternal(name, value);
|
||||
return;
|
||||
} else {
|
||||
// Let's hope it is of correct type. If not, the underlying
|
||||
@@ -497,6 +498,8 @@ private:
|
||||
/// @param stat observation
|
||||
void addObservation(const ObservationPtr& stat);
|
||||
|
||||
void addObservationInternal(const ObservationPtr& stat);
|
||||
|
||||
/// @private
|
||||
|
||||
/// @brief Tries to delete an observation.
|
||||
@@ -505,6 +508,8 @@ private:
|
||||
/// @return true if deleted, false if not found
|
||||
bool deleteObservation(const std::string& name);
|
||||
|
||||
bool deleteObservationInternal(const std::string& name);
|
||||
|
||||
/// @brief Utility method that attempts to extract statistic name
|
||||
///
|
||||
/// This method attempts to extract statistic name from the params
|
||||
@@ -562,6 +567,9 @@ private:
|
||||
|
||||
// This is a global context. All statistics will initially be stored here.
|
||||
StatContextPtr global_;
|
||||
|
||||
/// @brief Mutex for protecting stats.
|
||||
mutable std::mutex mutex_;
|
||||
};
|
||||
|
||||
};
|
||||
|
@@ -24,8 +24,7 @@ TEST(ContextTest, basic) {
|
||||
StatContext ctx;
|
||||
|
||||
// By default the context does not hold any statistics.
|
||||
EXPECT_EQ(0, ctx.stats_.size());
|
||||
EXPECT_TRUE(ctx.stats_.empty());
|
||||
EXPECT_EQ(0, ctx.size());
|
||||
|
||||
// It should be possible to add 'a' statistic
|
||||
EXPECT_NO_THROW(ctx.add(a));
|
||||
@@ -38,8 +37,7 @@ TEST(ContextTest, basic) {
|
||||
EXPECT_NO_THROW(ctx.add(c));
|
||||
|
||||
// By now we should have 3 statistics recorded
|
||||
EXPECT_EQ(3, ctx.stats_.size());
|
||||
EXPECT_FALSE(ctx.stats_.empty());
|
||||
EXPECT_EQ(3, ctx.size());
|
||||
|
||||
// Let's try to retrieve them
|
||||
ObservationPtr from_ctx;
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#define MULTI_THREADING_MGR_H
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <mutex>
|
||||
|
||||
namespace isc {
|
||||
namespace util {
|
||||
@@ -62,6 +63,16 @@ public:
|
||||
/// @param enabled The new mode.
|
||||
void setMode(bool enabled);
|
||||
|
||||
template<typename Callable>
|
||||
static void call(std::mutex& lk, const Callable& f) {
|
||||
if (MultiThreadingMgr::instance().getMode()) {
|
||||
std::lock_guard<std::mutex> lock(lk);
|
||||
f();
|
||||
} else {
|
||||
f();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief Constructor.
|
||||
|
Reference in New Issue
Block a user