From: Razvan Becheriu Date: Tue, 26 Mar 2019 05:45:30 +0000 (+0200) Subject: thread save StatsMgr X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9ce07d86c0894a683867336028796e833932cb11;p=thirdparty%2Fkea.git thread save StatsMgr --- diff --git a/src/lib/dhcpsrv/srv_config.cc b/src/lib/dhcpsrv/srv_config.cc index a4d3b59a61..5a4754d70b 100644 --- a/src/lib/dhcpsrv/srv_config.cc +++ b/src/lib/dhcpsrv/srv_config.cc @@ -38,6 +38,8 @@ SrvConfig::SrvConfig() cfg_host_operations6_(CfgHostOperations::createConfig6()), class_dictionary_(new ClientClassDictionary()), decline_timer_(0), echo_v4_client_id_(true), dhcp4o6_port_(0), + server_threads_(0), + server_max_thread_queue_size_(0), d2_client_config_(new D2ClientConfig()), configured_globals_(Element::createMap()), cfg_consist_(new CfgConsistency()) { @@ -56,6 +58,8 @@ SrvConfig::SrvConfig(const uint32_t sequence) cfg_host_operations6_(CfgHostOperations::createConfig6()), class_dictionary_(new ClientClassDictionary()), decline_timer_(0), echo_v4_client_id_(true), dhcp4o6_port_(0), + server_threads_(0), + server_max_thread_queue_size_(0), d2_client_config_(new D2ClientConfig()), configured_globals_(Element::createMap()), cfg_consist_(new CfgConsistency()) { @@ -250,7 +254,6 @@ SrvConfig::mergeGlobals(SrvConfig& other) { void SrvConfig::removeStatistics() { - // Removes statistics for v4 and v6 subnets getCfgSubnets4()->removeStatistics(); diff --git a/src/lib/stats/stats_mgr.cc b/src/lib/stats/stats_mgr.cc index e5b29cb5eb..41f2bcbca9 100644 --- a/src/lib/stats/stats_mgr.cc +++ b/src/lib/stats/stats_mgr.cc @@ -30,61 +30,107 @@ StatsMgr::StatsMgr() mutex_.reset(new std::mutex()); } -void StatsMgr::setValue(const std::string& name, const int64_t value) { - LockGuard lock(mutex_.get()); +void StatsMgr::setValue(const std::string& name, const int64_t value, bool lock) { + std::mutex* mlock = nullptr; + if (lock) { + mlock = mutex_.get(); + } + LockGuard lockGuard(mlock); setValueInternal(name, value); } -void StatsMgr::setValue(const std::string& name, const double value) { - LockGuard lock(mutex_.get()); +void StatsMgr::setValue(const std::string& name, const double value, bool lock) { + std::mutex* mlock = nullptr; + if (lock) { + mlock = mutex_.get(); + } + LockGuard lockGuard(mlock); setValueInternal(name, value); } -void StatsMgr::setValue(const std::string& name, const StatsDuration& value) { - LockGuard lock(mutex_.get()); +void StatsMgr::setValue(const std::string& name, const StatsDuration& value, bool lock) { + std::mutex* mlock = nullptr; + if (lock) { + mlock = mutex_.get(); + } + LockGuard lockGuard(mlock); setValueInternal(name, value); } -void StatsMgr::setValue(const std::string& name, const std::string& value) { - LockGuard lock(mutex_.get()); + +void StatsMgr::setValue(const std::string& name, const std::string& value, bool lock) { + std::mutex* mlock = nullptr; + if (lock) { + mlock = mutex_.get(); + } + LockGuard lockGuard(mlock); setValueInternal(name, value); } -void StatsMgr::addValue(const std::string& name, const int64_t value) { - LockGuard lock(mutex_.get()); +void StatsMgr::addValue(const std::string& name, const int64_t value, bool lock) { + std::mutex* mlock = nullptr; + if (lock) { + mlock = mutex_.get(); + } + LockGuard lockGuard(mlock); addValueInternal(name, value); } -void StatsMgr::addValue(const std::string& name, const double value) { - LockGuard lock(mutex_.get()); +void StatsMgr::addValue(const std::string& name, const double value, bool lock) { + std::mutex* mlock = nullptr; + if (lock) { + mlock = mutex_.get(); + } + LockGuard lockGuard(mlock); addValueInternal(name, value); } -void StatsMgr::addValue(const std::string& name, const StatsDuration& value) { - LockGuard lock(mutex_.get()); +void StatsMgr::addValue(const std::string& name, const StatsDuration& value, bool lock) { + std::mutex* mlock = nullptr; + if (lock) { + mlock = mutex_.get(); + } + LockGuard lockGuard(mlock); addValueInternal(name, value); } -void StatsMgr::addValue(const std::string& name, const std::string& value) { - LockGuard lock(mutex_.get()); +void StatsMgr::addValue(const std::string& name, const std::string& value, bool lock) { + std::mutex* mlock = nullptr; + if (lock) { + mlock = mutex_.get(); + } + LockGuard lockGuard(mlock); addValueInternal(name, value); } -ObservationPtr StatsMgr::getObservation(const std::string& name) const { - LockGuard lock(mutex_.get()); +ObservationPtr StatsMgr::getObservation(const std::string& name, bool lock) const { + std::mutex* mlock = nullptr; + if (lock) { + mlock = mutex_.get(); + } + LockGuard lockGuard(mlock); /// @todo: Implement contexts. // Currently we keep everything in a global context. return (global_->get(name)); + } -void StatsMgr::addObservation(const ObservationPtr& stat) { - LockGuard lock(mutex_.get()); +void StatsMgr::addObservation(const ObservationPtr& stat, bool lock) { + std::mutex* mlock = nullptr; + if (lock) { + mlock = mutex_.get(); + } + LockGuard lockGuard(mlock); /// @todo: Implement contexts. // Currently we keep everything in a global context. return (global_->add(stat)); } -bool StatsMgr::deleteObservation(const std::string& name) { - LockGuard lock(mutex_.get()); +bool StatsMgr::deleteObservation(const std::string& name, bool lock) { + std::mutex* mlock = nullptr; + if (lock) { + mlock = mutex_.get(); + } + LockGuard lockGuard(mlock); /// @todo: Implement contexts. // Currently we keep everything in a global context. return (global_->del(name)); @@ -102,7 +148,8 @@ void StatsMgr::setMaxSampleCount(const std::string& , uint32_t){ } bool StatsMgr::reset(const std::string& name) { - ObservationPtr obs = getObservation(name); + LockGuard lock(mutex_.get()); + ObservationPtr obs = getObservation(name, false); if (obs) { obs->reset(); return (true); @@ -122,8 +169,9 @@ void StatsMgr::removeAll() { } isc::data::ConstElementPtr StatsMgr::get(const std::string& name) const { + LockGuard lock(mutex_.get()); isc::data::ElementPtr response = isc::data::Element::createMap(); // a map - ObservationPtr obs = getObservation(name); + ObservationPtr obs = getObservation(name, false); if (obs) { response->set(name, obs->getJSON()); // that contains the observation } diff --git a/src/lib/stats/stats_mgr.h b/src/lib/stats/stats_mgr.h index 123de1f76c..d9052b8426 100644 --- a/src/lib/stats/stats_mgr.h +++ b/src/lib/stats/stats_mgr.h @@ -77,56 +77,56 @@ class StatsMgr : public boost::noncopyable { /// @param name name of the observation /// @param value integer value observed /// @throw InvalidStatType if statistic is not integer - void setValue(const std::string& name, const int64_t value); + void setValue(const std::string& name, const int64_t value, bool lock = true); /// @brief Records absolute floating point observation. /// /// @param name name of the observation /// @param value floating point value observed /// @throw InvalidStatType if statistic is not fp - void setValue(const std::string& name, const double value); + void setValue(const std::string& name, const double value, bool lock = true); /// @brief Records absolute duration observation. /// /// @param name name of the observation /// @param value duration value observed /// @throw InvalidStatType if statistic is not time duration - void setValue(const std::string& name, const StatsDuration& value); + void setValue(const std::string& name, const StatsDuration& value, bool lock = true); /// @brief Records absolute string observation. /// /// @param name name of the observation /// @param value string value observed /// @throw InvalidStatType if statistic is not a string - void setValue(const std::string& name, const std::string& value); + void setValue(const std::string& name, const std::string& value, bool lock = true); /// @brief Records incremental integer observation. /// /// @param name name of the observation /// @param value integer value observed /// @throw InvalidStatType if statistic is not integer - void addValue(const std::string& name, const int64_t value); + void addValue(const std::string& name, const int64_t value, bool lock = true); /// @brief Records incremental floating point observation. /// /// @param name name of the observation /// @param value floating point value observed /// @throw InvalidStatType if statistic is not fp - void addValue(const std::string& name, const double value); + void addValue(const std::string& name, const double value, bool lock = true); /// @brief Records incremental duration observation. /// /// @param name name of the observation /// @param value duration value observed /// @throw InvalidStatType if statistic is not time duration - void addValue(const std::string& name, const StatsDuration& value); + void addValue(const std::string& name, const StatsDuration& value, bool lock = true); /// @brief Records incremental string observation. /// /// @param name name of the observation /// @param value string value observed /// @throw InvalidStatType if statistic is not a string - void addValue(const std::string& name, const std::string& value); + void addValue(const std::string& name, const std::string& value, bool lock = true); /// @brief Determines maximum age of samples. /// @@ -207,7 +207,7 @@ class StatsMgr : public boost::noncopyable { /// Used in testing only. Production code should use @ref get() method. /// @param name name of the statistic /// @return Pointer to the Observation object - ObservationPtr getObservation(const std::string& name) const; + ObservationPtr getObservation(const std::string& name, bool lock = true) const; /// @brief Generates statistic name in a given context /// @@ -350,14 +350,13 @@ private: /// @throw InvalidStatType is statistic exists and has a different type. template 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 = getObservation(name, false); if (stat) { stat->setValue(value); } else { stat.reset(new Observation(name, value)); - addObservation(stat); + addObservation(stat, false); } } @@ -375,14 +374,13 @@ private: /// @throw InvalidStatType is statistic exists and has a different type. template 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 = getObservation(name, false); 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); + setValue(name, value, false); return; } else { // Let's hope it is of correct type. If not, the underlying @@ -398,7 +396,7 @@ private: /// That's an utility method used by public @ref setValue() and /// @ref addValue() methods. /// @param stat observation - void addObservation(const ObservationPtr& stat); + void addObservation(const ObservationPtr& stat, bool lock = true); /// @private @@ -406,7 +404,7 @@ private: /// /// @param name of the statistic to be deleted /// @return true if deleted, false if not found - bool deleteObservation(const std::string& name); + bool deleteObservation(const std::string& name, bool lock = true); /// @brief Utility method that attempts to extract statistic name ///