summaryrefslogtreecommitdiffstats
path: root/src/lib/database/audit_entry.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/database/audit_entry.h')
-rw-r--r--src/lib/database/audit_entry.h299
1 files changed, 299 insertions, 0 deletions
diff --git a/src/lib/database/audit_entry.h b/src/lib/database/audit_entry.h
new file mode 100644
index 0000000..6c46175
--- /dev/null
+++ b/src/lib/database/audit_entry.h
@@ -0,0 +1,299 @@
+// Copyright (C) 2019-2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef AUDIT_ENTRY_H
+#define AUDIT_ENTRY_H
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/multi_index/composite_key.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/hashed_index.hpp>
+#include <boost/multi_index/mem_fun.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/shared_ptr.hpp>
+#include <cstdint>
+#include <string>
+
+namespace isc {
+namespace db {
+
+class AuditEntry;
+
+/// @brief Pointer to the @c AuditEntry object.
+typedef boost::shared_ptr<AuditEntry> AuditEntryPtr;
+
+/// @brief Represents a single entry in the audit table.
+///
+/// The audit tables are used in the databases to track incremental
+/// changes, e.g. configuration changes applied via the configuration
+/// backend. The backend can query for the entries in the audit table
+/// to identify the SQL table in which the records were modified, the
+/// identifiers of the modified objects, type of the modifications,
+/// time of the modifications and optional log messages associated
+/// with the modifications.
+///
+/// The server should remember the most recent modification time out of
+/// all audit entries it has fetched. During the next attempt to fetch
+/// the most recent modifications in the database it will query for all
+/// entries with later modification time than stored. That way the
+/// server queries only for the audit entries it hasn't fetched yet.
+/// In the case two (or more) successive audit entries have the same
+/// modification time the strictly increasing modification id is used.
+///
+/// When the modification type of the entry is set to
+/// @c AuditEntry::ModificationType::DELETE, the corresponding
+/// configuration entry is already gone from the database. For example:
+/// when a subnet with ID of 123 is deleted from the dhcp4_subnet
+/// table, the audit entry similar to this will be stored in the audit
+/// table:
+///
+/// - object_type: "dhcp4_subnet"
+/// - object_id: 123
+/// - modification_type: 3 (DELETE)
+/// - modification_time: "2019-01-15 15:45:23"
+/// - revision id: 234
+/// - log_message: "DHCPv4 subnet 123 deleted"
+///
+/// The subnet is instantly removed from the dhcp4_subnet table. When
+/// the server finds such entry in the audit table, it removes the
+/// subnet 123 from its (in-memory) configuration. There is no need
+/// make additional queries to fetch updated data from the dhcp4_subnet
+/// table, unless there are also audit entries indicating that some
+/// new subnets have been added or some subnets have been updated.
+class AuditEntry {
+public:
+
+ /// @brief Types of the modifications.
+ ///
+ /// The numbers representing those modification types correspond
+ /// to the values representing them in the database.
+ enum class ModificationType : uint8_t {
+ CREATE = 0,
+ UPDATE = 1,
+ DELETE = 2
+ };
+
+ /// @brief Constructor using explicit modification time and id.
+ ///
+ /// @param object_type name of the table where data was modified.
+ /// @param object_id identifier of the modified record in this table.
+ /// @param modification_type type of the modification, e.g. DELETE.
+ /// @param modification_time time of modification for that record.
+ /// @param revision_id identifier of the revision.
+ /// @param log_message optional log message associated with the
+ /// modification.
+ AuditEntry(const std::string& object_type,
+ const uint64_t object_id,
+ const ModificationType& modification_type,
+ const boost::posix_time::ptime& modification_time,
+ const uint64_t revision_id,
+ const std::string& log_message);
+
+ /// @brief Constructor using default modification time.
+ ///
+ /// @param object_type name of the table where data was modified.
+ /// @param object_id identifier of the modified record in this table.
+ /// @param modification_type type of the modification, e.g. DELETE.
+ /// @param revision_id identifier of the revision.
+ /// @param log_message optional log message associated with the
+ /// modification.
+ AuditEntry(const std::string& object_type,
+ const uint64_t object_id,
+ const ModificationType& modification_type,
+ const uint64_t revision_id,
+ const std::string& log_message);
+
+ /// @brief Factory function creating an instance of @c AuditEntry.
+ ///
+ /// This function should be used to create an instance of the audit
+ /// entry within a hooks library in cases when the library may be
+ /// unloaded before the object is destroyed. This ensures that the
+ /// ownership of the object by the Kea process is retained.
+ ///
+ /// @param object_type name of the table where data was modified.
+ /// @param object_id identifier of the modified record in this table.
+ /// @param modification_type type of the modification, e.g. DELETE.
+ /// @param modification_time time of modification for that record.
+ /// @param revision_id identifier of the revision.
+ /// @param log_message optional log message associated with the
+ /// modification.
+ ///
+ /// @return Pointer to the @c AuditEntry instance.
+ static AuditEntryPtr create(const std::string& object_type,
+ const uint64_t object_id,
+ const ModificationType& modification_type,
+ const boost::posix_time::ptime& modification_time,
+ const uint64_t revision_id,
+ const std::string& log_message);
+
+ /// @brief Factory function creating an instance of @c AuditEntry.
+ ///
+ /// This function should be used to create an instance of the audit
+ /// entry within a hooks library in cases when the library may be
+ /// unloaded before the object is destroyed. This ensures that the
+ /// ownership of the object by the Kea process is retained.
+ ///
+ /// @param object_type name of the table where data was modified.
+ /// @param object_id identifier of the modified record in this table.
+ /// @param modification_type type of the modification, e.g. DELETE.
+ /// @param revision_id identifier of the revision.
+ /// @param log_message optional log message associated with the
+ /// modification.
+ ///
+ /// @return Pointer to the @c AuditEntry instance.
+ static AuditEntryPtr create(const std::string& object_type,
+ const uint64_t object_id,
+ const ModificationType& modification_type,
+ const uint64_t revision_id,
+ const std::string& log_message);
+
+ /// @brief Returns object type.
+ ///
+ /// @return Name of the table in which the modification is present.
+ std::string getObjectType() const {
+ return (object_type_);
+ }
+
+ /// @brief Returns object id.
+ ///
+ /// @return Identifier of the added, updated or deleted object.
+ uint64_t getObjectId() const {
+ return (object_id_);
+ }
+
+ /// @brief Returns modification type.
+ ///
+ /// @return Type of the modification, e.g. DELETE.
+ ModificationType getModificationType() const {
+ return (modification_type_);
+ }
+
+ /// @brief Returns modification time.
+ ///
+ /// @return Modification time of the corresponding record.
+ boost::posix_time::ptime getModificationTime() const {
+ return (modification_time_);
+ }
+
+ /// @brief Returns revision id.
+ ///
+ /// The revision id is used when two audit entries have the same
+ /// modification time.
+ ///
+ /// @return Identifier of the revision.
+ uint64_t getRevisionId() const {
+ return (revision_id_);
+ }
+
+ /// @brief Returns log message.
+ ///
+ /// @return Optional log message corresponding to the changes.
+ std::string getLogMessage() const {
+ return (log_message_);
+ }
+
+private:
+
+ /// @brief Validates the values specified for the audit entry.
+ ///
+ /// @throw BadValue if the object type is empty or if the
+ /// modification time is not a date time value.
+ void validate() const;
+
+ /// @brief Object type.
+ std::string object_type_;
+
+ /// @brief Object id.
+ uint64_t object_id_;
+
+ /// @brief Modification type.
+ ModificationType modification_type_;
+
+ /// @brief Modification time.
+ boost::posix_time::ptime modification_time_;
+
+ /// @brief Revision id.
+ ///
+ /// The revision id is used when two audit entries have the same
+ /// modification time.
+ uint64_t revision_id_;
+
+ /// @brief Log message.
+ std::string log_message_;
+};
+
+/// @brief Tag used to access index by object type.
+struct AuditEntryObjectTypeTag { };
+
+/// @brief Tag used to access index by modification time.
+struct AuditEntryModificationTimeIdTag { };
+
+/// @brief Tag used to access index by object id.
+struct AuditEntryObjectIdTag { };
+
+/// @brief Multi index container holding @c AuditEntry instances.
+///
+/// This container provides indexes to access the audit entries
+/// by object type and modification time.
+typedef boost::multi_index_container<
+ // The container holds pointers to @c AuditEntry objects.
+ AuditEntryPtr,
+ // First index allows for accessing by the object type.
+ 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
+ >
+ >
+ >,
+
+ // Second index allows for accessing by the modification time and id.
+ 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
+ >
+ >
+ >,
+
+ // Third index allows for accessing by the object id.
+ boost::multi_index::hashed_non_unique<
+ boost::multi_index::tag<AuditEntryObjectIdTag>,
+ boost::multi_index::const_mem_fun<
+ AuditEntry,
+ uint64_t,
+ &AuditEntry::getObjectId
+ >
+ >
+ >
+> AuditEntryCollection;
+
+//// @brief Pointer to the @c AuditEntryCollection object.
+typedef boost::shared_ptr<AuditEntryCollection> AuditEntryCollectionPtr;
+
+} // end of namespace isc::db
+} // end of namespace isc
+
+#endif