#pragma once
#include <optional>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "storage/wal/wal_record.h"
namespace lbug {
namespace catalog {
class Catalog;
}
namespace main {
class ClientContext;
}
namespace storage {
class Checkpointer;
class StorageManager;
class WALReplayer {
public:
struct GraphRecoveryState {
struct WALReplayRange {
std::string path;
uint64_t endOffset;
};
std::vector<WALReplayRange> walReplayRanges;
bool retireActiveWAL = false;
bool retireFrozenWAL = false;
common::oid_t persistedGraphOIDFloor = 0;
};
explicit WALReplayer(main::ClientContext& clientContext);
void replay(bool throwOnWalReplayFailure, bool enableChecksums) const;
GraphRecoveryState prepareGraphCheckpoint(StorageManager& storageManager, bool checkpointBundle,
std::optional<common::uuid> checkpointDatabaseID = std::nullopt) const;
void replayGraphWAL(StorageManager& storageManager,
const GraphRecoveryState& recoveryState) const;
void retireGraphCheckpointWALs(StorageManager& storageManager,
const GraphRecoveryState& recoveryState) const;
void removeGraphCheckpointShadow(StorageManager& storageManager) const;
private:
struct WALReplayInfo {
uint64_t offsetDeserialized = 0;
bool isLastRecordCheckpoint = false;
uint64_t lastCheckpointOffset = 0;
uint64_t offsetBeforeFirstCheckpoint = 0;
common::uuid walDatabaseID{};
uint64_t checkpointFormatVersion = 0;
};
void replayWALRecord(WALRecord& walRecord) const;
void recordReplayedEntryID(catalog::CatalogEntryType entryType, common::oid_t recordedEntryID,
common::oid_t replayedEntryID) const;
common::oid_t getReplayedEntryID(catalog::CatalogEntryType entryType,
common::oid_t recordedEntryID) const;
bool tryGetReplayedEntryID(catalog::CatalogEntryType entryType, common::oid_t recordedEntryID,
common::oid_t& replayedEntryID) const;
void replayCreateCatalogEntryRecord(WALRecord& walRecord) const;
void replayCreateIndexRecord(WALRecord& walRecord) const;
void replayDropCatalogEntryRecord(const WALRecord& walRecord) const;
void replayAlterTableEntryRecord(const WALRecord& walRecord) const;
void replayTableInsertionRecord(const WALRecord& walRecord) const;
void replayNodeDeletionRecord(const WALRecord& walRecord) const;
void replayNodeUpdateRecord(const WALRecord& walRecord) const;
void replayRelDeletionRecord(const WALRecord& walRecord) const;
void replayRelDetachDeletionRecord(const WALRecord& walRecord) const;
void replayRelUpdateRecord(const WALRecord& walRecord) const;
void replayCopyTableRecord(const WALRecord& walRecord) const;
void replayUpdateSequenceRecord(const WALRecord& walRecord) const;
void replayUpdateSequenceNamedRecord(const WALRecord& walRecord) const;
void replaySequenceRecord(common::sequence_id_t sequenceID, uint64_t kCount,
const std::string& sequenceName) const;
void replayNodeTableInsertRecord(const WALRecord& walRecord) const;
void replayRelTableInsertRecord(const WALRecord& walRecord) const;
void replayLoadExtensionRecord(const WALRecord& walRecord) const;
WALReplayInfo dryReplay(common::FileInfo& fileInfo, bool throwOnWalReplayFailure,
bool enableChecksums) const;
void replayFrozenWAL(Checkpointer& checkpointer, bool throwOnWalReplayFailure,
bool enableChecksums) const;
void replayActiveWAL(Checkpointer& checkpointer, bool throwOnWalReplayFailure,
bool enableChecksums, bool checkpointRead) const;
void replayCommittedCheckpoint(Checkpointer& checkpointer,
std::unique_ptr<common::FileInfo>& fileInfo, const std::string& checkpointWALPath,
const WALReplayInfo& replayInfo) const;
void replayPinnedActiveCheckpoint(Checkpointer& checkpointer,
std::unique_ptr<common::FileInfo>& fileInfo, const WALReplayInfo& replayInfo) const;
void completeInterruptedCheckpoint() const;
common::uuid readShadowDatabaseID(const std::string& path) const;
void throwIfShadowOwnedByAnotherDatabase() const;
void removeWALAndShadowFiles(const std::string& walFilePath) const;
void removeFileAndSyncParentDirectory(const std::string& path) const;
bool removeFileIfExists(const std::string& path) const;
std::unique_ptr<common::FileInfo> openWALFile() const;
void syncWALFile(const common::FileInfo& fileInfo) const;
void truncateWALFile(common::FileInfo& fileInfo, uint64_t size) const;
private:
main::ClientContext& clientContext;
std::string walPath;
std::string checkpointWalPath;
std::string shadowFilePath;
mutable std::unordered_set<std::string> failedOwnerNames;
mutable std::string cachedOwnerName;
mutable catalog::Catalog* cachedOwnerCatalog = nullptr;
mutable std::unordered_map<const catalog::Catalog*,
std::unordered_map<catalog::CatalogEntryType,
std::unordered_map<common::oid_t, common::oid_t>>>
replayedEntryIDs;
mutable common::oid_t graphOIDReplayFloor = 0;
mutable bool graphOIDReplayFloorValid = false;
mutable std::vector<std::unique_ptr<catalog::Catalog>> retiredCatalogs;
};
} }