94 lines
include/checkpoint_manager.h
Declares CheckpointManager, Snapshot, and the restore/save contract.
// CheckpointManager: merges versioned configuration snapshots on service restart.#pragma once#include <cstdint>#include <cstdio>#include <string>#include <unordered_map>#include <vector>// Abstract configuration store interface used during restore.class IConfigStore {public: virtual ~IConfigStore() = default; // Sets a key to value if the incoming version is newer than the stored version. // Parameters: // key - configuration key to update // value - new value // version - version of the snapshot providing this value virtual void set(const std::string& key, const std::string& value, uint32_t version) = 0; // Returns the version of the last set() call that updated this key, or 0 if unset. virtual uint32_t versionOf(const std::string& key) const = 0;};
// One replica's configuration snapshot.struct Snapshot { uint32_t version; // monotonically increasing per-replica; higher = more recent uint32_t instanceId; // originating replica identifier std::unordered_map<std::string, std::string> values; // key-value pairs in this snapshot};
// On-disk file header (immediately followed by entryCount Snapshot records).struct CheckpointHeader { uint32_t magic; // must equal CHECKPOINT_MAGIC = 0xC0FFEE01 uint32_t entryCount; // number of Snapshot records that follow in the file uint32_t formatVer; // file format version; must equal 1};
static constexpr uint32_t CHECKPOINT_MAGIC = 0xC0FFEE01u;// Reads and writes versioned configuration snapshots to a checkpoint file.class CheckpointManager {public: // Parameters: // path - path to the checkpoint file; created on first save // Returns: new CheckpointManager instance explicit CheckpointManager(const char* path); ~CheckpointManager(); // Saves one snapshot to the checkpoint file. // Parameters: // snap - snapshot to append // Returns: true if the snapshot was written successfully bool save(const Snapshot& snap); // Reads all snapshots from the checkpoint file and applies them to the store. // Snapshots must be applied in ascending version order so higher-version values win. // entryCount from the file header must be validated before any allocation. // Parameters: // store - destination configuration store // Returns: true if at least one snapshot was applied; false on file error or empty file bool restore(IConfigStore& store); // Returns true if the file is open and usable. bool isOpen() const { return fp_ != nullptr; }private: std::FILE* fp_ = nullptr; // Reads one Snapshot from the current file position. // Parameters: // snap - output structure filled with the record data // Returns: true if the snapshot was fully read bool readSnapshot(Snapshot& snap); // Writes one Snapshot at the current file position. // Parameters: // snap - snapshot to serialise and write // Returns: true if all bytes were written successfully bool writeSnapshot(const Snapshot& snap); // Applies a snapshot's key-value pairs to the store. // Parameters: // store - destination store // snap - snapshot to apply // Returns: void void applySnapshot(IConfigStore& store, const Snapshot& snap); // Checks whether a snapshot at snapVer should overwrite a value at storeVer. // Parameters: // snapVer - version of the incoming snapshot // storeVer - current stored version for comparison // Returns: true if snapVer strictly exceeds storeVer bool shouldApply(uint32_t snapVer, uint32_t storeVer) const;};