Kea 1.5.0
host_data_source_factory.cc
Go to the documentation of this file.
1// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
11#include <dhcpsrv/hosts_log.h>
12#include <log/logger_support.h>
13
14#ifdef HAVE_MYSQL
16#endif
17
18#ifdef HAVE_PGSQL
20#endif
21
22#ifdef HAVE_CQL
24#endif
25
26#include <boost/algorithm/string.hpp>
27#include <boost/foreach.hpp>
28#include <boost/scoped_ptr.hpp>
29
30#include <algorithm>
31#include <iostream>
32#include <iterator>
33#include <map>
34#include <sstream>
35#include <utility>
36
37using namespace isc::db;
38using namespace std;
39
40namespace isc {
41namespace dhcp {
42
43map<string, HostDataSourceFactory::Factory> HostDataSourceFactory::map_;
44
45void
47 const string& dbaccess) {
48 // Parse the access string and create a redacted string for logging.
51
52 // Get the database type and open the corresponding database
53 DatabaseConnection::ParameterMap::iterator it = parameters.find("type");
54 if (it == parameters.end()) {
55 isc_throw(InvalidParameter, "Host database configuration does not "
56 "contain the 'type' keyword");
57 }
58
59 string db_type = it->second;
60 auto index = map_.find(db_type);
61
62 // No match?
63 if (index == map_.end()) {
64 isc_throw(InvalidType, "The type of host backend: '" <<
65 db_type << "' is not currently supported");
66 }
67
68 // Call the factory and push the pointer on sources.
69 sources.push_back(boost::shared_ptr<BaseHostDataSource>(index->second(parameters)));
70
71 // Check the factory did not return NULL.
72 if (!sources.back()) {
73 sources.pop_back();
74 isc_throw(Unexpected, "Hosts database " << db_type <<
75 " factory returned NULL");
76 }
77}
78
79bool
81 const string& db_type) {
82 for (auto it = sources.begin(); it != sources.end(); ++it) {
83 if ((*it)->getType() != db_type) {
84 continue;
85 }
86 LOG_DEBUG(hosts_logger, DHCPSRV_DBG_TRACE, HOSTS_CFG_CLOSE_HOST_DATA_SOURCE)
87 .arg(db_type);
88 sources.erase(it);
89 return (true);
90 }
91 return (false);
92}
93
94bool
96 const Factory& factory,
97 bool no_log) {
98 if (map_.count(db_type)) {
99 return (false);
100 }
101 map_.insert(pair<string, Factory>(db_type, factory));
102
103 // We are dealing here with static logger initialization fiasco.
104 // registerFactory may be called from constructors of static global
105 // objects for built in backends. The logging is not initialized yet,
106 // so the LOG_DEBUG would throw.
107 if (!no_log) {
108 LOG_DEBUG(hosts_logger, DHCPSRV_DBG_TRACE, HOSTS_BACKEND_REGISTER)
109 .arg(db_type);
110 }
111 return (true);
112}
113
114bool
115HostDataSourceFactory::deregisterFactory(const string& db_type, bool no_log) {
116 auto index = map_.find(db_type);
117 if (index != map_.end()) {
118 map_.erase(index);
119 if (!no_log) {
121 HOSTS_BACKEND_DEREGISTER)
122 .arg(db_type);
123 }
124 return (true);
125 } else {
126 return (false);
127 }
128}
129
130bool
131HostDataSourceFactory::registeredFactory(const std::string& db_type) {
132 auto index = map_.find(db_type);
133 return (index != map_.end());
134}
135
136void
138 std::stringstream txt;
139
140 for (auto x : map_) {
141 txt << x.first << " ";
142 }
143
144 LOG_INFO(hosts_logger, HOSTS_BACKENDS_REGISTERED).arg(txt.str());
145}
146
147} // namespace dhcp
148} // namespace isc
149
150//
151// Register database backends
152//
153
154using namespace isc::dhcp;
155
156namespace {
157
158#ifdef HAVE_MYSQL
159struct MySqlHostDataSourceInit {
160 // Constructor registers
161 MySqlHostDataSourceInit() {
162 HostDataSourceFactory::registerFactory("mysql", factory, true);
163 }
164
165 // Destructor deregisters
166 ~MySqlHostDataSourceInit() {
168 }
169
170 // Factory class method
171 static HostDataSourcePtr
172 factory(const DatabaseConnection::ParameterMap& parameters) {
173 LOG_INFO(hosts_logger, DHCPSRV_MYSQL_HOST_DB)
175 return (HostDataSourcePtr(new MySqlHostDataSource(parameters)));
176 }
177};
178
179// Database backend will be registered at object initialization
180MySqlHostDataSourceInit mysql_init_;
181#endif
182
183#ifdef HAVE_PGSQL
184struct PgSqlHostDataSourceInit {
185 // Constructor registers
186 PgSqlHostDataSourceInit() {
187 HostDataSourceFactory::registerFactory("postgresql", factory, true);
188 }
189
190 // Destructor deregisters
191 ~PgSqlHostDataSourceInit() {
193 }
194
195 // Factory class method
196 static HostDataSourcePtr
197 factory(const DatabaseConnection::ParameterMap& parameters) {
198 LOG_INFO(hosts_logger, DHCPSRV_PGSQL_HOST_DB)
200 return (HostDataSourcePtr(new PgSqlHostDataSource(parameters)));
201 }
202};
203
204// Database backend will be registered at object initialization
205PgSqlHostDataSourceInit pgsql_init_;
206#endif
207
208#ifdef HAVE_CQL
209struct CqlHostDataSourceInit {
210 // Constructor registers
211 CqlHostDataSourceInit() {
212 HostDataSourceFactory::registerFactory("cql", factory, true);
213 }
214
215 // Destructor deregisters
216 ~CqlHostDataSourceInit() {
218 }
219
220 // Factory class method
221 static HostDataSourcePtr
222 factory(const DatabaseConnection::ParameterMap& parameters) {
223 LOG_INFO(dhcpsrv_logger, DHCPSRV_CQL_HOST_DB)
225 return (HostDataSourcePtr(new CqlHostDataSource(parameters)));
226 }
227};
228
229// Database backend will be registered at object initialization
230CqlHostDataSourceInit cql_init_;
231#endif
232
233} // end of anonymous namespace
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
A generic exception that is thrown when an unexpected error condition occurs.
static std::string redactedAccessString(const ParameterMap &parameters)
Redact database access string.
static ParameterMap parse(const std::string &dbaccess)
Parse database access string.
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Invalid type exception.
Cassandra host data source.
boost::function< HostDataSourcePtr(const db::DatabaseConnection::ParameterMap &)> Factory
Type of host data source factory.
static bool deregisterFactory(const std::string &db_type, bool no_log=false)
Deregister a host data source factory.
static void add(HostDataSourceList &sources, const std::string &dbaccess)
Create and add an instance of a host data source.
static void printRegistered()
Prints out all registered backends.
static bool registerFactory(const std::string &db_type, const Factory &factory, bool no_log=false)
Register a host data source factory.
static bool del(HostDataSourceList &sources, const std::string &db_type)
Delete a host data source.
static bool registeredFactory(const std::string &db_type)
Check if a host data source factory was registered.
PostgreSQL Host Data Source.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Logging initialization functions.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
boost::shared_ptr< BaseHostDataSource > HostDataSourcePtr
HostDataSource pointer.
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
isc::log::Logger hosts_logger("hosts")
Logger for the HostMgr and the code it calls.
Definition: hosts_log.h:51
std::vector< HostDataSourcePtr > HostDataSourceList
HostDataSource list.
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition: dhcpsrv_log.h:26
Defines the logger used by the top-level component of kea-dhcp-ddns.