Commit b3bbea1b authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[3668] Install LFC callback to trigger LFC periodically.

parent cc6e80a4
// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2013, 2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
......@@ -16,6 +16,7 @@
#define LEASE_MGR_H
#include <asiolink/io_address.h>
#include <asiolink/io_service.h>
#include <dhcp/duid.h>
#include <dhcp/option.h>
#include <dhcp/hwaddr.h>
......@@ -133,7 +134,8 @@ public:
///
/// @param parameters A data structure relating keywords and values
/// concerned with the database.
LeaseMgr(const ParameterMap& parameters) : parameters_(parameters)
LeaseMgr(const ParameterMap& parameters)
: parameters_(parameters), io_service_(new asiolink::IOService())
{}
/// @brief Destructor
......@@ -379,6 +381,12 @@ public:
/// @brief returns value of the parameter
virtual std::string getParameter(const std::string& name) const;
/// @brief Returns a reference to the @c IOService object used
/// by the Lease Manager.
const asiolink::IOServicePtr& getIOService() const {
return (io_service_);
}
private:
/// @brief list of parameters passed in dbconfig
///
......@@ -386,6 +394,10 @@ private:
/// password and other parameters required for DB access. It is not
/// intended to keep any DHCP-related parameters.
ParameterMap parameters_;
/// @brief Pointer to the IO service object used by the derived classes
/// to trigger interval timers.
asiolink::IOServicePtr io_service_;
};
}; // end of isc::dhcp namespace
......
......@@ -22,7 +22,7 @@
using namespace isc::dhcp;
Memfile_LeaseMgr::Memfile_LeaseMgr(const ParameterMap& parameters)
: LeaseMgr(parameters) {
: LeaseMgr(parameters), lfc_timer_(*getIOService()) {
// Check the universe and use v4 file or v6 file.
std::string universe = getParameter("universe");
if (universe == "4") {
......@@ -47,6 +47,9 @@ Memfile_LeaseMgr::Memfile_LeaseMgr(const ParameterMap& parameters)
// operation.
if (!persistLeases(V4) && !persistLeases(V6)) {
LOG_WARN(dhcpsrv_logger, DHCPSRV_MEMFILE_NO_STORAGE);
} else {
initTimers(universe == "4" ? V4 : V6);
}
}
......@@ -468,6 +471,34 @@ Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
return (lease_file);
}
void
Memfile_LeaseMgr::initTimers(const Universe& universe) {
std::string lfc_interval_str = "0";
try {
lfc_interval_str = getParameter("lfc-interval");
} catch (const std::exception& ex) {
// Ignore and default to 0.
}
uint32_t lfc_interval = 0;
try {
lfc_interval = boost::lexical_cast<uint32_t>(lfc_interval_str);
} catch (boost::bad_lexical_cast& ex) {
isc_throw(isc::BadValue, "invalid value of the LFC interval "
<< lfc_interval_str << " specified");
}
if (lfc_interval > 0) {
asiolink::IntervalTimer::Callback cb =
boost::bind(&Memfile_LeaseMgr::lfcCallback, this);
lfc_timer_.setup(cb, lfc_interval * 1000);
}
}
void
Memfile_LeaseMgr::lfcCallback() {
}
void
Memfile_LeaseMgr::load4() {
// If lease file hasn't been opened, we are working in non-persistent mode.
......
// Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
......@@ -15,6 +15,8 @@
#ifndef MEMFILE_LEASE_MGR_H
#define MEMFILE_LEASE_MGR_H
#include <asiolink/interval_timer.h>
#include <asiolink/io_service.h>
#include <dhcp/hwaddr.h>
#include <dhcpsrv/csv_lease_file4.h>
#include <dhcpsrv/csv_lease_file6.h>
......@@ -335,6 +337,16 @@ public:
protected:
/// @brief A callback function triggering Lease File Cleanup.
///
/// This method is virtual so as it can be overriden and customized in
/// the unit tests. In particular, the unit test which checks that the
/// callback function has been executed would override this function
/// to increase the execution counter each time it is executed.
virtual void lfcCallback();
private:
/// @brief Load all DHCPv4 leases from the file.
///
/// This method loads all DHCPv4 leases from a file to memory. It removes
......@@ -396,6 +408,14 @@ protected:
/// argument to this function.
std::string initLeaseFilePath(Universe u);
/// @brief Initialize the timers used to perform repeating tasks.
///
/// Currently only one timer is supported. This timer executes the
/// Lease File Cleanup periodically.
///
/// @param universe A V4 or V6 value.
void initTimers(const Universe& universe);
// This is a multi-index container, which holds elements that can
// be accessed using different search indexes.
typedef boost::multi_index_container<
......@@ -514,6 +534,9 @@ protected:
/// @brief Holds the pointer to the DHCPv6 lease file IO.
boost::shared_ptr<CSVLeaseFile6> lease_file6_;
/// @brief A timer scheduled to perform Lease File Cleanup.
asiolink::IntervalTimer lfc_timer_;
};
}; // end of isc::dhcp namespace
......
......@@ -25,6 +25,8 @@
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
#include <gtest/gtest.h>
#include <boost/bind.hpp>
#include <iostream>
#include <fstream>
#include <sstream>
......@@ -37,7 +39,45 @@ using namespace isc::dhcp::test;
namespace {
// empty class for now, but may be extended once Addr6 becomes bigger
/// @brief Class derived from @c Memfile_LeaseMgr to test timers.
///
/// This class provides a custom callback function which is invoked
/// when the timer for Lease File Cleanup goes off. It is used to
/// test that the timer is correctly installed.
class TestMemfileLeaseMgr : public Memfile_LeaseMgr {
public:
/// @brief Constructor.
///
/// Sets the counter for callbacks to 0.
TestMemfileLeaseMgr(const ParameterMap& parameters)
: Memfile_LeaseMgr(parameters) {
}
/// @brief Returns the number of callback executions.
int getLFCCount() {
return (lfc_cnt_);
}
protected:
/// @brief Custom callback.
///
/// This callback function increases the counter of callback executions.
/// By examining the counter value a test may verify that the callback
/// was triggered an expected number of times.
virtual void lfcCallback() {
++lfc_cnt_;
}
private:
/// @brief Counter of callback function executions.
int lfc_cnt_;
};
/// @brief Test fixture class for @c Memfile_LeaseMgr
class MemfileLeaseMgrTest : public GenericLeaseMgrTest {
public:
......@@ -46,7 +86,9 @@ public:
/// Creates memfile and stores it in lmptr_ pointer
MemfileLeaseMgrTest() :
io4_(getLeaseFilePath("leasefile4_0.csv")),
io6_(getLeaseFilePath("leasefile6_0.csv")) {
io6_(getLeaseFilePath("leasefile6_0.csv")),
io_service_(),
fail_on_callback_(false) {
// Make sure there are no dangling files after previous tests.
io4_.removeFile();
......@@ -116,12 +158,36 @@ public:
lmptr_ = &(LeaseMgrFactory::instance());
}
void setTestTime(const uint32_t ms) {
IntervalTimer::Callback cb =
boost::bind(&MemfileLeaseMgrTest::testTimerCallback, this);
test_timer_.reset(new IntervalTimer(*io_service_));
test_timer_->setup(cb, ms, IntervalTimer::ONE_SHOT);
}
/// @brief Test timer callback function.
void testTimerCallback() {
io_service_->stop();
if (fail_on_callback_) {
FAIL() << "Test timeout reached";
}
}
/// @brief Object providing access to v4 lease IO.
LeaseFileIO io4_;
/// @brief Object providing access to v6 lease IO.
LeaseFileIO io6_;
/// @brief Test timer for the test.
boost::shared_ptr<IntervalTimer> test_timer_;
/// @brief IO service object used for the timer tests.
asiolink::IOServicePtr io_service_;
/// @brief Indicates if the @c testTimerCallback should cause test failure.
bool fail_on_callback_;
};
// This test checks if the LeaseMgr can be instantiated and that it
......@@ -134,6 +200,7 @@ TEST_F(MemfileLeaseMgrTest, constructor) {
EXPECT_NO_THROW(lease_mgr.reset(new Memfile_LeaseMgr(pmap)));
pmap["lfc-interval"] = "10";
pmap["persist"] = "true";
pmap["name"] = getLeaseFilePath("leasefile4_1.csv");
EXPECT_NO_THROW(lease_mgr.reset(new Memfile_LeaseMgr(pmap)));
......@@ -143,6 +210,10 @@ TEST_F(MemfileLeaseMgrTest, constructor) {
pmap["persist"] = "bogus";
pmap["name"] = getLeaseFilePath("leasefile4_1.csv");
EXPECT_THROW(lease_mgr.reset(new Memfile_LeaseMgr(pmap)), isc::BadValue);
// The lfc-interval must be an integer.
pmap["lfc-interval"] = "bogus";
EXPECT_THROW(lease_mgr.reset(new Memfile_LeaseMgr(pmap)), isc::BadValue);
}
// Checks if the getType() and getName() methods both return "memfile".
......@@ -204,6 +275,29 @@ TEST_F(MemfileLeaseMgrTest, persistLeases) {
EXPECT_FALSE(lease_mgr->persistLeases(Memfile_LeaseMgr::V6));
}
// Check if it is possible to schedule the timer to perform the Lease
// File Cleanup periodically.
TEST_F(MemfileLeaseMgrTest, lfcTimer) {
LeaseMgr::ParameterMap pmap;
pmap["type"] = "memfile";
pmap["universe"] = "4";
// Specify the names of the lease files. Leases will be written.
pmap["name"] = getLeaseFilePath("leasefile4_0.csv");
pmap["lfc-interval"] = "1";
boost::shared_ptr<TestMemfileLeaseMgr>
lease_mgr(new TestMemfileLeaseMgr(pmap));
io_service_ = lease_mgr->getIOService();
// Run the test for at most 2.9 seconds.
setTestTime(2900);
io_service_->run();
// Within 2.9 we should record two LFC executions.
EXPECT_EQ(2, lease_mgr->getLFCCount());
}
// Checks that adding/getting/deleting a Lease6 object works.
TEST_F(MemfileLeaseMgrTest, addGetDelete6) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment