Status VersionSet::Recover() {structLogReporter :publiclog::Reader::Reporter {
Status*status;virtualvoidCorruption(size_t bytes,constStatus&s) {if(this->status->ok())*this->status=s;
}
};//读取CURRENT文件,获取最新的MANIFEST文件std::stringcurrent;
Status s=ReadFileToString(env_, CurrentFileName(dbname_),¤t);if(!s.ok()) {returns;
}if(current.empty()||current[current.size()-1]!='\n') {returnStatus::Corruption("CURRENT file does not end with newline");
}
current.resize(current.size()-1);
std::stringdscname=dbname_+"/"+current;
SequentialFile*file;//打开当前MANIFEST文件s=env_->NewSequentialFile(dscname,&file);if(!s.ok()) {returns;
}boolhave_log_number=false;boolhave_prev_log_number=false;boolhave_next_file=false;boolhave_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记录:VersionEditlog::Reader reader(file,&reporter,true/*checksum*/,0/*initial_offset*/);
Slice record;
std::stringscratch;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到VersionSetbuilder.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 versionVersion*v=newVersion(this);
builder.SaveTo(v);//Install recovered versionFinalize(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;
}returns;
}