]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#103,!277] Added CBControlBase::fetchConfigElement function.
authorMarcin Siodelski <marcin@isc.org>
Tue, 19 Mar 2019 12:03:26 +0000 (13:03 +0100)
committerMarcin Siodelski <marcin@isc.org>
Tue, 26 Mar 2019 07:08:56 +0000 (03:08 -0400)
src/lib/process/cb_ctl_base.h
src/lib/process/tests/cb_ctl_base_unittests.cc

index 90e881117030ec130aa6abb13764dec2ea6f903c..8547cacc975447820cf5f60830de482290ebbf75 100644 (file)
@@ -180,9 +180,12 @@ public:
         /// @todo We need a separate API call for the latter case to only
         /// fetch the last audit entry rather than all of them.
 
+        // Save the timestamp indicating last audit entry time.
+        auto lb_modification_time = last_audit_entry_time_;
+
         audit_entries = getMgr().getPool()->getRecentAuditEntries(backend_selector,
                                                                   server_selector,
-                                                                  last_audit_entry_time_);
+                                                                  lb_modification_time);
         // Store the last audit entry time. It should be set to the most recent
         // audit entry fetched. If returned audit is empty we don't update.
         updateLastAuditEntryTime(audit_entries);
@@ -198,12 +201,47 @@ public:
         // execute the server specific function that fetches and merges the data
         // into the given configuration.
         if (!fetch_updates_only || !audit_entries.empty()) {
-            databaseConfigApply(srv_cfg, backend_selector, server_selector, audit_entries);
+            databaseConfigApply(srv_cfg, backend_selector, server_selector,
+                                lb_modification_time, audit_entries);
         }
     }
 
 protected:
 
+    /// @brief Checks if there are new or updated configuration elements of
+    /// specific type to be fetched from the database.
+    ///
+    /// This is convenience method invoked from the implementations of the
+    /// @c databaseConfigApply function. This method is invoked in two cases:
+    /// when the server starts up and fetches the entire configuration available
+    /// for it and when it should fetch the updates to the existing configuration.
+    /// In the former case, the collection of audit entries is always empty.
+    /// In the latter case it contains audit entries indicating the updates
+    /// to be fetched. This method checks if the implementation of the
+    /// @c databaseConfigApply should fetch updated configuration of the
+    /// configuration elements of the specific type. Therefore, it returns true
+    /// if the audit entries collection is empty (the former case described
+    /// above) or the audit entries collection contains CREATE or UPDATE
+    /// entries of the specific type.
+    ///
+    /// @return true if there are new or updated configuration elements to
+    /// be fetched from the database or the audit entries collection is empty.
+    bool fetchConfigElement(const db::AuditEntryCollection& audit_entries,
+                            const std::string& object_type) const {
+        if (!audit_entries.empty()) {
+            const auto& index = audit_entries.get<db::AuditEntryObjectTypeTag>();
+            auto range = index.equal_range(object_type);
+            for (auto it = range.first; it != range.second; ++it) {
+                if ((*it)->getModificationType() != db::AuditEntry::ModificationType::DELETE) {
+                    return (true);
+                }
+            }
+            return (false);
+        }
+
+        return (true);
+    }
+
     /// @brief Server specific method to apply fetched configuration into
     /// the local configuration.
     ///
@@ -227,12 +265,15 @@ protected:
     /// @pararm srv_cfg Pointer to the local server configuration.
     /// @param backend_selector Backend selector.
     /// @param server_selector Server selector.
+    /// @param lb_modification_time Lower bound modification time for the
+    /// configuration elements to be fetched.
     /// @param audit_entries Audit entries fetched from the database since
     /// the last configuration update. This collection is empty if there
     /// were no updates.
     virtual void databaseConfigApply(const ConfigPtr& srv_cfg,
                                      const db::BackendSelector& backend_selector,
                                      const db::ServerSelector& server_selector,
+                                     const boost::posix_time::ptime& lb_modification_time,
                                      const db::AuditEntryCollection& audit_entries) = 0;
 
     /// @brief Returns the instance of the Config Backend Manager used by
index 9abc1a7d16b1879c244683b21e83242d8a95541b..19a07a879cd03320ae68412ff02bac1424f06ab2 100644 (file)
@@ -222,6 +222,7 @@ public:
 class CBControl : public CBControlBase<CBControlBackendMgr> {
 public:
 
+    using CBControlBase<CBControlBackendMgr>::fetchConfigElement;
     using CBControlBase<CBControlBackendMgr>::getMgr;
     using CBControlBase<CBControlBackendMgr>::getInitialAuditEntryTime;
 
@@ -246,6 +247,7 @@ public:
     virtual void databaseConfigApply(const ConfigPtr& srv_cfg,
                                      const BackendSelector& backend_selector,
                                      const ServerSelector& server_selector,
+                                     const boost::posix_time::ptime&,
                                      const AuditEntryCollection& audit_entries) {
         ++merges_num_;
         backend_selector_ = backend_selector;
@@ -379,6 +381,42 @@ TEST_F(CBControlBaseTest, getMgr) {
     EXPECT_EQ(TEST_INSTANCE_ID, mgr.getInstanceId());
 }
 
+// This test verifies that it is correctly determined whether the
+// server should fetch the particular configuration element.
+TEST_F(CBControlBaseTest, fetchConfigElement) {
+    db::AuditEntryCollection audit_entries;
+    // When audit entries collection is empty it indicates that this
+    // is the case of the full server reconfiguration. Always indicate
+    // that the configuration elements must be fetched.
+    EXPECT_TRUE(cb_ctl_.fetchConfigElement(audit_entries, "my_object_type"));
+
+    // Now test the case that there is a DELETE audit entry. In this case
+    // our function should indicate that the configuration should not be
+    // fetched for the given object type. Note that when the configuration
+    // element is deleted, it no longer exists in database so there is
+    // no reason to fetch the data from the database.
+    AuditEntryPtr audit_entry(new AuditEntry("dhcp4_subnet", 1234 ,
+                                             AuditEntry::ModificationType::DELETE,
+                                             "added audit entry"));
+    audit_entries.insert(audit_entry);
+    EXPECT_FALSE(cb_ctl_.fetchConfigElement(audit_entries, "my_object_type"));
+
+    // Add another audit entry which indicates creation of the configuration element.
+    // This time we should get 'true'.
+    audit_entry.reset(new AuditEntry("my_object_type", 5678,
+                                     AuditEntry::ModificationType::CREATE,
+                                     "added audit entry"));
+    audit_entries.insert(audit_entry);
+    EXPECT_TRUE(cb_ctl_.fetchConfigElement(audit_entries, "my_object_type"));
+
+    // Also we should get 'true' for the UPDATE case.
+    audit_entry.reset(new AuditEntry("another_object_type",
+                                     5678, AuditEntry::ModificationType::UPDATE,
+                                     "added audit entry"));
+    audit_entries.insert(audit_entry);
+    EXPECT_TRUE(cb_ctl_.fetchConfigElement(audit_entries, "another_object_type"));
+}
+
 // This test verifies that true is return when the server successfully
 // connects to the backend and false if there are no backends to connect
 // to.