Kea 2.7.6
lease_mgr_factory.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2024 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
12#include <boost/algorithm/string.hpp>
13
14#include <algorithm>
15#include <iostream>
16#include <iterator>
17#include <map>
18#include <sstream>
19#include <utility>
20
21using namespace isc::db;
22using namespace std;
23
24namespace isc {
25namespace dhcp {
26
27map<string, pair<LeaseMgrFactory::Factory, LeaseMgrFactory::DBVersion>> LeaseMgrFactory::map_;
28
29namespace {
30
33
34}
35
37LeaseMgrFactory::getLeaseMgrPtr() {
38 static TrackingLeaseMgrPtr lease_mgr_ptr;
39 return (lease_mgr_ptr);
40}
41
42void
43LeaseMgrFactory::create(const std::string& dbaccess) {
44 const std::string type = "type";
45
46 // Parse the access string and create a redacted string for logging.
48 std::string redacted = DatabaseConnection::redactedAccessString(parameters);
49
50 // Get the database type and open the corresponding database.
51 DatabaseConnection::ParameterMap::iterator it = parameters.find(type);
52 if (it == parameters.end()) {
54 isc_throw(InvalidParameter, "Database configuration parameters do not "
55 "contain the 'type' keyword");
56 }
57
58 string db_type = it->second;
59 auto index = map_.find(db_type);
60
61 // No match?
62 if (index == map_.end()) {
63 if ((db_type == "mysql") || (db_type == "postgresql")) {
65 string with = (db_type == "postgresql" ? "pgsql" : db_type);
66 isc_throw(InvalidType, "The Kea server has not been compiled with "
67 "support for lease database type: " << db_type
68 << ". Did you forget to use --with-"
69 << with << " during compilation or to load libdhcp_"
70 << with << " hook library?");
71 }
72 // Get here on no match
73 LOG_ERROR(dhcpsrv_logger, DHCPSRV_UNKNOWN_DB).arg(parameters[type]);
74 isc_throw(InvalidType, "Database access parameter 'type' does "
75 "not specify a supported database backend: " << parameters[type]);
76 }
77
78 // Call the factory.
79 getLeaseMgrPtr() = index->second.first(parameters);
80
81 // Check the factory did not return null.
82 if (!getLeaseMgrPtr()) {
83 isc_throw(Unexpected, "Lease database " << db_type <<
84 " factory returned null");
85 }
86}
87
88void
90 // Destroy current lease manager. This is a no-op if no lease manager
91 // is available.
92 if (getLeaseMgrPtr()) {
94 .arg(getLeaseMgrPtr()->getType());
95 getLeaseMgrPtr().reset();
96 }
97}
98
99void
100LeaseMgrFactory::recreate(const std::string& dbaccess, bool preserve_callbacks) {
102 // Preserve the callbacks if needed.
103 if (preserve_callbacks && haveInstance()) {
104 callbacks = instance().callbacks_;
105 }
106
107 // Re-create the manager.
108 destroy();
109 create(dbaccess);
110
111 if (callbacks) {
112 // Copy the callbacks to the new instance. It should be fast
113 // because we merely copy the pointer.
114 instance().callbacks_ = callbacks;
115 }
116}
117
118bool
120 return (!!getLeaseMgrPtr());
121}
122
125 TrackingLeaseMgr* lmptr = getLeaseMgrPtr().get();
126 if (!lmptr) {
127 isc_throw(NoLeaseManager, "no current lease manager is available");
128 }
129 return (*lmptr);
130}
131
132bool
134 const Factory& factory,
135 bool no_log,
136 DBVersion db_version) {
137 if (map_.count(db_type)) {
138 return (false);
139 }
140
141 static auto default_db_version = []() -> std::string {
142 return (std::string());
143 };
144
145 if (!db_version) {
146 db_version = default_db_version;
147 }
148
149 map_.insert(pair<string, pair<Factory, DBVersion>>(db_type, pair<Factory, DBVersion>(factory, db_version)));
150
151 // We are dealing here with static logger initialization fiasco.
152 // registerFactory may be called from constructors of static global
153 // objects for built in backends. The logging is not initialized yet,
154 // so the LOG_DEBUG would throw.
155 if (!no_log) {
157 .arg(db_type);
158 }
159 return (true);
160}
161
162bool
163LeaseMgrFactory::deregisterFactory(const string& db_type, bool no_log) {
164 auto index = map_.find(db_type);
165 if (index != map_.end()) {
166 map_.erase(index);
167 if (!no_log) {
170 .arg(db_type);
171 }
172 return (true);
173 } else {
174 return (false);
175 }
176}
177
178bool
179LeaseMgrFactory::registeredFactory(const std::string& db_type) {
180 auto index = map_.find(db_type);
181 return (index != map_.end());
182}
183
184void
186 std::stringstream txt;
187
188 for (auto const& x : map_) {
189 if (!txt.str().empty()) {
190 txt << " ";
191 }
192 txt << x.first;
193 }
194
196 .arg(txt.str());
197}
198
199std::list<std::string>
201 std::list<std::string> result;
202 for (auto const& x : map_) {
203 auto version = x.second.second();
204 if (!version.empty()) {
205 result.push_back(version);
206 }
207 }
208
209 return (result);
210}
211
212} // namespace dhcp
213} // namespace isc
int version()
returns Kea hooks version.
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.
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
static ParameterMap parse(const std::string &dbaccess)
Parse database access string.
Invalid type exception.
static void create(const std::string &dbaccess)
Create an instance of a lease manager.
static TrackingLeaseMgr & instance()
Return current lease manager.
static bool registerFactory(const std::string &db_type, const Factory &factory, bool no_log=false, DBVersion db_version=DBVersion())
Register a lease mgr factory.
static std::list< std::string > getDBVersions()
Return extended version info for registered backends.
static void destroy()
Destroy lease manager.
static bool registeredFactory(const std::string &db_type)
Check if a lease mgr factory was registered.
static bool haveInstance()
Indicates if the lease manager has been instantiated.
std::function< TrackingLeaseMgrPtr(const db::DatabaseConnection::ParameterMap &)> Factory
Type of lease mgr factory.
std::function< std::string()> DBVersion
Type of lease mgr version.
static bool deregisterFactory(const std::string &db_type, bool no_log=false)
Deregister a lease mgr factory.
static void logRegistered()
Logs out all registered backends.
static void recreate(const std::string &dbaccess, bool preserve_callbacks=true)
Recreate an instance of a lease manager with optionally preserving registered callbacks.
No lease manager exception.
Introduces callbacks into the LeaseMgr.
CallbackContainerPtr callbacks_
The multi-index container holding registered callbacks.
boost::shared_ptr< CallbackContainer > CallbackContainerPtr
Pointer to the callback container.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
#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
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition dhcpsrv_log.h:56
const isc::log::MessageID DHCPSRV_LEASE_MGR_BACKENDS_REGISTERED
const isc::log::MessageID DHCPSRV_LEASE_MGR_BACKEND_DEREGISTER
const isc::log::MessageID DHCPSRV_CLOSE_DB
const isc::log::MessageID DHCPSRV_UNKNOWN_DB
const isc::log::MessageID DHCPSRV_LEASE_MGR_BACKEND_REGISTER
const isc::log::MessageID DHCPSRV_NOTYPE_DB
std::unique_ptr< TrackingLeaseMgr > TrackingLeaseMgrPtr
TrackingLeaseMgr pointer.
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-lfc.
Initialization structure used to register and deregister Memfile Lease Mgr.