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