diff options
author | Francis Dupont <fdupont@isc.org> | 2018-02-23 16:45:46 +0100 |
---|---|---|
committer | Francis Dupont <fdupont@isc.org> | 2018-02-23 16:45:46 +0100 |
commit | d2bad4f7e32491c36d741642a2bb0baa040a7e67 (patch) | |
tree | 6ae98efd7409d907deca2933cad1f74511ea84f4 /src/lib/dhcpsrv | |
parent | [5533] Introduce get[46]Any and add tests (diff) | |
download | kea-d2bad4f7e32491c36d741642a2bb0baa040a7e67.tar.xz kea-d2bad4f7e32491c36d741642a2bb0baa040a7e67.zip |
[5533] Checkpoint: added code, test todo (where?)
Diffstat (limited to 'src/lib/dhcpsrv')
-rw-r--r-- | src/lib/dhcpsrv/Makefile.am | 2 | ||||
-rw-r--r-- | src/lib/dhcpsrv/cache_host_data_source.h | 64 | ||||
-rw-r--r-- | src/lib/dhcpsrv/cfg_db_access.cc | 3 | ||||
-rw-r--r-- | src/lib/dhcpsrv/host_mgr.cc | 77 | ||||
-rw-r--r-- | src/lib/dhcpsrv/host_mgr.h | 110 |
5 files changed, 217 insertions, 39 deletions
diff --git a/src/lib/dhcpsrv/Makefile.am b/src/lib/dhcpsrv/Makefile.am index a9c5ea7c36..34fd3a88e6 100644 --- a/src/lib/dhcpsrv/Makefile.am +++ b/src/lib/dhcpsrv/Makefile.am @@ -89,6 +89,7 @@ libkea_dhcpsrv_la_SOURCES += alloc_engine.cc alloc_engine.h libkea_dhcpsrv_la_SOURCES += alloc_engine_log.cc alloc_engine_log.h libkea_dhcpsrv_la_SOURCES += assignable_network.h libkea_dhcpsrv_la_SOURCES += base_host_data_source.h +libkea_dhcpsrv_la_SOURCES += cache_host_data_source.h libkea_dhcpsrv_la_SOURCES += callout_handle_store.h libkea_dhcpsrv_la_SOURCES += cfg_4o6.cc cfg_4o6.h libkea_dhcpsrv_la_SOURCES += cfg_db_access.cc cfg_db_access.h @@ -246,6 +247,7 @@ libkea_dhcpsrv_include_HEADERS = \ alloc_engine_log.h \ assignable_network.h \ base_host_data_source.h \ + cache_host_data_source.h \ callout_handle_store.h \ cfg_4o6.h \ cfg_db_access.h \ diff --git a/src/lib/dhcpsrv/cache_host_data_source.h b/src/lib/dhcpsrv/cache_host_data_source.h new file mode 100644 index 0000000000..d6d84bc38a --- /dev/null +++ b/src/lib/dhcpsrv/cache_host_data_source.h @@ -0,0 +1,64 @@ +// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the End User License +// Agreement. See COPYING file in the premium/ directory. + +#ifndef CACHE_HOST_DATA_SOURCE_H +#define CACHE_HOST_DATA_SOURCE_H + +#include <dhcpsrv/base_host_data_source.h> + +namespace isc { +namespace dhcp { + +/// @brief Abstract interface extending base simple data source for host +/// reservations to host cache. +/// Only the insert() method is required to use the cache. +class CacheHostDataSource : public BaseHostDataSource { +public: + + /// @brief Default destructor implementation. + virtual ~CacheHostDataSource() { } + + /// @brief Insert a host into the cache. + /// + /// Does the same than @c add() but with a different purpose. + /// + /// @param host Pointer to the new @c Host object being inserted. + /// @param[in,out] overwrite -1 if accepting conflicts, 0 if removing + /// conflicting entries, set to the number of removed entries. + /// @return true when succeeded. + virtual bool insert(const ConstHostPtr& host, int& overwrite) = 0; + + /// @brief Remove a host from the cache. + /// + /// Does the same than @c del, @c del4 or @c del6 but with + /// a more uniform interface and a different purpose. + /// + /// @param host Pointer to the existing @c Host object being removed. + /// @return true when found and removed. + virtual bool remove(const HostPtr& host) = 0; + + /// @brief Flush entries. + /// + /// @param count number of entries to remove, 0 means all. + virtual void flush(size_t count) = 0; + + /// @brief Return the number of entries. + /// + /// @return the current number of active entries in the cache. + virtual size_t size() const = 0; + + /// @brief Return the maximum number of entries. + /// + /// @return the maximum number of entries, 0 means unbound. + virtual size_t capacity() const = 0; +}; + +/// @brief CacheHostDataSource pointer. +typedef boost::shared_ptr<CacheHostDataSource> CacheHostDataSourcePtr; + +} // end of namespace isc::dhcp +} // end of namespace isc + +#endif // CACHE_HOST_DATA_SOURCE_H diff --git a/src/lib/dhcpsrv/cfg_db_access.cc b/src/lib/dhcpsrv/cfg_db_access.cc index ad6c396587..2163f1ec96 100644 --- a/src/lib/dhcpsrv/cfg_db_access.cc +++ b/src/lib/dhcpsrv/cfg_db_access.cc @@ -60,6 +60,9 @@ CfgDbAccess::createManagers() const { it != host_db_access_list.end(); ++it) { HostMgr::addSource(*it); } + + // Check for a host cache. + HostMgr::checkCacheSource(); } std::string diff --git a/src/lib/dhcpsrv/host_mgr.cc b/src/lib/dhcpsrv/host_mgr.cc index 1cb45c2ddb..c776d90444 100644 --- a/src/lib/dhcpsrv/host_mgr.cc +++ b/src/lib/dhcpsrv/host_mgr.cc @@ -64,6 +64,24 @@ HostMgr::getHostDataSource() const { return (alternate_sources_[0]); } +bool +HostMgr::checkCacheSource() { + if (getHostMgrPtr()->cache_ptr_) { + return (true); + } + HostDataSourceList& sources = getHostMgrPtr()->alternate_sources_; + if (sources.empty()) { + return (false); + } + CacheHostDataSourcePtr cache_ptr = + boost::dynamic_pointer_cast<CacheHostDataSource>(sources[0]); + if (cache_ptr) { + getHostMgrPtr()->cache_ptr_ = cache_ptr; + return (true); + } + return (false); +} + HostMgr& HostMgr::instance() { boost::scoped_ptr<HostMgr>& host_mgr_ptr = getHostMgrPtr(); @@ -132,6 +150,9 @@ HostMgr::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr, if (!host && hwaddr) { host = (*it)->get4(subnet_id, hwaddr, DuidPtr()); } + if (host && cache_ptr_ && (it != alternate_sources_.begin())) { + cache(host); + } } if (host && host->getNegative()) { return (ConstHostPtr()); @@ -171,6 +192,9 @@ HostMgr::get4Any(const SubnetID& subnet_id, .arg((*it)->getType()) .arg(host->toText()); + if (cache_ptr_ && (it != alternate_sources_.begin())) { + cache(host); + } return (host); } } @@ -179,6 +203,10 @@ HostMgr::get4Any(const SubnetID& subnet_id, .arg(subnet_id) .arg(Host::getIdentifierAsText(identifier_type, identifier_begin, identifier_len)); + if (negative_caching_) { + cacheNegative(subnet_id, SubnetID(0), + identifier_type, identifier_begin, identifier_len); + } return (host); } @@ -209,6 +237,9 @@ HostMgr::get4(const SubnetID& subnet_id, for (auto it = alternate_sources_.begin(); !host && it != alternate_sources_.end(); ++it) { host = (*it)->get4(subnet_id, address); + if (host && cache_ptr_ && (it != alternate_sources_.begin())) { + cache(host); + } } if (host && host->getNegative()) { return (ConstHostPtr()); @@ -238,6 +269,9 @@ HostMgr::get6(const SubnetID& subnet_id, const DuidPtr& duid, if (!host && hwaddr) { host = (*it)->get6(subnet_id, DuidPtr(), hwaddr); } + if (host && cache_ptr_ && (it != alternate_sources_.begin())) { + cache(host); + } } if (host && host->getNegative()) { return (ConstHostPtr()); @@ -258,6 +292,9 @@ HostMgr::get6(const IOAddress& prefix, const uint8_t prefix_len) const { for (auto it = alternate_sources_.begin(); !host && it != alternate_sources_.end(); ++it) { host = (*it)->get6(prefix, prefix_len); + if (host && cache_ptr_ && (it != alternate_sources_.begin())) { + cache(host); + } } if (host && host->getNegative()) { return (ConstHostPtr()); @@ -298,6 +335,9 @@ HostMgr::get6Any(const SubnetID& subnet_id, .arg((*it)->getType()) .arg(host->toText()); + if (cache_ptr_ && (it != alternate_sources_.begin())) { + cache(host); + } return (host); } } @@ -308,6 +348,11 @@ HostMgr::get6Any(const SubnetID& subnet_id, .arg(Host::getIdentifierAsText(identifier_type, identifier_begin, identifier_len)); + if (negative_caching_) { + cacheNegative(SubnetID(0), subnet_id, + identifier_type, identifier_begin, identifier_len); + } + return (host); } @@ -338,6 +383,9 @@ HostMgr::get6(const SubnetID& subnet_id, for (auto it = alternate_sources_.begin(); !host && it != alternate_sources_.end(); ++it) { host = (*it)->get6(subnet_id, addr); + if (host && cache_ptr_ && (it != alternate_sources_.begin())) { + cache(host); + } } if (host && host->getNegative()) { return (ConstHostPtr()); @@ -413,5 +461,34 @@ HostMgr::del6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_ return (false); } +void +HostMgr::cache(ConstHostPtr host) const { + if (cache_ptr_) { + // Replace any existing value. + int overwrite = 0; + // Don't check the result as it does not matter? + cache_ptr_->insert(host, overwrite); + } +} + +void +HostMgr::cacheNegative(const SubnetID& ipv4_subnet_id, + const SubnetID& ipv6_subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, + const size_t identifier_len) const { + if (cache_ptr_ && negative_caching_) { + HostPtr host(new Host(identifier_begin, identifier_len, + identifier_type, + ipv4_subnet_id, ipv6_subnet_id, + IOAddress::IPV4_ZERO_ADDRESS())); + host->setNegative(true); + // Don't replace any existing value. + int overwrite = -1; + // nor matter if it fails. + cache_ptr_->insert(host, overwrite); + } +} + } // end of isc::dhcp namespace } // end of isc namespace diff --git a/src/lib/dhcpsrv/host_mgr.h b/src/lib/dhcpsrv/host_mgr.h index fa003ac22d..e7392172cf 100644 --- a/src/lib/dhcpsrv/host_mgr.h +++ b/src/lib/dhcpsrv/host_mgr.h @@ -10,6 +10,7 @@ #include <dhcp/duid.h> #include <dhcp/hwaddr.h> #include <dhcpsrv/base_host_data_source.h> +#include <dhcpsrv/cache_host_data_source.h> #include <dhcpsrv/host.h> #include <dhcpsrv/subnet_id.h> #include <boost/noncopyable.hpp> @@ -81,6 +82,12 @@ public: /// @brief Delete all alternate host data source. static void delAllSources(); + /// @brief Check for the cache host data source. + /// + /// Checks if the first host data source implements + /// the cache abstract class and sets cache_ptr_. + static bool checkCacheSource(); + /// @brief Returns a sole instance of the @c HostMgr. /// /// This method should be used to retrieve an instance of the @c HostMgr @@ -308,44 +315,6 @@ public: /// @return true if addition was successful. virtual bool add(const HostPtr& host); - /// @brief Return backend type - /// - /// Returns the type of the backend (e.g. "mysql", "memfile" etc.) - /// - /// @return Type of the backend. - virtual std::string getType() const { - return (std::string("host_mgr")); - } - - /// @brief Returns the host data source list. - /// - /// @return reference to the host data source list. - HostDataSourceList& getHostDataSourceList() { - return (alternate_sources_); - } - - /// @brief Returns the fist host data source. - /// - /// May return NULL if the host data source list is empty. - /// @return pointer to the first host data source (or NULL) - HostDataSourcePtr getHostDataSource() const; - - /// @brief Sets alternate host data source list. - /// - /// Note: This should be used only for testing. Do not use - /// in production. Normal control flow assumes that - /// HostMgr::create() and HostMgr::add() is called and it instantiates - /// appropriate host data sources. However, some tests - /// (e.g. host_cmds) implement their own very simple - /// data source. It's not production ready by any means, - /// so it does not belong in host_data_source_factory.cc. - /// The testing nature of this method is reflected in its name. - /// - /// @param sources new source list to be set - void setTestHostDataSourceList(const HostDataSourceList& sources) { - alternate_sources_ = sources; - } - /// @brief Attempts to delete a host by address. /// /// This method supports both v4 and v6. @@ -383,14 +352,77 @@ public: del6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type, const uint8_t* identifier_begin, const size_t identifier_len); + /// @brief Return backend type + /// + /// Returns the type of the backend (e.g. "mysql", "memfile" etc.) + /// + /// @return Type of the backend. + virtual std::string getType() const { + return (std::string("host_mgr")); + } + + /// @brief Returns the host data source list. + /// + /// @return reference to the host data source list. + HostDataSourceList& getHostDataSourceList() { + return (alternate_sources_); + } + + /// @brief Returns the first host data source. + /// + /// May return NULL if the host data source list is empty. + /// @return pointer to the first host data source (or NULL). + HostDataSourcePtr getHostDataSource() const; + + /// @brief Returns the negative caching flag. + /// + /// @return the negative caching flag. + bool getNegativeCaching() const { + return (negative_caching_); + } + + /// @brief Sets the negative caching flag. + /// + void setNegativeCaching(bool negative_caching) { + negative_caching_ = negative_caching; + } + +protected: + /// @brief The negative caching flag. + /// + /// When true and the first data source is a cache negative answers + /// to get[46] for aubnet and identifier are cached. + bool negative_caching_; + + /// @brief Cache an answer. + /// + /// @param host Pointer to the missied host. + virtual void cache(ConstHostPtr host) const; + + /// @brief Cache a negative answer. + /// + /// @param ipv4_subnet_id Identifier of the IPv4 subnet. + /// @param ipv6_subnet_id Identifier of the IPv6 subnet. + /// @param identifier_type Identifier type. + /// @param identifier_begin Pointer to a beginning of the Identifier. + /// @param identifier_len Identifier length. + virtual void cacheNegative(const SubnetID& ipv4_subnet_id, + const SubnetID& ipv6_subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, + const size_t identifier_len) const; + private: /// @brief Private default constructor. - HostMgr() { } + HostMgr() : negative_caching_(false) { } /// @brief List of alternate host data sources. HostDataSourceList alternate_sources_; + /// @brief Pointer to the cache. + CacheHostDataSourcePtr cache_ptr_; + /// @brief Returns a pointer to the currently used instance of the /// @c HostMgr. static boost::scoped_ptr<HostMgr>& getHostMgrPtr(); |