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