summaryrefslogtreecommitdiffstats
path: root/src/rocksdb/db/wal_edit.h
blob: bb5c5e292ee1cfc7427abf11ec69c1fb5c45401b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).

// WAL related classes used in VersionEdit and VersionSet.
// Modifications to WalAddition and WalDeletion may need to update
// VersionEdit and its related tests.

#pragma once

#include <map>
#include <ostream>
#include <string>
#include <unordered_map>
#include <vector>

#include "logging/event_logger.h"
#include "port/port.h"
#include "rocksdb/rocksdb_namespace.h"

namespace ROCKSDB_NAMESPACE {

class JSONWriter;
class Slice;
class Status;

using WalNumber = uint64_t;

// Metadata of a WAL.
class WalMetadata {
 public:
  WalMetadata() = default;

  explicit WalMetadata(uint64_t synced_size_bytes)
      : synced_size_bytes_(synced_size_bytes) {}

  bool HasSyncedSize() const { return synced_size_bytes_ != kUnknownWalSize; }

  void SetSyncedSizeInBytes(uint64_t bytes) { synced_size_bytes_ = bytes; }

  uint64_t GetSyncedSizeInBytes() const { return synced_size_bytes_; }

 private:
  friend bool operator==(const WalMetadata& lhs, const WalMetadata& rhs);
  friend bool operator!=(const WalMetadata& lhs, const WalMetadata& rhs);
  // The size of WAL is unknown, used when the WAL is not synced yet or is
  // empty.
  constexpr static uint64_t kUnknownWalSize =
      std::numeric_limits<uint64_t>::max();

  // Size of the most recently synced WAL in bytes.
  uint64_t synced_size_bytes_ = kUnknownWalSize;
};

inline bool operator==(const WalMetadata& lhs, const WalMetadata& rhs) {
  return lhs.synced_size_bytes_ == rhs.synced_size_bytes_;
}

inline bool operator!=(const WalMetadata& lhs, const WalMetadata& rhs) {
  return !(lhs == rhs);
}

// These tags are persisted to MANIFEST, so it's part of the user API.
enum class WalAdditionTag : uint32_t {
  // Indicates that there are no more tags.
  kTerminate = 1,
  // Synced Size in bytes.
  kSyncedSize = 2,
  // Add tags in the future, such as checksum?
};

// Records the event of adding a WAL in VersionEdit.
class WalAddition {
 public:
  WalAddition() : number_(0), metadata_() {}

  explicit WalAddition(WalNumber number) : number_(number), metadata_() {}

  WalAddition(WalNumber number, WalMetadata meta)
      : number_(number), metadata_(std::move(meta)) {}

  WalNumber GetLogNumber() const { return number_; }

  const WalMetadata& GetMetadata() const { return metadata_; }

  void EncodeTo(std::string* dst) const;

  Status DecodeFrom(Slice* src);

  std::string DebugString() const;

 private:
  WalNumber number_;
  WalMetadata metadata_;
};

std::ostream& operator<<(std::ostream& os, const WalAddition& wal);
JSONWriter& operator<<(JSONWriter& jw, const WalAddition& wal);

using WalAdditions = std::vector<WalAddition>;

// Records the event of deleting WALs before the specified log number.
class WalDeletion {
 public:
  WalDeletion() : number_(kEmpty) {}

  explicit WalDeletion(WalNumber number) : number_(number) {}

  WalNumber GetLogNumber() const { return number_; }

  void EncodeTo(std::string* dst) const;

  Status DecodeFrom(Slice* src);

  std::string DebugString() const;

  bool IsEmpty() const { return number_ == kEmpty; }

  void Reset() { number_ = kEmpty; }

 private:
  static constexpr WalNumber kEmpty = 0;

  WalNumber number_;
};

std::ostream& operator<<(std::ostream& os, const WalDeletion& wal);
JSONWriter& operator<<(JSONWriter& jw, const WalDeletion& wal);

// Used in VersionSet to keep the current set of WALs.
//
// When a WAL is synced or becomes obsoleted,
// a VersionEdit is logged to MANIFEST and
// the WAL is added to or deleted from WalSet.
//
// Not thread safe, needs external synchronization such as holding DB mutex.
class WalSet {
 public:
  // Add WAL(s).
  // If the WAL is closed,
  // then there must be an existing unclosed WAL,
  // otherwise, return Status::Corruption.
  // Can happen when applying a VersionEdit or recovering from MANIFEST.
  Status AddWal(const WalAddition& wal);
  Status AddWals(const WalAdditions& wals);

  // Delete WALs with log number smaller than the specified wal number.
  // Can happen when applying a VersionEdit or recovering from MANIFEST.
  Status DeleteWalsBefore(WalNumber wal);

  // Resets the internal state.
  void Reset();

  // WALs with number less than MinWalNumberToKeep should not exist in WalSet.
  WalNumber GetMinWalNumberToKeep() const { return min_wal_number_to_keep_; }

  const std::map<WalNumber, WalMetadata>& GetWals() const { return wals_; }

  // Checks whether there are missing or corrupted WALs.
  // Returns Status::OK if there is no missing nor corrupted WAL,
  // otherwise returns Status::Corruption.
  // logs_on_disk is a map from log number to the log filename.
  // Note that logs_on_disk may contain logs that is obsolete but
  // haven't been deleted from disk.
  Status CheckWals(
      Env* env,
      const std::unordered_map<WalNumber, std::string>& logs_on_disk) const;

 private:
  std::map<WalNumber, WalMetadata> wals_;
  // WAL number < min_wal_number_to_keep_ should not exist in wals_.
  // It's monotonically increasing, in-memory only, not written to MANIFEST.
  WalNumber min_wal_number_to_keep_ = 0;
};

}  // namespace ROCKSDB_NAMESPACE