Coverage Report

Created: 2024-10-29 12:15

/root/bitcoin/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
0
void VersionEdit::Clear() {
27
0
  comparator_.clear();
28
0
  log_number_ = 0;
29
0
  prev_log_number_ = 0;
30
0
  last_sequence_ = 0;
31
0
  next_file_number_ = 0;
32
0
  has_comparator_ = false;
33
0
  has_log_number_ = false;
34
0
  has_prev_log_number_ = false;
35
0
  has_next_file_number_ = false;
36
0
  has_last_sequence_ = false;
37
0
  deleted_files_.clear();
38
0
  new_files_.clear();
39
0
}
40
41
0
void VersionEdit::EncodeTo(std::string* dst) const {
42
0
  if (has_comparator_) {
43
0
    PutVarint32(dst, kComparator);
44
0
    PutLengthPrefixedSlice(dst, comparator_);
45
0
  }
46
0
  if (has_log_number_) {
47
0
    PutVarint32(dst, kLogNumber);
48
0
    PutVarint64(dst, log_number_);
49
0
  }
50
0
  if (has_prev_log_number_) {
51
0
    PutVarint32(dst, kPrevLogNumber);
52
0
    PutVarint64(dst, prev_log_number_);
53
0
  }
54
0
  if (has_next_file_number_) {
55
0
    PutVarint32(dst, kNextFileNumber);
56
0
    PutVarint64(dst, next_file_number_);
57
0
  }
58
0
  if (has_last_sequence_) {
59
0
    PutVarint32(dst, kLastSequence);
60
0
    PutVarint64(dst, last_sequence_);
61
0
  }
62
63
0
  for (size_t i = 0; i < compact_pointers_.size(); i++) {
64
0
    PutVarint32(dst, kCompactPointer);
65
0
    PutVarint32(dst, compact_pointers_[i].first);  // level
66
0
    PutLengthPrefixedSlice(dst, compact_pointers_[i].second.Encode());
67
0
  }
68
69
0
  for (const auto& deleted_file_kvp : deleted_files_) {
70
0
    PutVarint32(dst, kDeletedFile);
71
0
    PutVarint32(dst, deleted_file_kvp.first);   // level
72
0
    PutVarint64(dst, deleted_file_kvp.second);  // file number
73
0
  }
74
75
0
  for (size_t i = 0; i < new_files_.size(); i++) {
76
0
    const FileMetaData& f = new_files_[i].second;
77
0
    PutVarint32(dst, kNewFile);
78
0
    PutVarint32(dst, new_files_[i].first);  // level
79
0
    PutVarint64(dst, f.number);
80
0
    PutVarint64(dst, f.file_size);
81
0
    PutLengthPrefixedSlice(dst, f.smallest.Encode());
82
0
    PutLengthPrefixedSlice(dst, f.largest.Encode());
83
0
  }
84
0
}
85
86
0
static bool GetInternalKey(Slice* input, InternalKey* dst) {
87
0
  Slice str;
88
0
  if (GetLengthPrefixedSlice(input, &str)) {
89
0
    return dst->DecodeFrom(str);
90
0
  } else {
91
0
    return false;
92
0
  }
93
0
}
94
95
0
static bool GetLevel(Slice* input, int* level) {
96
0
  uint32_t v;
97
0
  if (GetVarint32(input, &v) && v < config::kNumLevels) {
98
0
    *level = v;
99
0
    return true;
100
0
  } else {
101
0
    return false;
102
0
  }
103
0
}
104
105
0
Status VersionEdit::DecodeFrom(const Slice& src) {
106
0
  Clear();
107
0
  Slice input = src;
108
0
  const char* msg = nullptr;
109
0
  uint32_t tag;
110
111
  // Temporary storage for parsing
112
0
  int level;
113
0
  uint64_t number;
114
0
  FileMetaData f;
115
0
  Slice str;
116
0
  InternalKey key;
117
118
0
  while (msg == nullptr && GetVarint32(&input, &tag)) {
119
0
    switch (tag) {
120
0
      case kComparator:
121
0
        if (GetLengthPrefixedSlice(&input, &str)) {
122
0
          comparator_ = str.ToString();
123
0
          has_comparator_ = true;
124
0
        } else {
125
0
          msg = "comparator name";
126
0
        }
127
0
        break;
128
129
0
      case kLogNumber:
130
0
        if (GetVarint64(&input, &log_number_)) {
131
0
          has_log_number_ = true;
132
0
        } else {
133
0
          msg = "log number";
134
0
        }
135
0
        break;
136
137
0
      case kPrevLogNumber:
138
0
        if (GetVarint64(&input, &prev_log_number_)) {
139
0
          has_prev_log_number_ = true;
140
0
        } else {
141
0
          msg = "previous log number";
142
0
        }
143
0
        break;
144
145
0
      case kNextFileNumber:
146
0
        if (GetVarint64(&input, &next_file_number_)) {
147
0
          has_next_file_number_ = true;
148
0
        } else {
149
0
          msg = "next file number";
150
0
        }
151
0
        break;
152
153
0
      case kLastSequence:
154
0
        if (GetVarint64(&input, &last_sequence_)) {
155
0
          has_last_sequence_ = true;
156
0
        } else {
157
0
          msg = "last sequence number";
158
0
        }
159
0
        break;
160
161
0
      case kCompactPointer:
162
0
        if (GetLevel(&input, &level) && GetInternalKey(&input, &key)) {
163
0
          compact_pointers_.push_back(std::make_pair(level, key));
164
0
        } else {
165
0
          msg = "compaction pointer";
166
0
        }
167
0
        break;
168
169
0
      case kDeletedFile:
170
0
        if (GetLevel(&input, &level) && GetVarint64(&input, &number)) {
171
0
          deleted_files_.insert(std::make_pair(level, number));
172
0
        } else {
173
0
          msg = "deleted file";
174
0
        }
175
0
        break;
176
177
0
      case kNewFile:
178
0
        if (GetLevel(&input, &level) && GetVarint64(&input, &f.number) &&
179
0
            GetVarint64(&input, &f.file_size) &&
180
0
            GetInternalKey(&input, &f.smallest) &&
181
0
            GetInternalKey(&input, &f.largest)) {
182
0
          new_files_.push_back(std::make_pair(level, f));
183
0
        } else {
184
0
          msg = "new-file entry";
185
0
        }
186
0
        break;
187
188
0
      default:
189
0
        msg = "unknown tag";
190
0
        break;
191
0
    }
192
0
  }
193
194
0
  if (msg == nullptr && !input.empty()) {
195
0
    msg = "invalid tag";
196
0
  }
197
198
0
  Status result;
199
0
  if (msg != nullptr) {
200
0
    result = Status::Corruption("VersionEdit", msg);
201
0
  }
202
0
  return result;
203
0
}
204
205
0
std::string VersionEdit::DebugString() const {
206
0
  std::string r;
207
0
  r.append("VersionEdit {");
208
0
  if (has_comparator_) {
209
0
    r.append("\n  Comparator: ");
210
0
    r.append(comparator_);
211
0
  }
212
0
  if (has_log_number_) {
213
0
    r.append("\n  LogNumber: ");
214
0
    AppendNumberTo(&r, log_number_);
215
0
  }
216
0
  if (has_prev_log_number_) {
217
0
    r.append("\n  PrevLogNumber: ");
218
0
    AppendNumberTo(&r, prev_log_number_);
219
0
  }
220
0
  if (has_next_file_number_) {
221
0
    r.append("\n  NextFile: ");
222
0
    AppendNumberTo(&r, next_file_number_);
223
0
  }
224
0
  if (has_last_sequence_) {
225
0
    r.append("\n  LastSeq: ");
226
0
    AppendNumberTo(&r, last_sequence_);
227
0
  }
228
0
  for (size_t i = 0; i < compact_pointers_.size(); i++) {
229
0
    r.append("\n  CompactPointer: ");
230
0
    AppendNumberTo(&r, compact_pointers_[i].first);
231
0
    r.append(" ");
232
0
    r.append(compact_pointers_[i].second.DebugString());
233
0
  }
234
0
  for (const auto& deleted_files_kvp : deleted_files_) {
235
0
    r.append("\n  DeleteFile: ");
236
0
    AppendNumberTo(&r, deleted_files_kvp.first);
237
0
    r.append(" ");
238
0
    AppendNumberTo(&r, deleted_files_kvp.second);
239
0
  }
240
0
  for (size_t i = 0; i < new_files_.size(); i++) {
241
0
    const FileMetaData& f = new_files_[i].second;
242
0
    r.append("\n  AddFile: ");
243
0
    AppendNumberTo(&r, new_files_[i].first);
244
0
    r.append(" ");
245
0
    AppendNumberTo(&r, f.number);
246
0
    r.append(" ");
247
0
    AppendNumberTo(&r, f.file_size);
248
0
    r.append(" ");
249
0
    r.append(f.smallest.DebugString());
250
0
    r.append(" .. ");
251
0
    r.append(f.largest.DebugString());
252
0
  }
253
0
  r.append("\n}\n");
254
0
  return r;
255
0
}
256
257
}  // namespace leveldb