Kea  2.1.7-git
base_config_backend_pool.h
Go to the documentation of this file.
1 // Copyright (C) 2018-2021 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>
14 #include <database/db_exceptions.h>
16 #include <functional>
17 #include <list>
18 #include <string>
19 
20 namespace isc {
21 namespace cb {
22 
23 
43 template<typename ConfigBackendType>
45 public:
46 
48  typedef boost::shared_ptr<ConfigBackendType> ConfigBackendTypePtr;
49 
51  virtual ~BaseConfigBackendPool() { }
52 
56  void addBackend(ConfigBackendTypePtr backend) {
57  backends_.push_back(backend);
58  }
59 
61  void delAllBackends() {
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 
114 protected:
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 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 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 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 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 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 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 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
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.
uint16_t getBackendPort() const
Returns port selected.
std::string toText() const
Returns selections as text.
bool del(const std::string &db_type, const std::string &dbaccess, bool if_unusable)
Deletes all backends of the given type from the pool.
static Type stringToBackendType(const std::string &type)
Converts string to backend type.
static ParameterMap parse(const std::string &dbaccess)
Parse database access string.
void delAllBackends()
Deletes all backends from the pool.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
void getAllBackendPropertiesConst(PropertyCollectionType(ConfigBackendType::*MethodPointer)() const, const db::BackendSelector &backend_selector, PropertyCollectionType &properties) const
Get all configuration properties from the backend.
std::string getBackendHost() const
Returns host selected.
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.
Server selector for associating objects in a database with specific servers.
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.
Base class for configuration backend pools.
void addBackend(ConfigBackendTypePtr backend)
Adds a backend to the pool.
std::list< ConfigBackendTypePtr > backends_
Holds configuration backends belonging to the pool.
Defines the logger used by the top-level component of kea-lfc.
std::list< ConfigBackendTypePtr > selectBackends(const db::BackendSelector &backend_selector) const
Selects existing backends matching the selector.
Config Backend selector.
virtual ~BaseConfigBackendPool()
Virtual destructor.
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(const std::string &db_type)
Deletes all backends of the given type 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.
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
Type getBackendType() const
Returns backend type selected.
bool amUnspecified() const
Checks if selector is "unspecified".
boost::shared_ptr< ConfigBackendType > ConfigBackendTypePtr
Shared pointer to the Configuration Backend used.
Specification of the database backend to be used yields multiple results.
Definition: db_exceptions.h:82