Commit 8b3b3f6c authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[3669] Memfile backend rotates the lease file before running LFC.

parent c8bf8ed9
......@@ -17,6 +17,7 @@
#include <dhcpsrv/lease_file_loader.h>
#include <dhcpsrv/memfile_lease_mgr.h>
#include <exceptions/exceptions.h>
#include <cstdio>
#include <iostream>
#include <sstream>
......@@ -28,6 +29,7 @@ const uint32_t MAX_LEASE_ERRORS = 100;
} // end of anonymous namespace
using namespace isc::dhcp;
using namespace isc::util;
Memfile_LeaseMgr::Memfile_LeaseMgr(const ParameterMap& parameters)
: LeaseMgr(parameters), lfc_timer_(*getIOService()) {
......@@ -51,7 +53,7 @@ Memfile_LeaseMgr::Memfile_LeaseMgr(const ParameterMap& parameters)
// issue a warning. It is ok not to write leases to disk when
// doing testing, but it should not be done in normal server
// operation.
if (!persistLeases(V4) && !persistLeases(V6)) {
if (!persistLeases(V4) && !persistLeases(V6)) {
LOG_WARN(dhcpsrv_logger, DHCPSRV_MEMFILE_NO_STORAGE);
} else {
......@@ -418,6 +420,32 @@ Memfile_LeaseMgr::rollback() {
DHCPSRV_MEMFILE_ROLLBACK);
}
std::string
Memfile_LeaseMgr::appendSuffix(const std::string& file_name,
const LFCFileType& file_type) {
std::string name(file_name);
switch (file_type) {
case FILE_INPUT:
name += ".1";
break;
case FILE_PREVIOUS:
name += ".2";
break;
case FILE_OUTPUT:
name += ".output";
break;
case FILE_FINISH:
name += ".completed";
break;
default:
// Do not append any suffix for the FILE_CURRENT.
;
}
return (name);
}
uint32_t
Memfile_LeaseMgr::getIOServiceExecInterval() const {
return (static_cast<uint32_t>(lfc_timer_.getInterval() / 1000));
......@@ -512,6 +540,28 @@ Memfile_LeaseMgr::lfcCallback() {
/// @todo Extend this method to spawn the new process which will
/// perform the Lease File Cleanup in background.
LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LFC_START);
// Check if we're in the v4 or v6 space and use the appropriate file.
if (lease_file4_) {
leaseFileCleanup(lease_file4_);
} else if (lease_file6_) {
leaseFileCleanup(lease_file6_);
}
}
template<typename LeaseFileType>
void Memfile_LeaseMgr::
leaseFileCleanup(boost::shared_ptr<LeaseFileType>& lease_file) {
CSVFile lease_file_copy(appendSuffix(lease_file->getFilename(), FILE_INPUT));
if (!lease_file_copy.exists()) {
lease_file->close();
rename(lease_file->getFilename().c_str(),
lease_file_copy.getFilename().c_str());
lease_file.reset(new LeaseFileType(lease_file->getFilename()));
lease_file->open();
}
}
template<typename LeaseObjectType, typename LeaseFileType, typename StorageType>
......@@ -530,13 +580,13 @@ loadLeasesFromFiles(const std::string& filename,
} else {
// If the leasefile.completed doesn't exist, let's load the leases
// from leasefile.2 and leasefile.1, if they exist.
lease_file.reset(new LeaseFileType(std::string(filename + ".2")));
lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_PREVIOUS)));
if (lease_file->exists()) {
LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
MAX_LEASE_ERRORS);
}
lease_file.reset(new LeaseFileType(std::string(filename + ".1")));
lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_INPUT)));
if (lease_file->exists()) {
LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
MAX_LEASE_ERRORS);
......
......@@ -112,6 +112,18 @@ public:
V6
};
/// @brief Types of the lease files used by the Lease File Cleanup.
///
/// This enumeration is used by a method which appends the appropriate
/// suffix to the lease file name.
enum LFCFileType {
FILE_CURRENT,
FILE_INPUT,
FILE_PREVIOUS,
FILE_OUTPUT,
FILE_FINISH
};
/// @brief The sole lease manager constructor
///
/// dbconfig is a generic way of passing parameters. Parameters
......@@ -320,6 +332,24 @@ public:
/// support transactions, this is a no-op.
virtual void rollback();
/// @brief Appends appropriate suffix to the file name.
///
/// The suffix is selected using the LFC file type specified as a
/// parameter. Each file type uses a unique suffix or no suffix:
/// - Current File: no suffix
/// - Lease File Copy or Input File: ".1"
/// - Previous File: ".2"
/// - LFC Output File: ".output"
/// - LFC Finish File: ".completed"
///
/// See http://kea.isc.org/wiki/LFCDesign for details.
///
/// @param file_name A base file name to which suffix is appended.
/// @param file_type An LFC file type.
/// @return A lease file name with a suffix appended.
static std::string appendSuffix(const std::string& file_name,
const LFCFileType& file_type);
/// @brief Returns the interval at which the @c IOService events should
/// be released.
///
......@@ -359,7 +389,7 @@ public:
/// server shut down.
bool persistLeases(Universe u) const;
private:
protected:
/// @brief A callback function triggering Lease File Cleanup.
///
......@@ -397,6 +427,9 @@ private:
/// argument to this function.
std::string initLeaseFilePath(Universe u);
template<typename LeaseFileType>
void leaseFileCleanup(boost::shared_ptr<LeaseFileType>& lease_file);
/// @brief Load leases from the persistent storage.
///
/// This method loads DHCPv4 or DHCPv6 leases from lease files in the
......
// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 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
......@@ -20,13 +20,17 @@ namespace isc {
namespace dhcp {
namespace test {
LeaseFileIO::LeaseFileIO(const std::string& filename)
: testfile_(filename) {
removeFile();
LeaseFileIO::LeaseFileIO(const std::string& filename, const bool recreate)
: testfile_(filename), recreate_(recreate) {
if (recreate_) {
removeFile();
}
}
LeaseFileIO::~LeaseFileIO() {
removeFile();
if (recreate_) {
removeFile();
}
}
bool
......
......@@ -32,7 +32,9 @@ public:
/// @brief Constructor
///
/// @param filename Abolsute path to the file.
LeaseFileIO(const std::string& filename);
/// @param recreate A boolean flag indicating if the new file should
/// be created, even if one exists.
LeaseFileIO(const std::string& filename, const bool recreate = true);
/// @brief Destructor.
~LeaseFileIO();
......@@ -56,6 +58,10 @@ public:
/// @brief Absolute path to the file used in the tests.
std::string testfile_;
/// @brief Indicates if the file should be recreated during object
/// construction and removed during destruction.
bool recreate_;
};
}
......
......@@ -30,6 +30,7 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <queue>
using namespace std;
using namespace isc;
......@@ -77,6 +78,20 @@ private:
};
/// @brief A derivation of the lease manager exposing protected methods.
class NakedMemfileLeaseMgr : public Memfile_LeaseMgr {
public:
/// @brief Constructor.
///
/// Creates instance of the lease manager.
NakedMemfileLeaseMgr(const ParameterMap& parameters)
: Memfile_LeaseMgr(parameters) {
}
using Memfile_LeaseMgr::lfcCallback;
};
/// @brief Test fixture class for @c Memfile_LeaseMgr
class MemfileLeaseMgrTest : public GenericLeaseMgrTest {
public:
......@@ -90,9 +105,9 @@ public:
io_service_(),
fail_on_callback_(false) {
// Make sure there are no dangling files after previous tests.
io4_.removeFile();
io6_.removeFile();
// Remove lease files and products of Lease File Cleanup.
removeFiles(getLeaseFilePath("leasefile4_0.csv"));
removeFiles(getLeaseFilePath("leasefile6_0.csv"));
}
/// @brief Reopens the connection to the backend.
......@@ -112,6 +127,30 @@ public:
/// destroys lease manager backend.
virtual ~MemfileLeaseMgrTest() {
LeaseMgrFactory::destroy();
// Remove lease files and products of Lease File Cleanup.
removeFiles(getLeaseFilePath("leasefile4_0.csv"));
removeFiles(getLeaseFilePath("leasefile6_0.csv"));
}
/// @brief Remove files being products of Lease File Cleanup.
///
/// @param base_name Path to the lease file name. This file is removed
/// and all files which names are crated from this name (having specific
/// suffixes used by Lease File Cleanup mechanism).
void removeFiles(const std::string& base_name) const {
// Generate suffixes and append them to the base name. The
// resulting file names are the ones that may exist as a
// result of LFC.
for (int i = static_cast<int>(Memfile_LeaseMgr::FILE_CURRENT);
i <= static_cast<int>(Memfile_LeaseMgr::FILE_FINISH);
++i) {
Memfile_LeaseMgr::LFCFileType type = static_cast<
Memfile_LeaseMgr::LFCFileType>(i);
std::string suffix = Memfile_LeaseMgr::appendSuffix(base_name, type);
LeaseFileIO io(Memfile_LeaseMgr::appendSuffix(base_name, type));
io.removeFile();
}
}
/// @brief Return path to the lease file used by unit tests.
......@@ -331,6 +370,37 @@ TEST_F(MemfileLeaseMgrTest, lfcTimerDisabled) {
EXPECT_EQ(0, lease_mgr->getLFCCount());
}
// This test that the callback function performing a Lease File Cleanup
// works as expected.
TEST_F(MemfileLeaseMgrTest, leaseFileCleanup) {
std::string new_file_contents =
"address,hwaddr,client_id,valid_lifetime,expire,"
"subnet_id,fqdn_fwd,fqdn_rev,hostname\n";
std::string current_file_contents = new_file_contents +
"192.0.2.2,02:02:02:02:02:02,,200,200,8,1,1,,\n";
LeaseFileIO current_file(getLeaseFilePath("leasefile4_0.csv"));
current_file.writeFile(current_file_contents);
LeaseMgr::ParameterMap pmap;
pmap["type"] = "memfile";
pmap["universe"] = "4";
pmap["name"] = getLeaseFilePath("leasefile4_0.csv");
pmap["lfc-interval"] = "1";
boost::scoped_ptr<NakedMemfileLeaseMgr>
lease_mgr(new NakedMemfileLeaseMgr(pmap));
ASSERT_NO_THROW(lease_mgr->lfcCallback());
LeaseFileIO input_file(getLeaseFilePath("leasefile4_0.csv.1"), false);
ASSERT_TRUE(input_file.exists());
EXPECT_EQ(current_file_contents, input_file.readFile());
ASSERT_TRUE(current_file.exists());
EXPECT_EQ(new_file_contents, current_file.readFile());
}
// Test that the backend returns a correct value of the interval
// at which the IOService must be executed to run the handlers
// for the installed timers.
......
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