Coverage Report

Created: 2026-05-30 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/leveldb/db/version_edit.cc
Line
Count
Source
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
612
void VersionEdit::Clear() {
27
612
  comparator_.clear();
28
612
  log_number_ = 0;
29
612
  prev_log_number_ = 0;
30
612
  last_sequence_ = 0;
31
612
  next_file_number_ = 0;
32
612
  has_comparator_ = false;
33
612
  has_log_number_ = false;
34
612
  has_prev_log_number_ = false;
35
612
  has_next_file_number_ = false;
36
612
  has_last_sequence_ = false;
37
612
  compact_pointers_.clear();
38
612
  deleted_files_.clear();
39
612
  new_files_.clear();
40
612
}
41
42
272
void VersionEdit::EncodeTo(std::string* dst) const {
43
272
  if (has_comparator_) {
44
147
    PutVarint32(dst, kComparator);
45
147
    PutLengthPrefixedSlice(dst, comparator_);
46
147
  }
47
272
  if (has_log_number_) {
48
172
    PutVarint32(dst, kLogNumber);
49
172
    PutVarint64(dst, log_number_);
50
172
  }
51
272
  if (has_prev_log_number_) {
52
125
    PutVarint32(dst, kPrevLogNumber);
53
125
    PutVarint64(dst, prev_log_number_);
54
125
  }
55
272
  if (has_next_file_number_) {
56
172
    PutVarint32(dst, kNextFileNumber);
57
172
    PutVarint64(dst, next_file_number_);
58
172
  }
59
272
  if (has_last_sequence_) {
60
172
    PutVarint32(dst, kLastSequence);
61
172
    PutVarint64(dst, last_sequence_);
62
172
  }
63
64
294
  for (size_t i = 0; i < compact_pointers_.size(); i++) {
65
22
    PutVarint32(dst, kCompactPointer);
66
22
    PutVarint32(dst, compact_pointers_[i].first);  // level
67
22
    PutLengthPrefixedSlice(dst, compact_pointers_[i].second.Encode());
68
22
  }
69
70
272
  for (const auto& deleted_file_kvp : deleted_files_) {
71
21
    PutVarint32(dst, kDeletedFile);
72
21
    PutVarint32(dst, deleted_file_kvp.first);   // level
73
21
    PutVarint64(dst, deleted_file_kvp.second);  // file number
74
21
  }
75
76
390
  for (size_t i = 0; i < new_files_.size(); i++) {
77
118
    const FileMetaData& f = new_files_[i].second;
78
118
    PutVarint32(dst, kNewFile);
79
118
    PutVarint32(dst, new_files_[i].first);  // level
80
118
    PutVarint64(dst, f.number);
81
118
    PutVarint64(dst, f.file_size);
82
118
    PutLengthPrefixedSlice(dst, f.smallest.Encode());
83
118
    PutLengthPrefixedSlice(dst, f.largest.Encode());
84
118
  }
85
272
}
86
87
210
static bool GetInternalKey(Slice* input, InternalKey* dst) {
88
210
  Slice str;
89
210
  if (GetLengthPrefixedSlice(input, &str)) {
90
210
    return dst->DecodeFrom(str);
91
210
  } else {
92
0
    return false;
93
0
  }
94
210
}
95
96
135
static bool GetLevel(Slice* input, int* level) {
97
135
  uint32_t v;
98
135
  if (GetVarint32(input, &v) && v < config::kNumLevels) {
99
135
    *level = v;
100
135
    return true;
101
135
  } else {
102
0
    return false;
103
0
  }
104
135
}
105
106
170
Status VersionEdit::DecodeFrom(const Slice& src) {
107
170
  Clear();
108
170
  Slice input = src;
109
170
  const char* msg = nullptr;
110
170
  uint32_t tag;
111
112
  // Temporary storage for parsing
113
170
  int level;
114
170
  uint64_t number;
115
170
  FileMetaData f;
116
170
  Slice str;
117
170
  InternalKey key;
118
119
826
  while (msg == nullptr && GetVarint32(&input, &tag)) {
120
656
    switch (tag) {
121
100
      case kComparator:
122
100
        if (GetLengthPrefixedSlice(&input, &str)) {
123
100
          comparator_ = str.ToString();
124
100
          has_comparator_ = true;
125
100
        } else {
126
0
          msg = "comparator name";
127
0
        }
128
100
        break;
129
130
117
      case kLogNumber:
131
117
        if (GetVarint64(&input, &log_number_)) {
132
117
          has_log_number_ = true;
133
117
        } else {
134
0
          msg = "log number";
135
0
        }
136
117
        break;
137
138
70
      case kPrevLogNumber:
139
70
        if (GetVarint64(&input, &prev_log_number_)) {
140
70
          has_prev_log_number_ = true;
141
70
        } else {
142
0
          msg = "previous log number";
143
0
        }
144
70
        break;
145
146
117
      case kNextFileNumber:
147
117
        if (GetVarint64(&input, &next_file_number_)) {
148
117
          has_next_file_number_ = true;
149
117
        } else {
150
0
          msg = "next file number";
151
0
        }
152
117
        break;
153
154
117
      case kLastSequence:
155
117
        if (GetVarint64(&input, &last_sequence_)) {
156
117
          has_last_sequence_ = true;
157
117
        } else {
158
0
          msg = "last sequence number";
159
0
        }
160
117
        break;
161
162
18
      case kCompactPointer:
163
18
        if (GetLevel(&input, &level) && GetInternalKey(&input, &key)) {
164
18
          compact_pointers_.push_back(std::make_pair(level, key));
165
18
        } else {
166
0
          msg = "compaction pointer";
167
0
        }
168
18
        break;
169
170
21
      case kDeletedFile:
171
21
        if (GetLevel(&input, &level) && GetVarint64(&input, &number)) {
172
21
          deleted_files_.insert(std::make_pair(level, number));
173
21
        } else {
174
0
          msg = "deleted file";
175
0
        }
176
21
        break;
177
178
96
      case kNewFile:
179
96
        if (GetLevel(&input, &level) && GetVarint64(&input, &f.number) &&
180
96
            GetVarint64(&input, &f.file_size) &&
181
96
            GetInternalKey(&input, &f.smallest) &&
182
96
            GetInternalKey(&input, &f.largest)) {
183
96
          new_files_.push_back(std::make_pair(level, f));
184
96
        } else {
185
0
          msg = "new-file entry";
186
0
        }
187
96
        break;
188
189
0
      default:
190
0
        msg = "unknown tag";
191
0
        break;
192
656
    }
193
656
  }
194
195
170
  if (msg == nullptr && !input.empty()) {
196
0
    msg = "invalid tag";
197
0
  }
198
199
170
  Status result;
200
170
  if (msg != nullptr) {
201
0
    result = Status::Corruption("VersionEdit", msg);
202
0
  }
203
170
  return result;
204
170
}
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