leveldb程式碼閱讀(16)——流程分析:開啟資料庫(詳細版本)
阿新 • • 發佈:2019-02-02
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_), ¤t);
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;
}
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
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_
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
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;
}