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.
501Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit,502Version* base) {503mutex_.AssertHeld();504const uint64_t start_micros = env_->NowMicros();505FileMetaData meta;506meta.number = versions_->NewFileNumber();507pending_outputs_.insert(meta.number);508Iterator* iter = mem->NewIterator();509Log(options_.info_log, "Level-0 table #%llu: started",510(unsigned long long)meta.number);512Status s;513{514mutex_.Unlock();515s = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta);516mutex_.Lock();517}519Log(options_.info_log, "Level-0 table #%llu: %lld bytes %s",520(unsigned long long)meta.number, (unsigned long long)meta.file_size,521s.ToString().c_str());522delete iter;523pending_outputs_.erase(meta.number);525// Note that if file_size is zero, the file has been deleted and526// should not be added to the manifest.527int level = 0;528if (s.ok() && meta.file_size > 0) {529const Slice min_user_key = meta.smallest.user_key();530const Slice max_user_key = meta.largest.user_key();531if (base != nullptr) {532level = base->PickLevelForMemTableOutput(min_user_key, max_user_key);533}534edit->AddFile(level, meta.number, meta.file_size, meta.smallest,535meta.largest);536}538CompactionStats stats;539stats.micros = env_->NowMicros() - start_micros;540stats.bytes_written = meta.file_size;541stats_[level].Add(stats);542return s;543}545void DBImpl::CompactMemTable() {546mutex_.AssertHeld();547assert(imm_ != nullptr);549// Save the contents of the memtable as a new Table550VersionEdit edit;551Version* base = versions_->current();552base->Ref();553Status s = WriteLevel0Table(imm_, &edit, base);554base->Unref();556if (s.ok() && shutting_down_.load(std::memory_order_acquire)) {557s = Status::IOError("Deleting DB during memtable compaction");558}560// Replace immutable memtable with the generated Table561if (s.ok()) {562edit.SetPrevLogNumber(0);563edit.SetLogNumber(logfile_number_); // Earlier logs no longer needed564s = versions_->LogAndApply(&edit, &mutex_);565}567if (s.ok()) {568// Commit to the new state569imm_->Unref();570imm_ = nullptr;571has_imm_.store(false, std::memory_order_release);572DeleteObsoleteFiles();573} else {574RecordBackgroundError(s);575}576}578void DBImpl::CompactRange(const Slice* begin, const Slice* end) {579int max_level_with_files = 1;580{581MutexLock l(&mutex_);582Version* base = versions_->current();583for (int level = 1; level < config::kNumLevels; level++) {584if (base->OverlapInLevel(level, begin, end)) {585max_level_with_files = level;586}587}588}589TEST_CompactMemTable(); // TODO(sanjay): Skip if memtable does not overlap590for (int level = 0; level < max_level_with_files; level++) {591TEST_CompactRange(level, begin, end);592}593}595void DBImpl::TEST_CompactRange(int level, const Slice* begin,596const Slice* end) {597assert(level >= 0);598assert(level + 1 < config::kNumLevels);600InternalKey begin_storage, end_storage;602ManualCompaction manual;603manual.level = level;604manual.done = false;605if (begin == nullptr) {606manual.begin = nullptr;607} else {608begin_storage = InternalKey(*begin, kMaxSequenceNumber, kValueTypeForSeek);609manual.begin = &begin_storage;610}611if (end == nullptr) {612manual.end = nullptr;613} else {614end_storage = InternalKey(*end, 0, static_cast<ValueType>(0));615manual.end = &end_storage;616}618MutexLock l(&mutex_);619while (!manual.done && !shutting_down_.load(std::memory_order_acquire) &&620bg_error_.ok()) {621if (manual_compaction_ == nullptr) { // Idle622manual_compaction_ = &manual;623MaybeScheduleCompaction();624} else { // Running either my compaction or another compaction.625background_work_finished_signal_.Wait();626}627}628if (manual_compaction_ == &manual) {629// Cancel my manual compaction since we aborted early for some reason.630manual_compaction_ = nullptr;631}632}634Status DBImpl::TEST_CompactMemTable() {635// nullptr batch means just wait for earlier writes to be done636Status s = Write(WriteOptions(), nullptr);637if (s.ok()) {638// Wait until the compaction completes639MutexLock l(&mutex_);640while (imm_ != nullptr && bg_error_.ok()) {641background_work_finished_signal_.Wait();642}643if (imm_ != nullptr) {644s = bg_error_;645}646}647return s;648}650void DBImpl::RecordBackgroundError(const Status& s) {651mutex_.AssertHeld();652if (bg_error_.ok()) {653bg_error_ = s;654background_work_finished_signal_.SignalAll();655}656}658void DBImpl::MaybeScheduleCompaction() {659mutex_.AssertHeld();660if (background_compaction_scheduled_) {661// Already scheduled662} else if (shutting_down_.load(std::memory_order_acquire)) {663// DB is being deleted; no more background compactions664} else if (!bg_error_.ok()) {665// Already got an error; no more changes666} else if (imm_ == nullptr && manual_compaction_ == nullptr &&667!versions_->NeedsCompaction()) {668// No work to be done669} else {670background_compaction_scheduled_ = true;671env_->Schedule(&DBImpl::BGWork, this);672}673}675void DBImpl::BGWork(void* db) {676reinterpret_cast<DBImpl*>(db)->BackgroundCall();677}679void DBImpl::BackgroundCall() {680MutexLock l(&mutex_);681assert(background_compaction_scheduled_);682if (shutting_down_.load(std::memory_order_acquire)) {683// No more background work when shutting down.684} else if (!bg_error_.ok()) {685// No more background work after a background error.686} else {687BackgroundCompaction();688}690background_compaction_scheduled_ = false;692// Previous compaction may have produced too many files in a level,693// so reschedule another compaction if needed.694MaybeScheduleCompaction();695background_work_finished_signal_.SignalAll();696}698void DBImpl::BackgroundCompaction() {699mutex_.AssertHeld();701if (imm_ != nullptr) {702CompactMemTable();703return;704}706Compaction* c;707bool is_manual = (manual_compaction_ != nullptr);708InternalKey manual_end;709if (is_manual) {710ManualCompaction* m = manual_compaction_;711c = versions_->CompactRange(m->level, m->begin, m->end);712m->done = (c == nullptr);713if (c != nullptr) {714manual_end = c->input(0, c->num_input_files(0) - 1)->largest;715}716Log(options_.info_log,717"Manual compaction at level-%d from %s .. %s; will stop at %s\n",718m->level, (m->begin ? m->begin->DebugString().c_str() : "(begin)"),719(m->end ? m->end->DebugString().c_str() : "(end)"),720(m->done ? "(end)" : manual_end.DebugString().c_str()));721} else {722c = versions_->PickCompaction();723}725Status status;726if (c == nullptr) {727// Nothing to do728} else if (!is_manual && c->IsTrivialMove()) {729// Move file to next level730assert(c->num_input_files(0) == 1);731FileMetaData* f = c->input(0, 0);732c->edit()->DeleteFile(c->level(), f->number);733c->edit()->AddFile(c->level() + 1, f->number, f->file_size, f->smallest,734f->largest);735status = versions_->LogAndApply(c->edit(), &mutex_);736if (!status.ok()) {737RecordBackgroundError(status);738}739VersionSet::LevelSummaryStorage tmp;740Log(options_.info_log, "Moved #%lld to level-%d %lld bytes %s: %s\n",741static_cast<unsigned long long>(f->number), c->level() + 1,742static_cast<unsigned long long>(f->file_size),743status.ToString().c_str(), versions_->LevelSummary(&tmp));744} else {745CompactionState* compact = new CompactionState(c);746status = DoCompactionWork(compact);747if (!status.ok()) {748RecordBackgroundError(status);749}750CleanupCompaction(compact);
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.