Kea 2.6.0
base_config_backend_pool.h
Go to the documentation of this file.
1// Copyright (C) 2018-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#ifndef BASE_CONFIG_BACKEND_POOL_H
8#define BASE_CONFIG_BACKEND_POOL_H
9
10#include <cc/data.h>
16#include <functional>
17#include <list>
18#include <string>
19
20namespace isc {
21namespace cb {
22
23
43template<typename ConfigBackendType>
45public:
46
48 typedef boost::shared_ptr<ConfigBackendType> ConfigBackendTypePtr;
49
52
57 backends_.push_back(backend);
58 }
59
62 backends_.clear();
63 }
64
68 void delAllBackends(const std::string& db_type) {
69 typename std::list<ConfigBackendTypePtr>::iterator backend = backends_.begin();
70
71 while (backend != backends_.end()) {
72 if ((*backend)->getType() == db_type) {
73 backend = backends_.erase(backend);
74 } else {
75 ++backend;
76 }
77 }
78 }
79
89 bool del(const std::string& db_type, const std::string& dbaccess,
90 bool if_unusable) {
93 bool deleted = false;
94 if (if_unusable) {
95 deleted = true;
96 }
97
98 typename std::list<ConfigBackendTypePtr>::iterator backend = backends_.begin();
99
100 while (backend != backends_.end()) {
101 if ((*backend)->getType() != db_type || (*backend)->getParameters() != parameters) {
102 ++backend;
103 } else if (if_unusable && (!(*backend)->isUnusable())) {
104 deleted = false;
105 ++backend;
106 } else {
107 backends_.erase(backend);
108 return (true);
109 }
110 }
111 return (deleted);
112 }
113
114protected:
115
163 template<typename PropertyType, typename... FnPtrArgs, typename... Args>
164 void getPropertyPtrConst(PropertyType (ConfigBackendType::*MethodPointer)
165 (const db::ServerSelector&, FnPtrArgs...) const,
166 const db::BackendSelector& backend_selector,
167 const db::ServerSelector& server_selector,
168 PropertyType& property,
169 Args... input) const {
170
171 // If no particular backend is selected, call each backend and return
172 // the first non-null (non zero) value.
173 if (backend_selector.amUnspecified()) {
174 for (auto const& backend : backends_) {
175 property = ((*backend).*MethodPointer)(server_selector, input...);
176 if (property) {
177 break;
178 }
179 }
180
181 } else {
182 // Backend selected, find the one that matches selection.
183 auto backends = selectBackends(backend_selector);
184 if (!backends.empty()) {
185 for (auto const& backend : backends) {
186 property = ((*backend).*MethodPointer)(server_selector, input...);
187 if (property) {
188 break;
189 }
190 }
191
192 } else {
193 isc_throw(db::NoSuchDatabase, "no such database found for selector: "
194 << backend_selector.toText());
195 }
196 }
197 }
198
242 template<typename PropertyType, typename... FnPtrArgs, typename... Args>
243 void getBackendPropertyPtrConst(PropertyType (ConfigBackendType::*MethodPointer)
244 (FnPtrArgs...) const,
245 const db::BackendSelector& backend_selector,
246 PropertyType& property,
247 Args... input) const {
248 auto backends = selectBackends(backend_selector);
249 if (backends.empty()) {
250 isc_throw(db::NoSuchDatabase, "no such database found for selector: "
251 << backend_selector.toText());
252
253 } else if (backends.size() > 1) {
254 isc_throw(db::AmbiguousDatabase, "more than one database found for "
255 "selector: " << backend_selector.toText());
256 }
257
258 property = ((*(*(backends.begin())).*MethodPointer)(input...));
259 }
260
307 template<typename PropertyCollectionType, typename... FnPtrArgs, typename... Args>
308 void getMultiplePropertiesConst(PropertyCollectionType (ConfigBackendType::*MethodPointer)
309 (const db::ServerSelector&, FnPtrArgs...) const,
310 const db::BackendSelector& backend_selector,
311 const db::ServerSelector& server_selector,
312 PropertyCollectionType& properties,
313 Args... input) const {
314 if (backend_selector.amUnspecified()) {
315 for (auto const& backend : backends_) {
316 properties = ((*backend).*MethodPointer)(server_selector, input...);
317 if (!properties.empty()) {
318 break;
319 }
320 }
321
322 } else {
323 auto backends = selectBackends(backend_selector);
324 if (!backends.empty()) {
325 for (auto const& backend : backends) {
326 properties = ((*backend).*MethodPointer)(server_selector, input...);
327 if (!properties.empty()) {
328 break;
329 }
330 }
331
332 } else {
333 isc_throw(db::NoSuchDatabase, "no such database found for selector: "
334 << backend_selector.toText());
335 }
336 }
337 }
338
378 template<typename PropertyCollectionType>
379 void getAllPropertiesConst(PropertyCollectionType (ConfigBackendType::*MethodPointer)
380 (const db::ServerSelector&) const,
381 const db::BackendSelector& backend_selector,
382 const db::ServerSelector& server_selector,
383 PropertyCollectionType& properties) const {
384 if (backend_selector.amUnspecified()) {
385 for (auto const& backend : backends_) {
386 properties = ((*backend).*MethodPointer)(server_selector);
387 if (!properties.empty()) {
388 break;
389 }
390 }
391
392 } else {
393 auto backends = selectBackends(backend_selector);
394 if (!backends.empty()) {
395 for (auto const& backend : backends) {
396 properties = ((*backend).*MethodPointer)(server_selector);
397 if (!properties.empty()) {
398 break;
399 }
400 }
401
402 } else {
403 isc_throw(db::NoSuchDatabase, "no such database found for selector: "
404 << backend_selector.toText());
405 }
406 }
407 }
408
445 template<typename PropertyCollectionType>
446 void getAllBackendPropertiesConst(PropertyCollectionType (ConfigBackendType::*MethodPointer)() const,
447 const db::BackendSelector& backend_selector,
448 PropertyCollectionType& properties) const {
449 auto backends = selectBackends(backend_selector);
450 if (backends.empty()) {
451 isc_throw(db::NoSuchDatabase, "no such database found for selector: "
452 << backend_selector.toText());
453
454 } else if (backends.size() > 1) {
455 isc_throw(db::AmbiguousDatabase, "more than one database found for "
456 "selector: " << backend_selector.toText());
457 }
458
459 properties = (*(*(backends.begin())).*MethodPointer)();
460 }
461
508 template<typename ReturnValue, typename... FnPtrArgs, typename... Args>
509 ReturnValue createUpdateDeleteProperty(ReturnValue (ConfigBackendType::*MethodPointer)
510 (const db::ServerSelector&, FnPtrArgs...),
511 const db::BackendSelector& backend_selector,
512 const db::ServerSelector& server_selector,
513 Args... input) {
514 auto backends = selectBackends(backend_selector);
515 if (backends.empty()) {
516 isc_throw(db::NoSuchDatabase, "no such database found for selector: "
517 << backend_selector.toText());
518
519 } else if (backends.size() > 1) {
520 isc_throw(db::AmbiguousDatabase, "more than one database found for "
521 "selector: " << backend_selector.toText());
522 }
523
524 return ((*(*(backends.begin())).*MethodPointer)(server_selector, input...));
525 }
526
570 template<typename ReturnValue, typename... FnPtrArgs, typename... Args>
571 ReturnValue createUpdateDeleteBackendProperty(ReturnValue (ConfigBackendType::*MethodPointer)
572 (FnPtrArgs...),
573 const db::BackendSelector& backend_selector,
574 Args... input) {
575 auto backends = selectBackends(backend_selector);
576 if (backends.empty()) {
577 isc_throw(db::NoSuchDatabase, "no such database found for selector: "
578 << backend_selector.toText());
579
580 } else if (backends.size() > 1) {
581 isc_throw(db::AmbiguousDatabase, "more than one database found for "
582 "selector: " << backend_selector.toText());
583 }
584
585 return ((*(*(backends.begin())).*MethodPointer)(input...));
586 }
587
594 std::list<ConfigBackendTypePtr>
595 selectBackends(const db::BackendSelector& backend_selector) const {
596
597 std::list<ConfigBackendTypePtr> selected;
598
599 // In case there is only one backend and the caller hasn't specified
600 // any particular backend, simply return it.
601 if ((backends_.size() == 1) && backend_selector.amUnspecified()) {
602 selected.push_back(*backends_.begin());
603 return (selected);
604 }
605
606 // For other cases we return empty list.
607 if (backends_.empty() || backend_selector.amUnspecified()) {
608 return (selected);
609 }
610
611 // Go over all backends.
612 for (auto const& backend : backends_) {
613 // If backend type is specified and it is not matching,
614 // do not select this backend.
615 if ((backend_selector.getBackendType() != db::BackendSelector::Type::UNSPEC) &&
616 (backend_selector.getBackendType() !=
617 db::BackendSelector::stringToBackendType(backend->getType()))) {
618 continue;
619 }
620
621 // If the host has been specified by the backend's host is not
622 // matching, do not select this backend.
623 if ((!backend_selector.getBackendHost().empty()) &&
624 (backend_selector.getBackendHost() != backend->getHost())) {
625 continue;
626 }
627
628 // If the port has been specified by the backend's port is not
629 // matching, do not select this backend.
630 if ((backend_selector.getBackendPort() != 0) &&
631 (backend_selector.getBackendPort() != backend->getPort())) {
632 continue;
633 }
634
635 // Passed all checks, so the backend is matching. Add it to the list.
636 selected.push_back(backend);
637 }
638
639 return (selected);
640 }
641
643 std::list<ConfigBackendTypePtr> backends_;
644};
645
646} // end of namespace isc::cb
647} // end of namespace isc
648
649#endif // BASE_CONFIG_BACKEND_POOL_H
Base class for configuration backend pools.
void getPropertyPtrConst(PropertyType(ConfigBackendType::*MethodPointer)(const db::ServerSelector &, FnPtrArgs...) const, const db::BackendSelector &backend_selector, const db::ServerSelector &server_selector, PropertyType &property, Args... input) const
Retrieve a single configuration property from the pool.
boost::shared_ptr< ConfigBackendType > ConfigBackendTypePtr
Shared pointer to the Configuration Backend used.
void delAllBackends()
Deletes all backends from the pool.
void getBackendPropertyPtrConst(PropertyType(ConfigBackendType::*MethodPointer)(FnPtrArgs...) const, const db::BackendSelector &backend_selector, PropertyType &property, Args... input) const
Retrieve a single configuration property from the backend.
ReturnValue createUpdateDeleteProperty(ReturnValue(ConfigBackendType::*MethodPointer)(const db::ServerSelector &, FnPtrArgs...), const db::BackendSelector &backend_selector, const db::ServerSelector &server_selector, Args... input)
Add, update or delete property from the backend.
void delAllBackends(const std::string &db_type)
Deletes all backends of the given type from the pool.
void getMultiplePropertiesConst(PropertyCollectionType(ConfigBackendType::*MethodPointer)(const db::ServerSelector &, FnPtrArgs...) const, const db::BackendSelector &backend_selector, const db::ServerSelector &server_selector, PropertyCollectionType &properties, Args... input) const
Retrieve multiple configuration properties from the pool.
ReturnValue createUpdateDeleteBackendProperty(ReturnValue(ConfigBackendType::*MethodPointer)(FnPtrArgs...), const db::BackendSelector &backend_selector, Args... input)
Add, update or delete property from the backend.
void addBackend(ConfigBackendTypePtr backend)
Adds a backend to the pool.
std::list< ConfigBackendTypePtr > selectBackends(const db::BackendSelector &backend_selector) const
Selects existing backends matching the selector.
void getAllPropertiesConst(PropertyCollectionType(ConfigBackendType::*MethodPointer)(const db::ServerSelector &) const, const db::BackendSelector &backend_selector, const db::ServerSelector &server_selector, PropertyCollectionType &properties) const
Retrieve all configuration properties from the pool.
virtual ~BaseConfigBackendPool()
Virtual destructor.
void getAllBackendPropertiesConst(PropertyCollectionType(ConfigBackendType::*MethodPointer)() const, const db::BackendSelector &backend_selector, PropertyCollectionType &properties) const
Get all configuration properties from the backend.
std::list< ConfigBackendTypePtr > backends_
Holds configuration backends belonging to the pool.
bool del(const std::string &db_type, const std::string &dbaccess, bool if_unusable)
Deletes all backends of the given type from the pool.
Specification of the database backend to be used yields multiple results.
Definition: db_exceptions.h:82
Config Backend selector.
Type getBackendType() const
Returns backend type selected.
std::string toText() const
Returns selections as text.
static Type stringToBackendType(const std::string &type)
Converts string to backend type.
std::string getBackendHost() const
Returns host selected.
uint16_t getBackendPort() const
Returns port selected.
bool amUnspecified() const
Checks if selector is "unspecified".
static ParameterMap parse(const std::string &dbaccess)
Parse database access string.
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Error when specified database could not be found in the server configuration.
Definition: db_exceptions.h:74
Server selector for associating objects in a database with specific servers.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Defines the logger used by the top-level component of kea-lfc.