1. 程式人生 > >leveldb程式碼閱讀(16)——流程分析:開啟資料庫(詳細版本)

leveldb程式碼閱讀(16)——流程分析:開啟資料庫(詳細版本)

Status VersionSet::Recover() {
  
struct LogReporter : public log::Reader::Reporter {
    Status
* status;
    
virtualvoid Corruption(size_t bytes, const Status& s) {
      
if (this->status->ok()) *this->status = s;
    }
  };

  
// 讀取CURRENT檔案,獲取最新的MANIFEST檔案  std::string current;
  Status s 
= ReadFileToString(env_, CurrentFileName(dbname_), &current);
  
if (!s.ok()) {
    
return s;
  }
  
if (current.empty() || current[current.size()-1!='\n') {
    
return Status::Corruption("CURRENT file does not end with newline");
  }
  current.resize(current.size() 
-1);

  std::
string dscname = dbname_ 
+"/"+ current;
  SequentialFile
* file;
  
//開啟當前MANIFEST檔案  s = env_->NewSequentialFile(dscname, &file);
  
if (!s.ok()) {
    
return s;
  }

  
bool have_log_number =false;
  
bool have_prev_log_number =false;
  
bool have_next_file =false;
  
bool have_last_sequence =false;
  uint64_t next_file 
=0;
  uint64_t last_sequence 
=0;
  uint64_t log_number 
=0;
  uint64_t prev_log_number 
=0;
  Builder builder(
this, current_);

  {
    LogReporter reporter;
    reporter.status 
=&s;
    
//使用log::Reader讀取log記錄:VersionEdit    log::Reader reader(file, &reporter, true/*checksum*/0/*initial_offset*/);
    Slice record;
    std::
string scratch;
    
while (reader.ReadRecord(&record, &scratch) && s.ok()) {
      VersionEdit edit;
      s 
= edit.DecodeFrom(record);
      
if (s.ok()) {
        
if (edit.has_comparator_ &&
            edit.comparator_ 
!= icmp_.user_comparator()->Name()) {
          s 
= Status::InvalidArgument(
              edit.comparator_ 
+"does not match existing comparator ",
              icmp_.user_comparator()
->Name());
        }
      }

      
if (s.ok()) {
        
//應用Edit到VersionSet        builder.Apply(&edit);
      }

      
if (edit.has_log_number_) {
        log_number 
= edit.log_number_;
        have_log_number 
=true;
      }

      
if (edit.has_prev_log_number_) {
        prev_log_number 
= edit.prev_log_number_;
        have_prev_log_number 
=true;
      }

      
if (edit.has_next_file_number_) {
        next_file 
= edit.next_file_number_;
        have_next_file 
=true;
      }

      
if (edit.has_last_sequence_) {
        last_sequence 
= edit.last_sequence_;
        have_last_sequence 
=true;
      }
    }
  }
  delete file;
  file 
= NULL;

  
if (s.ok()) {
    
if (!have_next_file) {
      s 
= Status::Corruption("no meta-nextfile entry in descriptor");
    } 
elseif (!have_log_number) {
      s 
= Status::Corruption("no meta-lognumber entry in descriptor");
    } 
elseif (!have_last_sequence) {
      s 
= Status::Corruption("no last-sequence-number entry in descriptor");
    }

    
if (!have_prev_log_number) {
      prev_log_number 
=0;
    }

    MarkFileNumberUsed(prev_log_number);
    MarkFileNumberUsed(log_number);
  }

  
if (s.ok()) { //生成新的version,並設為current version    Version* v =new Version(this);
    builder.SaveTo(v);
    
// Install recovered version    Finalize(v);
    AppendVersion(v);
    manifest_file_number_ 
= next_file;
    next_file_number_ 
= next_file +1;
    last_sequence_ 
= last_sequence;
    log_number_ 
= log_number;
    prev_log_number_ 
= prev_log_number;
  }

  
return s;
}