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