Home | History | Annotate | Download | only in db
      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 (DeletedFileSet::const_iterator iter = deleted_files_.begin();
     70        iter != deleted_files_.end();
     71        ++iter) {
     72     PutVarint32(dst, kDeletedFile);
     73     PutVarint32(dst, iter->first);   // level
     74     PutVarint64(dst, iter->second);  // file number
     75   }
     76 
     77   for (size_t i = 0; i < new_files_.size(); i++) {
     78     const FileMetaData& f = new_files_[i].second;
     79     PutVarint32(dst, kNewFile);
     80     PutVarint32(dst, new_files_[i].first);  // level
     81     PutVarint64(dst, f.number);
     82     PutVarint64(dst, f.file_size);
     83     PutLengthPrefixedSlice(dst, f.smallest.Encode());
     84     PutLengthPrefixedSlice(dst, f.largest.Encode());
     85   }
     86 }
     87 
     88 static bool GetInternalKey(Slice* input, InternalKey* dst) {
     89   Slice str;
     90   if (GetLengthPrefixedSlice(input, &str)) {
     91     dst->DecodeFrom(str);
     92     return true;
     93   } else {
     94     return false;
     95   }
     96 }
     97 
     98 static bool GetLevel(Slice* input, int* level) {
     99   uint32_t v;
    100   if (GetVarint32(input, &v) &&
    101       v < config::kNumLevels) {
    102     *level = v;
    103     return true;
    104   } else {
    105     return false;
    106   }
    107 }
    108 
    109 Status VersionEdit::DecodeFrom(const Slice& src) {
    110   Clear();
    111   Slice input = src;
    112   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   while (msg == NULL && GetVarint32(&input, &tag)) {
    123     switch (tag) {
    124       case kComparator:
    125         if (GetLengthPrefixedSlice(&input, &str)) {
    126           comparator_ = str.ToString();
    127           has_comparator_ = true;
    128         } else {
    129           msg = "comparator name";
    130         }
    131         break;
    132 
    133       case kLogNumber:
    134         if (GetVarint64(&input, &log_number_)) {
    135           has_log_number_ = true;
    136         } else {
    137           msg = "log number";
    138         }
    139         break;
    140 
    141       case kPrevLogNumber:
    142         if (GetVarint64(&input, &prev_log_number_)) {
    143           has_prev_log_number_ = true;
    144         } else {
    145           msg = "previous log number";
    146         }
    147         break;
    148 
    149       case kNextFileNumber:
    150         if (GetVarint64(&input, &next_file_number_)) {
    151           has_next_file_number_ = true;
    152         } else {
    153           msg = "next file number";
    154         }
    155         break;
    156 
    157       case kLastSequence:
    158         if (GetVarint64(&input, &last_sequence_)) {
    159           has_last_sequence_ = true;
    160         } else {
    161           msg = "last sequence number";
    162         }
    163         break;
    164 
    165       case kCompactPointer:
    166         if (GetLevel(&input, &level) &&
    167             GetInternalKey(&input, &key)) {
    168           compact_pointers_.push_back(std::make_pair(level, key));
    169         } else {
    170           msg = "compaction pointer";
    171         }
    172         break;
    173 
    174       case kDeletedFile:
    175         if (GetLevel(&input, &level) &&
    176             GetVarint64(&input, &number)) {
    177           deleted_files_.insert(std::make_pair(level, number));
    178         } else {
    179           msg = "deleted file";
    180         }
    181         break;
    182 
    183       case kNewFile:
    184         if (GetLevel(&input, &level) &&
    185             GetVarint64(&input, &f.number) &&
    186             GetVarint64(&input, &f.file_size) &&
    187             GetInternalKey(&input, &f.smallest) &&
    188             GetInternalKey(&input, &f.largest)) {
    189           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   if (msg == NULL && !input.empty()) {
    202     msg = "invalid tag";
    203   }
    204 
    205   Status result;
    206   if (msg != NULL) {
    207     result = Status::Corruption("VersionEdit", msg);
    208   }
    209   return result;
    210 }
    211 
    212 std::string VersionEdit::DebugString() const {
    213   std::string r;
    214   r.append("VersionEdit {");
    215   if (has_comparator_) {
    216     r.append("\n  Comparator: ");
    217     r.append(comparator_);
    218   }
    219   if (has_log_number_) {
    220     r.append("\n  LogNumber: ");
    221     AppendNumberTo(&r, log_number_);
    222   }
    223   if (has_prev_log_number_) {
    224     r.append("\n  PrevLogNumber: ");
    225     AppendNumberTo(&r, prev_log_number_);
    226   }
    227   if (has_next_file_number_) {
    228     r.append("\n  NextFile: ");
    229     AppendNumberTo(&r, next_file_number_);
    230   }
    231   if (has_last_sequence_) {
    232     r.append("\n  LastSeq: ");
    233     AppendNumberTo(&r, last_sequence_);
    234   }
    235   for (size_t i = 0; i < compact_pointers_.size(); i++) {
    236     r.append("\n  CompactPointer: ");
    237     AppendNumberTo(&r, compact_pointers_[i].first);
    238     r.append(" ");
    239     r.append(compact_pointers_[i].second.DebugString());
    240   }
    241   for (DeletedFileSet::const_iterator iter = deleted_files_.begin();
    242        iter != deleted_files_.end();
    243        ++iter) {
    244     r.append("\n  DeleteFile: ");
    245     AppendNumberTo(&r, iter->first);
    246     r.append(" ");
    247     AppendNumberTo(&r, iter->second);
    248   }
    249   for (size_t i = 0; i < new_files_.size(); i++) {
    250     const FileMetaData& f = new_files_[i].second;
    251     r.append("\n  AddFile: ");
    252     AppendNumberTo(&r, new_files_[i].first);
    253     r.append(" ");
    254     AppendNumberTo(&r, f.number);
    255     r.append(" ");
    256     AppendNumberTo(&r, f.file_size);
    257     r.append(" ");
    258     r.append(f.smallest.DebugString());
    259     r.append(" .. ");
    260     r.append(f.largest.DebugString());
    261   }
    262   r.append("\n}\n");
    263   return r;
    264 }
    265 
    266 }  // namespace leveldb
    267