2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-09-03 23:45:27 +00:00

[#2764] Added lease tracking to the backends

This commit is contained in:
Marcin Siodelski
2023-02-21 10:15:43 +01:00
committed by Marcin Siodelski
parent 3030cb9f75
commit 2f2fb84863
14 changed files with 963 additions and 82 deletions

View 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);
}
}

View 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

View 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);

View 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.

View 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

View 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.

View 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

View 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 {

View 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

View 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

View 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

View 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());
}

View 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);

View 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