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>
13 #include <database/db_exceptions.h>
15 #include <functional>
16 #include <list>
17 #include <string>
18 
19 namespace isc {
20 namespace cb {
21 
22 
42 template<typename ConfigBackendType>
44 public:
45 
47  typedef boost::shared_ptr<ConfigBackendType> ConfigBackendTypePtr;
48 
50  virtual ~BaseConfigBackendPool() { }
51 
56  backends_.push_back(backend);
57  }
58 
60  void delAllBackends() {
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 
79 protected:
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
isc::db::BackendSelector::getBackendHost
std::string getBackendHost() const
Returns host selected.
Definition: backend_selector.h:156
isc::db::NoSuchDatabase
Error when specified database could not be found in the server configuration.
Definition: db_exceptions.h:79
isc::cb::BaseConfigBackendPool::getMultiplePropertiesConst
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.
Definition: base_config_backend_pool.h:211
base_config_backend.h
db_exceptions.h
isc::db::BackendSelector
Config Backend selector.
Definition: backend_selector.h:54
isc::cb::BaseConfigBackendPool
Base class for configuration backend pools.
Definition: base_config_backend_pool.h:43
server_selector.h
isc::cb::BaseConfigBackendPool::getPropertyPtrConst
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.
Definition: base_config_backend_pool.h:129
isc
Defines the logger used by the top-level component of kea-dhcp-ddns.
Definition: agent_parser.cc:144
isc::db::AmbiguousDatabase
Specification of the database backend to be used yields multiple results.
Definition: db_exceptions.h:87
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:192
isc::db::BackendSelector::getBackendType
Type getBackendType() const
Returns backend type selected.
Definition: backend_selector.h:148
isc::cb::BaseConfigBackendPool::delAllBackends
void delAllBackends(const std::string &db_type)
Deletes all backends of the given type from the pool.
Definition: base_config_backend_pool.h:67
isc::cb::BaseConfigBackendPool::ConfigBackendTypePtr
boost::shared_ptr< ConfigBackendType > ConfigBackendTypePtr
Shared pointer to the Configuration Backend used.
Definition: base_config_backend_pool.h:47
isc::db::BackendSelector::Type::UNSPEC
@ UNSPEC
isc::db::ServerSelector
Server selector for associating objects in a database with specific servers.
Definition: server_selector.h:45
isc::cb::BaseConfigBackendPool::getAllPropertiesConst
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.
Definition: base_config_backend_pool.h:282
isc::db::BackendSelector::toText
std::string toText() const
Returns selections as text.
Definition: backend_selector.cc:85
isc::db::BackendSelector::getBackendPort
uint16_t getBackendPort() const
Returns port selected.
Definition: backend_selector.h:164
isc::db::BackendSelector::amUnspecified
bool amUnspecified() const
Checks if selector is "unspecified".
Definition: backend_selector.cc:78
isc::cb::BaseConfigBackendPool::createUpdateDeleteProperty
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.
Definition: base_config_backend_pool.h:360
isc::db::BackendSelector::stringToBackendType
static Type stringToBackendType(const std::string &type)
Converts string to backend type.
Definition: backend_selector.cc:113
backend_selector.h
isc::cb::BaseConfigBackendPool::delAllBackends
void delAllBackends()
Deletes all backends from the pool.
Definition: base_config_backend_pool.h:60
data.h
isc::cb::BaseConfigBackendPool::addBackend
void addBackend(ConfigBackendTypePtr backend)
Adds a backend to the pool.
Definition: base_config_backend_pool.h:55
isc::cb::BaseConfigBackendPool::backends_
std::list< ConfigBackendTypePtr > backends_
Holds configuration backends belonging to the pool.
Definition: base_config_backend_pool.h:433
isc::cb::BaseConfigBackendPool::~BaseConfigBackendPool
virtual ~BaseConfigBackendPool()
Virtual destructor.
Definition: base_config_backend_pool.h:50
isc::cb::BaseConfigBackendPool::selectBackends
std::list< ConfigBackendTypePtr > selectBackends(const db::BackendSelector &backend_selector) const
Selects existing backends matching the selector.
Definition: base_config_backend_pool.h:385