]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1239] updating poke time is now Kea thread safe
authorRazvan Becheriu <razvan@isc.org>
Wed, 3 Jun 2020 19:21:31 +0000 (22:21 +0300)
committerRazvan Becheriu <razvan@isc.org>
Tue, 16 Jun 2020 09:02:51 +0000 (09:02 +0000)
src/hooks/dhcp/high_availability/communication_state.cc
src/hooks/dhcp/high_availability/communication_state.h
src/hooks/dhcp/high_availability/tests/ha_test.h

index 67658b36a1f77b39d5eb266b01aa469ea80995cd..488849390243461fa9fd4a5ba30d16f224ee2a5d 100644 (file)
 #include <dhcp/pkt6.h>
 #include <http/date_time.h>
 #include <util/boost_time_utils.h>
+#include <util/multi_threading_mgr.h>
+
 #include <boost/bind.hpp>
 #include <boost/pointer_cast.hpp>
+
 #include <sstream>
 #include <utility>
 
@@ -29,7 +32,10 @@ using namespace isc::data;
 using namespace isc::dhcp;
 using namespace isc::http;
 using namespace isc::log;
+using namespace isc::util;
+
 using namespace boost::posix_time;
+using namespace std;
 
 namespace {
 
@@ -54,13 +60,28 @@ CommunicationState::CommunicationState(const IOServicePtr& io_service,
       heartbeat_impl_(0), partner_state_(-1), partner_scopes_(),
       clock_skew_(0, 0, 0, 0), last_clock_skew_warn_(),
       my_time_at_skew_(), partner_time_at_skew_(),
-      analyzed_messages_count_(0) {
+      analyzed_messages_count_(0), mutex_(new mutex()) {
 }
 
 CommunicationState::~CommunicationState() {
     stopHeartbeat();
 }
 
+void
+CommunicationState::modifyPokeTime(const long secs) {
+    if (MultiThreadingMgr::instance().getMode()) {
+        std::lock_guard<std::mutex> lk(*mutex_);
+        modifyPokeTimeInternal(secs);
+    } else {
+        modifyPokeTimeInternal(secs);
+    }
+}
+
+void
+CommunicationState::modifyPokeTimeInternal(const long secs) {
+    poke_time_ += boost::posix_time::seconds(secs);
+}
+
 void
 CommunicationState::setPartnerState(const std::string& state) {
     try {
@@ -151,12 +172,29 @@ CommunicationState::stopHeartbeat() {
     }
 }
 
-void
-CommunicationState::poke() {
+boost::posix_time::time_duration
+CommunicationState::updatePokeTime() {
+    if (MultiThreadingMgr::instance().getMode()) {
+        std::lock_guard<std::mutex> lk(*mutex_);
+        return (updatePokeTimeInternal());
+    } else {
+        return (updatePokeTimeInternal());
+    }
+}
+
+boost::posix_time::time_duration
+CommunicationState::updatePokeTimeInternal() {
     // Remember previous poke time.
     boost::posix_time::ptime prev_poke_time = poke_time_;
     // Set poke time to the current time.
     poke_time_ = boost::posix_time::microsec_clock::universal_time();
+    return (poke_time_ - prev_poke_time);
+}
+
+void
+CommunicationState::poke() {
+    // Update poke time and compute duration.
+    boost::posix_time::time_duration duration_since_poke = updatePokeTime();
 
     // If we have been tracking the DHCP messages directed to the partner,
     // we need to clear any gathered information because the connection
@@ -170,7 +208,6 @@ CommunicationState::poke() {
         // lower than 1s is when we're performing lease updates. In order to avoid the
         // overhead of re-scheduling the timer too frequently we reschedule it only if the
         // duration is 1s or more. This matches the time resolution for heartbeats.
-        boost::posix_time::time_duration duration_since_poke = poke_time_ - prev_poke_time;
         if (duration_since_poke.total_seconds() > 0) {
             // A poke causes the timer to be re-scheduled to prevent it
             // from triggering a heartbeat shortly after confirming the
@@ -183,6 +220,16 @@ CommunicationState::poke() {
 
 int64_t
 CommunicationState::getDurationInMillisecs() const {
+    if (MultiThreadingMgr::instance().getMode()) {
+        std::lock_guard<std::mutex> lk(*mutex_);
+        return (getDurationInMillisecsInternal());
+    } else {
+        return (getDurationInMillisecsInternal());
+    }
+}
+
+int64_t
+CommunicationState::getDurationInMillisecsInternal() const {
     ptime now = boost::posix_time::microsec_clock::universal_time();
     time_duration duration = now - poke_time_;
     return (duration.total_milliseconds());
index 0350fbca94a5ab3d2a6b3f9f42262cc08b15c226..2ffffa4f8ab89eaa832c08fb0ff44bb8141257df 100644 (file)
@@ -13,6 +13,7 @@
 #include <asiolink/io_service.h>
 #include <cc/data.h>
 #include <dhcp/pkt.h>
+
 #include <boost/date_time/posix_time/posix_time.hpp>
 #include <boost/function.hpp>
 #include <boost/multi_index_container.hpp>
 #include <boost/multi_index/indexed_by.hpp>
 #include <boost/multi_index/member.hpp>
 #include <boost/multi_index/ordered_index.hpp>
+#include <boost/scoped_ptr.hpp>
 #include <boost/shared_ptr.hpp>
+
 #include <map>
+#include <mutex>
 #include <set>
 #include <string>
 
@@ -344,8 +348,45 @@ public:
     /// @return JSON element holding the report.
     data::ElementPtr getReport() const;
 
+    /// @brief Modifies poke time by adding seconds to it.
+    ///
+    /// Used in unittests only.
+    ///
+    /// Should be called in a thread safe context.
+    ///
+    /// @param secs number of seconds to be added to the poke time. If
+    /// the value is negative it will set the poke time in the past
+    /// comparing to current value.
+    void modifyPokeTime(const long secs);
+
+    /// @brief Modifies poke time by adding seconds to it.
+    ///
+    /// Used in unittests only.
+    ///
+    /// @param secs number of seconds to be added to the poke time. If
+    /// the value is negative it will set the poke time in the past
+    /// comparing to current value.
+    void modifyPokeTimeInternal(const long secs);
+
 protected:
 
+    /// @brief Returns duration between the poke time and current time.
+    ///
+    /// @return Duration between the poke time and current time.
+    int64_t getDurationInMillisecsInternal() const;
+
+    /// @brief Update the poke time and compute the duration.
+    ///
+    /// @return The time elapsed.
+    boost::posix_time::time_duration updatePokeTime();
+
+    /// @brief Update the poke time and compute the duration.
+    ///
+    /// Should be called in a thread safe context.
+    ///
+    /// @return The time elapsed.
+    boost::posix_time::time_duration updatePokeTimeInternal();
+
     /// @brief Pointer to the common IO service instance.
     asiolink::IOServicePtr io_service_;
 
@@ -387,6 +428,9 @@ protected:
 
     /// @brief Total number of analyzed messages to be responded by partner.
     size_t analyzed_messages_count_;
+
+    /// @brief The mutex used to protect internal state.
+    const boost::scoped_ptr<std::mutex> mutex_;
 };
 
 /// @brief Type of the pointer to the @c CommunicationState object.
index 9b41acfbcc96211991c29dedd9edceecb7520503..94d230827b8f7525b64feeae798984569e36c794 100644 (file)
@@ -45,15 +45,6 @@ public:
         : StateType(io_service, config) {
     }
 
-    /// @brief Modifies poke time by adding seconds to it.
-    ///
-    /// @param secs number of seconds to be added to the poke time. If
-    /// the value is negative it will set the poke time in the past
-    /// comparing to current value.
-    void modifyPokeTime(const long secs) {
-        StateType::poke_time_ += boost::posix_time::seconds(secs);
-    }
-
     /// @brief Checks if the object was poked recently.
     ///
     /// @return true if the object was poked less than 5 seconds ago,