Kea 2.0.3
host_data_source_factory.cc
Go to the documentation of this file.
1// Copyright (C) 2015-2021 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 if ((db_type == "mysql") ||
65 (db_type == "postgresql") ||
66 (db_type == "cql")) {
67 string with = (db_type == "postgresql" ? "pgsql" : db_type);
68 isc_throw(InvalidType, "The type of host backend: '" << db_type
69 << "' is not compiled in. Did you forget to use --with-"
70 << with << " during compilation?");
71 }
72 isc_throw(InvalidType, "The type of host backend: '" <<
73 db_type << "' is not supported");
74 }
75
76 // Call the factory and push the pointer on sources.
77 sources.push_back(index->second(parameters));
78
79 // Check the factory did not return NULL.
80 if (!sources.back()) {
81 sources.pop_back();
82 isc_throw(Unexpected, "Hosts database " << db_type <<
83 " factory returned NULL");
84 }
85}
86
87bool
89 const string& db_type) {
90 for (auto it = sources.begin(); it != sources.end(); ++it) {
91 if ((*it)->getType() != db_type) {
92 continue;
93 }
95 .arg(db_type);
96 sources.erase(it);
97 return (true);
98 }
99 return (false);
100}
101
102bool
104 const string& db_type,
105 const string& dbaccess,
106 bool if_unusable) {
109 bool deleted = false;
110 if (if_unusable) {
111 deleted = true;
112 }
113
114 for (auto it = sources.begin(); it != sources.end(); ++it) {
115 if ((*it)->getType() != db_type || (*it)->getParameters() != parameters) {
116 continue;
117 }
118 if (if_unusable && (!(*it)->isUnusable())) {
119 deleted = false;
120 continue;
121 }
123 .arg((*it)->getType());
124 sources.erase(it);
125 return (true);
126 }
127 return (deleted);
128}
129
130bool
132 const Factory& factory,
133 bool no_log) {
134 if (map_.count(db_type)) {
135 return (false);
136 }
137 map_.insert(pair<string, Factory>(db_type, factory));
138
139 // We are dealing here with static logger initialization fiasco.
140 // registerFactory may be called from constructors of static global
141 // objects for built in backends. The logging is not initialized yet,
142 // so the LOG_DEBUG would throw.
143 if (!no_log) {
145 .arg(db_type);
146 }
147 return (true);
148}
149
150bool
151HostDataSourceFactory::deregisterFactory(const string& db_type, bool no_log) {
152 auto index = map_.find(db_type);
153 if (index != map_.end()) {
154 map_.erase(index);
155 if (!no_log) {
158 .arg(db_type);
159 }
160 return (true);
161 } else {
162 return (false);
163 }
164}
165
166bool
167HostDataSourceFactory::registeredFactory(const std::string& db_type) {
168 auto index = map_.find(db_type);
169 return (index != map_.end());
170}
171
172void
174 std::stringstream txt;
175
176 for (auto x : map_) {
177 txt << x.first << " ";
178 }
179
181}
182
183} // namespace dhcp
184} // namespace isc
185
186//
187// Register database backends
188//
189
190using namespace isc::dhcp;
191
192namespace {
193
194#ifdef HAVE_MYSQL
195struct MySqlHostDataSourceInit {
196 // Constructor registers
197 MySqlHostDataSourceInit() {
198 HostDataSourceFactory::registerFactory("mysql", factory, true);
199 }
200
201 // Destructor deregisters
202 ~MySqlHostDataSourceInit() {
203 HostDataSourceFactory::deregisterFactory("mysql", true);
204 }
205
206 // Factory class method
207 static HostDataSourcePtr
208 factory(const DatabaseConnection::ParameterMap& parameters) {
210 .arg(DatabaseConnection::redactedAccessString(parameters));
211 return (HostDataSourcePtr(new MySqlHostDataSource(parameters)));
212 }
213};
214
215// Database backend will be registered at object initialization
216MySqlHostDataSourceInit mysql_init_;
217#endif
218
219#ifdef HAVE_PGSQL
220struct PgSqlHostDataSourceInit {
221 // Constructor registers
222 PgSqlHostDataSourceInit() {
223 HostDataSourceFactory::registerFactory("postgresql", factory, true);
224 }
225
226 // Destructor deregisters
227 ~PgSqlHostDataSourceInit() {
228 HostDataSourceFactory::deregisterFactory("postgresql", true);
229 }
230
231 // Factory class method
232 static HostDataSourcePtr
233 factory(const DatabaseConnection::ParameterMap& parameters) {
235 .arg(DatabaseConnection::redactedAccessString(parameters));
236 return (HostDataSourcePtr(new PgSqlHostDataSource(parameters)));
237 }
238};
239
240// Database backend will be registered at object initialization
241PgSqlHostDataSourceInit pgsql_init_;
242#endif
243
244#ifdef HAVE_CQL
245struct CqlHostDataSourceInit {
246 // Constructor registers
247 CqlHostDataSourceInit() {
248 HostDataSourceFactory::registerFactory("cql", factory, true);
249 }
250
251 // Destructor deregisters
252 ~CqlHostDataSourceInit() {
253 HostDataSourceFactory::deregisterFactory("cql", true);
254 }
255
256 // Factory class method
257 static HostDataSourcePtr
258 factory(const DatabaseConnection::ParameterMap& parameters) {
260 .arg(DatabaseConnection::redactedAccessString(parameters));
261 return (HostDataSourcePtr(new CqlHostDataSource(parameters)));
262 }
263};
264
265// Database backend will be registered at object initialization
266CqlHostDataSourceInit cql_init_;
267#endif
268
269} // 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 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.
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.
std::function< HostDataSourcePtr(const db::DatabaseConnection::ParameterMap &)> Factory
Type of host data source factory.
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 hosts_logger("hosts")
Logger for the HostMgr and the code it calls.
Definition: hosts_log.h:51
const isc::log::MessageID HOSTS_BACKEND_DEREGISTER
const isc::log::MessageID DHCPSRV_CQL_HOST_DB
std::vector< HostDataSourcePtr > HostDataSourceList
HostDataSource list.
const isc::log::MessageID HOSTS_CFG_CLOSE_HOST_DATA_SOURCE
const isc::log::MessageID DHCPSRV_PGSQL_HOST_DB
const isc::log::MessageID HOSTS_BACKEND_REGISTER
const isc::log::MessageID DHCPSRV_MYSQL_HOST_DB
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition: dhcpsrv_log.h:26
const isc::log::MessageID HOSTS_BACKENDS_REGISTERED
Defines the logger used by the top-level component of kea-lfc.