version_edit.cc raw

   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
 258