Kea 2.7.6
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.
boost::shared_ptr< ConfigBackendType > ConfigBackendTypePtr
Shared pointer to the Configuration Backend used.
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.
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.
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".
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
static ParameterMap parse(const std::string &dbaccess)
Parse database access string.
Error when specified database could not be found in the server configuration.
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.