1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. 2 // This source code is licensed under both the GPLv2 (found in the 3 // COPYING file in the root directory) and Apache 2.0 License 4 // (found in the LICENSE.Apache file in the root directory). 5 6 // WAL related classes used in VersionEdit and VersionSet. 7 // Modifications to WalAddition and WalDeletion may need to update 8 // VersionEdit and its related tests. 9 10 #pragma once 11 12 #include <map> 13 #include <ostream> 14 #include <string> 15 #include <unordered_map> 16 #include <vector> 17 18 #include "logging/event_logger.h" 19 #include "port/port.h" 20 #include "rocksdb/rocksdb_namespace.h" 21 22 namespace ROCKSDB_NAMESPACE { 23 24 class JSONWriter; 25 class Slice; 26 class Status; 27 28 using WalNumber = uint64_t; 29 30 // Metadata of a WAL. 31 class WalMetadata { 32 public: 33 WalMetadata() = default; 34 WalMetadata(uint64_t synced_size_bytes)35 explicit WalMetadata(uint64_t synced_size_bytes) 36 : synced_size_bytes_(synced_size_bytes) {} 37 HasSyncedSize()38 bool HasSyncedSize() const { return synced_size_bytes_ != kUnknownWalSize; } 39 SetSyncedSizeInBytes(uint64_t bytes)40 void SetSyncedSizeInBytes(uint64_t bytes) { synced_size_bytes_ = bytes; } 41 GetSyncedSizeInBytes()42 uint64_t GetSyncedSizeInBytes() const { return synced_size_bytes_; } 43 44 private: 45 // The size of WAL is unknown, used when the WAL is not synced yet or is 46 // empty. 47 constexpr static uint64_t kUnknownWalSize = port::kMaxUint64; 48 49 // Size of the most recently synced WAL in bytes. 50 uint64_t synced_size_bytes_ = kUnknownWalSize; 51 }; 52 53 // These tags are persisted to MANIFEST, so it's part of the user API. 54 enum class WalAdditionTag : uint32_t { 55 // Indicates that there are no more tags. 56 kTerminate = 1, 57 // Synced Size in bytes. 58 kSyncedSize = 2, 59 // Add tags in the future, such as checksum? 60 }; 61 62 // Records the event of adding a WAL in VersionEdit. 63 class WalAddition { 64 public: WalAddition()65 WalAddition() : number_(0), metadata_() {} 66 WalAddition(WalNumber number)67 explicit WalAddition(WalNumber number) : number_(number), metadata_() {} 68 WalAddition(WalNumber number,WalMetadata meta)69 WalAddition(WalNumber number, WalMetadata meta) 70 : number_(number), metadata_(std::move(meta)) {} 71 GetLogNumber()72 WalNumber GetLogNumber() const { return number_; } 73 GetMetadata()74 const WalMetadata& GetMetadata() const { return metadata_; } 75 76 void EncodeTo(std::string* dst) const; 77 78 Status DecodeFrom(Slice* src); 79 80 std::string DebugString() const; 81 82 private: 83 WalNumber number_; 84 WalMetadata metadata_; 85 }; 86 87 std::ostream& operator<<(std::ostream& os, const WalAddition& wal); 88 JSONWriter& operator<<(JSONWriter& jw, const WalAddition& wal); 89 90 using WalAdditions = std::vector<WalAddition>; 91 92 // Records the event of deleting WALs before the specified log number. 93 class WalDeletion { 94 public: WalDeletion()95 WalDeletion() : number_(kEmpty) {} 96 WalDeletion(WalNumber number)97 explicit WalDeletion(WalNumber number) : number_(number) {} 98 GetLogNumber()99 WalNumber GetLogNumber() const { return number_; } 100 101 void EncodeTo(std::string* dst) const; 102 103 Status DecodeFrom(Slice* src); 104 105 std::string DebugString() const; 106 IsEmpty()107 bool IsEmpty() const { return number_ == kEmpty; } 108 Reset()109 void Reset() { number_ = kEmpty; } 110 111 private: 112 static constexpr WalNumber kEmpty = 0; 113 114 WalNumber number_; 115 }; 116 117 std::ostream& operator<<(std::ostream& os, const WalDeletion& wal); 118 JSONWriter& operator<<(JSONWriter& jw, const WalDeletion& wal); 119 120 // Used in VersionSet to keep the current set of WALs. 121 // 122 // When a WAL is synced or becomes obsoleted, 123 // a VersionEdit is logged to MANIFEST and 124 // the WAL is added to or deleted from WalSet. 125 // 126 // Not thread safe, needs external synchronization such as holding DB mutex. 127 class WalSet { 128 public: 129 // Add WAL(s). 130 // If the WAL is closed, 131 // then there must be an existing unclosed WAL, 132 // otherwise, return Status::Corruption. 133 // Can happen when applying a VersionEdit or recovering from MANIFEST. 134 Status AddWal(const WalAddition& wal); 135 Status AddWals(const WalAdditions& wals); 136 137 // Delete WALs with log number smaller than the specified wal number. 138 // Can happen when applying a VersionEdit or recovering from MANIFEST. 139 Status DeleteWalsBefore(WalNumber wal); 140 141 // Resets the internal state. 142 void Reset(); 143 144 // WALs with number less than MinWalNumberToKeep should not exist in WalSet. GetMinWalNumberToKeep()145 WalNumber GetMinWalNumberToKeep() const { return min_wal_number_to_keep_; } 146 GetWals()147 const std::map<WalNumber, WalMetadata>& GetWals() const { return wals_; } 148 149 // Checks whether there are missing or corrupted WALs. 150 // Returns Status::OK if there is no missing nor corrupted WAL, 151 // otherwise returns Status::Corruption. 152 // logs_on_disk is a map from log number to the log filename. 153 // Note that logs_on_disk may contain logs that is obsolete but 154 // haven't been deleted from disk. 155 Status CheckWals( 156 Env* env, 157 const std::unordered_map<WalNumber, std::string>& logs_on_disk) const; 158 159 private: 160 std::map<WalNumber, WalMetadata> wals_; 161 // WAL number < min_wal_number_to_keep_ should not exist in wals_. 162 // It's monotonically increasing, in-memory only, not written to MANIFEST. 163 WalNumber min_wal_number_to_keep_ = 0; 164 }; 165 166 } // namespace ROCKSDB_NAMESPACE 167