Coverage Report

Created: 2025-08-11 06:53

/src/leveldb/db/version_edit.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file. See the AUTHORS file for names of contributors.
4
5
#include "db/version_edit.h"
6
7
#include "db/version_set.h"
8
#include "util/coding.h"
9
10
namespace leveldb {
11
12
// Tag numbers for serialized VersionEdit.  These numbers are written to
13
// disk and should not be changed.
14
enum Tag {
15
  kComparator = 1,
16
  kLogNumber = 2,
17
  kNextFileNumber = 3,
18
  kLastSequence = 4,
19
  kCompactPointer = 5,
20
  kDeletedFile = 6,
21
  kNewFile = 7,
22
  // 8 was used for large value refs
23
  kPrevLogNumber = 9
24
};
25
26
859k
void VersionEdit::Clear() {
27
859k
  comparator_.clear();
28
859k
  log_number_ = 0;
29
859k
  prev_log_number_ = 0;
30
859k
  last_sequence_ = 0;
31
859k
  next_file_number_ = 0;
32
859k
  has_comparator_ = false;
33
859k
  has_log_number_ = false;
34
859k
  has_prev_log_number_ = false;
35
859k
  has_next_file_number_ = false;
36
859k
  has_last_sequence_ = false;
37
859k
  compact_pointers_.clear();
38
859k
  deleted_files_.clear();
39
859k
  new_files_.clear();
40
859k
}
41
42
294k
void VersionEdit::EncodeTo(std::string* dst) const {
43
294k
  if (has_comparator_) {
44
121k
    PutVarint32(dst, kComparator);
45
121k
    PutLengthPrefixedSlice(dst, comparator_);
46
121k
  }
47
294k
  if (has_log_number_) {
48
178k
    PutVarint32(dst, kLogNumber);
49
178k
    PutVarint64(dst, log_number_);
50
178k
  }
51
294k
  if (has_prev_log_number_) {
52
173k
    PutVarint32(dst, kPrevLogNumber);
53
173k
    PutVarint64(dst, prev_log_number_);
54
173k
  }
55
294k
  if (has_next_file_number_) {
56
178k
    PutVarint32(dst, kNextFileNumber);
57
178k
    PutVarint64(dst, next_file_number_);
58
178k
  }
59
294k
  if (has_last_sequence_) {
60
178k
    PutVarint32(dst, kLastSequence);
61
178k
    PutVarint64(dst, last_sequence_);
62
178k
  }
63
64
410k
  for (size_t i = 0; i < compact_pointers_.size(); i++) {
65
116k
    PutVarint32(dst, kCompactPointer);
66
116k
    PutVarint32(dst, compact_pointers_[i].first);  // level
67
116k
    PutLengthPrefixedSlice(dst, compact_pointers_[i].second.Encode());
68
116k
  }
69
70
294k
  for (const auto& deleted_file_kvp : deleted_files_) {
71
64.9k
    PutVarint32(dst, kDeletedFile);
72
64.9k
    PutVarint32(dst, deleted_file_kvp.first);   // level
73
64.9k
    PutVarint64(dst, deleted_file_kvp.second);  // file number
74
64.9k
  }
75
76
1.12M
  for (size_t i = 0; i < new_files_.size(); i++) {
77
831k
    const FileMetaData& f = new_files_[i].second;
78
831k
    PutVarint32(dst, kNewFile);
79
831k
    PutVarint32(dst, new_files_[i].first);  // level
80
831k
    PutVarint64(dst, f.number);
81
831k
    PutVarint64(dst, f.file_size);
82
831k
    PutLengthPrefixedSlice(dst, f.smallest.Encode());
83
831k
    PutLengthPrefixedSlice(dst, f.largest.Encode());
84
831k
  }
85
294k
}
86
87
1.74M
static bool GetInternalKey(Slice* input, InternalKey* dst) {
88
1.74M
  Slice str;
89
1.74M
  if (GetLengthPrefixedSlice(input, &str)) {
90
1.74M
    return dst->DecodeFrom(str);
91
1.74M
  } else {
92
0
    return false;
93
0
  }
94
1.74M
}
95
96
988k
static bool GetLevel(Slice* input, int* level) {
97
988k
  uint32_t v;
98
988k
  if (GetVarint32(input, &v) && v < config::kNumLevels) {
99
988k
    *level = v;
100
988k
    return true;
101
988k
  } else {
102
0
    return false;
103
0
  }
104
988k
}
105
106
278k
Status VersionEdit::DecodeFrom(const Slice& src) {
107
278k
  Clear();
108
278k
  Slice input = src;
109
278k
  const char* msg = nullptr;
110
278k
  uint32_t tag;
111
112
  // Temporary storage for parsing
113
278k
  int level;
114
278k
  uint64_t number;
115
278k
  FileMetaData f;
116
278k
  Slice str;
117
278k
  InternalKey key;
118
119
2.05M
  while (msg == nullptr && GetVarint32(&input, &tag)) {
120
1.77M
    switch (tag) {
121
116k
      case kComparator:
122
116k
        if (GetLengthPrefixedSlice(&input, &str)) {
123
116k
          comparator_ = str.ToString();
124
116k
          has_comparator_ = true;
125
116k
        } else {
126
0
          msg = "comparator name";
127
0
        }
128
116k
        break;
129
130
168k
      case kLogNumber:
131
168k
        if (GetVarint64(&input, &log_number_)) {
132
168k
          has_log_number_ = true;
133
168k
        } else {
134
0
          msg = "log number";
135
0
        }
136
168k
        break;
137
138
162k
      case kPrevLogNumber:
139
162k
        if (GetVarint64(&input, &prev_log_number_)) {
140
162k
          has_prev_log_number_ = true;
141
162k
        } else {
142
0
          msg = "previous log number";
143
0
        }
144
162k
        break;
145
146
168k
      case kNextFileNumber:
147
168k
        if (GetVarint64(&input, &next_file_number_)) {
148
168k
          has_next_file_number_ = true;
149
168k
        } else {
150
0
          msg = "next file number";
151
0
        }
152
168k
        break;
153
154
168k
      case kLastSequence:
155
168k
        if (GetVarint64(&input, &last_sequence_)) {
156
168k
          has_last_sequence_ = true;
157
168k
        } else {
158
0
          msg = "last sequence number";
159
0
        }
160
168k
        break;
161
162
112k
      case kCompactPointer:
163
112k
        if (GetLevel(&input, &level) && GetInternalKey(&input, &key)) {
164
112k
          compact_pointers_.push_back(std::make_pair(level, key));
165
112k
        } else {
166
0
          msg = "compaction pointer";
167
0
        }
168
112k
        break;
169
170
60.6k
      case kDeletedFile:
171
60.6k
        if (GetLevel(&input, &level) && GetVarint64(&input, &number)) {
172
60.6k
          deleted_files_.insert(std::make_pair(level, number));
173
60.6k
        } else {
174
0
          msg = "deleted file";
175
0
        }
176
60.6k
        break;
177
178
815k
      case kNewFile:
179
815k
        if (GetLevel(&input, &level) && GetVarint64(&input, &f.number) &&
180
815k
            GetVarint64(&input, &f.file_size) &&
181
815k
            GetInternalKey(&input, &f.smallest) &&
182
815k
            GetInternalKey(&input, &f.largest)) {
183
815k
          new_files_.push_back(std::make_pair(level, f));
184
815k
        } else {
185
0
          msg = "new-file entry";
186
0
        }
187
815k
        break;
188
189
0
      default:
190
0
        msg = "unknown tag";
191
0
        break;
192
1.77M
    }
193
1.77M
  }
194
195
278k
  if (msg == nullptr && !input.empty()) {
196
0
    msg = "invalid tag";
197
0
  }
198
199
278k
  Status result;
200
278k
  if (msg != nullptr) {
201
0
    result = Status::Corruption("VersionEdit", msg);
202
0
  }
203
278k
  return result;
204
278k
}
205
206
0
std::string VersionEdit::DebugString() const {
207
0
  std::string r;
208
0
  r.append("VersionEdit {");
209
0
  if (has_comparator_) {
210
0
    r.append("\n  Comparator: ");
211
0
    r.append(comparator_);
212
0
  }
213
0
  if (has_log_number_) {
214
0
    r.append("\n  LogNumber: ");
215
0
    AppendNumberTo(&r, log_number_);
216
0
  }
217
0
  if (has_prev_log_number_) {
218
0
    r.append("\n  PrevLogNumber: ");
219
0
    AppendNumberTo(&r, prev_log_number_);
220
0
  }
221
0
  if (has_next_file_number_) {
222
0
    r.append("\n  NextFile: ");
223
0
    AppendNumberTo(&r, next_file_number_);
224
0
  }
225
0
  if (has_last_sequence_) {
226
0
    r.append("\n  LastSeq: ");
227
0
    AppendNumberTo(&r, last_sequence_);
228
0
  }
229
0
  for (size_t i = 0; i < compact_pointers_.size(); i++) {
230
0
    r.append("\n  CompactPointer: ");
231
0
    AppendNumberTo(&r, compact_pointers_[i].first);
232
0
    r.append(" ");
233
0
    r.append(compact_pointers_[i].second.DebugString());
234
0
  }
235
0
  for (const auto& deleted_files_kvp : deleted_files_) {
236
0
    r.append("\n  RemoveFile: ");
237
0
    AppendNumberTo(&r, deleted_files_kvp.first);
238
0
    r.append(" ");
239
0
    AppendNumberTo(&r, deleted_files_kvp.second);
240
0
  }
241
0
  for (size_t i = 0; i < new_files_.size(); i++) {
242
0
    const FileMetaData& f = new_files_[i].second;
243
0
    r.append("\n  AddFile: ");
244
0
    AppendNumberTo(&r, new_files_[i].first);
245
0
    r.append(" ");
246
0
    AppendNumberTo(&r, f.number);
247
0
    r.append(" ");
248
0
    AppendNumberTo(&r, f.file_size);
249
0
    r.append(" ");
250
0
    r.append(f.smallest.DebugString());
251
0
    r.append(" .. ");
252
0
    r.append(f.largest.DebugString());
253
0
  }
254
0
  r.append("\n}\n");
255
0
  return r;
256
0
}
257
258
}  // namespace leveldb