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