]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2764] Added lease tracking to the backends
authorMarcin Siodelski <marcin@isc.org>
Tue, 21 Feb 2023 09:15:43 +0000 (10:15 +0100)
committerMarcin Siodelski <msiodelski@gmail.com>
Tue, 14 Mar 2023 18:23:31 +0000 (19:23 +0100)
14 files changed:
src/lib/dhcpsrv/memfile_lease_mgr.cc
src/lib/dhcpsrv/memfile_lease_mgr.h
src/lib/dhcpsrv/mysql_lease_mgr.cc
src/lib/dhcpsrv/mysql_lease_mgr.h
src/lib/dhcpsrv/pgsql_lease_mgr.cc
src/lib/dhcpsrv/pgsql_lease_mgr.h
src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc
src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.h
src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc
src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
src/lib/dhcpsrv/tests/pgsql_lease_mgr_unittest.cc
src/lib/dhcpsrv/tests/tracking_lease_mgr_unittest.cc
src/lib/dhcpsrv/tracking_lease_mgr.cc
src/lib/dhcpsrv/tracking_lease_mgr.h

index 5cb8a4267be10ec3a4eb1c6ff6233e0198eb9878..b94c1593d8d64a213d3aaaadaf1c6357bc96bd47 100644 (file)
@@ -637,7 +637,7 @@ const int Memfile_LeaseMgr::MAJOR_VERSION_V6;
 const int Memfile_LeaseMgr::MINOR_VERSION_V6;
 
 Memfile_LeaseMgr::Memfile_LeaseMgr(const DatabaseConnection::ParameterMap& parameters)
-    : LeaseMgr(), lfc_setup_(), conn_(parameters), mutex_(new std::mutex) {
+    : TrackingLeaseMgr(), lfc_setup_(), conn_(parameters), mutex_(new std::mutex) {
     bool conversion_needed = false;
 
     // Check if the extended info tables are enabled.
@@ -727,6 +727,11 @@ Memfile_LeaseMgr::addLeaseInternal(const Lease4Ptr& lease) {
     // Increment class lease counters.
     class_lease_counter_.addLease(lease);
 
+    // Run installed callbacks.
+    if (hasCallbacks()) {
+        trackAddLease(lease, true);
+    }
+
     return (true);
 }
 
@@ -771,6 +776,11 @@ Memfile_LeaseMgr::addLeaseInternal(const Lease6Ptr& lease) {
         static_cast<void>(addExtendedInfo6(lease));
     }
 
+    // Run installed callbacks.
+    if (hasCallbacks()) {
+        trackAddLease(lease, true);
+    }
+
     return (true);
 }
 
@@ -1451,6 +1461,11 @@ Memfile_LeaseMgr::updateLease4Internal(const Lease4Ptr& lease) {
 
     // Adjust class lease counters.
     class_lease_counter_.updateLease(lease, old_lease);
+
+    // Run installed callbacks.
+    if (hasCallbacks()) {
+        trackUpdateLease(lease, true);
+    }
 }
 
 void
@@ -1526,6 +1541,11 @@ Memfile_LeaseMgr::updateLease6Internal(const Lease6Ptr& lease) {
             break;
         }
     }
+
+    // Run installed callbacks.
+    if (hasCallbacks()) {
+        trackUpdateLease(lease, true);
+    }
 }
 
 void
@@ -1571,6 +1591,11 @@ Memfile_LeaseMgr::deleteLeaseInternal(const Lease4Ptr& lease) {
         // Decrement class lease counters.
         class_lease_counter_.removeLease(lease);
 
+        // Run installed callbacks.
+        if (hasCallbacks()) {
+            trackDeleteLease(lease, true);
+        }
+
         return (true);
     }
 }
@@ -1625,6 +1650,11 @@ Memfile_LeaseMgr::deleteLeaseInternal(const Lease6Ptr& lease) {
             deleteExtendedInfo6(lease->addr_);
         }
 
+        // Run installed callbacks.
+        if (hasCallbacks()) {
+            trackDeleteLease(lease, true);
+        }
+
         return (true);
     }
 }
index 6745f69f24876b4ce041561f42f115cd343ca13b..0a88b31b640b92fa69fee990e860ffd2038e46bd 100644 (file)
@@ -15,7 +15,7 @@
 #include <dhcpsrv/csv_lease_file6.h>
 #include <dhcpsrv/memfile_lease_limits.h>
 #include <dhcpsrv/memfile_lease_storage.h>
-#include <dhcpsrv/lease_mgr.h>
+#include <dhcpsrv/tracking_lease_mgr.h>
 
 #include <boost/scoped_ptr.hpp>
 #include <boost/shared_ptr.hpp>
@@ -77,7 +77,7 @@ class LFCSetup;
 /// is not specified, the default location in the installation
 /// directory is used: <install-dir>/var/lib/kea/kea-leases4.csv and
 /// <install-dir>/var/lib/kea/kea-leases6.csv.
-class Memfile_LeaseMgr : public LeaseMgr {
+class Memfile_LeaseMgr : public TrackingLeaseMgr {
 public:
 
     /// @defgroup v4 memfile backend versions
index 3e79e7923a1fa4945ce59349cade9e568013ce67..572dafc42aa3a502b2bc892fb12ff710f1e89fc8 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2023 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -1794,6 +1794,48 @@ MySqlLeaseMgr::MySqlLeaseContextAlloc::~MySqlLeaseContextAlloc() {
     // If running in single-threaded mode, there's nothing to do here.
 }
 
+// MySqlLeaseTrackingContextAlloc Constructor and Destructor
+
+MySqlLeaseMgr::MySqlLeaseTrackingContextAlloc::MySqlLeaseTrackingContextAlloc(
+    MySqlLeaseMgr& mgr, const LeasePtr& lease) : ctx_(), mgr_(mgr), lease_(lease) {
+
+    if (MultiThreadingMgr::instance().getMode()) {
+        // multi-threaded
+        {
+            // we need to protect the whole pool_ operation, hence extra scope {}
+            lock_guard<mutex> lock(mgr_.pool_->mutex_);
+            if (mgr_.hasCallbacks() && !mgr_.tryLock(lease)) {
+                isc_throw(DbOperationError, "unable to lock the lease " << lease->addr_);
+            }
+            if (!mgr_.pool_->pool_.empty()) {
+                ctx_ = mgr_.pool_->pool_.back();
+                mgr_.pool_->pool_.pop_back();
+            }
+        }
+        if (!ctx_) {
+            ctx_ = mgr_.createContext();
+        }
+    } else {
+        // single-threaded
+        if (mgr_.pool_->pool_.empty()) {
+            isc_throw(Unexpected, "No available MySQL lease context?!");
+        }
+        ctx_ = mgr_.pool_->pool_.back();
+    }
+}
+
+MySqlLeaseMgr::MySqlLeaseTrackingContextAlloc::~MySqlLeaseTrackingContextAlloc() {
+    if (MultiThreadingMgr::instance().getMode()) {
+        // multi-threaded
+        lock_guard<mutex> lock(mgr_.pool_->mutex_);
+        if (mgr_.hasCallbacks()) {
+            mgr_.unlock(lease_);
+        }
+        mgr_.pool_->pool_.push_back(ctx_);
+    }
+    // If running in single-threaded mode, there's nothing to do here.
+}
+
 void
 MySqlLeaseMgr::setExtendedInfoTablesEnabled(const db::DatabaseConnection::ParameterMap& /* parameters */) {
     isc_throw(isc::NotImplemented, "extended info tables are not yet supported by mysql");
@@ -1802,7 +1844,7 @@ MySqlLeaseMgr::setExtendedInfoTablesEnabled(const db::DatabaseConnection::Parame
 // MySqlLeaseMgr Constructor and Destructor
 
 MySqlLeaseMgr::MySqlLeaseMgr(const DatabaseConnection::ParameterMap& parameters)
-    : parameters_(parameters), timer_name_("") {
+    : TrackingLeaseMgr(), parameters_(parameters), timer_name_("") {
 
     // Check if the extended info tables are enabled.
     LeaseMgr::setExtendedInfoTablesEnabled(parameters);
@@ -1955,7 +1997,6 @@ bool
 MySqlLeaseMgr::addLeaseCommon(MySqlLeaseContextPtr& ctx,
                               StatementIndex stindex,
                               std::vector<MYSQL_BIND>& bind) {
-
     // Bind the parameters to the statement
     int status = mysql_stmt_bind_param(ctx->conn_.statements_[stindex], &bind[0]);
     checkError(ctx, status, stindex, "unable to bind parameters");
@@ -1983,7 +2024,7 @@ MySqlLeaseMgr::addLease(const Lease4Ptr& lease) {
         .arg(lease->addr_.toText());
 
     // Get a context
-    MySqlLeaseContextAlloc get_context(*this);
+    MySqlLeaseTrackingContextAlloc get_context(*this, lease);
     MySqlLeaseContextPtr ctx = get_context.ctx_;
 
     // Create the MYSQL_BIND array for the lease
@@ -1996,6 +2037,11 @@ MySqlLeaseMgr::addLease(const Lease4Ptr& lease) {
     // of the Lease up to the point of insertion in the database).
     lease->updateCurrentExpirationTime();
 
+    // Run installed callbacks.
+    if (hasCallbacks()) {
+        trackAddLease(lease, false);
+    }
+
     return (result);
 }
 
@@ -2006,7 +2052,7 @@ MySqlLeaseMgr::addLease(const Lease6Ptr& lease) {
         .arg(lease->type_);
 
     // Get a context
-    MySqlLeaseContextAlloc get_context(*this);
+    MySqlLeaseTrackingContextAlloc get_context(*this, lease);
     MySqlLeaseContextPtr ctx = get_context.ctx_;
 
     // Create the MYSQL_BIND array for the lease
@@ -2019,6 +2065,11 @@ MySqlLeaseMgr::addLease(const Lease6Ptr& lease) {
     // of the Lease up to the point of insertion in the database).
     lease->updateCurrentExpirationTime();
 
+    // Run installed callbacks.
+    if (hasCallbacks()) {
+        trackAddLease(lease, false);
+    }
+
     return (result);
 }
 
@@ -2853,7 +2904,7 @@ MySqlLeaseMgr::updateLease4(const Lease4Ptr& lease) {
         .arg(lease->addr_.toText());
 
     // Get a context
-    MySqlLeaseContextAlloc get_context(*this);
+    MySqlLeaseTrackingContextAlloc get_context(*this, lease);
     MySqlLeaseContextPtr ctx = get_context.ctx_;
 
     // Create the MYSQL_BIND array for the data being updated
@@ -2890,6 +2941,11 @@ MySqlLeaseMgr::updateLease4(const Lease4Ptr& lease) {
 
     // Update lease current expiration time.
     lease->updateCurrentExpirationTime();
+
+    // Run installed callbacks.
+    if (hasCallbacks()) {
+        trackUpdateLease(lease, false);
+    }
 }
 
 void
@@ -2901,7 +2957,7 @@ MySqlLeaseMgr::updateLease6(const Lease6Ptr& lease) {
         .arg(lease->type_);
 
     // Get a context
-    MySqlLeaseContextAlloc get_context(*this);
+    MySqlLeaseTrackingContextAlloc get_context(*this, lease);
     MySqlLeaseContextPtr ctx = get_context.ctx_;
 
     // Create the MYSQL_BIND array for the data being updated
@@ -2943,6 +2999,11 @@ MySqlLeaseMgr::updateLease6(const Lease6Ptr& lease) {
 
     // Update lease current expiration time.
     lease->updateCurrentExpirationTime();
+
+    // Run installed callbacks.
+    if (hasCallbacks()) {
+        trackUpdateLease(lease, false);
+    }
 }
 
 // Delete lease methods.  Similar to other groups of methods, these comprise
@@ -2951,13 +3012,9 @@ MySqlLeaseMgr::updateLease6(const Lease6Ptr& lease) {
 // handles the common processing.
 
 uint64_t
-MySqlLeaseMgr::deleteLeaseCommon(StatementIndex stindex,
+MySqlLeaseMgr::deleteLeaseCommon(MySqlLeaseContextPtr& ctx,
+                                 StatementIndex stindex,
                                  MYSQL_BIND* bind) {
-
-    // Get a context
-    MySqlLeaseContextAlloc get_context(*this);
-    MySqlLeaseContextPtr ctx = get_context.ctx_;
-
     // Bind the input parameters to the statement
     int status = mysql_stmt_bind_param(ctx->conn_.statements_[stindex], bind);
     checkError(ctx, status, stindex, "unable to bind WHERE clause parameter");
@@ -3000,10 +3057,17 @@ MySqlLeaseMgr::deleteLease(const Lease4Ptr& lease) {
     inbind[1].buffer = reinterpret_cast<char*>(&expire);
     inbind[1].buffer_length = sizeof(expire);
 
-    auto affected_rows = deleteLeaseCommon(DELETE_LEASE4, inbind);
+    // Get a context
+    MySqlLeaseTrackingContextAlloc get_context(*this, lease);
+    MySqlLeaseContextPtr ctx = get_context.ctx_;
+
+    auto affected_rows = deleteLeaseCommon(ctx, DELETE_LEASE4, inbind);
 
     // Check success case first as it is the most likely outcome.
     if (affected_rows == 1) {
+        if (hasCallbacks()) {
+            trackDeleteLease(lease, false);
+        }
         return (true);
     }
 
@@ -3052,10 +3116,17 @@ MySqlLeaseMgr::deleteLease(const Lease6Ptr& lease) {
     inbind[1].buffer = reinterpret_cast<char*>(&expire);
     inbind[1].buffer_length = sizeof(expire);
 
-    auto affected_rows = deleteLeaseCommon(DELETE_LEASE6, inbind);
+    // Get a context
+    MySqlLeaseTrackingContextAlloc get_context(*this, lease);
+    MySqlLeaseContextPtr ctx = get_context.ctx_;
+
+    auto affected_rows = deleteLeaseCommon(ctx, DELETE_LEASE6, inbind);
 
     // Check success case first as it is the most likely outcome.
     if (affected_rows == 1) {
+        if (hasCallbacks()) {
+            trackDeleteLease(lease, false);
+        }
         return (true);
     }
 
@@ -3104,8 +3175,12 @@ MySqlLeaseMgr::deleteExpiredReclaimedLeasesCommon(const uint32_t secs,
     inbind[1].buffer = reinterpret_cast<char*>(&expire_time);
     inbind[1].buffer_length = sizeof(expire_time);
 
+    // Get a context
+    MySqlLeaseContextAlloc get_context(*this);
+    MySqlLeaseContextPtr ctx = get_context.ctx_;
+
     // Get the number of deleted leases and log it.
-    uint64_t deleted_leases = deleteLeaseCommon(statement_index, inbind);
+    uint64_t deleted_leases = deleteLeaseCommon(ctx, statement_index, inbind);
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_DELETED_EXPIRED_RECLAIMED)
         .arg(deleted_leases);
 
index 8c2668f21dcd54e9d74d5c00a54dd99086c6ca6b..0def8c6aa9f02d38ac97216fb3fd3c9f74d833a3 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2023 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -10,7 +10,7 @@
 #include <asiolink/io_service.h>
 #include <dhcp/hwaddr.h>
 #include <dhcpsrv/dhcpsrv_exceptions.h>
-#include <dhcpsrv/lease_mgr.h>
+#include <dhcpsrv/tracking_lease_mgr.h>
 #include <mysql/mysql_connection.h>
 
 #include <boost/scoped_ptr.hpp>
@@ -89,7 +89,7 @@ typedef boost::shared_ptr<MySqlLeaseContextPool> MySqlLeaseContextPoolPtr;
 /// database.  Use of this backend presupposes that a MySQL database is
 /// available and that the Kea schema has been created within it.
 
-class MySqlLeaseMgr : public LeaseMgr {
+class MySqlLeaseMgr : public TrackingLeaseMgr {
 public:
 
     /// @brief Constructor
@@ -906,6 +906,7 @@ private:
     /// to the prepared statement, executes the statement and checks to
     /// see how many rows were deleted.
     ///
+    /// @param ctx Context
     /// @param stindex Index of prepared statement to be executed
     /// @param bind Array of MYSQL_BIND objects representing the parameters.
     ///        (Note that the number is determined by the number of parameters
@@ -915,7 +916,8 @@ private:
     ///
     /// @throw isc::db::DbOperationError An operation on the open database has
     ///        failed.
-    uint64_t deleteLeaseCommon(StatementIndex stindex,
+    uint64_t deleteLeaseCommon(MySqlLeaseContextPtr& ctx,
+                               StatementIndex stindex,
                                MYSQL_BIND* bind);
 
     /// @brief Delete expired-reclaimed leases.
@@ -1117,7 +1119,7 @@ private:
     /// @return The number of updates in the database or 0.
     virtual size_t buildExtendedInfoTables6(bool update, bool current) override;
 
-    /// @brief Context RAII Allocator.
+    /// @brief Context RAII allocator.
     class MySqlLeaseContextAlloc {
     public:
 
@@ -1143,6 +1145,39 @@ private:
         const MySqlLeaseMgr& mgr_;
     };
 
+    /// @brief Context RAII allocator for lease tracking.
+    ///
+    /// This context should be used in the non-const calls that
+    /// may trigger callbacks for lease tracking.
+    class MySqlLeaseTrackingContextAlloc {
+    public:
+
+        /// @brief Constructor
+        ///
+        /// This constructor takes a context of the pool if one is available
+        /// or creates a new one.
+        ///
+        /// @param mgr A parent instance
+        /// @param lease allocated or deallocated lease instance.
+        MySqlLeaseTrackingContextAlloc(MySqlLeaseMgr& mgr, const LeasePtr& lease);
+
+        /// @brief Destructor
+        ///
+        /// This destructor puts back the context in the pool.
+        ~MySqlLeaseTrackingContextAlloc();
+
+        /// @brief The context
+        MySqlLeaseContextPtr ctx_;
+
+    private:
+
+        /// @brief The manager
+        MySqlLeaseMgr& mgr_;
+
+        /// @brief Tracked lease instance.
+        LeasePtr lease_;
+    };
+
 protected:
 
     /// Extended information / Bulk Lease Query shared interface.
index 7c51d622fd4d9e84d291900a22ef2a17a69dd2cf..b42d66b396370886fc6f41386c82e490f624a5bf 100644 (file)
@@ -1250,6 +1250,48 @@ PgSqlLeaseMgr::PgSqlLeaseContextAlloc::~PgSqlLeaseContextAlloc() {
     // If running in single-threaded mode, there's nothing to do here.
 }
 
+// PgSqlLeaseTrackingContextAlloc Constructor and Destructor
+
+PgSqlLeaseMgr::PgSqlLeaseTrackingContextAlloc::PgSqlLeaseTrackingContextAlloc(
+    PgSqlLeaseMgr& mgr, const LeasePtr& lease) : ctx_(), mgr_(mgr), lease_(lease) {
+
+    if (MultiThreadingMgr::instance().getMode()) {
+        // multi-threaded
+        {
+            // we need to protect the whole pool_ operation, hence extra scope {}
+            lock_guard<mutex> lock(mgr_.pool_->mutex_);
+            if (mgr_.hasCallbacks() && !mgr_.tryLock(lease)) {
+                isc_throw(DbOperationError, "unable to lock the lease " << lease->addr_);
+            }
+            if (!mgr_.pool_->pool_.empty()) {
+                ctx_ = mgr_.pool_->pool_.back();
+                mgr_.pool_->pool_.pop_back();
+            }
+        }
+        if (!ctx_) {
+            ctx_ = mgr_.createContext();
+        }
+    } else {
+        // single-threaded
+        if (mgr_.pool_->pool_.empty()) {
+            isc_throw(Unexpected, "No available PostgreSQL lease context?!");
+        }
+        ctx_ = mgr_.pool_->pool_.back();
+    }
+}
+
+PgSqlLeaseMgr::PgSqlLeaseTrackingContextAlloc::~PgSqlLeaseTrackingContextAlloc() {
+    if (MultiThreadingMgr::instance().getMode()) {
+        // multi-threaded
+        lock_guard<mutex> lock(mgr_.pool_->mutex_);
+        if (mgr_.hasCallbacks()) {
+            mgr_.unlock(lease_);
+        }
+        mgr_.pool_->pool_.push_back(ctx_);
+    }
+    // If running in single-threaded mode, there's nothing to do here.
+}
+
 void
 PgSqlLeaseMgr::setExtendedInfoTablesEnabled(const db::DatabaseConnection::ParameterMap& /* parameters */) {
     isc_throw(isc::NotImplemented, "extended info tables are not yet supported by mysql");
@@ -1258,7 +1300,7 @@ PgSqlLeaseMgr::setExtendedInfoTablesEnabled(const db::DatabaseConnection::Parame
 // PgSqlLeaseMgr Constructor and Destructor
 
 PgSqlLeaseMgr::PgSqlLeaseMgr(const DatabaseConnection::ParameterMap& parameters)
-    : parameters_(parameters), timer_name_("") {
+    : TrackingLeaseMgr(), parameters_(parameters), timer_name_("") {
 
     // Check if the extended info tables are enabled.
     LeaseMgr::setExtendedInfoTablesEnabled(parameters);
@@ -1452,7 +1494,7 @@ PgSqlLeaseMgr::addLease(const Lease4Ptr& lease) {
         .arg(lease->addr_.toText());
 
     // Get a context
-    PgSqlLeaseContextAlloc get_context(*this);
+    PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
     PgSqlLeaseContextPtr ctx = get_context.ctx_;
 
     PsqlBindArray bind_array;
@@ -1463,6 +1505,11 @@ PgSqlLeaseMgr::addLease(const Lease4Ptr& lease) {
     // of the Lease up to the point of insertion in the database).
     lease->updateCurrentExpirationTime();
 
+    // Run installed callbacks.
+    if (hasCallbacks()) {
+        trackAddLease(lease, false);
+    }
+
     return (result);
 }
 
@@ -1473,7 +1520,7 @@ PgSqlLeaseMgr::addLease(const Lease6Ptr& lease) {
         .arg(lease->type_);
 
     // Get a context
-    PgSqlLeaseContextAlloc get_context(*this);
+    PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
     PgSqlLeaseContextPtr ctx = get_context.ctx_;
 
     PsqlBindArray bind_array;
@@ -1485,6 +1532,11 @@ PgSqlLeaseMgr::addLease(const Lease6Ptr& lease) {
     // of the Lease up to the point of insertion in the database).
     lease->updateCurrentExpirationTime();
 
+    // Run installed callbacks.
+    if (hasCallbacks()) {
+        trackAddLease(lease, false);
+    }
+
     return (result);
 }
 
@@ -2116,7 +2168,7 @@ PgSqlLeaseMgr::updateLease4(const Lease4Ptr& lease) {
         .arg(lease->addr_.toText());
 
     // Get a context
-    PgSqlLeaseContextAlloc get_context(*this);
+    PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
     PgSqlLeaseContextPtr ctx = get_context.ctx_;
 
     // Create the BIND array for the data being updated
@@ -2142,6 +2194,11 @@ PgSqlLeaseMgr::updateLease4(const Lease4Ptr& lease) {
 
     // Update lease current expiration time.
     lease->updateCurrentExpirationTime();
+
+    // Run installed callbacks.
+    if (hasCallbacks()) {
+        trackUpdateLease(lease, false);
+    }
 }
 
 void
@@ -2153,7 +2210,7 @@ PgSqlLeaseMgr::updateLease6(const Lease6Ptr& lease) {
         .arg(lease->type_);
 
     // Get a context
-    PgSqlLeaseContextAlloc get_context(*this);
+    PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
     PgSqlLeaseContextPtr ctx = get_context.ctx_;
 
     // Create the BIND array for the data being updated
@@ -2179,15 +2236,17 @@ PgSqlLeaseMgr::updateLease6(const Lease6Ptr& lease) {
 
     // Update lease current expiration time.
     lease->updateCurrentExpirationTime();
+
+    // Run installed callbacks.
+    if (hasCallbacks()) {
+        trackUpdateLease(lease, false);
+    }
 }
 
 uint64_t
-PgSqlLeaseMgr::deleteLeaseCommon(StatementIndex stindex,
+PgSqlLeaseMgr::deleteLeaseCommon(PgSqlLeaseContextPtr& ctx,
+                                 StatementIndex stindex,
                                  PsqlBindArray& bind_array) {
-    // Get a context
-    PgSqlLeaseContextAlloc get_context(*this);
-    PgSqlLeaseContextPtr ctx = get_context.ctx_;
-
     PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name,
                                  tagged_statements[stindex].nbparams,
                                  &bind_array.values_[0],
@@ -2222,10 +2281,17 @@ PgSqlLeaseMgr::deleteLease(const Lease4Ptr& lease) {
     }
     bind_array.add(expire_str);
 
-    auto affected_rows = deleteLeaseCommon(DELETE_LEASE4, bind_array);
+    // Get a context
+    PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
+    PgSqlLeaseContextPtr ctx = get_context.ctx_;
+
+    auto affected_rows = deleteLeaseCommon(ctx, DELETE_LEASE4, bind_array);
 
     // Check success case first as it is the most likely outcome.
     if (affected_rows == 1) {
+        if (hasCallbacks()) {
+            trackDeleteLease(lease, false);
+        }
         return (true);
     }
 
@@ -2263,10 +2329,17 @@ PgSqlLeaseMgr::deleteLease(const Lease6Ptr& lease) {
     }
     bind_array.add(expire_str);
 
-    auto affected_rows = deleteLeaseCommon(DELETE_LEASE6, bind_array);
+    // Get a context
+    PgSqlLeaseTrackingContextAlloc get_context(*this, lease);
+    PgSqlLeaseContextPtr ctx = get_context.ctx_;
+
+    auto affected_rows = deleteLeaseCommon(ctx, DELETE_LEASE6, bind_array);
 
     // Check success case first as it is the most likely outcome.
     if (affected_rows == 1) {
+        if (hasCallbacks()) {
+            trackDeleteLease(lease, false);
+        }
         return (true);
     }
 
@@ -2309,8 +2382,12 @@ PgSqlLeaseMgr::deleteExpiredReclaimedLeasesCommon(const uint32_t secs,
         static_cast<time_t>(secs));
     bind_array.add(expiration_str);
 
+    // Get a context
+    PgSqlLeaseContextAlloc get_context(*this);
+    PgSqlLeaseContextPtr ctx = get_context.ctx_;
+
     // Delete leases.
-    return (deleteLeaseCommon(statement_index, bind_array));
+    return (deleteLeaseCommon(ctx, statement_index, bind_array));
 }
 
 string
index cfa0b277ff0cc8788a988c2b137738bd9e3cb764..0b79629a2ae71a442eb97b33461b54ccb5ba135f 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2013-2022 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2023 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -11,6 +11,7 @@
 #include <dhcp/hwaddr.h>
 #include <dhcpsrv/dhcpsrv_exceptions.h>
 #include <dhcpsrv/lease_mgr.h>
+#include <dhcpsrv/tracking_lease_mgr.h>
 #include <pgsql/pgsql_connection.h>
 #include <pgsql/pgsql_exchange.h>
 
@@ -88,7 +89,7 @@ typedef boost::shared_ptr<PgSqlLeaseContextPool> PgSqlLeaseContextPoolPtr;
 /// database.  Use of this backend presupposes that a PostgreSQL database is
 /// available and that the Kea schema has been created within it.
 
-class PgSqlLeaseMgr : public LeaseMgr {
+class PgSqlLeaseMgr : public TrackingLeaseMgr {
 public:
 
     /// @brief Constructor
@@ -881,6 +882,7 @@ private:
     /// to the prepared statement, executes the statement and checks to
     /// see how many rows were deleted.
     ///
+    /// @param ctx Context
     /// @param stindex Index of prepared statement to be executed
     /// @param bind_array Array containing lease values and where clause
     /// parameters for the delete
@@ -889,7 +891,8 @@ private:
     ///
     /// @throw isc::db::DbOperationError An operation on the open database has
     ///        failed.
-    uint64_t deleteLeaseCommon(StatementIndex stindex,
+    uint64_t deleteLeaseCommon(PgSqlLeaseContextPtr& ctx,
+                               StatementIndex stindex,
                                db::PsqlBindArray& bind_array);
 
     /// @brief Delete expired-reclaimed leases.
@@ -1076,7 +1079,7 @@ private:
     /// @brief Write V6 leases to a file.
     virtual void writeLeases6(const std::string& /*filename*/) override;
 
-    /// @brief Context RAII Allocator.
+    /// @brief Context RAII allocator.
     class PgSqlLeaseContextAlloc {
     public:
 
@@ -1102,6 +1105,39 @@ private:
         const PgSqlLeaseMgr& mgr_;
     };
 
+    /// @brief Context RAII allocator for lease tracking.
+    ///
+    /// This context should be used in the non-const calls that
+    /// may trigger callbacks for lease tracking.
+    class PgSqlLeaseTrackingContextAlloc {
+    public:
+
+        /// @brief Constructor
+        ///
+        /// This constructor takes a context of the pool if one is available
+        /// or creates a new one.
+        ///
+        /// @param mgr A parent instance
+        /// @param lease allocated or deallocated lease instance.
+        PgSqlLeaseTrackingContextAlloc(PgSqlLeaseMgr& mgr, const LeasePtr& lease);
+
+        /// @brief Destructor
+        ///
+        /// This destructor puts back the context in the pool.
+        ~PgSqlLeaseTrackingContextAlloc();
+
+        /// @brief The context
+        PgSqlLeaseContextPtr ctx_;
+
+    private:
+
+        /// @brief The manager
+        PgSqlLeaseMgr& mgr_;
+
+        /// @brief Tracked lease instance.
+        LeasePtr lease_;
+    };
+
 protected:
 
     /// Extended information / Bulk Lease Query shared interface.
index 3ea4ad71697f8f1e8cce9222ad96249094264003..8f6a1720bd6febb64e36fb3b115569b3e14dbbbc 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <gtest/gtest.h>
 
+#include <functional>
 #include <limits>
 #include <sstream>
 
@@ -2945,9 +2946,10 @@ GenericLeaseMgrTest::makeLease6(const Lease::Type& type,
 }
 
 void
-GenericLeaseMgrTest::logCallback(const TrackingLeaseMgr::CallbackType type, SubnetID subnet_id,
-                                 const LeasePtr& lease) {
-    logs_.push_back(Log{type, subnet_id, lease});
+GenericLeaseMgrTest::logCallback(TrackingLeaseMgr::CallbackType type, SubnetID subnet_id,
+                                 LeasePtr lease, bool mt_safe) {
+    auto locked = (lmptr_ ? lmptr_->isLocked(lease) : false);
+    logs_.push_back(Log{type, subnet_id, lease, mt_safe, locked});
 }
 
 int
@@ -4157,6 +4159,246 @@ GenericLeaseMgrTest::testClassLeaseCount6(Lease::Type ltype) {
     ASSERT_FALSE(lease);
 }
 
+void
+GenericLeaseMgrTest::testTrackAddLease4(bool expect_locked, bool expect_mt_safe) {
+    // Register a callback for all subnets.
+    lmptr_->registerCallback(TrackingLeaseMgr::TRACK_ADD_LEASE, 0, "flq",
+                             std::bind(&GenericLeaseMgrTest::logCallback,
+                                       this,
+                                       TrackingLeaseMgr::TRACK_ADD_LEASE,
+                                       0,
+                                       ph::_1,
+                                       ph::_2));
+    // Add a lease. It should trigger the callback.
+    Lease4Ptr lease = initializeLease4(straddress4_[1]);
+    EXPECT_TRUE(lmptr_->addLease(lease));
+
+    // Make sure that the callback has been invoked.
+    ASSERT_EQ(1, logs_.size());
+
+    // This flag should be false for the Memfile backend and true
+    // for the SQL backends.
+    if (expect_locked) {
+        EXPECT_TRUE(logs_[0].locked);
+    } else {
+        EXPECT_FALSE(logs_[0].locked);
+    }
+    // This flag should be set to true for the Memfile backends.
+    // It should be false for other backends. If the backends do
+    // not provide the MT-safe context, the callbacks must protect
+    // against the concurrent access on their own.
+    if (expect_mt_safe) {
+        EXPECT_TRUE(logs_[0].mt_safe);
+    } else {
+        EXPECT_FALSE(logs_[0].mt_safe);
+    }
+
+    // The lease locks should have been released.
+    EXPECT_FALSE(lmptr_->isLocked(lease));
+}
+
+void
+GenericLeaseMgrTest::testTrackAddLease6(bool expect_locked, bool expect_mt_safe) {
+    // Register a callback for all subnets.
+    lmptr_->registerCallback(TrackingLeaseMgr::TRACK_ADD_LEASE, 0, "flq",
+                             std::bind(&GenericLeaseMgrTest::logCallback,
+                                       this,
+                                       TrackingLeaseMgr::TRACK_ADD_LEASE,
+                                       0,
+                                       ph::_1,
+                                       ph::_2));
+    // Add a lease. It should trigger the callback.
+    Lease6Ptr lease = initializeLease6(straddress6_[1]);
+    EXPECT_TRUE(lmptr_->addLease(lease));
+
+    // Make sure that the callback has been invoked.
+    ASSERT_EQ(1, logs_.size());
+
+    // This flag should be false for the Memfile backend and true
+    // for the SQL backends.
+    if (expect_locked) {
+        EXPECT_TRUE(logs_[0].locked);
+    } else {
+        EXPECT_FALSE(logs_[0].locked);
+    }
+    // This flag should be set to true for the Memfile backends.
+    // It should be false for other backends. If the backends do
+    // not provide the MT-safe context, the callbacks must protect
+    // against the concurrent access on their own.
+    if (expect_mt_safe) {
+        EXPECT_TRUE(logs_[0].mt_safe);
+    } else {
+        EXPECT_FALSE(logs_[0].mt_safe);
+    }
+
+    // The lease locks should have been released.
+    EXPECT_FALSE(lmptr_->isLocked(lease));
+}
+
+void
+GenericLeaseMgrTest::testTrackUpdateLease4(bool expect_locked, bool expect_mt_safe) {
+    // Register a callback for all subnets.
+    lmptr_->registerCallback(TrackingLeaseMgr::TRACK_UPDATE_LEASE, 0, "flq",
+                             std::bind(&GenericLeaseMgrTest::logCallback,
+                                       this,
+                                       TrackingLeaseMgr::TRACK_UPDATE_LEASE,
+                                       0,
+                                       ph::_1,
+                                       ph::_2));
+    // Add a lease.
+    Lease4Ptr lease = initializeLease4(straddress4_[1]);
+    EXPECT_TRUE(lmptr_->addLease(lease));
+    EXPECT_TRUE(logs_.empty());
+
+    lmptr_->updateLease4(lease);
+
+    // Make sure that the callback has been invoked.
+    ASSERT_EQ(1, logs_.size());
+
+    // This flag should be false for the Memfile backend and true
+    // for the SQL backends.
+    if (expect_locked) {
+        EXPECT_TRUE(logs_[0].locked);
+    } else {
+        EXPECT_FALSE(logs_[0].locked);
+    }
+    // This flag should be set to true for the Memfile backends.
+    // It should be false for other backends. If the backends do
+    // not provide the MT-safe context, the callbacks must protect
+    // against the concurrent access on their own.
+    if (expect_mt_safe) {
+        EXPECT_TRUE(logs_[0].mt_safe);
+    } else {
+        EXPECT_FALSE(logs_[0].mt_safe);
+    }
+
+    // The lease locks should have been released.
+    EXPECT_FALSE(lmptr_->isLocked(lease));
+}
+
+void
+GenericLeaseMgrTest::testTrackUpdateLease6(bool expect_locked, bool expect_mt_safe) {
+    // Register a callback for all subnets.
+    lmptr_->registerCallback(TrackingLeaseMgr::TRACK_UPDATE_LEASE, 0, "flq",
+                             std::bind(&GenericLeaseMgrTest::logCallback,
+                                       this,
+                                       TrackingLeaseMgr::TRACK_UPDATE_LEASE,
+                                       0,
+                                       ph::_1,
+                                       ph::_2));
+    // Add a lease.
+    Lease6Ptr lease = initializeLease6(straddress6_[1]);
+    EXPECT_TRUE(lmptr_->addLease(lease));
+    EXPECT_TRUE(logs_.empty());
+
+    lmptr_->updateLease6(lease);
+
+    // Make sure that the callback has been invoked.
+    ASSERT_EQ(1, logs_.size());
+
+    // This flag should be false for the Memfile backend and true
+    // for the SQL backends.
+    if (expect_locked) {
+        EXPECT_TRUE(logs_[0].locked);
+    } else {
+        EXPECT_FALSE(logs_[0].locked);
+    }
+    // This flag should be set to true for the Memfile backends.
+    // It should be false for other backends. If the backends do
+    // not provide the MT-safe context, the callbacks must protect
+    // against the concurrent access on their own.
+    if (expect_mt_safe) {
+        EXPECT_TRUE(logs_[0].mt_safe);
+    } else {
+        EXPECT_FALSE(logs_[0].mt_safe);
+    }
+
+    // The lease locks should have been released.
+    EXPECT_FALSE(lmptr_->isLocked(lease));
+}
+
+void
+GenericLeaseMgrTest::testTrackDeleteLease4(bool expect_locked, bool expect_mt_safe) {
+    // Register a callback for all subnets.
+    lmptr_->registerCallback(TrackingLeaseMgr::TRACK_DELETE_LEASE, 0, "flq",
+                             std::bind(&GenericLeaseMgrTest::logCallback,
+                                       this,
+                                       TrackingLeaseMgr::TRACK_DELETE_LEASE,
+                                       0,
+                                       ph::_1,
+                                       ph::_2));
+    // Add a lease.
+    Lease4Ptr lease = initializeLease4(straddress4_[1]);
+    EXPECT_TRUE(lmptr_->addLease(lease));
+    EXPECT_TRUE(logs_.empty());
+
+    lmptr_->deleteLease(lease);
+
+    // Make sure that the callback has been invoked.
+    ASSERT_EQ(1, logs_.size());
+
+    // This flag should be false for the Memfile backend and true
+    // for the SQL backends.
+    if (expect_locked) {
+        EXPECT_TRUE(logs_[0].locked);
+    } else {
+        EXPECT_FALSE(logs_[0].locked);
+    }
+    // This flag should be set to true for the Memfile backends.
+    // It should be false for other backends. If the backends do
+    // not provide the MT-safe context, the callbacks must protect
+    // against the concurrent access on their own.
+    if (expect_mt_safe) {
+        EXPECT_TRUE(logs_[0].mt_safe);
+    } else {
+        EXPECT_FALSE(logs_[0].mt_safe);
+    }
+
+    // The lease locks should have been released.
+    EXPECT_FALSE(lmptr_->isLocked(lease));
+}
+
+void
+GenericLeaseMgrTest::testTrackDeleteLease6(bool expect_locked, bool expect_mt_safe) {
+    // Register a callback for all subnets.
+    lmptr_->registerCallback(TrackingLeaseMgr::TRACK_DELETE_LEASE, 0, "flq",
+                             std::bind(&GenericLeaseMgrTest::logCallback,
+                                       this,
+                                       TrackingLeaseMgr::TRACK_DELETE_LEASE,
+                                       0,
+                                       ph::_1,
+                                       ph::_2));
+    // Add a lease.
+    Lease6Ptr lease = initializeLease6(straddress6_[1]);
+    EXPECT_TRUE(lmptr_->addLease(lease));
+    EXPECT_TRUE(logs_.empty());
+
+    lmptr_->deleteLease(lease);
+
+    // Make sure that the callback has been invoked.
+    ASSERT_EQ(1, logs_.size());
+
+    // This flag should be false for the Memfile backend and true
+    // for the SQL backends.
+    if (expect_locked) {
+        EXPECT_TRUE(logs_[0].locked);
+    } else {
+        EXPECT_FALSE(logs_[0].locked);
+    }
+    // This flag should be set to true for the Memfile backends.
+    // It should be false for other backends. If the backends do
+    // not provide the MT-safe context, the callbacks must protect
+    // against the concurrent access on their own.
+    if (expect_mt_safe) {
+        EXPECT_TRUE(logs_[0].mt_safe);
+    } else {
+        EXPECT_FALSE(logs_[0].mt_safe);
+    }
+
+    // The lease locks should have been released.
+    EXPECT_FALSE(lmptr_->isLocked(lease));
+}
+
 }  // namespace test
 }  // namespace dhcp
 }  // namespace isc
index b7c707df8514da1fa58b855420522514c81ce20f..82f7e41684147c53475dbd66b53ff6c4f1a92522 100644 (file)
@@ -45,6 +45,8 @@ public:
         TrackingLeaseMgr::CallbackType type;
         SubnetID subnet_id;
         LeasePtr lease;
+        bool mt_safe;
+        bool locked;
     } Log;
 
     /// @brief Default constructor.
@@ -173,8 +175,10 @@ public:
     /// @param type callback type.
     /// @param subnet_id subnet identifier.
     /// @param lease lease instance.
-    void logCallback(const TrackingLeaseMgr::CallbackType type, SubnetID subnet_id,
-                     const LeasePtr& lease);
+    /// @param mt a boolean flag indicating if the function has been called
+    /// in the thread-safe context.
+    void logCallback(TrackingLeaseMgr::CallbackType type, SubnetID subnet_id,
+                     LeasePtr lease, bool mt_safe);
 
     /// @brief Counts log entries.
     ///
@@ -568,6 +572,60 @@ public:
     /// @brief Checks a few v6 lease limit checking scenarios.
     void testLeaseLimits6();
 
+    /// @brief Checks if the backends call the callbacks when an
+    /// IPv4 lease is added.
+    ///
+    /// @param expect_locked a boolean flag indicating if the test should
+    /// expect that the lease is locked before the callback.
+    /// @param expect_mt_safe a boolean flag indicating if the test should
+    /// expect that the callbacks are called in the MT-safe context.
+    void testTrackAddLease4(bool expect_locked, bool expect_mt_safe);
+
+    /// @brief Checks if the backends call the callbacks when an
+    /// IPv6 lease is added.
+    ///
+    /// @param expect_locked a boolean flag indicating if the test should
+    /// expect that the lease is locked before the callback.
+    /// @param expect_mt_safe a boolean flag indicating if the test should
+    /// expect that the callbacks are called in the MT-safe context.
+    void testTrackAddLease6(bool expect_locked, bool expect_mt_safe);
+
+    /// @brief Checks if the backends call the callbacks when an
+    /// IPv4 lease is updated.
+    ///
+    /// @param expect_locked a boolean flag indicating if the test should
+    /// expect that the lease is locked before the callback.
+    /// @param expect_mt_safe a boolean flag indicating if the test should
+    /// expect that the callbacks are called in the MT-safe context.
+    void testTrackUpdateLease4(bool expect_locked, bool expect_mt_safe);
+
+    /// @brief Checks if the backends call the callbacks when an
+    /// IPv6 lease is updated.
+    ///
+    /// @param expect_locked a boolean flag indicating if the test should
+    /// expect that the lease is locked before the callback.
+    /// @param expect_mt_safe a boolean flag indicating if the test should
+    /// expect that the callbacks are called in the MT-safe context.
+    void testTrackUpdateLease6(bool expect_locked, bool expect_mt_safe);
+
+    /// @brief Checks if the backends call the callbacks when an
+    /// IPv4 lease is deleted.
+    ///
+    /// @param expect_locked a boolean flag indicating if the test should
+    /// expect that the lease is locked before the callback.
+    /// @param expect_mt_safe a boolean flag indicating if the test should
+    /// expect that the callbacks are called in the MT-safe context.
+    void testTrackDeleteLease4(bool expect_locked, bool expect_mt_safe);
+
+    /// @brief Checks if the backends call the callbacks when an
+    /// IPv6 lease is deleted.
+    ///
+    /// @param expect_locked a boolean flag indicating if the test should
+    /// expect that the lease is locked before the callback.
+    /// @param expect_mt_safe a boolean flag indicating if the test should
+    /// expect that the callbacks are called in the MT-safe context.
+    void testTrackDeleteLease6(bool expect_locked, bool expect_mt_safe);
+
     /// @brief String forms of IPv4 addresses
     std::vector<std::string> straddress4_;
 
@@ -587,7 +645,7 @@ public:
     std::vector<Log> logs_;
 
     /// @brief Pointer to the lease manager
-    LeaseMgr* lmptr_;
+    TrackingLeaseMgr* lmptr_;
 };
 
 class LeaseMgrDbLostCallbackTest : public ::testing::Test {
index fba9dc1568d3ec3a60fd057c6214cb0d48e26ef9..94d5d4d9d4adb8b8df54b847431c88fb65427732 100644 (file)
@@ -235,7 +235,7 @@ public:
                 " lease database backend.\n";
             throw;
         }
-        lmptr_ = &(LeaseMgrFactory::instance());
+        lmptr_ = static_cast<TrackingLeaseMgr*>(&(LeaseMgrFactory::instance()));
     }
 
     /// @brief Runs IOService and stops after a specified time.
@@ -2017,7 +2017,7 @@ TEST_F(MemfileLeaseMgrTest, lease4ContainerIndexUpdate) {
     // Recreate Memfile_LeaseMgr.
     LeaseMgrFactory::destroy();
     ASSERT_NO_THROW(LeaseMgrFactory::create(dbaccess));
-    lmptr_ = &(LeaseMgrFactory::instance());
+    lmptr_ = static_cast<TrackingLeaseMgr*>(&(LeaseMgrFactory::instance()));
 
     // We will store addresses here, so it will be easier to randomly
     // pick a lease.
@@ -2060,7 +2060,7 @@ TEST_F(MemfileLeaseMgrTest, lease4ContainerIndexUpdate) {
         // Recreate Memfile_LeaseMgr.
         LeaseMgrFactory::destroy();
         LeaseMgrFactory::create(dbaccess);
-        lmptr_ = &(LeaseMgrFactory::instance());
+        lmptr_ = static_cast<TrackingLeaseMgr*>(&(LeaseMgrFactory::instance()));
     });
 
     // Ok, let's check if the leases are really accessible.
@@ -2147,7 +2147,7 @@ TEST_F(MemfileLeaseMgrTest, lease6ContainerIndexUpdate) {
     // Recreate Memfile_LeaseMgr.
     LeaseMgrFactory::destroy();
     ASSERT_NO_THROW(LeaseMgrFactory::create(dbaccess));
-    lmptr_ = &(LeaseMgrFactory::instance());
+    lmptr_ = static_cast<TrackingLeaseMgr*>(&(LeaseMgrFactory::instance()));
 
     // We will store addresses here, so it will be easier to randomly
     // pick a lease.
@@ -2191,7 +2191,7 @@ TEST_F(MemfileLeaseMgrTest, lease6ContainerIndexUpdate) {
         // Recreate Memfile_LeaseMgr.
         LeaseMgrFactory::destroy();
         LeaseMgrFactory::create(dbaccess);
-        lmptr_ = &(LeaseMgrFactory::instance());
+        lmptr_ = static_cast<TrackingLeaseMgr*>(&(LeaseMgrFactory::instance()));
     });
 
     // Ok, let's check if the leases are really accessible.
@@ -4237,4 +4237,107 @@ TEST_F(MemfileLeaseMgrTest, buildExtendedInfoTables6rebuild) {
     EXPECT_EQ(exp_remote_id, ex_info->id_);
 }
 
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is added.
+TEST_F(MemfileLeaseMgrTest, trackAddLease4) {
+    startBackend(V4);
+    // Expect that lease is not locked and the MT-safe context.
+    testTrackAddLease4(false, true);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is added.
+TEST_F(MemfileLeaseMgrTest, trackAddLease4MultiThreading) {
+    startBackend(V4);
+    MultiThreadingMgr::instance().setMode(true);
+    // Expect that lease is not locked and the MT-safe context.
+    testTrackAddLease4(false, true);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is added.
+TEST_F(MemfileLeaseMgrTest, trackAddLease6) {
+    startBackend(V6);
+    // Expect that lease is not locked and the MT-safe context.
+    testTrackAddLease6(false, true);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is added.
+TEST_F(MemfileLeaseMgrTest, trackAddLease6MultiThreading) {
+    startBackend(V6);
+    MultiThreadingMgr::instance().setMode(true);
+    // Expect that lease is not locked and the MT-safe context.
+    testTrackAddLease6(false, true);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is added.
+TEST_F(MemfileLeaseMgrTest, trackUpdateLease4) {
+    startBackend(V4);
+    // Expect that lease is not locked and the MT-safe context.
+    testTrackUpdateLease4(false, true);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is added.
+TEST_F(MemfileLeaseMgrTest, trackUpdateLease4MultiThreading) {
+    startBackend(V4);
+    MultiThreadingMgr::instance().setMode(true);
+    // Expect that lease is not locked and the MT-safe context.
+    testTrackUpdateLease4(false, true);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is added.
+TEST_F(MemfileLeaseMgrTest, trackUpdateLease6) {
+    startBackend(V6);
+    // Expect that lease is not locked and the MT-safe context.
+    testTrackUpdateLease6(false, true);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is added.
+TEST_F(MemfileLeaseMgrTest, trackUpdateLease6MultiThreading) {
+    startBackend(V6);
+    MultiThreadingMgr::instance().setMode(true);
+    // Expect that lease is not locked and the MT-safe context.
+    testTrackUpdateLease6(false, true);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is added.
+TEST_F(MemfileLeaseMgrTest, trackDeleteLease4) {
+    startBackend(V4);
+    // Expect that lease is not locked and the MT-safe context.
+    testTrackDeleteLease4(false, true);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is added.
+TEST_F(MemfileLeaseMgrTest, trackDeleteLease4MultiThreading) {
+    startBackend(V4);
+    MultiThreadingMgr::instance().setMode(true);
+    // Expect that lease is not locked and the MT-safe context.
+    testTrackDeleteLease4(false, true);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is added.
+TEST_F(MemfileLeaseMgrTest, trackDeleteLease6) {
+    startBackend(V6);
+    // Expect that lease is not locked and the MT-safe context.
+    testTrackDeleteLease6(false, true);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is added.
+TEST_F(MemfileLeaseMgrTest, trackDeleteLease6MultiThreading) {
+    startBackend(V6);
+    MultiThreadingMgr::instance().setMode(true);
+    // Expect that lease is not locked and the MT-safe context.
+    testTrackDeleteLease6(false, true);
+}
+
+
 }  // namespace
index 548b043a1a105e5eefccab75a3513a2dca1578a2..291c72f620bd31452be99d2de72f1a7813df86f8 100644 (file)
@@ -64,7 +64,7 @@ public:
             throw;
         }
 
-        lmptr_ = &(LeaseMgrFactory::instance());
+        lmptr_ = static_cast<TrackingLeaseMgr*>(&(LeaseMgrFactory::instance()));
 
         MultiThreadingMgr::instance().setMode(false);
     }
@@ -104,7 +104,7 @@ public:
     void reopen(Universe) {
         LeaseMgrFactory::destroy();
         LeaseMgrFactory::create(validMySQLConnectionString());
-        lmptr_ = &(LeaseMgrFactory::instance());
+        lmptr_ = static_cast<TrackingLeaseMgr*>(&(LeaseMgrFactory::instance()));
     }
 };
 
@@ -1174,4 +1174,106 @@ TEST_F(MySqlLeaseMgrTest, checkLimits6) {
     testLeaseLimits6();
 }
 
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is added.
+TEST_F(MySqlLeaseMgrTest, trackAddLease4) {
+    // It is unnecessary to lock the lease in ST. The backend does not
+    // provide the MT-safe context for the callbacks.
+    testTrackAddLease4(false, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is added.
+TEST_F(MySqlLeaseMgrTest, trackAddLease4MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    // The lease should be locked in the MT mode. The backend does not
+    // provide an MT-safe context.
+    testTrackAddLease4(true, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is added.
+TEST_F(MySqlLeaseMgrTest, trackAddLease6) {
+    // It is unnecessary to lock the lease in ST. The backend does not
+    // provide the MT-safe context for the callbacks.
+    testTrackAddLease6(false, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is added.
+TEST_F(MySqlLeaseMgrTest, trackAddLease6MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    // The lease should be locked in the MT mode. The backend does not
+    // provide an MT-safe context.
+    testTrackAddLease6(true, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is updated.
+TEST_F(MySqlLeaseMgrTest, trackUpdateLease4) {
+    // It is unnecessary to lock the lease in ST. The backend does not
+    // provide the MT-safe context for the callbacks.
+    testTrackUpdateLease4(false, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is updated.
+TEST_F(MySqlLeaseMgrTest, trackUpdateLease4MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    // The lease should be locked in the MT mode. The backend does not
+    // provide an MT-safe context.
+    testTrackUpdateLease4(true, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is updated.
+TEST_F(MySqlLeaseMgrTest, trackUpdateLease6) {
+    // It is unnecessary to lock the lease in ST. The backend does not
+    // provide the MT-safe context for the callbacks.
+    testTrackUpdateLease6(false, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is updated.
+TEST_F(MySqlLeaseMgrTest, trackUpdateLease6MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    // The lease should be locked in the MT mode. The backend does not
+    // provide an MT-safe context.
+    testTrackUpdateLease6(true, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is deleted.
+TEST_F(MySqlLeaseMgrTest, trackDeleteLease4) {
+    // It is unnecessary to lock the lease in ST. The backend does not
+    // provide the MT-safe context for the callbacks.
+    testTrackDeleteLease4(false, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is deleted.
+TEST_F(MySqlLeaseMgrTest, trackDeleteLease4MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    // The lease should be locked in the MT mode. The backend does not
+    // provide an MT-safe context.
+    testTrackDeleteLease4(true, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is deleted.
+TEST_F(MySqlLeaseMgrTest, trackDeleteLease6) {
+    // It is unnecessary to lock the lease in ST. The backend does not
+    // provide the MT-safe context for the callbacks.
+    testTrackDeleteLease6(false, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is deleted.
+TEST_F(MySqlLeaseMgrTest, trackDeleteLease6MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    // The lease should be locked in the MT mode. The backend does not
+    // provide an MT-safe context.
+    testTrackDeleteLease6(true, false);
+}
+
 }  // namespace
index 90b06ca706ce8c9c6ac73e47169b87f3e10a75e8..42d47bf03ca454e7d5c7c22ca9b1192e9f4a0332 100644 (file)
@@ -64,7 +64,7 @@ public:
             throw;
         }
 
-        lmptr_ = &(LeaseMgrFactory::instance());
+        lmptr_ = static_cast<TrackingLeaseMgr*>(&(LeaseMgrFactory::instance()));
 
         MultiThreadingMgr::instance().setMode(false);
     }
@@ -104,7 +104,7 @@ public:
     void reopen(Universe) {
         LeaseMgrFactory::destroy();
         LeaseMgrFactory::create(validPgSQLConnectionString());
-        lmptr_ = &(LeaseMgrFactory::instance());
+        lmptr_ = static_cast<TrackingLeaseMgr*>(&(LeaseMgrFactory::instance()));
     }
 };
 
@@ -1163,4 +1163,106 @@ TEST_F(PgSqlLeaseMgrTest, checkLimits6) {
     testLeaseLimits6();
 }
 
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is added.
+TEST_F(PgSqlLeaseMgrTest, trackAddLease4) {
+    // It is unnecessary to lock the lease in ST. The backend does not
+    // provide the MT-safe context for the callbacks.
+    testTrackAddLease4(false, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is added.
+TEST_F(PgSqlLeaseMgrTest, trackAddLease4MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    // The lease should be locked in the MT mode. The backend does not
+    // provide an MT-safe context.
+    testTrackAddLease4(true, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is added.
+TEST_F(PgSqlLeaseMgrTest, trackAddLease6) {
+    // It is unnecessary to lock the lease in ST. The backend does not
+    // provide the MT-safe context for the callbacks.
+    testTrackAddLease6(false, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is added.
+TEST_F(PgSqlLeaseMgrTest, trackAddLease6MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    // The lease should be locked in the MT mode. The backend does not
+    // provide an MT-safe context.
+    testTrackAddLease6(true, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is updated.
+TEST_F(PgSqlLeaseMgrTest, trackUpdateLease4) {
+    // It is unnecessary to lock the lease in ST. The backend does not
+    // provide the MT-safe context for the callbacks.
+    testTrackUpdateLease4(false, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is updated.
+TEST_F(PgSqlLeaseMgrTest, trackUpdateLease4MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    // The lease should be locked in the MT mode. The backend does not
+    // provide an MT-safe context.
+    testTrackUpdateLease4(true, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is updated.
+TEST_F(PgSqlLeaseMgrTest, trackUpdateLease6) {
+    // It is unnecessary to lock the lease in ST. The backend does not
+    // provide the MT-safe context for the callbacks.
+    testTrackUpdateLease6(false, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is updated.
+TEST_F(PgSqlLeaseMgrTest, trackUpdateLease6MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    // The lease should be locked in the MT mode. The backend does not
+    // provide an MT-safe context.
+    testTrackUpdateLease6(true, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is deleted.
+TEST_F(PgSqlLeaseMgrTest, trackDeleteLease4) {
+    // It is unnecessary to lock the lease in ST. The backend does not
+    // provide the MT-safe context for the callbacks.
+    testTrackDeleteLease4(false, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv4 lease is deleted.
+TEST_F(PgSqlLeaseMgrTest, trackDeleteLease4MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    // The lease should be locked in the MT mode. The backend does not
+    // provide an MT-safe context.
+    testTrackDeleteLease4(true, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is deleted.
+TEST_F(PgSqlLeaseMgrTest, trackDeleteLease6) {
+    // It is unnecessary to lock the lease in ST. The backend does not
+    // provide the MT-safe context for the callbacks.
+    testTrackDeleteLease6(false, false);
+}
+
+/// @brief Checks if the backends call the callbacks when an
+/// IPv6 lease is deleted.
+TEST_F(PgSqlLeaseMgrTest, trackDeleteLease6MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    // The lease should be locked in the MT mode. The backend does not
+    // provide an MT-safe context.
+    testTrackDeleteLease6(true, false);
+}
+
 }  // namespace
index 64d284d2eae373fb6cafab503ba1319c3120087c..6b71fffb2174ee4ec13ec38c96b53a7075cf9179 100644 (file)
@@ -61,15 +61,20 @@ TEST_F(TrackingLeaseMgrTest, tryLock) {
     // An attempt to lock an already locked lease should fail.
     EXPECT_TRUE(mgr.tryLock(initializeLease<Lease4>(1, "192.0.2.1")));
     EXPECT_FALSE(mgr.tryLock(initializeLease<Lease4>(1, "192.0.2.1")));
+    EXPECT_TRUE(mgr.isLocked(initializeLease<Lease4>(1, "192.0.2.1")));
 
     // We can lock another lease but we cannot lock an already locked one.
     EXPECT_TRUE(mgr.tryLock(initializeLease<Lease4>(1, "192.0.2.2")));
     EXPECT_FALSE(mgr.tryLock(initializeLease<Lease4>(1, "192.0.2.1")));
     EXPECT_FALSE(mgr.tryLock(initializeLease<Lease4>(2, "192.0.2.2")));
+    EXPECT_TRUE(mgr.isLocked(initializeLease<Lease4>(1, "192.0.1.2")));
+    EXPECT_TRUE(mgr.isLocked(initializeLease<Lease4>(2, "192.0.2.2")));
 
     // If we unlock the lease, it can be locked again. However, unlocking
     // the lease should not affect other locks.
     mgr.unlock(initializeLease<Lease4>(1, "192.0.2.1"));
+    EXPECT_FALSE(mgr.isLocked(initializeLease<Lease4>(1, "192.0.2.1")));
+    EXPECT_TRUE(mgr.isLocked(initializeLease<Lease4>(2, "192.0.2.2")));
     EXPECT_FALSE(mgr.tryLock(initializeLease<Lease4>(2, "192.0.2.2")));
     EXPECT_TRUE(mgr.tryLock(initializeLease<Lease4>(1, "192.0.2.1")));
 }
@@ -85,35 +90,35 @@ TEST_F(TrackingLeaseMgrTest, registerCallbacks) {
                                                    this,
                                                    TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                    0,
-                                                   _1)));
+                                                   _1, _2)));
     // Callback for lease add and subnet id 1.
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_ADD_LEASE, 1, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                    1,
-                                                   _1)));
+                                                   _1, _2)));
     // Callback for lease add and subnet id 2.
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_ADD_LEASE, 2, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                    1,
-                                                   _1)));
+                                                   _1, _2)));
     // Callback for lease update and subnet id 0.
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_UPDATE_LEASE, 0, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_UPDATE_LEASE,
                                                    0,
-                                                   _1)));
+                                                   _1, _2)));
     // Callback for lease delete and subnet id 0.
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_DELETE_LEASE, 0, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_DELETE_LEASE,
                                                    1,
-                                                   _1)));
+                                                   _1, _2)));
 
     // This call should trigger the lease add callbacks for subnet id 0 and 1.
     EXPECT_NO_THROW(mgr.trackAddLease(initializeLease<Lease4>(1, "192.0.2.1"), false));
@@ -140,7 +145,7 @@ TEST_F(TrackingLeaseMgrTest, registerCallbacksConflicts) {
                                                    this,
                                                    TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                    0,
-                                                   _1)));
+                                                   _1, _2)));
 
     // Another attempt should fail.
     EXPECT_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_ADD_LEASE, 0, "flq",
@@ -148,7 +153,7 @@ TEST_F(TrackingLeaseMgrTest, registerCallbacksConflicts) {
                                                 this,
                                                 TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                 0,
-                                                _1)),
+                                                _1, _2)),
                  InvalidOperation);
 
     // It should succeed for a different owner.
@@ -157,7 +162,7 @@ TEST_F(TrackingLeaseMgrTest, registerCallbacksConflicts) {
                                                    this,
                                                    TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                    0,
-                                                   _1)));
+                                                   _1, _2)));
 
     // It should also succeed for a different subnet id.
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_ADD_LEASE, 5, "qlf",
@@ -165,7 +170,7 @@ TEST_F(TrackingLeaseMgrTest, registerCallbacksConflicts) {
                                                    this,
                                                    TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                    5,
-                                                   _1)));
+                                                   _1, _2)));
 
     // But, another attempt for the subnet id should fail.
     EXPECT_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_ADD_LEASE, 5, "qlf",
@@ -173,7 +178,7 @@ TEST_F(TrackingLeaseMgrTest, registerCallbacksConflicts) {
                                                 this,
                                                 TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                 5,
-                                                _1)),
+                                                _1, _2)),
                  InvalidOperation);
 }
 
@@ -187,19 +192,19 @@ TEST_F(TrackingLeaseMgrTest, trackUpdateLease) {
                                                    this,
                                                    TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                    0,
-                                                   _1)));
+                                                   _1, _2)));
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_UPDATE_LEASE, 0, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_UPDATE_LEASE,
                                                    0,
-                                                   _1)));
+                                                   _1, _2)));
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_DELETE_LEASE, 0, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_DELETE_LEASE,
                                                    0,
-                                                   _1)));
+                                                   _1, _2)));
     EXPECT_NO_THROW(mgr.trackUpdateLease(initializeLease<Lease4>(1, "192.0.2.1"), false));
     EXPECT_EQ(1, logs_.size());
     EXPECT_EQ(1, countLogs(TrackingLeaseMgr::TRACK_UPDATE_LEASE, 0));
@@ -215,19 +220,19 @@ TEST_F(TrackingLeaseMgrTest, trackDeleteLease) {
                                                    this,
                                                    TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                    0,
-                                                   _1)));
+                                                   _1, _2)));
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_UPDATE_LEASE, 0, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_UPDATE_LEASE,
                                                    0,
-                                                   _1)));
+                                                   _1, _2)));
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_DELETE_LEASE, 0, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_DELETE_LEASE,
                                                    0,
-                                                   _1)));
+                                                   _1, _2)));
     EXPECT_NO_THROW(mgr.trackDeleteLease(initializeLease<Lease4>(1, "192.0.2.1"), false));
     EXPECT_EQ(1, logs_.size());
     EXPECT_EQ(1, countLogs(TrackingLeaseMgr::TRACK_DELETE_LEASE, 0));
@@ -244,43 +249,43 @@ TEST_F(TrackingLeaseMgrTest, unregisterCallbacksBySubnetID) {
                                                    this,
                                                    TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                    0,
-                                                   _1)));
+                                                   _1, _2)));
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_ADD_LEASE, 1, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                    1,
-                                                   _1)));
+                                                   _1, _2)));
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_ADD_LEASE, 2, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                    2,
-                                                   _1)));
+                                                   _1, _2)));
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_UPDATE_LEASE, 1, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_UPDATE_LEASE,
                                                    1,
-                                                   _1)));
+                                                   _1, _2)));
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_UPDATE_LEASE, 2, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_UPDATE_LEASE,
                                                    2,
-                                                   _1)));
+                                                   _1, _2)));
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_DELETE_LEASE, 1, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_DELETE_LEASE,
                                                    1,
-                                                   _1)));
+                                                   _1, _2)));
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_DELETE_LEASE, 2, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_DELETE_LEASE,
                                                    2,
-                                                   _1)));
+                                                   _1, _2)));
 
     // Unregister the callbacks for subnet id 1.
     EXPECT_NO_THROW(mgr.unregisterCallbacks(SubnetID(1)));
@@ -317,13 +322,13 @@ TEST_F(TrackingLeaseMgrTest, unregisterAllCallbacks) {
                                                    this,
                                                    TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                    0,
-                                                   _1)));
+                                                   _1, _2)));
     EXPECT_NO_THROW(mgr.registerCallback(TrackingLeaseMgr::TRACK_UPDATE_LEASE, 0, "flq",
                                          std::bind(&TrackingLeaseMgrTest::logCallback,
                                                    this,
                                                    TrackingLeaseMgr::TRACK_UPDATE_LEASE,
                                                    0,
-                                                   _1)));
+                                                   _1, _2)));
     // Make sure they have been registered.
     EXPECT_TRUE(mgr.hasCallbacks());
 
@@ -343,7 +348,7 @@ TEST_F(TrackingLeaseMgrTest, hasCallbacks) {
                                                    this,
                                                    TrackingLeaseMgr::TRACK_ADD_LEASE,
                                                    0,
-                                                   _1)));
+                                                   _1, _2)));
     EXPECT_TRUE(mgr.hasCallbacks());
 }
 
index 79697f3ced7704b4b1bbedaa4f8951b73620cd31..0a8e7402d7034f4b21e46630a1ea9ada563a6fd0 100644 (file)
@@ -35,6 +35,11 @@ TrackingLeaseMgr::unlock(const LeasePtr& lease) {
     locked_leases_.erase(lease->addr_);
 }
 
+bool
+TrackingLeaseMgr::isLocked(const LeasePtr& lease) {
+    return (locked_leases_.find(lease->addr_) != locked_leases_.end());
+}
+
 void
 TrackingLeaseMgr::trackAddLease(const LeasePtr& lease, bool mt_safe) {
     runCallbacks(TRACK_ADD_LEASE, lease, mt_safe);
index 7db4d5df1bcac30587fc32b30f5200266472d226..0aefc79e8d51f99cf3b75cbb395a132487e1fda6 100644 (file)
@@ -156,6 +156,17 @@ protected:
     /// @param lease a lease instance for which unlocking should be attempted.
     void unlock(const LeasePtr& lease);
 
+public:
+
+    /// @brief Checks if the lease is locked.
+    ///
+    /// This function is useful in the unit tests.
+    ///
+    /// @return true if the lease is locked, false otherwise.
+    bool isLocked(const LeasePtr& lease);
+
+protected:
+
     /// @brief Invokes the callbacks when a new lease is added.
     ///
     /// It executes all callbacks of the @c TRACK_ADD_LEASE type for a subnet id of 0