Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
751VersionSet::~VersionSet() {752current_->Unref();753assert(dummy_versions_.next_ == &dummy_versions_); // List must be empty754delete descriptor_log_;755delete descriptor_file_;756}758void VersionSet::AppendVersion(Version* v) {759// Make "v" current760assert(v->refs_ == 0);761assert(v != current_);762if (current_ != nullptr) {763current_->Unref();764}765current_ = v;766v->Ref();768// Append to linked list769v->prev_ = dummy_versions_.prev_;770v->next_ = &dummy_versions_;771v->prev_->next_ = v;772v->next_->prev_ = v;773}775Status VersionSet::LogAndApply(VersionEdit* edit, port::Mutex* mu) {776if (edit->has_log_number_) {777assert(edit->log_number_ >= log_number_);778assert(edit->log_number_ < next_file_number_);779} else {780edit->SetLogNumber(log_number_);781}783if (!edit->has_prev_log_number_) {784edit->SetPrevLogNumber(prev_log_number_);785}787edit->SetNextFile(next_file_number_);788edit->SetLastSequence(last_sequence_);790Version* v = new Version(this);791{792Builder builder(this, current_);793builder.Apply(edit);794builder.SaveTo(v);795}796Finalize(v);798// Initialize new descriptor log file if necessary by creating799// a temporary file that contains a snapshot of the current version.800std::string new_manifest_file;801Status s;802if (descriptor_log_ == nullptr) {803// No reason to unlock *mu here since we only hit this path in the804// first call to LogAndApply (when opening the database).805assert(descriptor_file_ == nullptr);806new_manifest_file = DescriptorFileName(dbname_, manifest_file_number_);807edit->SetNextFile(next_file_number_);808s = env_->NewWritableFile(new_manifest_file, &descriptor_file_);809if (s.ok()) {810descriptor_log_ = new log::Writer(descriptor_file_);811s = WriteSnapshot(descriptor_log_);812}813}815// Unlock during expensive MANIFEST log write816{817mu->Unlock();819// Write new record to MANIFEST log820if (s.ok()) {821std::string record;822edit->EncodeTo(&record);823s = descriptor_log_->AddRecord(record);824if (s.ok()) {825s = descriptor_file_->Sync();826}827if (!s.ok()) {828Log(options_->info_log, "MANIFEST write: %s\n", s.ToString().c_str());829}830}832// If we just created a new descriptor file, install it by writing a833// new CURRENT file that points to it.834if (s.ok() && !new_manifest_file.empty()) {835s = SetCurrentFile(env_, dbname_, manifest_file_number_);836}838mu->Lock();839}841// Install the new version842if (s.ok()) {843AppendVersion(v);844log_number_ = edit->log_number_;845prev_log_number_ = edit->prev_log_number_;846} else {847delete v;848if (!new_manifest_file.empty()) {849delete descriptor_log_;850delete descriptor_file_;851descriptor_log_ = nullptr;852descriptor_file_ = nullptr;853env_->DeleteFile(new_manifest_file);854}855}857return s;858}860Status VersionSet::Recover(bool* save_manifest) {861struct LogReporter : public log::Reader::Reporter {862Status* status;863void Corruption(size_t bytes, const Status& s) override {864if (this->status->ok()) *this->status = s;865}866};868// Read "CURRENT" file, which contains a pointer to the current manifest file869std::string current;870Status s = ReadFileToString(env_, CurrentFileName(dbname_), ¤t);871if (!s.ok()) {872return s;873}874if (current.empty() || current[current.size() - 1] != '\n') {875return Status::Corruption("CURRENT file does not end with newline");876}877current.resize(current.size() - 1);879std::string dscname = dbname_ + "/" + current;880SequentialFile* file;881s = env_->NewSequentialFile(dscname, &file);882if (!s.ok()) {883if (s.IsNotFound()) {884return Status::Corruption("CURRENT points to a non-existent file",885s.ToString());886}887return s;888}890bool have_log_number = false;891bool have_prev_log_number = false;892bool have_next_file = false;893bool have_last_sequence = false;894uint64_t next_file = 0;895uint64_t last_sequence = 0;896uint64_t log_number = 0;897uint64_t prev_log_number = 0;898Builder builder(this, current_);900{901LogReporter reporter;902reporter.status = &s;903log::Reader reader(file, &reporter, true /*checksum*/,9040 /*initial_offset*/);905Slice record;906std::string scratch;907while (reader.ReadRecord(&record, &scratch) && s.ok()) {908VersionEdit edit;909s = edit.DecodeFrom(record);910if (s.ok()) {911if (edit.has_comparator_ &&912edit.comparator_ != icmp_.user_comparator()->Name()) {913s = Status::InvalidArgument(914edit.comparator_ + " does not match existing comparator ",915icmp_.user_comparator()->Name());916}917}919if (s.ok()) {920builder.Apply(&edit);921}923if (edit.has_log_number_) {924log_number = edit.log_number_;925have_log_number = true;926}928if (edit.has_prev_log_number_) {929prev_log_number = edit.prev_log_number_;930have_prev_log_number = true;931}933if (edit.has_next_file_number_) {934next_file = edit.next_file_number_;935have_next_file = true;936}938if (edit.has_last_sequence_) {939last_sequence = edit.last_sequence_;940have_last_sequence = true;941}942}943}944delete file;945file = nullptr;947if (s.ok()) {948if (!have_next_file) {949s = Status::Corruption("no meta-nextfile entry in descriptor");950} else if (!have_log_number) {951s = Status::Corruption("no meta-lognumber entry in descriptor");952} else if (!have_last_sequence) {953s = Status::Corruption("no last-sequence-number entry in descriptor");954}956if (!have_prev_log_number) {957prev_log_number = 0;958}960MarkFileNumberUsed(prev_log_number);961MarkFileNumberUsed(log_number);962}964if (s.ok()) {965Version* v = new Version(this);966builder.SaveTo(v);967// Install recovered version968Finalize(v);969AppendVersion(v);970manifest_file_number_ = next_file;971next_file_number_ = next_file + 1;972last_sequence_ = last_sequence;973log_number_ = log_number;974prev_log_number_ = prev_log_number;976// See if we can reuse the existing MANIFEST file.977if (ReuseManifest(dscname, current)) {978// No need to save new manifest979} else {980*save_manifest = true;981}982}984return s;985}987bool VersionSet::ReuseManifest(const std::string& dscname,988const std::string& dscbase) {989if (!options_->reuse_logs) {990return false;991}992FileType manifest_type;993uint64_t manifest_number;994uint64_t manifest_size = 0;995if (!ParseFileName(dscbase, &manifest_number, &manifest_type) ||996manifest_type != kDescriptorFile ||997!env_->GetFileSize(dscname, &manifest_size).ok() ||998// Make new compacted MANIFEST if old one is too big999manifest_size >= TargetFileSize(options_)) {1000return false;
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.