]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5533] Checkpoint: added code, test todo (where?)
authorFrancis Dupont <fdupont@isc.org>
Fri, 23 Feb 2018 15:45:46 +0000 (16:45 +0100)
committerFrancis Dupont <fdupont@isc.org>
Fri, 23 Feb 2018 15:45:46 +0000 (16:45 +0100)
src/lib/dhcpsrv/Makefile.am
src/lib/dhcpsrv/cache_host_data_source.h [new file with mode: 0644]
src/lib/dhcpsrv/cfg_db_access.cc
src/lib/dhcpsrv/host_mgr.cc
src/lib/dhcpsrv/host_mgr.h

index a9c5ea7c36da8612ced65dcd302028809ba7dd09..34fd3a88e62b6bf78ee36c15a4610c1d26423861 100644 (file)
@@ -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 (file)
index 0000000..d6d84bc
--- /dev/null
@@ -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
index ad6c3965875a96039a505275ea086ee5af782e17..2163f1ec967b806c70bc9a51db2ecb75276c97d4 100644 (file)
@@ -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 
index 1cb45c2ddbe554f02c2dc105cb640ba2cac014f5..c776d90444508722b9aa96aa40b7421d83046e44 100644 (file)
@@ -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
index fa003ac22d4d85e2f4a4f7db9e182edc486c6454..e7392172cf46cddaaf13be55c9352ce0746be519 100644 (file)
@@ -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();