from the lease file. All leases currently held in the memory will be
replaced by those read from the file.
-% DHCPSRV_MEMFILE_LEASES_RELOAD6 reloading leases from %1
-An info message issued when the server is about to start reading DHCPv6 leases
-from the lease file. All leases currently held in the memory will be
-replaced by those read from the file.
-
-% DHCPSRV_MEMFILE_LEASE_LOAD4 loading lease %1
-A debug message issued when DHCPv4 lease is being loaded from the file to
-memory.
-
-% DHCPSRV_MEMFILE_LEASE_LOAD6 loading lease %1
-A debug message issued when DHCPv6 lease is being loaded from the file to
-memory.
+% DHCPSRV_MEMFILE_LEASE_LOAD loading lease %1
+A debug message issued when DHCP lease is being loaded from the file to memory.
+ % DHCPSRV_MEMFILE_LFC_SETUP setting up the Lease File Cleanup interval to %1 sec
+ An informational message logged when the Memfile lease database backend
+ configures the LFC to be executed periodically. The argument holds the
+ interval in seconds in which the LFC will be executed.
+
+ % DHCPSRV_MEMFILE_LFC_START starting Lease File Cleanup
+ An informational message issued when the Memfile lease database backend
+ starts the periodic Lease File Cleanup.
+
% DHCPSRV_MEMFILE_NO_STORAGE running in non-persistent mode, leases will be lost after restart
A warning message issued when writes of leases to disk have been disabled
in the configuration. This mode is useful for some kinds of performance
return (lease_file);
}
-void
-Memfile_LeaseMgr::load4() {
- // If lease file hasn't been opened, we are working in non-persistent mode.
- // That's fine, just leave.
- if (!persistLeases(V4)) {
- return;
- }
+ void
+ Memfile_LeaseMgr::initTimers() {
+ 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);
+ LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LFC_SETUP).arg(lfc_interval);
+ lfc_timer_.setup(cb, lfc_interval * 1000);
+ }
+ }
+
+ void
+ 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);
+ }
+
+template<typename LeaseObjectType, typename LeaseFileType, typename StorageType>
+void Memfile_LeaseMgr::
+loadLeasesFromFiles(const std::string& filename,
+ boost::shared_ptr<LeaseFileType>& lease_file,
+ StorageType& storage) {
+ storage.clear();
- LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LEASES_RELOAD4)
- .arg(lease_file4_->getFilename());
-
- // Remove existing leases (if any). We will recreate them based on the
- // data on disk.
- storage4_.clear();
-
- Lease4Ptr lease;
- do {
- /// @todo Currently we stop parsing on first failure. It is possible
- /// that only one (or a few) leases are bad, so in theory we could
- /// continue parsing but that would require some error counters to
- /// prevent endless loops. That is enhancement for later time.
- if (!lease_file4_->next(lease)) {
- isc_throw(DbOperationError, "Failed to parse the DHCPv6 lease in"
- " the lease file: " << lease_file4_->getReadMsg());
- }
- // If we got the lease, we update the internal container holding
- // leases. Otherwise, we reached the end of file and we leave.
- if (lease) {
- LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL_DATA,
- DHCPSRV_MEMFILE_LEASE_LOAD4)
- .arg(lease->toText());
- loadLease4(lease);
- }
- } while (lease);
-}
+ // Load the leasefile.completed, if exists.
+ lease_file.reset(new LeaseFileType(std::string(filename + ".completed")));
+ if (lease_file->exists()) {
+ LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
+ MAX_LEASE_ERRORS);
-void
-Memfile_LeaseMgr::loadLease4(Lease4Ptr& lease) {
- // Check if the lease already exists.
- Lease4Storage::iterator lease_it = storage4_.find(lease->addr_);
- // Lease doesn't exist.
- if (lease_it == storage4_.end()) {
- // Add the lease only if valid lifetime is greater than 0.
- // We use valid lifetime of 0 to indicate that lease should
- // be removed.
- if (lease->valid_lft_ > 0) {
- storage4_.insert(lease);
- }
} else {
- // We use valid lifetime of 0 to indicate that the lease is
- // to be removed. In such case, erase the lease.
- if (lease->valid_lft_ == 0) {
- storage4_.erase(lease_it);
-
- } else {
- // Update existing lease.
- **lease_it = *lease;
+ // 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")));
+ if (lease_file->exists()) {
+ LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
+ MAX_LEASE_ERRORS);
}
- }
-}
-
-void
-Memfile_LeaseMgr::load6() {
- // If lease file hasn't been opened, we are working in non-persistent mode.
- // That's fine, just leave.
- if (!persistLeases(V6)) {
- return;
- }
- LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LEASES_RELOAD6)
- .arg(lease_file6_->getFilename());
-
- // Remove existing leases (if any). We will recreate them based on the
- // data on disk.
- storage6_.clear();
-
- Lease6Ptr lease;
- do {
- /// @todo Currently we stop parsing on first failure. It is possible
- /// that only one (or a few) leases are bad, so in theory we could
- /// continue parsing but that would require some error counters to
- /// prevent endless loops. That is enhancement for later time.
- if (!lease_file6_->next(lease)) {
- isc_throw(DbOperationError, "Failed to parse the DHCPv6 lease in"
- " the lease file: " << lease_file6_->getReadMsg());
- }
- // If we got the lease, we update the internal container holding
- // leases. Otherwise, we reached the end of file and we leave.
- if (lease) {
- LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL_DATA,
- DHCPSRV_MEMFILE_LEASE_LOAD6)
- .arg(lease->toText());
-
- loadLease6(lease);
- }
- } while (lease);
-}
-
-void
-Memfile_LeaseMgr::loadLease6(Lease6Ptr& lease) {
- // Check if the lease already exists.
- Lease6Storage::iterator lease_it = storage6_.find(lease->addr_);
- // Lease doesn't exist.
- if (lease_it == storage6_.end()) {
- // Add the lease only if valid lifetime is greater than 0.
- // We use valid lifetime of 0 to indicate that lease should
- // be removed.
- if (lease->valid_lft_ > 0) {
- storage6_.insert(lease);
- }
- } else {
- // We use valid lifetime of 0 to indicate that the lease is
- // to be removed. In such case, erase the lease.
- if (lease->valid_lft_ == 0) {
- storage6_.erase(lease_it);
-
- } else {
- // Update existing lease.
- **lease_it = *lease;
+ lease_file.reset(new LeaseFileType(std::string(filename + ".1")));
+ if (lease_file->exists()) {
+ LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
+ MAX_LEASE_ERRORS);
}
}
/// server shut down.
bool persistLeases(Universe u) const;
-protected:
+private:
- /// @brief Load all DHCPv4 leases from the file.
- ///
- /// This method loads all DHCPv4 leases from a file to memory. It removes
- /// existing leases before reading a file.
- ///
- /// @throw isc::DbOperationError If failed to read a lease from the lease
- /// file.
- void load4();
-
- /// @brief Loads a single DHCPv4 lease from the file.
- ///
- /// This method reads a single lease record from the lease file. If the
- /// corresponding record doesn't exist in the in-memory container, the
- /// lease is added to the container (except for a lease which valid lifetime
- /// is 0). If the corresponding lease exists, the lease being read updates
- /// the existing lease. If the lease being read from the lease file has
- /// valid lifetime of 0 and the corresponding lease exists in the in-memory
- /// database, the existing lease is removed.
- ///
- /// @param lease Pointer to the lease read from the lease file.
- void loadLease4(Lease4Ptr& lease);
-
- /// @brief Load all DHCPv6 leases from the file.
- ///
- /// This method loads all DHCPv6 leases from a file to memory. It removes
- /// existing leases before reading a file.
- ///
- /// @throw isc::DbOperationError If failed to read a lease from the lease
- /// file.
- void load6();
-
- /// @brief Loads a single DHCPv6 lease from the file.
- ///
- /// This method reads a single lease record from the lease file. If the
- /// corresponding record doesn't exist in the in-memory container, the
- /// lease is added to the container (except for a lease which valid lifetime
- /// is 0). If the corresponding lease exists, the lease being read updates
- /// the existing lease. If the lease being read from the lease file has
- /// valid lifetime of 0 and the corresponding lease exists in the in-memory
- /// database, the existing lease is removed.
+ /// @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.
+ ///
+ /// @todo Once the callback is implemented, there is a need to
+ /// extend the documentation of this method. Currently, it simply
+ /// logs that it has been called.
+ virtual void lfcCallback();
+
+ private:
+
- /// @param lease Pointer to the lease read from the lease file.
- void loadLease6(Lease6Ptr& lease);
-
++ /// @brief Initialize the timers used to perform repeating tasks.
+ ///
++ /// Currently only one timer is supported. This timer executes the
++ /// Lease File Cleanup periodically.
++ void initTimers();
/// @brief Initialize the location of the lease file.
///
/// This method uses the parameters passed as a map to the constructor to