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