Commit d2bad4f7 authored by Francis Dupont's avatar Francis Dupont
Browse files

[5533] Checkpoint: added code, test todo (where?)

parent f922c7d1
......@@ -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 \
......
// 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
......@@ -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
......
......@@ -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
......@@ -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();
......
Markdown is supported
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