Commit 405ae2f6 authored by Francis Dupont's avatar Francis Dupont
Browse files

[5531] Checkpoint: 3/4 code done

parent 0006fb98
// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -14,6 +14,8 @@
#include <exceptions/exceptions.h>
#include <boost/shared_ptr.hpp>
#include <vector>
namespace isc {
namespace dhcp {
......@@ -245,7 +247,8 @@ public:
/// is identified by HW address, another one by DUID.
///
/// @param host Pointer to the new @c Host object being added.
virtual void add(const HostPtr& host) = 0;
/// @return true if addition was successful.
virtual bool add(const HostPtr& host) = 0;
/// @brief Attempts to delete a host by (subnet-id, address)
///
......@@ -310,6 +313,9 @@ public:
/// @brief HostDataSource pointer
typedef boost::shared_ptr<BaseHostDataSource> HostDataSourcePtr;
/// @brief HostDataSource list
typedef std::vector<HostDataSourcePtr> HostDataSourceList;
}
}
......
// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -44,9 +44,9 @@ CfgDbAccess::createManagers() const {
LeaseMgrFactory::create(getLeaseDbAccessString());
// Recreate host data source.
HostDataSourceFactory::destroy();
HostMgr::create();
if (!host_db_access_.empty()) {
HostMgr::create(getHostDbAccessString());
HostMgr::addSource(getHostDbAccessString());
}
}
......
// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -549,7 +549,7 @@ CfgHosts::getHostInternal(const SubnetID& subnet_id, const bool subnet6,
return (host);
}
void
bool
CfgHosts::add(const HostPtr& host) {
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_ADD_HOST)
.arg(host ? host->toText() : "(no-host)");
......@@ -569,6 +569,8 @@ CfgHosts::add(const HostPtr& host) {
add4(host);
add6(host);
return (true);
}
void
......
// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -318,9 +318,10 @@ public:
///
/// @param host Pointer to the new @c Host object being added.
///
/// @return always return true as additions are successful or throw.
/// @throw DuplicateHost If a host for a particular HW address or DUID
/// has already been added to the IPv4 or IPv6 subnet.
virtual void add(const HostPtr& host);
virtual bool add(const HostPtr& host);
/// @brief Attempts to delete a host by address.
///
......
// Copyright (C) 2016-2017 Deutsche Telekom AG.
// Copyright (C) 2016-2018 Deutsche Telekom AG.
//
// Author: Andrei Pavel <andrei.pavel@qualitance.com>
//
......@@ -1820,11 +1820,13 @@ CqlHostDataSource::~CqlHostDataSource() {
delete impl_;
}
void
bool
CqlHostDataSource::add(const HostPtr& host) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_HOST_ADD);
impl_->add(host);
return (true);
}
ConstHostCollection
......
// Copyright (C) 2016-2017 Deutsche Telekom AG.
// Copyright (C) 2016-2018 Deutsche Telekom AG.
//
// Author: Andrei Pavel <andrei.pavel@qualitance.com>
//
......@@ -98,7 +98,8 @@ public:
/// Host, where one instance is identified by different identifier types.
///
/// @param host pointer to the new @ref Host being added.
virtual void add(const HostPtr& host) override;
/// @return true as addition is successful or throws.
virtual bool add(const HostPtr& host) override;
/// @brief Retrieves a single @ref Host connected to an IPv4 subnet.
///
......
......@@ -40,14 +40,9 @@ namespace dhcp {
map<string, HostDataSourceFactory::Factory> HostDataSourceFactory::map_;
HostDataSourcePtr&
HostDataSourceFactory::getHostDataSourcePtr() {
static HostDataSourcePtr hostDataSourcePtr;
return (hostDataSourcePtr);
}
void
HostDataSourceFactory::create(const string& dbaccess) {
HostDataSourceFactory::add(HostDataSourceList& sources,
const string& dbaccess) {
// Parse the access string and create a redacted string for logging.
DatabaseConnection::ParameterMap parameters =
DatabaseConnection::parse(dbaccess);
......@@ -68,25 +63,30 @@ HostDataSourceFactory::create(const string& dbaccess) {
db_type << " is invalid");
}
// Call the factory
getHostDataSourcePtr().reset(index->second(parameters));
// Call the factory and push the pointer on sources.
sources.push_back(boost::shared_ptr<BaseHostDataSource>(index->second(parameters)));
// Check the factory did not return NULL.
if (!getHostDataSourcePtr()) {
if (!sources.back()) {
sources.pop_back();
isc_throw(Unexpected, "Hosts database " << db_type <<
" factory returned NULL");
}
}
void
HostDataSourceFactory::destroy() {
// Destroy current host data source instance. This is a no-op if no host
// data source is available.
if (getHostDataSourcePtr()) {
bool
HostDataSourceFactory::del(HostDataSourceList& sources,
const string& db_type) {
for (auto it = sources.begin(); it != sources.end(); ++it) {
if ((*it)->getType() != db_type) {
continue;
}
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, HOSTS_CFG_CLOSE_HOST_DATA_SOURCE)
.arg(getHostDataSourcePtr()->getType());
.arg(db_type);
sources.erase(it);
return (true);
}
getHostDataSourcePtr().reset();
return (false);
}
bool
......
......@@ -40,21 +40,18 @@ public:
class HostDataSourceFactory {
public:
/// @brief Create an instance of a host data source.
/// @brief Create and add an instance of a host data source.
///
/// Each database backend has its own host data source type. This static
/// method sets the "current" host data source to be an object of the
/// appropriate type. The actual host data source is returned by the
/// "instance" method.
///
/// @note When called, the current host data source is <b>always</b> destroyed
/// and a new one created - even if the parameters are the same.
/// method adds an object of the appropriate type to a list of
/// host data sources.
///
/// dbaccess is a generic way of passing parameters. Parameters are passed
/// in the "name=value" format, separated by spaces. The data MUST include
/// a keyword/value pair of the form "type=dbtype" giving the database
/// type, e.q. "mysql" or "sqlite3".
///
/// @param sources host data source list.
/// @param dbaccess Database access parameters. These are in the form of
/// "keyword=value" pairs, separated by spaces. They are backend-
/// -end specific, although must include the "type" keyword which
......@@ -64,21 +61,17 @@ public:
/// keyword.
/// @throw isc::dhcp::InvalidType The "type" keyword in dbaccess does not
/// identify a supported backend.
static void create(const std::string& dbaccess);
static void add(HostDataSourceList& sources, const std::string& dbaccess);
/// @brief Destroy host data source
/// @brief Delete a host data source.
///
/// Destroys the current host data source object. This should have the effect
/// of closing the database connection. The method is a no-op if no
/// host data source is available.
static void destroy();
/// @brief Hold pointer to host data source instance
/// Delete the first instance of a host data source of the given type.
/// This should have the effect of closing the database connection.
///
/// Holds a pointer to the singleton host data source. The singleton
/// is encapsulated in this method to avoid a "static initialization
/// fiasco" if defined in an external static variable.
static HostDataSourcePtr& getHostDataSourcePtr();
/// @param sources host data source list.
/// @param db_type database backend type.
/// @return true when found and removed, false when not found.
static bool del(HostDataSourceList& sources, const std::string& db_type);
/// @brief Type of host data source factory
///
......
// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -37,24 +37,31 @@ HostMgr::getHostMgrPtr() {
}
void
HostMgr::create(const std::string& access) {
HostMgr::create() {
getHostMgrPtr().reset(new HostMgr());
}
if (!access.empty()) {
// If the user specified parameters, let's pass them to the create
// method. It will destroy any prior instances and will create
// the new one.
HostDataSourceFactory::create(access);
} else {
// Ok, no parameters were specified. We should destroy the existing
// instance.
HostDataSourceFactory::destroy();
}
void
HostMgr::addSource(const std::string& access) {
HostDataSourceFactory::add(getHostMgrPtr()->alternate_sources_, access);
}
bool
HostMgr::delSource(const std::string& db_type) {
return (HostDataSourceFactory::del(getHostMgrPtr()->alternate_sources_, db_type));
}
// Now store the host data source pointer. It may be NULL. That's ok as
// NULL value indicates that there's no host data source configured.
getHostMgrPtr()->alternate_source_ =
HostDataSourceFactory::getHostDataSourcePtr();
void
HostMgr::delAllSources() {
getHostMgrPtr()->alternate_sources_.clear();
}
HostDataSourcePtr
HostMgr::getHostDataSource() const {
if (alternate_sources_.empty()) {
return (HostDataSourcePtr());
}
return (alternate_sources_[0]);
}
HostMgr&
......@@ -69,8 +76,9 @@ HostMgr::instance() {
ConstHostCollection
HostMgr::getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid) const {
ConstHostCollection hosts = getCfgHosts()->getAll(hwaddr, duid);
if (alternate_source_) {
ConstHostCollection hosts_plus = alternate_source_->getAll(hwaddr, duid);
for (auto it = alternate_sources_.begin();
it != alternate_sources_.end(); ++it) {
ConstHostCollection hosts_plus = (*it)->getAll(hwaddr, duid);
hosts.insert(hosts.end(), hosts_plus.begin(), hosts_plus.end());
}
return (hosts);
......@@ -83,10 +91,10 @@ HostMgr::getAll(const Host::IdentifierType& identifier_type,
ConstHostCollection hosts = getCfgHosts()->getAll(identifier_type,
identifier_begin,
identifier_len);
if (alternate_source_) {
for (auto it = alternate_sources_.begin();
it != alternate_sources_.end(); ++it) {
ConstHostCollection hosts_plus =
alternate_source_->getAll(identifier_type, identifier_begin,
identifier_len);
(*it)->getAll(identifier_type, identifier_begin, identifier_len);
hosts.insert(hosts.end(), hosts_plus.begin(), hosts_plus.end());
}
return (hosts);
......@@ -96,8 +104,9 @@ HostMgr::getAll(const Host::IdentifierType& identifier_type,
ConstHostCollection
HostMgr::getAll4(const IOAddress& address) const {
ConstHostCollection hosts = getCfgHosts()->getAll4(address);
if (alternate_source_) {
ConstHostCollection hosts_plus = alternate_source_->getAll4(address);
for (auto it = alternate_sources_.begin();
it != alternate_sources_.end(); ++it) {
ConstHostCollection hosts_plus = (*it)->getAll4(address);
hosts.insert(hosts.end(), hosts_plus.begin(), hosts_plus.end());
}
return (hosts);
......@@ -107,17 +116,21 @@ ConstHostPtr
HostMgr::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
const DuidPtr& duid) const {
ConstHostPtr host = getCfgHosts()->get4(subnet_id, hwaddr, duid);
if (!host && alternate_source_) {
for (auto it = alternate_sources_.begin();
it != alternate_sources_.end(); ++it) {
if (host) {
break;
}
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_HWADDR_DUID)
.arg(subnet_id)
.arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)")
.arg(duid ? duid->toText() : "(duid)");
if (duid) {
host = alternate_source_->get4(subnet_id, HWAddrPtr(), duid);
host = (*it)->get4(subnet_id, HWAddrPtr(), duid);
}
if (!host && hwaddr) {
host = alternate_source_->get4(subnet_id, hwaddr, DuidPtr());
host = (*it)->get4(subnet_id, hwaddr, DuidPtr());
}
}
return (host);
......@@ -130,32 +143,37 @@ HostMgr::get4(const SubnetID& subnet_id,
const size_t identifier_len) const {
ConstHostPtr host = getCfgHosts()->get4(subnet_id, identifier_type,
identifier_begin, identifier_len);
if (!host && alternate_source_) {
for (auto it = alternate_sources_.begin();
it != alternate_sources_.end(); ++it) {
if (host) {
break;
}
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER)
.arg(subnet_id)
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
.arg(Host::getIdentifierAsText(identifier_type,
identifier_begin,
identifier_len));
host = alternate_source_->get4(subnet_id, identifier_type,
identifier_begin, identifier_len);
host = (*it)->get4(subnet_id, identifier_type,
identifier_begin, identifier_len);
if (host) {
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER_HOST)
.arg(subnet_id)
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
.arg(Host::getIdentifierAsText(identifier_type,
identifier_begin,
identifier_len))
.arg(host->toText());
} else {
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER_NULL)
.arg(subnet_id)
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
identifier_len));
break;
}
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER_NULL)
.arg(subnet_id)
.arg(Host::getIdentifierAsText(identifier_type,
identifier_begin,
identifier_len));
}
return (host);
......@@ -165,12 +183,16 @@ ConstHostPtr
HostMgr::get4(const SubnetID& subnet_id,
const asiolink::IOAddress& address) const {
ConstHostPtr host = getCfgHosts()->get4(subnet_id, address);
if (!host && alternate_source_) {
for (auto it = alternate_sources_.begin();
it != alternate_sources_.end(); ++it) {
if (host) {
break;
}
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_ADDRESS4)
.arg(subnet_id)
.arg(address.toText());
host = alternate_source_->get4(subnet_id, address);
host = (*it)->get4(subnet_id, address);
}
return (host);
}
......@@ -180,17 +202,21 @@ ConstHostPtr
HostMgr::get6(const SubnetID& subnet_id, const DuidPtr& duid,
const HWAddrPtr& hwaddr) const {
ConstHostPtr host = getCfgHosts()->get6(subnet_id, duid, hwaddr);
if (!host && alternate_source_) {
for (auto it = alternate_sources_.begin();
it != alternate_sources_.end(); ++it) {
if (host) {
break;
}
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_DUID_HWADDR)
.arg(subnet_id)
.arg(duid ? duid->toText() : "(duid)")
.arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)");
if (duid) {
host = alternate_source_->get6(subnet_id, duid, HWAddrPtr());
host = (*it)->get6(subnet_id, duid, HWAddrPtr());
}
if (!host && hwaddr) {
host = alternate_source_->get6(subnet_id, DuidPtr(), hwaddr);
host = (*it)->get6(subnet_id, DuidPtr(), hwaddr);
}
}
return (host);
......@@ -199,12 +225,16 @@ HostMgr::get6(const SubnetID& subnet_id, const DuidPtr& duid,
ConstHostPtr
HostMgr::get6(const IOAddress& prefix, const uint8_t prefix_len) const {
ConstHostPtr host = getCfgHosts()->get6(prefix, prefix_len);
if (!host && alternate_source_) {
for (auto it = alternate_sources_.begin();
it != alternate_sources_.end(); ++it) {
if (host) {
break;
}
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
HOSTS_MGR_ALTERNATE_GET6_PREFIX)
.arg(prefix.toText())
.arg(static_cast<int>(prefix_len));
host = alternate_source_->get6(prefix, prefix_len);
host = (*it)->get6(prefix, prefix_len);
}
return (host);
}
......@@ -216,34 +246,37 @@ HostMgr::get6(const SubnetID& subnet_id,
const size_t identifier_len) const {
ConstHostPtr host = getCfgHosts()->get6(subnet_id, identifier_type,
identifier_begin, identifier_len);
if (!host && alternate_source_) {
for (auto it = alternate_sources_.begin();
it != alternate_sources_.end(); ++it) {
if (host) {
break;
}
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER)
.arg(subnet_id)
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
.arg(Host::getIdentifierAsText(identifier_type,
identifier_begin,
identifier_len));
host = alternate_source_->get6(subnet_id, identifier_type,
identifier_begin, identifier_len);
host = (*it)->get6(subnet_id, identifier_type,
identifier_begin, identifier_len);
if (host) {
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER_HOST)
.arg(subnet_id)
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
identifier_len))
.arg(host->toText());
} else {
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER_NULL)
.arg(subnet_id)
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
identifier_len));
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER_HOST)
.arg(subnet_id)
.arg(Host::getIdentifierAsText(identifier_type,
identifier_begin,
identifier_len))
.arg(host->toText());
break;
}
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER_NULL)
.arg(subnet_id)
.arg(Host::getIdentifierAsText(identifier_type,
identifier_begin,
identifier_len));
}
return (host);
}
......@@ -252,57 +285,86 @@ ConstHostPtr
HostMgr::get6(const SubnetID& subnet_id,
const asiolink::IOAddress& addr) const {
ConstHostPtr host = getCfgHosts()->get6(subnet_id, addr);
if (!host && alternate_source_) {
for (auto it = alternate_sources_.begin();
it != alternate_sources_.end(); ++it) {
if (host) {
break;
}
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE,
HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_ADDRESS6)
.arg(subnet_id)
.arg(addr.toText());
host = alternate_source_->get6(subnet_id, addr);
host = (*it)->get6(subnet_id, addr);
}
return (host);
}
void
bool
HostMgr::add(const HostPtr& host) {
if (!alternate_source_) {
if (alternate_sources_.empty()) {
isc_throw(NoHostDataSourceManager, "Unable to add new host because there is "
"no hosts-database configured.");
}
alternate_source_->add(host);
for (auto it = alternate_sources_.begin();
it != alternate_sources_.end(); ++it) {
if ((*it)->add(host)) {
return (true);
}
}
// This should never happen as at least one backend implements addition.
return (false);
}
bool
HostMgr::del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
if (!alternate_source_) {
if (alternate_sources_.empty()) {
isc_throw(NoHostDataSourceManager, "Unable to delete a host because there is "
"no hosts-database configured.");
}
return (alternate_source_->del(subnet_id, addr));
for (auto it = alternate_sources_.begin();
it != alternate_sources_.end(); ++it) {
if ((*it)->del(subnet_id, addr)) {
return (true);
}
}
return (false);
}
bool
HostMgr::del4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin, const size_t identifier_len) {
if (!alternate_source_) {
if (alternate_sources_.empty()) {
isc_throw(NoHostDataSourceManager, "Unable to delete a host because there is "
"no hosts-database configured.");
}
return (alternate_source_->del4(subnet_id, identifier_type,
identifier_begin, identifier_len));
for (auto it = alternate_sources_.begin();
it != alternate_sources_.end(); ++it) {
if ((*it)->del4(subnet_id, identifier_type,
identifier_begin, identifier_len)) {
return (true);
}
}
return (false);
}
bool
HostMgr::del6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin, const size_t identifier_len) {
if (!alternate_source_) {
if (alternate_sources_.empty()) {