| Kea 3.0.2-git

cb_ctl_base.h
Go to the documentation of this file.
1// Copyright (C) 2019-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 CB_CTL_BASE_H
8#define CB_CTL_BASE_H
9
10#include <database/audit_entry.h>
11#include <database/backend_selector.h>
12#include <database/database_connection.h>
13#include <database/server_selector.h>
14#include <process/config_base.h>
15#include <process/config_ctl_info.h>
16#include <boost/foreach.hpp>
17#include <boost/date_time/posix_time/posix_time.hpp>
18#include <boost/date_time/gregorian/gregorian.hpp>
19#include <process/d_log.h>
20
21 namespace isc {
22 namespace process {
23
24
81 template<typename ConfigBackendMgrType>
82 class CBControlBase {
83 public:
84
90 enum class FetchMode {
91 FETCH_ALL,
92 FETCH_UPDATE
93 };
94
99 CBControlBase()
100 : last_audit_revision_time_(getInitialAuditRevisionTime()),
101 last_audit_revision_id_(0) {
102 }
103
107 virtual ~CBControlBase() {
108 databaseConfigDisconnect();
109 }
110
115 void reset() {
116 databaseConfigDisconnect();
117 last_audit_revision_time_ = getInitialAuditRevisionTime();
118 last_audit_revision_id_ = 0;
119 }
120
133 bool databaseConfigConnect(const ConfigPtr& srv_cfg) {
134 // We need to get rid of any existing backends. These would be any
135 // opened by previous configuration cycle.
136 databaseConfigDisconnect();
137
138 // Fetch the config-control info.
139 ConstConfigControlInfoPtr config_ctl = srv_cfg->getConfigControlInfo();
140 if (!config_ctl || config_ctl->getConfigDatabases().empty()) {
141 // No config dbs, nothing to do.
142 return (false);
143 }
144
145 // Iterate over the configured DBs and instantiate them.
146 for (auto const& db : config_ctl->getConfigDatabases()) {
147 const std::string& redacted = db.redactedAccessString();
148 LOG_INFO(dctl_logger, DCTL_OPEN_CONFIG_DB)
149 .arg(redacted);
150 try {
151 getMgr().addBackend(db.getAccessString());
152 } catch (const isc::db::DbOpenErrorWithRetry& err) {
153 LOG_INFO(dctl_logger, DCTL_DB_OPEN_CONNECTION_WITH_RETRY_FAILED)
154 .arg(redacted).arg(err.what());
155 }
156 }
157
158 // Let the caller know we have opened DBs.
159 return (true);
160 }
161
163 void databaseConfigDisconnect() {
164 getMgr().delAllBackends();
165 }
166
181 virtual void databaseConfigFetch(const ConfigPtr& srv_cfg,
182 const FetchMode& fetch_mode = FetchMode::FETCH_ALL) {
183 // If the server starts up we need to connect to the database(s).
184 // If there are no databases available simply do nothing.
185 if ((fetch_mode == FetchMode::FETCH_ALL) && !databaseConfigConnect(srv_cfg)) {
186 // There are no CB databases so we're done
187 return;
188 }
189
190 LOG_INFO(dctl_logger, DCTL_CONFIG_FETCH);
191
192 // For now we find data based on first backend that has it.
193 db::BackendSelector backend_selector(db::BackendSelector::Type::UNSPEC);
194
195 // Use the server_tag if set, otherwise use ALL.
196 std::string server_tag = srv_cfg->getServerTag();
197 db::ServerSelector server_selector =
198 (server_tag.empty()? db::ServerSelector::ALL() : db::ServerSelector::ONE(server_tag));
199
200 // This collection will hold the audit entries since the last update if
201 // we're running this method to fetch the configuration updates.
202 db::AuditEntryCollection audit_entries;
203
204 // If we're fetching updates we need to retrieve audit entries to see
205 // which objects have to be updated. If we're performing full reconfiguration
206 // we also need audit entries to set the last_audit_revision_time_ to the
207 // time of the most recent audit entry.
208
211
212 // Save the timestamp indicating last audit revision time.
213 auto lb_modification_time = last_audit_revision_time_;
214 // Save the identifier indicating last audit revision id.
215 auto lb_modification_id = last_audit_revision_id_;
216
217 audit_entries = getMgr().getPool()->getRecentAuditEntries(backend_selector,
218 server_selector,
219 lb_modification_time,
220 lb_modification_id);
221 // Store the last audit revision time. It should be set to the most recent
222 // audit entry fetched. If returned audit is empty we don't update.
223 updateLastAuditRevisionTimeId(audit_entries);
224
225 // If this is full reconfiguration we don't need the audit entries anymore.
226 // Let's remove them and proceed as if they don't exist.
227 if (fetch_mode == FetchMode::FETCH_ALL) {
228 audit_entries.clear();
229 }
230
231 // If we fetch the entire config or we're updating the config and there are
232 // audit entries indicating that there are some pending updates, let's
233 // execute the server specific function that fetches and merges the data
234 // into the given configuration.
235 if ((fetch_mode == FetchMode::FETCH_ALL) || !audit_entries.empty()) {
236 try {
237 databaseConfigApply(backend_selector, server_selector,
238 lb_modification_time, audit_entries);
239 } catch (...) {
240 // Revert last audit revision time and id so as we can retry
241 // from the last successful attempt.
244 last_audit_revision_time_ = lb_modification_time;
245 last_audit_revision_id_ = lb_modification_id;
246 throw;
247 }
248 }
249 }
250
251 protected:
252
269 db::AuditEntryCollection
270 fetchConfigElement(const db::AuditEntryCollection& audit_entries,
271 const std::string& object_type) const {
272 db::AuditEntryCollection result;
273 auto const& index = audit_entries.get<db::AuditEntryObjectTypeTag>();
274 auto range = index.equal_range(object_type);
275 BOOST_FOREACH(auto const& it, range) {
276 if (it->getModificationType() != db::AuditEntry::ModificationType::DELETE) {
277 result.insert(it);
278 }
279 }
280
281 return (result);
282 }
283
311 virtual void databaseConfigApply(const db::BackendSelector& backend_selector,
312 const db::ServerSelector& server_selector,
313 const boost::posix_time::ptime& lb_modification_time,
314 const db::AuditEntryCollection& audit_entries) = 0;
315
320 ConfigBackendMgrType& getMgr() const {
321 return (ConfigBackendMgrType::instance());
322 }
323
328 static boost::posix_time::ptime getInitialAuditRevisionTime() {
329 static boost::posix_time::ptime
330 initial_time(boost::gregorian::date(2000, boost::gregorian::Jan, 1));
331 return (initial_time);
332 }
333
341 void updateLastAuditRevisionTimeId(const db::AuditEntryCollection& audit_entries) {
342 // Do nothing if there are no audit entries. It is the case if
343 // there were no updates to the configuration.
344 if (audit_entries.empty()) {
345 return;
346 }
347
348 // Get the audit entries sorted by modification time and id,
349 // and pick the latest entry.
350 auto const& index = audit_entries.get<db::AuditEntryModificationTimeIdTag>();
351 last_audit_revision_time_ = (*index.rbegin())->getModificationTime();
352 last_audit_revision_id_ = (*index.rbegin())->getRevisionId();
353 }
354
356 boost::posix_time::ptime last_audit_revision_time_;
357
364 uint64_t last_audit_revision_id_;
365};
366
371 inline bool
372 hasObjectId(const db::AuditEntryCollection& audit_entries,
373 const uint64_t& object_id) {
374 auto const& object_id_idx = audit_entries.get<db::AuditEntryObjectIdTag>();
375 return (object_id_idx.count(object_id) > 0);
376}
377
378} // end of namespace isc::process
379} // end of namespace isc
380
381#endif /* CB_CTL_BASE_H */
audit_entry.h
backend_selector.h
isc::Exception::what
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
Definition exceptions/exceptions.cc:32
isc::db::AuditEntry::ModificationType::DELETE
@ DELETE
Definition audit_entry.h:76
isc::db::BackendSelector
Config Backend selector.
Definition backend_selector.h:55
isc::db::BackendSelector::Type::UNSPEC
@ UNSPEC
Definition backend_selector.h:65
isc::db::DbOpenErrorWithRetry
Exception thrown on failure to open database but permit retries.
Definition database_connection.h:38
isc::db::ServerSelector
Server selector for associating objects in a database with specific servers.
Definition server_selector.h:46
isc::db::ServerSelector::ALL
static ServerSelector ALL()
Factory returning "all servers" selector.
Definition server_selector.h:64
isc::db::ServerSelector::ONE
static ServerSelector ONE(const std::string &server_tag)
Factory returning selector of one server.
Definition server_selector.h:72
isc::process::CBControlBase::FetchMode
FetchMode
Fetch mode used in invocations to databaseConfigFetch.
Definition cb_ctl_base.h:90
isc::process::CBControlBase::FetchMode::FETCH_ALL
@ FETCH_ALL
Definition cb_ctl_base.h:91
isc::process::CBControlBase::FetchMode::FETCH_UPDATE
@ FETCH_UPDATE
Definition cb_ctl_base.h:92
isc::process::CBControlBase::fetchConfigElement
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:270
isc::process::CBControlBase::databaseConfigConnect
bool databaseConfigConnect(const ConfigPtr &srv_cfg)
(Re)connects to the specified configuration backends.
Definition cb_ctl_base.h:133
isc::process::CBControlBase::last_audit_revision_id_
uint64_t last_audit_revision_id_
Stores the most recent audit revision identifier.
Definition cb_ctl_base.h:364
isc::process::CBControlBase::databaseConfigApply
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.
isc::process::CBControlBase::databaseConfigFetch
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:181
isc::process::CBControlBase::CBControlBase
CBControlBase()
Constructor.
Definition cb_ctl_base.h:99
isc::process::CBControlBase::~CBControlBase
virtual ~CBControlBase()
Virtual destructor.
Definition cb_ctl_base.h:107
isc::process::CBControlBase::last_audit_revision_time_
boost::posix_time::ptime last_audit_revision_time_
Stores the most recent audit revision timestamp.
Definition cb_ctl_base.h:356
isc::process::CBControlBase::reset
void reset()
Resets the state of this object.
Definition cb_ctl_base.h:115
isc::process::CBControlBase::databaseConfigDisconnect
void databaseConfigDisconnect()
Disconnects from the configuration backends.
Definition cb_ctl_base.h:163
isc::process::CBControlBase::updateLastAuditRevisionTimeId
void updateLastAuditRevisionTimeId(const db::AuditEntryCollection &audit_entries)
Updates timestamp of the most recent audit entry fetched from the database.
Definition cb_ctl_base.h:341
isc::process::CBControlBase::getInitialAuditRevisionTime
static boost::posix_time::ptime getInitialAuditRevisionTime()
Convenience method returning initial timestamp to set the last_audit_revision_time_ to.
Definition cb_ctl_base.h:328
isc::process::CBControlBase::getMgr
ConfigBackendMgrType & getMgr() const
Returns the instance of the Config Backend Manager used by this object.
Definition cb_ctl_base.h:320
config_base.h
config_ctl_info.h
d_log.h
database_connection.h
LOG_INFO
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition macros.h:20
isc::db
Definition audit_entry.cc:14
isc::db::AuditEntryCollection
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
isc::process
Definition cb_ctl_base.h:22
isc::process::dctl_logger
isc::log::Logger dctl_logger("dctl")
Defines the logger used within libkea-process library.
Definition d_log.h:18
isc::process::hasObjectId
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:372
isc::process::ConfigPtr
boost::shared_ptr< ConfigBase > ConfigPtr
Non-const pointer to the ConfigBase.
Definition config_base.h:176
isc::process::DCTL_OPEN_CONFIG_DB
const isc::log::MessageID DCTL_OPEN_CONFIG_DB
Definition process_messages.h:26
isc::process::DCTL_CONFIG_FETCH
const isc::log::MessageID DCTL_CONFIG_FETCH
Definition process_messages.h:17
isc::process::ConstConfigControlInfoPtr
boost::shared_ptr< const ConfigControlInfo > ConstConfigControlInfoPtr
Defines a pointer to a const ConfigControlInfo.
Definition config_ctl_info.h:242
isc::process::DCTL_DB_OPEN_CONNECTION_WITH_RETRY_FAILED
const isc::log::MessageID DCTL_DB_OPEN_CONNECTION_WITH_RETRY_FAILED
Definition process_messages.h:20
isc
Defines the logger used by the top-level component of kea-lfc.
Definition agent_parser.cc:148
server_selector.h
isc::db::AuditEntryModificationTimeIdTag
Tag used to access index by modification time.
Definition audit_entry.h:232
isc::db::AuditEntryObjectIdTag
Tag used to access index by object id.
Definition audit_entry.h:235
isc::db::AuditEntryObjectTypeTag
Tag used to access index by object type.
Definition audit_entry.h:229