Kea  2.1.7-git
cb_ctl_base.h
Go to the documentation of this file.
1 // Copyright (C) 2019-2020 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 CB_CTL_BASE_H
8 #define CB_CTL_BASE_H
9 
10 #include <database/audit_entry.h>
13 #include <process/config_base.h>
15 #include <boost/date_time/posix_time/posix_time.hpp>
16 #include <boost/date_time/gregorian/gregorian.hpp>
17 #include <process/d_log.h>
18 
19 namespace isc {
20 namespace process {
21 
22 
79 template<typename ConfigBackendMgrType>
81 public:
82 
88  enum class FetchMode {
89  FETCH_ALL,
91  };
92 
100  }
101 
105  virtual ~CBControlBase() {
107  }
108 
113  void reset() {
117  }
118 
131  bool databaseConfigConnect(const ConfigPtr& srv_cfg) {
132  // We need to get rid of any existing backends. These would be any
133  // opened by previous configuration cycle.
135 
136  // Fetch the config-control info.
137  ConstConfigControlInfoPtr config_ctl = srv_cfg->getConfigControlInfo();
138  if (!config_ctl || config_ctl->getConfigDatabases().empty()) {
139  // No config dbs, nothing to do.
140  return (false);
141  }
142 
143  // Iterate over the configured DBs and instantiate them.
144  for (auto db : config_ctl->getConfigDatabases()) {
146  .arg(db.redactedAccessString());
147  getMgr().addBackend(db.getAccessString());
148  }
149 
150  // Let the caller know we have opened DBs.
151  return (true);
152  }
153 
156  getMgr().delAllBackends();
157  }
158 
173  virtual void databaseConfigFetch(const ConfigPtr& srv_cfg,
174  const FetchMode& fetch_mode = FetchMode::FETCH_ALL) {
175  // If the server starts up we need to connect to the database(s).
176  // If there are no databases available simply do nothing.
177  if ((fetch_mode == FetchMode::FETCH_ALL) && !databaseConfigConnect(srv_cfg)) {
178  // There are no CB databases so we're done
179  return;
180  }
181 
183 
184  // For now we find data based on first backend that has it.
186 
187  // Use the server_tag if set, otherwise use ALL.
188  std::string server_tag = srv_cfg->getServerTag();
189  db::ServerSelector server_selector =
190  (server_tag.empty()? db::ServerSelector::ALL() : db::ServerSelector::ONE(server_tag));
191 
192  // This collection will hold the audit entries since the last update if
193  // we're running this method to fetch the configuration updates.
194  db::AuditEntryCollection audit_entries;
195 
196  // If we're fetching updates we need to retrieve audit entries to see
197  // which objects have to be updated. If we're performing full reconfiguration
198  // we also need audit entries to set the last_audit_revision_time_ to the
199  // time of the most recent audit entry.
200 
203 
204  // Save the timestamp indicating last audit revision time.
205  auto lb_modification_time = last_audit_revision_time_;
206  // Save the identifier indicating last audit revision id.
207  auto lb_modification_id = last_audit_revision_id_;
208 
209  audit_entries = getMgr().getPool()->getRecentAuditEntries(backend_selector,
210  server_selector,
211  lb_modification_time,
212  lb_modification_id);
213  // Store the last audit revision time. It should be set to the most recent
214  // audit entry fetched. If returned audit is empty we don't update.
215  updateLastAuditRevisionTimeId(audit_entries);
216 
217  // If this is full reconfiguration we don't need the audit entries anymore.
218  // Let's remove them and proceed as if they don't exist.
219  if (fetch_mode == FetchMode::FETCH_ALL) {
220  audit_entries.clear();
221  }
222 
223  // If we fetch the entire config or we're updating the config and there are
224  // audit entries indicating that there are some pending updates, let's
225  // execute the server specific function that fetches and merges the data
226  // into the given configuration.
227  if ((fetch_mode == FetchMode::FETCH_ALL) || !audit_entries.empty()) {
228  try {
229  databaseConfigApply(backend_selector, server_selector,
230  lb_modification_time, audit_entries);
231  } catch (...) {
232  // Revert last audit revision time and id so as we can retry
233  // from the last successful attempt.
236  last_audit_revision_time_ = lb_modification_time;
237  last_audit_revision_id_ = lb_modification_id;
238  throw;
239  }
240  }
241  }
242 
243 protected:
244 
263  const std::string& object_type) const {
265  const auto& index = audit_entries.get<db::AuditEntryObjectTypeTag>();
266  auto range = index.equal_range(object_type);
267  for (auto it = range.first; it != range.second; ++it) {
268  if ((*it)->getModificationType() != db::AuditEntry::ModificationType::DELETE) {
269  result.insert(*it);
270  }
271  }
272 
273  return (result);
274  }
275 
303  virtual void databaseConfigApply(const db::BackendSelector& backend_selector,
304  const db::ServerSelector& server_selector,
305  const boost::posix_time::ptime& lb_modification_time,
306  const db::AuditEntryCollection& audit_entries) = 0;
307 
312  ConfigBackendMgrType& getMgr() const {
313  return (ConfigBackendMgrType::instance());
314  }
315 
320  static boost::posix_time::ptime getInitialAuditRevisionTime() {
321  static boost::posix_time::ptime
322  initial_time(boost::gregorian::date(2000, boost::gregorian::Jan, 1));
323  return (initial_time);
324  }
325 
334  // Do nothing if there are no audit entries. It is the case if
335  // there were no updates to the configuration.
336  if (audit_entries.empty()) {
337  return;
338  }
339 
340  // Get the audit entries sorted by modification time and id,
341  // and pick the latest entry.
342  const auto& index = audit_entries.get<db::AuditEntryModificationTimeIdTag>();
343  last_audit_revision_time_ = (*index.rbegin())->getModificationTime();
344  last_audit_revision_id_ = (*index.rbegin())->getRevisionId();
345  }
346 
348  boost::posix_time::ptime last_audit_revision_time_;
349 
357 };
358 
363 inline bool
365  const uint64_t& object_id) {
366  const auto& object_id_idx = audit_entries.get<db::AuditEntryObjectIdTag>();
367  return (object_id_idx.count(object_id) > 0);
368 }
369 
370 } // end of namespace isc::process
371 } // end of namespace isc
372 
373 #endif /* CB_CTL_BASE_H */
CBControlBase()
Constructor.
Definition: cb_ctl_base.h:97
void updateLastAuditRevisionTimeId(const db::AuditEntryCollection &audit_entries)
Updates timestamp of the most recent audit entry fetched from the database.
Definition: cb_ctl_base.h:333
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
bool hasObjectId(const db::AuditEntryCollection &audit_entries, const uint64_t &object_id)
Checks if an object is in a collection od audit entries.
Definition: cb_ctl_base.h:364
Base class for implementing server specific mechanisms to control the use of the Configuration Backen...
Definition: cb_ctl_base.h:80
FetchMode
Fetch mode used in invocations to databaseConfigFetch.
Definition: cb_ctl_base.h:88
isc::log::Logger dctl_logger("dctl")
Defines the logger used within libkea-process library.
Definition: d_log.h:18
static ServerSelector ONE(const std::string &server_tag)
Factory returning selector of one server.
Tag used to access index by modification time.
Definition: audit_entry.h:232
Tag used to access index by object id.
Definition: audit_entry.h:235
virtual void databaseConfigApply(const db::BackendSelector &backend_selector, const db::ServerSelector &server_selector, const boost::posix_time::ptime &lb_modification_time, const db::AuditEntryCollection &audit_entries)=0
Server specific method to fetch and apply back end configuration into the local configuration.
const isc::log::MessageID DCTL_CONFIG_FETCH
Server selector for associating objects in a database with specific servers.
void databaseConfigDisconnect()
Disconnects from the configuration backends.
Definition: cb_ctl_base.h:155
db::AuditEntryCollection fetchConfigElement(const db::AuditEntryCollection &audit_entries, const std::string &object_type) const
Returns audit entries for new or updated configuration elements of specific type to be fetched from t...
Definition: cb_ctl_base.h:262
ConfigBackendMgrType & getMgr() const
Returns the instance of the Config Backend Manager used by this object.
Definition: cb_ctl_base.h:312
Defines the logger used by the top-level component of kea-lfc.
const isc::log::MessageID DCTL_OPEN_CONFIG_DB
bool databaseConfigConnect(const ConfigPtr &srv_cfg)
(Re)connects to the specified configuration backends.
Definition: cb_ctl_base.h:131
Config Backend selector.
static ServerSelector ALL()
Factory returning "all servers" selector.
uint64_t last_audit_revision_id_
Stores the most recent audit revision identifier.
Definition: cb_ctl_base.h:356
void reset()
Resets the state of this object.
Definition: cb_ctl_base.h:113
virtual void databaseConfigFetch(const ConfigPtr &srv_cfg, const FetchMode &fetch_mode=FetchMode::FETCH_ALL)
Fetches the entire or partial configuration from the database.
Definition: cb_ctl_base.h:173
virtual ~CBControlBase()
Virtual destructor.
Definition: cb_ctl_base.h:105
boost::multi_index_container< AuditEntryPtr, boost::multi_index::indexed_by< boost::multi_index::ordered_non_unique< boost::multi_index::tag< AuditEntryObjectTypeTag >, boost::multi_index::composite_key< AuditEntry, boost::multi_index::const_mem_fun< AuditEntry, std::string, &AuditEntry::getObjectType >, boost::multi_index::const_mem_fun< AuditEntry, AuditEntry::ModificationType, &AuditEntry::getModificationType > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< AuditEntryModificationTimeIdTag >, boost::multi_index::composite_key< AuditEntry, boost::multi_index::const_mem_fun< AuditEntry, boost::posix_time::ptime, &AuditEntry::getModificationTime >, boost::multi_index::const_mem_fun< AuditEntry, uint64_t, &AuditEntry::getRevisionId > > >, boost::multi_index::hashed_non_unique< boost::multi_index::tag< AuditEntryObjectIdTag >, boost::multi_index::const_mem_fun< AuditEntry, uint64_t, &AuditEntry::getObjectId > > >> AuditEntryCollection
Multi index container holding AuditEntry instances.
Definition: audit_entry.h:291
Tag used to access index by object type.
Definition: audit_entry.h:229
boost::posix_time::ptime last_audit_revision_time_
Stores the most recent audit revision timestamp.
Definition: cb_ctl_base.h:348
static boost::posix_time::ptime getInitialAuditRevisionTime()
Convenience method returning initial timestamp to set the last_audit_revision_time_ to...
Definition: cb_ctl_base.h:320
boost::shared_ptr< ConfigBase > ConfigPtr
Non-const pointer to the ConfigBase.
Definition: config_base.h:176
boost::shared_ptr< const ConfigControlInfo > ConstConfigControlInfoPtr
Defines a pointer to a const ConfigControlInfo.