Kea 3.2.0-git
lease_mgr_factory.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2026 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
9#include <dhcpsrv/cfgmgr.h>
10#include <dhcpsrv/dhcpsrv_log.h>
13#include <boost/algorithm/string.hpp>
14
15#include <algorithm>
16#include <iostream>
17#include <iterator>
18#include <map>
19#include <sstream>
20#include <utility>
21
22using namespace isc::db;
23using namespace std;
24
25namespace isc {
26namespace dhcp {
27
28map<string, pair<LeaseMgrFactory::Factory, LeaseMgrFactory::DBVersion>> LeaseMgrFactory::map_;
29
30namespace {
31
33isc::dhcp::MemfileLeaseMgrInit memfile_init;
34
35}
36
38LeaseMgrFactory::getLeaseMgrPtr() {
39 static TrackingLeaseMgrPtr lease_mgr_ptr;
40 return (lease_mgr_ptr);
41}
42
44
45void
46LeaseMgrFactory::initAllocators(bool use_staging /* = false */) {
48 return;
49 }
50 auto cfg = (use_staging ? CfgMgr::instance().getStagingCfg()
52 if (CfgMgr::instance().getFamily() == AF_INET) {
53 cfg->getCfgSubnets4()->initAllocatorsAfterConfigure();
54 } else {
55 cfg->getCfgSubnets6()->initAllocatorsAfterConfigure();
56 }
58}
59
60void
61LeaseMgrFactory::create(const std::string& dbaccess) {
62 const std::string type = "type";
63
64 // Parse the access string and create a redacted string for logging.
66 std::string redacted = DatabaseConnection::redactedAccessString(parameters);
67
68 // Get the database type and open the corresponding database.
69 DatabaseConnection::ParameterMap::iterator it = parameters.find(type);
70 if (it == parameters.end()) {
72 isc_throw(InvalidParameter, "Database configuration parameters do not "
73 "contain the 'type' keyword");
74 }
75
76 string db_type = it->second;
77 auto index = map_.find(db_type);
78
79 // No match?
80 if (index == map_.end()) {
81 if ((db_type == "mysql") || (db_type == "postgresql")) {
83 string libdhcp(db_type == "postgresql" ? "pgsql" : db_type);
84 isc_throw(InvalidType, "The Kea server has not been compiled with "
85 "support for lease database type: " << db_type
86 << ". Did you forget to use -D "
87 << db_type << "=enabled during setup or to load libdhcp_"
88 << libdhcp << " hook library?");
89 }
90 // Get here on no match
91 LOG_ERROR(dhcpsrv_logger, DHCPSRV_UNKNOWN_DB).arg(parameters[type]);
92 isc_throw(InvalidType, "Database access parameter 'type' does "
93 "not specify a supported database backend: " << parameters[type]);
94 }
95
96 // Call the factory.
97 getLeaseMgrPtr() = index->second.first(parameters);
98
99 // Check the factory did not return null.
100 if (!getLeaseMgrPtr()) {
101 isc_throw(Unexpected, "Lease database " << db_type <<
102 " factory returned null");
103 }
104}
105
106void
108 // Destroy current lease manager. This is a no-op if no lease manager
109 // is available.
110 if (getLeaseMgrPtr()) {
112 .arg(getLeaseMgrPtr()->getType());
113 getLeaseMgrPtr().reset();
114 }
115}
116
117void
118LeaseMgrFactory::recreate(const std::string& dbaccess, bool preserve_callbacks) {
120 // Preserve the callbacks if needed.
121 if (preserve_callbacks && haveInstance()) {
122 callbacks = instance().callbacks_;
123 }
124
125 // Re-create the manager.
126 destroy();
127 create(dbaccess);
128
129 // Init lease allocators. We do this here for allocators which require
130 // the lease manager access (i.e. SFLQ and FLQ) for initialization.
131 // When preserve_callbacks is true the current configuration is used,
132 // if it is false the staging configuration is used.
133 LeaseMgrFactory::initAllocators(!preserve_callbacks);
134
135 if (callbacks) {
136 // Copy the callbacks to the new instance. It should be fast
137 // because we merely copy the pointer.
138 instance().callbacks_ = callbacks;
139 }
140}
141
142bool
144 return (!!getLeaseMgrPtr());
145}
146
149 TrackingLeaseMgr* lmptr = getLeaseMgrPtr().get();
150 if (!lmptr) {
151 isc_throw(NoLeaseManager, "no current lease manager is available");
152 }
153 return (*lmptr);
154}
155
156bool
158 const Factory& factory,
159 bool no_log,
160 DBVersion db_version) {
161 if (map_.count(db_type)) {
162 return (false);
163 }
164
165 static auto default_db_version = []() -> std::string {
166 return (std::string());
167 };
168
169 if (!db_version) {
170 db_version = default_db_version;
171 }
172
173 map_.insert(pair<string, pair<Factory, DBVersion>>(db_type, pair<Factory, DBVersion>(factory, db_version)));
174
175 // We are dealing here with static logger initialization fiasco.
176 // registerFactory may be called from constructors of static global
177 // objects for built in backends. The logging is not initialized yet,
178 // so the LOG_DEBUG would throw.
179 if (!no_log) {
181 .arg(db_type);
182 }
183 return (true);
184}
185
186bool
187LeaseMgrFactory::deregisterFactory(const string& db_type, bool no_log) {
188 auto index = map_.find(db_type);
189 if (index != map_.end()) {
190 map_.erase(index);
191 if (!no_log) {
194 .arg(db_type);
195 }
196 return (true);
197 } else {
198 return (false);
199 }
200}
201
202bool
203LeaseMgrFactory::registeredFactory(const std::string& db_type) {
204 auto index = map_.find(db_type);
205 return (index != map_.end());
206}
207
208void
210 std::stringstream txt;
211
212 for (auto const& x : map_) {
213 if (!txt.str().empty()) {
214 txt << " ";
215 }
216 txt << x.first;
217 }
218
220 .arg(txt.str());
221}
222
223std::list<std::string>
225 std::list<std::string> result;
226 for (auto const& x : map_) {
227 auto version = x.second.second();
228 if (!version.empty()) {
229 result.push_back(version);
230 }
231 }
232
233 return (result);
234}
235
236} // namespace dhcp
237} // namespace isc
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.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition cfgmgr.cc:121
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition cfgmgr.cc:116
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 bool init_allocators_
Flag which indicates if allocators must be initialized.
std::function< TrackingLeaseMgrPtr(const db::DatabaseConnection::ParameterMap &)> Factory
Type of lease mgr factory.
static void destroy()
Destroy lease manager.
static bool registeredFactory(const std::string &db_type)
Check if a lease mgr factory was registered.
std::function< std::string()> DBVersion
Type of lease mgr version.
static void initAllocators(bool use_staging=false)
Initializes the lease allocators for all subnets.
static bool haveInstance()
Indicates if the lease manager has been instantiated.
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.
boost::shared_ptr< CallbackContainer > CallbackContainerPtr
Pointer to the callback container.
CallbackContainerPtr callbacks_
The multi-index container holding registered callbacks.
int version()
returns Kea hooks version.
#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.