classVersion{public:structGetStats{FileMetaData*seek_file;intseek_file_level;};voidAddIterators(constReadOptions&,std::vector<Iterator*>*iters);StatusGet(constReadOptions&,constLookupKey&key,std::string*val,GetStats*stats);boolUpdateStats(constGetStats&stats);boolRecordReadSample(Slicekey);voidRef();voidUnref();voidGetOverlappingInputs(intlevel,constInternalKey*begin,// nullptr means before all keys
constInternalKey*end,// nullptr means after all keys
std::vector<FileMetaData*>*inputs);boolOverlapInLevel(intlevel,constSlice*smallest_user_key,constSlice*largest_user_key);intPickLevelForMemTableOutput(constSlice&smallest_user_key,constSlice&largest_user_key);intNumFiles(intlevel)const{returnfiles_[level].size();}std::stringDebugString()const;private:friendclassCompaction;friendclassVersionSet;classLevelFileNumIterator;explicitVersion(VersionSet*vset):vset_(vset),next_(this),prev_(this),refs_(0),file_to_compact_(nullptr),file_to_compact_level_(-1),compaction_score_(-1),compaction_level_(-1){}Version(constVersion&)=delete;Version&operator=(constVersion&)=delete;~Version();Iterator*NewConcatenatingIterator(constReadOptions&,intlevel)const;voidForEachOverlapping(Sliceuser_key,Sliceinternal_key,void*arg,bool(*func)(void*,int,FileMetaData*));VersionSet*vset_;// VersionSet to which this Version belongs
Version*next_;// Next version in linked list
Version*prev_;// Previous version in linked list
intrefs_;// Number of live refs to this version
std::vector<FileMetaData*>files_[config::kNumLevels];FileMetaData*file_to_compact_;intfile_to_compact_level_;doublecompaction_score_;intcompaction_level_;};structFileMetaData{FileMetaData():refs(0),allowed_seeks(1<<30),file_size(0){}intrefs;// 引用计数
intallowed_seeks;// 用于seek compaction
uint64_tnumber;// 唯一标识一个sstable
uint64_tfile_size;// 文件大小
InternalKeysmallest;// 最小key
InternalKeylargest;// 最大key
};
classVersionSet{public:VersionSet(conststd::string&dbname,constOptions*options,TableCache*table_cache,constInternalKeyComparator*);VersionSet(constVersionSet&)=delete;VersionSet&operator=(constVersionSet&)=delete;~VersionSet();StatusLogAndApply(VersionEdit*edit,port::Mutex*mu)EXCLUSIVE_LOCKS_REQUIRED(mu);StatusRecover(bool*save_manifest);Version*current()const{returncurrent_;}uint64_tManifestFileNumber()const{returnmanifest_file_number_;}uint64_tNewFileNumber(){returnnext_file_number_++;}voidReuseFileNumber(uint64_tfile_number){if(next_file_number_==file_number+1){next_file_number_=file_number;}}intNumLevelFiles(intlevel)const;int64_tNumLevelBytes(intlevel)const;uint64_tLastSequence()const{returnlast_sequence_;}voidSetLastSequence(uint64_ts){assert(s>=last_sequence_);last_sequence_=s;}voidMarkFileNumberUsed(uint64_tnumber);uint64_tLogNumber()const{returnlog_number_;}uint64_tPrevLogNumber()const{returnprev_log_number_;}Compaction*PickCompaction();Compaction*CompactRange(intlevel,constInternalKey*begin,constInternalKey*end);int64_tMaxNextLevelOverlappingBytes();Iterator*MakeInputIterator(Compaction*c);boolNeedsCompaction()const{Version*v=current_;return(v->compaction_score_>=1)||(v->file_to_compact_!=nullptr);}voidAddLiveFiles(std::set<uint64_t>*live);uint64_tApproximateOffsetOf(Version*v,constInternalKey&key);structLevelSummaryStorage{charbuffer[100];};constchar*LevelSummary(LevelSummaryStorage*scratch)const;private:classBuilder;friendclassCompaction;friendclassVersion;boolReuseManifest(conststd::string&dscname,conststd::string&dscbase);voidFinalize(Version*v);voidGetRange(conststd::vector<FileMetaData*>&inputs,InternalKey*smallest,InternalKey*largest);voidGetRange2(conststd::vector<FileMetaData*>&inputs1,conststd::vector<FileMetaData*>&inputs2,InternalKey*smallest,InternalKey*largest);voidSetupOtherInputs(Compaction*c);StatusWriteSnapshot(log::Writer*log);voidAppendVersion(Version*v);Env*constenv_;conststd::stringdbname_;constOptions*constoptions_;TableCache*consttable_cache_;constInternalKeyComparatoricmp_;uint64_tnext_file_number_;uint64_tmanifest_file_number_;uint64_tlast_sequence_;uint64_tlog_number_;uint64_tprev_log_number_;// 0 or backing store for memtable being compacted
WritableFile*descriptor_file_;log::Writer*descriptor_log_;Versiondummy_versions_;// Head of circular doubly-linked list of versions.
Version*current_;// == dummy_versions_.prev_
std::stringcompact_pointer_[config::kNumLevels];};
// https://github.com/google/leveldb/blob/master/db/version_set.cc
StatusVersionSet::Recover(bool*save_manifest){structLogReporter:publiclog::Reader::Reporter{Status*status;voidCorruption(size_tbytes,constStatus&s)override{if(this->status->ok())*this->status=s;}};//读取CURRENT文件,找到Manifest文件
std::stringcurrent;Statuss=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;s=env_->NewSequentialFile(dscname,&file);if(!s.ok()){if(s.IsNotFound()){returnStatus::Corruption("CURRENT points to a non-existent file",s.ToString());}returns;}boolhave_log_number=false;boolhave_prev_log_number=false;boolhave_next_file=false;boolhave_last_sequence=false;uint64_tnext_file=0;uint64_tlast_sequence=0;uint64_tlog_number=0;uint64_tprev_log_number=0;Builderbuilder(this,current_);intread_records=0;{LogReporterreporter;reporter.status=&s;log::Readerreader(file,&reporter,true/*checksum*/,0/*initial_offset*/);Slicerecord;std::stringscratch;//读取versionedit并获取变更
while(reader.ReadRecord(&record,&scratch)&&s.ok()){++read_records;VersionEditedit;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()){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;}}}deletefile;file=nullptr;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*v=newVersion(this);builder.SaveTo(v);Finalize(v);//加入versionset并设置current指针
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;//判断是否能够复用已有MANIFEST文件
if(ReuseManifest(dscname,current)){}else{*save_manifest=true;}}else{std::stringerror=s.ToString();Log(options_->info_log,"Error recovering version set with %d records: %s",read_records,error.c_str());}returns;}
预览: