Kea 1.5.0
base_config_backend_pool.h
Go to the documentation of this file.
1// Copyright (C) 2018 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>
15#include <functional>
16#include <list>
17#include <string>
18
19namespace isc {
20namespace cb {
21
22
42template<typename ConfigBackendType>
44public:
45
47 typedef boost::shared_ptr<ConfigBackendType> ConfigBackendTypePtr;
48
51
56 backends_.push_back(backend);
57 }
58
61 backends_.clear();
62 }
63
67 void delAllBackends(const std::string& db_type) {
68 typename std::list<ConfigBackendTypePtr>::iterator backend = backends_.begin();
69
70 while (backend != backends_.end()) {
71 if ((*backend)->getType() == db_type) {
72 backend = backends_.erase(backend);
73 } else {
74 ++backend;
75 }
76 }
77 }
78
79protected:
80
128 template<typename PropertyType, typename... FnPtrArgs, typename... Args>
129 void getPropertyPtrConst(PropertyType (ConfigBackendType::*MethodPointer)
130 (const db::ServerSelector&, FnPtrArgs...) const,
131 const db::BackendSelector& backend_selector,
132 const db::ServerSelector& server_selector,
133 PropertyType& property,
134 Args... input) const {
135
136 // If no particular backend is selected, call each backend and return
137 // the first non-null (non zero) value.
138 if (backend_selector.amUnspecified()) {
139 for (auto backend : backends_) {
140 property = ((*backend).*MethodPointer)(server_selector, input...);
141 if (property) {
142 break;
143 }
144 }
145
146 } else {
147 // Backend selected, find the one that matches selection.
148 auto backends = selectBackends(backend_selector);
149 if (!backends.empty()) {
150 for (auto backend : backends) {
151 property = ((*backend).*MethodPointer)(server_selector, input...);
152 if (property) {
153 break;
154 }
155 }
156
157 } else {
158 isc_throw(db::NoSuchDatabase, "no such database found for selector: "
159 << backend_selector.toText());
160 }
161 }
162 }
163
210 template<typename PropertyCollectionType, typename... FnPtrArgs, typename... Args>
211 void getMultiplePropertiesConst(PropertyCollectionType (ConfigBackendType::*MethodPointer)
212 (const db::ServerSelector&, FnPtrArgs...) const,
213 const db::BackendSelector& backend_selector,
214 const db::ServerSelector& server_selector,
215 PropertyCollectionType& properties,
216 Args... input) const {
217 if (backend_selector.amUnspecified()) {
218 for (auto backend : backends_) {
219 properties = ((*backend).*MethodPointer)(server_selector, input...);
220 if (!properties.empty()) {
221 break;
222 }
223 }
224
225 } else {
226 auto backends = selectBackends(backend_selector);
227 if (!backends.empty()) {
228 for (auto backend : backends) {
229 properties = ((*backend).*MethodPointer)(server_selector, input...);
230 if (!properties.empty()) {
231 break;
232 }
233 }
234
235 } else {
236 isc_throw(db::NoSuchDatabase, "no database found for selector: "
237 << backend_selector.toText());
238 }
239 }
240 }
241
281 template<typename PropertyCollectionType>
282 void getAllPropertiesConst(PropertyCollectionType (ConfigBackendType::*MethodPointer)
283 (const db::ServerSelector&) const,
284 const db::BackendSelector& backend_selector,
285 const db::ServerSelector& server_selector,
286 PropertyCollectionType& properties) const {
287 if (backend_selector.amUnspecified()) {
288 for (auto backend : backends_) {
289 properties = ((*backend).*MethodPointer)(server_selector);
290 if (!properties.empty()) {
291 break;
292 }
293 }
294
295 } else {
296 auto backends = selectBackends(backend_selector);
297 if (!backends.empty()) {
298 for (auto backend : backends) {
299 properties = ((*backend).*MethodPointer)(server_selector);
300 if (!properties.empty()) {
301 break;
302 }
303 }
304
305 } else {
306 isc_throw(db::NoSuchDatabase, "no database found for selector: "
307 << backend_selector.toText());
308 }
309 }
310 }
311
312
359 template<typename ReturnValue, typename... FnPtrArgs, typename... Args>
360 ReturnValue createUpdateDeleteProperty(ReturnValue (ConfigBackendType::*MethodPointer)
361 (const db::ServerSelector&, FnPtrArgs...),
362 const db::BackendSelector& backend_selector,
363 const db::ServerSelector& server_selector,
364 Args... input) {
365 auto backends = selectBackends(backend_selector);
366 if (backends.empty()) {
367 isc_throw(db::NoSuchDatabase, "no database found for selector: "
368 << backend_selector.toText());
369
370 } else if (backends.size() > 1) {
371 isc_throw(db::AmbiguousDatabase, "more than 1 database found for "
372 "selector: " << backend_selector.toText());
373 }
374
375 return ((*(*(backends.begin())).*MethodPointer)(server_selector, input...));
376 }
377
384 std::list<ConfigBackendTypePtr>
385 selectBackends(const db::BackendSelector& backend_selector) const {
386
387 std::list<ConfigBackendTypePtr> selected;
388
389 // In case there is only one backend and the caller hasn't specified
390 // any particular backend, simply return it.
391 if ((backends_.size() == 1) && backend_selector.amUnspecified()) {
392 selected.push_back(*backends_.begin());
393 return (selected);
394 }
395
396 // For other cases we return empty list.
397 if (backends_.empty() || backend_selector.amUnspecified()) {
398 return (selected);
399 }
400
401 // Go over all backends.
402 for (auto backend : backends_) {
403 // If backend type is specified and it is not matching,
404 // do not select this backend.
405 if ((backend_selector.getBackendType() != db::BackendSelector::Type::UNSPEC) &&
406 (backend_selector.getBackendType() !=
407 db::BackendSelector::stringToBackendType(backend->getType()))) {
408 continue;
409 }
410
411 // If the host has been specified by the backend's host is not
412 // matching, do not select this backend.
413 if ((!backend_selector.getBackendHost().empty()) &&
414 (backend_selector.getBackendHost() != backend->getHost())) {
415 continue;
416 }
417
418 // If the port has been specified by the backend's port is not
419 // matching, do not select this backend.
420 if ((backend_selector.getBackendPort() != 0) &&
421 (backend_selector.getBackendPort() != backend->getPort())) {
422 continue;
423 }
424
425 // Passed all checks, so the backend is matching. Add it to the list.
426 selected.push_back(backend);
427 }
428
429 return (selected);
430 }
431
433 std::list<ConfigBackendTypePtr> backends_;
434};
435
436} // end of namespace isc::cb
437} // end of namespace isc
438
439#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.
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.
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.
std::list< ConfigBackendTypePtr > backends_
Holds configuration backends belonging to the pool.
Specification of the database backend to be used yields multiple results.
Definition: db_exceptions.h:87
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".
Error when specified database could not be found in the server configuration.
Definition: db_exceptions.h:79
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-dhcp-ddns.