From e891976e33d5b16e2c2779202f30e7ab2e4e1da7 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Mon, 5 Sep 2022 17:43:04 +0200 Subject: [PATCH] [#1654] Checkpoint: UT and hook to do --- src/lib/dhcpsrv/lease_mgr.cc | 2 +- src/lib/dhcpsrv/lease_mgr.h | 57 ++++++++++------ src/lib/dhcpsrv/memfile_lease_mgr.cc | 66 +++++++++++++++++++ src/lib/dhcpsrv/memfile_lease_mgr.h | 24 +++++++ src/lib/dhcpsrv/mysql_lease_mgr.cc | 10 +++ src/lib/dhcpsrv/mysql_lease_mgr.h | 6 ++ src/lib/dhcpsrv/pgsql_lease_mgr.cc | 10 +++ src/lib/dhcpsrv/pgsql_lease_mgr.h | 6 ++ src/lib/dhcpsrv/tests/lease_mgr_unittest.cc | 10 ++- .../tests/memfile_lease_mgr_unittest.cc | 16 +++++ 10 files changed, 184 insertions(+), 23 deletions(-) diff --git a/src/lib/dhcpsrv/lease_mgr.cc b/src/lib/dhcpsrv/lease_mgr.cc index 1530281fac..3e7c5a360b 100644 --- a/src/lib/dhcpsrv/lease_mgr.cc +++ b/src/lib/dhcpsrv/lease_mgr.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-2022 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 diff --git a/src/lib/dhcpsrv/lease_mgr.h b/src/lib/dhcpsrv/lease_mgr.h index 04764cbe35..3ba306a319 100644 --- a/src/lib/dhcpsrv/lease_mgr.h +++ b/src/lib/dhcpsrv/lease_mgr.h @@ -829,11 +829,12 @@ public: /// or equal to this value will be included /// /// @return collection of IPv4 leases - virtual Lease4Collection getLeases4ByRelayId(const OptionBuffer& relay_id, - const asiolink::IOAddress& lower_bound_address, - const LeasePageSize& page_size, - const time_t& qry_start_time = 0, - const time_t& qry_end_time = 0) = 0; + virtual Lease4Collection + getLeases4ByRelayId(const OptionBuffer& relay_id, + const asiolink::IOAddress& lower_bound_address, + const LeasePageSize& page_size, + const time_t& qry_start_time = 0, + const time_t& qry_end_time = 0) = 0; /// @brief Returns existing IPv4 leases with a given remote-id. /// @@ -847,11 +848,12 @@ public: /// or equal to this value will be included. Defaults to zero. /// /// @return collection of IPv4 leases - virtual Lease4Collection getLeases4ByRemoteId(const OptionBuffer& remote_id, - const asiolink::IOAddress& lower_bound_address, - const LeasePageSize& page_size, - const time_t& qry_start_time = 0, - const time_t& qry_end_time = 0) = 0; + virtual Lease4Collection + getLeases4ByRemoteId(const OptionBuffer& remote_id, + const asiolink::IOAddress& lower_bound_address, + const LeasePageSize& page_size, + const time_t& qry_start_time = 0, + const time_t& qry_end_time = 0) = 0; /// @brief Returns existing IPv6 leases with a given relay-id. /// @@ -862,10 +864,11 @@ public: /// @param page_size maximum size of the page returned. /// /// @return collection of IPv6 leases - virtual Lease6Collection getLeases6ByRelayId(const DUID& relay_id, - const asiolink::IOAddress& link_addr, - const asiolink::IOAddress& lower_bound_address, - const LeasePageSize& page_size) = 0; + virtual Lease6Collection + getLeases6ByRelayId(const DUID& relay_id, + const asiolink::IOAddress& link_addr, + const asiolink::IOAddress& lower_bound_address, + const LeasePageSize& page_size) = 0; /// @brief Returns existing IPv6 leases with a given remote-id. /// @@ -876,10 +879,11 @@ public: /// @param page_size maximum size of the page returned. /// /// @return collection of IPv6 leases - virtual Lease6Collection getLeases6ByRemoteId(const OptionBuffer& remote_id, - const asiolink::IOAddress& link_addr, - const asiolink::IOAddress& lower_bound_address, - const LeasePageSize& page_size) = 0; + virtual Lease6Collection + getLeases6ByRemoteId(const OptionBuffer& remote_id, + const asiolink::IOAddress& link_addr, + const asiolink::IOAddress& lower_bound_address, + const LeasePageSize& page_size) = 0; /// @brief Returns existing IPv6 leases with on a given link. /// @@ -889,9 +893,20 @@ public: /// @param page_size maximum size of the page returned. /// /// @return collection of IPv6 leases - virtual Lease6Collection getLeases6ByLink(const asiolink::IOAddress& link_addr, - const asiolink::IOAddress& lower_bound_address, - const LeasePageSize& page_size) = 0; + virtual Lease6Collection + getLeases6ByLink(const asiolink::IOAddress& link_addr, + const asiolink::IOAddress& lower_bound_address, + const LeasePageSize& page_size) = 0; + + /// @brief Write V4 leases to a file. + /// + /// @param filename File name to write leases. + virtual void writeLeases4(const std::string& filename) = 0; + + /// @brief Write V6 leases to a file. + /// + /// @param filename File name to write leases. + virtual void writeLeases6(const std::string& filename) = 0; private: /// The IOService object, used for all ASIO operations. diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc index 131667b5b3..5cc970cfdc 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.cc +++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc @@ -2428,5 +2428,71 @@ Memfile_LeaseMgr::getLeases6ByLink(const IOAddress& /* link_addr */, isc_throw(NotImplemented, "Memfile_LeaseMgr::getLeases6ByLink not implemented"); } +void +Memfile_LeaseMgr::writeLeases4(const std::string& filename) { + if (MultiThreadingMgr::instance().getMode()) { + std::lock_guard lock(*mutex_); + writeLeases4Internal(filename); + } else { + writeLeases4Internal(filename); + } +} + +void +Memfile_LeaseMgr::writeLeases4Internal(const std::string& filename) { + if (lease_file4_->getFilename() == filename) { + lease_file4_->close(); + } + try { + std::ostringstream old; + old << filename << ".bak" << getpid(); + ::rename(filename.c_str(), old.str().c_str()); + CSVLeaseFile4 backup(filename); + backup.open(); + for (const auto& lease : storage4_) { + backup.append(*lease); + } + backup.close(); + } catch (const std::exception&) { + if (lease_file4_->getFilename() == filename) { + lease_file4_->open(true); + } + throw; + } +} + +void +Memfile_LeaseMgr::writeLeases6(const std::string& filename) { + if (MultiThreadingMgr::instance().getMode()) { + std::lock_guard lock(*mutex_); + writeLeases6Internal(filename); + } else { + writeLeases6Internal(filename); + } +} + +void +Memfile_LeaseMgr::writeLeases6Internal(const std::string& filename) { + if (lease_file6_->getFilename() == filename) { + lease_file6_->close(); + } + try { + std::ostringstream old; + old << filename << ".bak" << getpid(); + ::rename(filename.c_str(), old.str().c_str()); + CSVLeaseFile6 backup(filename); + backup.open(); + for (const auto& lease : storage6_) { + backup.append(*lease); + } + backup.close(); + } catch (const std::exception&) { + if (lease_file6_->getFilename() == filename) { + lease_file6_->open(true); + } + throw; + } +} + } // namespace dhcp } // namespace isc diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.h b/src/lib/dhcpsrv/memfile_lease_mgr.h index 40945388e7..6d119c7076 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.h +++ b/src/lib/dhcpsrv/memfile_lease_mgr.h @@ -1066,6 +1066,7 @@ private: /// @brief stores IPv6 leases Lease6Storage storage6_; +protected: /// @brief Holds the pointer to the DHCPv4 lease file IO. boost::shared_ptr lease_file4_; @@ -1356,6 +1357,29 @@ public: getLeases6ByLink(const asiolink::IOAddress& link_addr, const asiolink::IOAddress& lower_bound_address, const LeasePageSize& page_size) override; + + /// @brief Write V4 leases to a file. + /// + /// @param filename File name to write leases. + virtual void writeLeases4(const std::string& filename) override; + + /// @brief Write V6 leases to a file. + /// + /// @param filename File name to write leases. + virtual void writeLeases6(const std::string& filename) override; + +private: + /// @brief Write V4 leases to a file. + /// + /// @param filename File name to write leases. + /// Must be called from a thread-safe context. + virtual void writeLeases4Internal(const std::string& filename); + + /// @brief Write V6 leases to a file. + /// + /// @param filename File name to write leases. + /// Must be called from a thread-safe context. + virtual void writeLeases6Internal(const std::string& filename); }; } // namespace dhcp diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.cc b/src/lib/dhcpsrv/mysql_lease_mgr.cc index d541cc82db..70438a7afc 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.cc +++ b/src/lib/dhcpsrv/mysql_lease_mgr.cc @@ -3210,6 +3210,16 @@ MySqlLeaseMgr::clearClassLeaseCounts() { isc_throw(NotImplemented, "MySqlLeaseMgr::clearClassLeaseCounts() not implemented"); } +void +MySqlLeaseMgr::writeLeases4(const std::string&) { + isc_throw(NotImplemented, "MySqlLeaseMgr::writeLeases4() not implemented"); +} + +void +MySqlLeaseMgr::writeLeases6(const std::string&) { + isc_throw(NotImplemented, "MySqlLeaseMgr::writeLeases6() not implemented"); +} + LeaseStatsQueryPtr MySqlLeaseMgr::startLeaseStatsQuery4() { // Get a context diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.h b/src/lib/dhcpsrv/mysql_lease_mgr.h index a011c3ad16..15e08286d0 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.h +++ b/src/lib/dhcpsrv/mysql_lease_mgr.h @@ -997,6 +997,12 @@ private: /// @brief Clears the class-lease count map. virtual void clearClassLeaseCounts() override; + /// @brief Write V4 leases to a file. + virtual void writeLeases4(const std::string& /*filename*/) override; + + /// @brief Write V6 leases to a file. + virtual void writeLeases6(const std::string& /*filename*/) override; + /// @brief Check Error and Throw Exception /// /// This method invokes @ref MySqlConnection::checkError. diff --git a/src/lib/dhcpsrv/pgsql_lease_mgr.cc b/src/lib/dhcpsrv/pgsql_lease_mgr.cc index c4c4d8dc34..611fcbcc6e 100644 --- a/src/lib/dhcpsrv/pgsql_lease_mgr.cc +++ b/src/lib/dhcpsrv/pgsql_lease_mgr.cc @@ -2413,6 +2413,16 @@ PgSqlLeaseMgr::clearClassLeaseCounts() { isc_throw(NotImplemented, "PgSqlLeaseMgr::clearClassLeaseCounts() not implemented"); } +void +PgSqlLeaseMgr::writeLeases4(const std::string&) { + isc_throw(NotImplemented, "PgSqlLeaseMgr::writeLeases4() not implemented"); +} + +void +PgSqlLeaseMgr::writeLeases6(const std::string&) { + isc_throw(NotImplemented, "PgSqlLeaseMgr::writeLeases6() not implemented"); +} + LeaseStatsQueryPtr PgSqlLeaseMgr::startLeaseStatsQuery4() { // Get a context diff --git a/src/lib/dhcpsrv/pgsql_lease_mgr.h b/src/lib/dhcpsrv/pgsql_lease_mgr.h index 820be40516..999c58d7bd 100644 --- a/src/lib/dhcpsrv/pgsql_lease_mgr.h +++ b/src/lib/dhcpsrv/pgsql_lease_mgr.h @@ -1056,6 +1056,12 @@ private: const asiolink::IOAddress& lower_bound_address, const LeasePageSize& page_size) override; + /// @brief Write V4 leases to a file. + virtual void writeLeases4(const std::string& /*filename*/) override; + + /// @brief Write V6 leases to a file. + virtual void writeLeases6(const std::string& /*filename*/) override; + /// @brief Context RAII Allocator. class PgSqlLeaseContextAlloc { public: diff --git a/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc index 90f7ef3bf8..8abbe3284b 100644 --- a/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc @@ -396,7 +396,6 @@ public: isc_throw(NotImplemented, "ConcreteLeaseMgr::clearClassLeaseCounts() not implemented"); } - /// @brief Stub implementation. Lease4Collection getLeases4ByRelayId(const OptionBuffer& /* relay_id */, @@ -441,6 +440,15 @@ public: const IOAddress& /* lower_bound_address */, const LeasePageSize& /* page_size */) override { isc_throw(NotImplemented, "ConcreteLeaseMgr::getLeases6ByLink not implemented"); + + /// @brief Pretends to write V4 leases to a file. + virtual void writeLeases4(const std::string&) override { + isc_throw(NotImplemented, "ConcreteLeaseMgr::writeLeases4() not implemented"); + } + + /// @brief Pretends to write V6 leases to a file. + virtual void writeLeases6(const std::string&) override { + isc_throw(NotImplemented, "ConcreteLeaseMgr::writeLeases6() not implemented"); } /// @brief Returns backend type. diff --git a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc index a0986d9982..9586775e10 100644 --- a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc @@ -2804,4 +2804,20 @@ TEST_F(MemfileLeaseMgrTest, classLeaseRecount6) { EXPECT_EQ(2, memfile_mgr->getClassLeaseCount("slice", Lease::TYPE_PD)); } +/// @brief Class derived from @c Memfile_LeaseMgr to test write to file. +class WFMemfileLeaseMgr : public Memfile_LeaseMgr { +public: + + /// @brief Constructor. + WFMemfileLeaseMgr(const DatabaseConnection::ParameterMap& parameters) + : Memfile_LeaseMgr(parameters) { + } + + using Memfile_LeaseMgr::lease_file4_; + using Memfile_LeaseMgr::lease_file6_; +}; + +//////// test plan: +// bad file, basic, overwrite file, not-persistent x v4/v6 + } // namespace