From: Francis Dupont Date: Sun, 11 Feb 2018 00:56:53 +0000 (+0100) Subject: [5528] Code and tests done X-Git-Tag: trac5531_base~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=60d9fe4e7b03205643a7134e0a65da0f8a93ea37;p=thirdparty%2Fkea.git [5528] Code and tests done --- diff --git a/src/lib/dhcpsrv/host_data_source_factory.cc b/src/lib/dhcpsrv/host_data_source_factory.cc index c9e5203c91..3a63770cba 100644 --- a/src/lib/dhcpsrv/host_data_source_factory.cc +++ b/src/lib/dhcpsrv/host_data_source_factory.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2015-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 @@ -38,6 +38,8 @@ using namespace std; namespace isc { namespace dhcp { +map HostDataSourceFactory::map_; + HostDataSourcePtr& HostDataSourceFactory::getHostDataSourcePtr() { static HostDataSourcePtr hostDataSourcePtr; @@ -45,7 +47,7 @@ HostDataSourceFactory::getHostDataSourcePtr() { } void -HostDataSourceFactory::create(const std::string& dbaccess) { +HostDataSourceFactory::create(const string& dbaccess) { // Parse the access string and create a redacted string for logging. DatabaseConnection::ParameterMap parameters = DatabaseConnection::parse(dbaccess); @@ -57,38 +59,23 @@ HostDataSourceFactory::create(const std::string& dbaccess) { "contain the 'type' keyword"); } - std::string db_type = it->second; + string db_type = it->second; + auto index = map_.find(db_type); -#ifdef HAVE_MYSQL - if (db_type == "mysql") { - LOG_INFO(dhcpsrv_logger, DHCPSRV_MYSQL_HOST_DB) - .arg(DatabaseConnection::redactedAccessString(parameters)); - getHostDataSourcePtr().reset(new MySqlHostDataSource(parameters)); - return; + // No match? + if (index == map_.end()) { + isc_throw(InvalidType, "Hosts database access parameter 'type': " << + db_type << " is invalid"); } -#endif -#ifdef HAVE_PGSQL - if (db_type == "postgresql") { - LOG_INFO(dhcpsrv_logger, DHCPSRV_PGSQL_HOST_DB) - .arg(DatabaseConnection::redactedAccessString(parameters)); - getHostDataSourcePtr().reset(new PgSqlHostDataSource(parameters)); - return; - } -#endif + // Call the factory + getHostDataSourcePtr().reset(index->second(parameters)); -#ifdef HAVE_CQL - if (db_type == "cql") { - LOG_INFO(dhcpsrv_logger, DHCPSRV_CQL_HOST_DB) - .arg(DatabaseConnection::redactedAccessString(parameters)); - getHostDataSourcePtr().reset(new CqlHostDataSource(parameters)); - return; + // Check the factory did not return NULL. + if (!getHostDataSourcePtr()) { + isc_throw(Unexpected, "Hosts database " << db_type << + " factory returned NULL"); } -#endif - - // Get here on no match. - isc_throw(InvalidType, "Hosts database access parameter 'type': " << - db_type << " is invalid"); } void @@ -102,17 +89,111 @@ HostDataSourceFactory::destroy() { getHostDataSourcePtr().reset(); } -#if 0 -BaseHostDataSource& -HostDataSourceFactory::instance() { - BaseHostDataSource* hdsptr = getHostDataSourcePtr().get(); - if (hdsptr == NULL) { - isc_throw(NoHostDataSourceManager, - "no current host data source instance is available"); +bool +HostDataSourceFactory::registerFactory(const string& db_type, + const Factory& factory) { + if (map_.count(db_type)) { + return (false); + } + map_.insert(pair(db_type, factory)); + return (true); +} + +bool +HostDataSourceFactory::deregisterFactory(const string& db_type) { + auto index = map_.find(db_type); + if (index != map_.end()) { + map_.erase(index); + return (true); + } else { + return (false); } - return (*hdsptr); } -#endif } // namespace dhcp } // namespace isc + +// +// Register database backends +// + +using namespace isc::dhcp; + +namespace { + +#ifdef HAVE_MYSQL +struct MySqlHostDataSourceInit { + // Constructor registers + MySqlHostDataSourceInit() { + HostDataSourceFactory::registerFactory("mysql", factory); + } + + // Destructor deregisters + ~MySqlHostDataSourceInit() { + HostDataSourceFactory::deregisterFactory("mysql"); + } + + // Factory class method + static BaseHostDataSource* + factory(const DatabaseConnection::ParameterMap& parameters) { + LOG_INFO(dhcpsrv_logger, DHCPSRV_MYSQL_HOST_DB) + .arg(DatabaseConnection::redactedAccessString(parameters)); + return (new MySqlHostDataSource(parameters)); + } +}; + +// Database backend will be registered at object initialization +MySqlHostDataSourceInit mysql_init; +#endif + +#ifdef HAVE_PGSQL +struct PgSqlHostDataSourceInit { + // Constructor registers + PgSqlHostDataSourceInit() { + HostDataSourceFactory::registerFactory("postgresql", factory); + } + + // Destructor deregisters + ~PgSqlHostDataSourceInit() { + HostDataSourceFactory::deregisterFactory("postgresql"); + } + + // Factory class method + static BaseHostDataSource* + factory(const DatabaseConnection::ParameterMap& parameters) { + LOG_INFO(dhcpsrv_logger, DHCPSRV_PGSQL_HOST_DB) + .arg(DatabaseConnection::redactedAccessString(parameters)); + return (new PgSqlHostDataSource(parameters)); + } +}; + +// Database backend will be registered at object initialization +PgSqlHostDataSourceInit mysql_init; +#endif + +#ifdef HAVE_CQL +struct CqlHostDataSourceInit { + // Constructor registers + CqlHostDataSourceInit() { + HostDataSourceFactory::registerFactory("cql", factory); + } + + // Destructor deregisters + ~CqlHostDataSourceInit() { + HostDataSourceFactory::deregisterFactory("cql"); + } + + // Factory class method + static BaseHostDataSource* + factory(const DatabaseConnection::ParameterMap& parameters) { + LOG_INFO(dhcpsrv_logger, DHCPSRV_CQL_HOST_DB) + .arg(DatabaseConnection::redactedAccessString(parameters)); + return (new CqlHostDataSource(parameters)); + } +}; + +// Database backend will be registered at object initialization +CqlHostDataSourceInit mysql_init; +#endif + +} // end of anonymous namespace diff --git a/src/lib/dhcpsrv/host_data_source_factory.h b/src/lib/dhcpsrv/host_data_source_factory.h index d7c3123a6b..68492213dc 100644 --- a/src/lib/dhcpsrv/host_data_source_factory.h +++ b/src/lib/dhcpsrv/host_data_source_factory.h @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2015-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 @@ -11,8 +11,10 @@ #include #include #include +#include #include +#include namespace isc { namespace dhcp { @@ -77,6 +79,36 @@ public: /// is encapsulated in this method to avoid a "static initialization /// fiasco" if defined in an external static variable. static HostDataSourcePtr& getHostDataSourcePtr(); + + /// @brief Type of host data source factory + /// + /// A factory takes a parameter map and returns a pointer to a host + /// data source. In case of failure it must throw and not return NULL. + typedef boost::function Factory; + + /// @brief Register a host data source factory + /// + /// Associate the factory to a database type in the map. + /// + /// @param db_type database type + /// @param factory host data source factory + /// @return true if the factory was successfully added to the map, false + /// if it already exists. + static bool registerFactory(const std::string& db_type, + const Factory& factory); + + /// @brief Deregister a host data source factory + /// + /// Disassociate the factory to a database type in the map. + /// + /// @param db_type database type + /// @return true if the factory was successfully removed from the map, + /// false if it was not found. + static bool deregisterFactory(const std::string& db_type); + +private: + /// @brief Factory map + static std::map map_; }; diff --git a/src/lib/dhcpsrv/tests/Makefile.am b/src/lib/dhcpsrv/tests/Makefile.am index 83a178a0d3..95c5c4f753 100644 --- a/src/lib/dhcpsrv/tests/Makefile.am +++ b/src/lib/dhcpsrv/tests/Makefile.am @@ -91,6 +91,7 @@ libdhcpsrv_unittests_SOURCES += dbaccess_parser_unittest.cc libdhcpsrv_unittests_SOURCES += dhcp4o6_ipc_unittest.cc libdhcpsrv_unittests_SOURCES += duid_config_parser_unittest.cc libdhcpsrv_unittests_SOURCES += expiration_config_parser_unittest.cc +libdhcpsrv_unittests_SOURCES += host_data_source_factory_unittest.cc libdhcpsrv_unittests_SOURCES += host_mgr_unittest.cc libdhcpsrv_unittests_SOURCES += host_unittest.cc libdhcpsrv_unittests_SOURCES += host_reservation_parser_unittest.cc