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.
751c->ReleaseInputs();752DeleteObsoleteFiles();753}754delete c;756if (status.ok()) {757// Done758} else if (shutting_down_.load(std::memory_order_acquire)) {759// Ignore compaction errors found during shutting down760} else {761Log(options_.info_log, "Compaction error: %s", status.ToString().c_str());762}764if (is_manual) {765ManualCompaction* m = manual_compaction_;766if (!status.ok()) {767m->done = true;768}769if (!m->done) {770// We only compacted part of the requested range. Update *m771// to the range that is left to be compacted.772m->tmp_storage = manual_end;773m->begin = &m->tmp_storage;774}775manual_compaction_ = nullptr;776}777}779void DBImpl::CleanupCompaction(CompactionState* compact) {780mutex_.AssertHeld();781if (compact->builder != nullptr) {782// May happen if we get a shutdown call in the middle of compaction783compact->builder->Abandon();784delete compact->builder;785} else {786assert(compact->outfile == nullptr);787}788delete compact->outfile;789for (size_t i = 0; i < compact->outputs.size(); i++) {790const CompactionState::Output& out = compact->outputs[i];791pending_outputs_.erase(out.number);792}793delete compact;794}796Status DBImpl::OpenCompactionOutputFile(CompactionState* compact) {797assert(compact != nullptr);798assert(compact->builder == nullptr);799uint64_t file_number;800{801mutex_.Lock();802file_number = versions_->NewFileNumber();803pending_outputs_.insert(file_number);804CompactionState::Output out;805out.number = file_number;806out.file_size = 0;807out.smallest.Clear();808out.largest.Clear();809compact->outputs.push_back(out);810mutex_.Unlock();811}813// Make the output file814std::string fname = TableFileName(dbname_, file_number);815Status s = env_->NewWritableFile(fname, &compact->outfile);816if (s.ok()) {817compact->builder = new TableBuilder(options_, compact->outfile);818}819return s;820}822Status DBImpl::FinishCompactionOutputFile(CompactionState* compact,823Iterator* input) {824assert(compact != nullptr);825assert(compact->outfile != nullptr);826assert(compact->builder != nullptr);828const uint64_t output_number = compact->current_output()->number;829assert(output_number != 0);831// Check for iterator errors832Status s = input->status();833const uint64_t current_entries = compact->builder->NumEntries();834if (s.ok()) {835s = compact->builder->Finish();836} else {837compact->builder->Abandon();838}839const uint64_t current_bytes = compact->builder->FileSize();840compact->current_output()->file_size = current_bytes;841compact->total_bytes += current_bytes;842delete compact->builder;843compact->builder = nullptr;845// Finish and check for file errors846if (s.ok()) {847s = compact->outfile->Sync();848}849if (s.ok()) {850s = compact->outfile->Close();851}852delete compact->outfile;853compact->outfile = nullptr;855if (s.ok() && current_entries > 0) {856// Verify that the table is usable857Iterator* iter =858table_cache_->NewIterator(ReadOptions(), output_number, current_bytes);859s = iter->status();860delete iter;861if (s.ok()) {862Log(options_.info_log, "Generated table #%llu@%d: %lld keys, %lld bytes",863(unsigned long long)output_number, compact->compaction->level(),864(unsigned long long)current_entries,865(unsigned long long)current_bytes);866}867}868return s;869}871Status DBImpl::InstallCompactionResults(CompactionState* compact) {872mutex_.AssertHeld();873Log(options_.info_log, "Compacted %d@%d + %d@%d files => %lld bytes",874compact->compaction->num_input_files(0), compact->compaction->level(),875compact->compaction->num_input_files(1), compact->compaction->level() + 1,876static_cast<long long>(compact->total_bytes));878// Add compaction outputs879compact->compaction->AddInputDeletions(compact->compaction->edit());880const int level = compact->compaction->level();881for (size_t i = 0; i < compact->outputs.size(); i++) {882const CompactionState::Output& out = compact->outputs[i];883compact->compaction->edit()->AddFile(level + 1, out.number, out.file_size,884out.smallest, out.largest);885}886return versions_->LogAndApply(compact->compaction->edit(), &mutex_);887}889Status DBImpl::DoCompactionWork(CompactionState* compact) {890const uint64_t start_micros = env_->NowMicros();891int64_t imm_micros = 0; // Micros spent doing imm_ compactions893Log(options_.info_log, "Compacting %d@%d + %d@%d files",894compact->compaction->num_input_files(0), compact->compaction->level(),895compact->compaction->num_input_files(1),896compact->compaction->level() + 1);898assert(versions_->NumLevelFiles(compact->compaction->level()) > 0);899assert(compact->builder == nullptr);900assert(compact->outfile == nullptr);901if (snapshots_.empty()) {902compact->smallest_snapshot = versions_->LastSequence();903} else {904compact->smallest_snapshot = snapshots_.oldest()->sequence_number();905}907Iterator* input = versions_->MakeInputIterator(compact->compaction);909// Release mutex while we're actually doing the compaction work910mutex_.Unlock();912input->SeekToFirst();913Status status;914ParsedInternalKey ikey;915std::string current_user_key;916bool has_current_user_key = false;917SequenceNumber last_sequence_for_key = kMaxSequenceNumber;918while (input->Valid() && !shutting_down_.load(std::memory_order_acquire)) {919// Prioritize immutable compaction work920if (has_imm_.load(std::memory_order_relaxed)) {921const uint64_t imm_start = env_->NowMicros();922mutex_.Lock();923if (imm_ != nullptr) {924CompactMemTable();925// Wake up MakeRoomForWrite() if necessary.926background_work_finished_signal_.SignalAll();927}928mutex_.Unlock();929imm_micros += (env_->NowMicros() - imm_start);930}932Slice key = input->key();933if (compact->compaction->ShouldStopBefore(key) &&934compact->builder != nullptr) {935status = FinishCompactionOutputFile(compact, input);936if (!status.ok()) {937break;938}939}941// Handle key/value, add to state, etc.942bool drop = false;943if (!ParseInternalKey(key, &ikey)) {944// Do not hide error keys945current_user_key.clear();946has_current_user_key = false;947last_sequence_for_key = kMaxSequenceNumber;948} else {949if (!has_current_user_key ||950user_comparator()->Compare(ikey.user_key, Slice(current_user_key)) !=9510) {952// First occurrence of this user key953current_user_key.assign(ikey.user_key.data(), ikey.user_key.size());954has_current_user_key = true;955last_sequence_for_key = kMaxSequenceNumber;956}958if (last_sequence_for_key <= compact->smallest_snapshot) {959// Hidden by an newer entry for same user key960drop = true; // (A)961} else if (ikey.type == kTypeDeletion &&962ikey.sequence <= compact->smallest_snapshot &&963compact->compaction->IsBaseLevelForKey(ikey.user_key)) {964// For this user key:965// (1) there is no data in higher levels966// (2) data in lower levels will have larger sequence numbers967// (3) data in layers that are being compacted here and have968// smaller sequence numbers will be dropped in the next969// few iterations of this loop (by rule (A) above).970// Therefore this deletion marker is obsolete and can be dropped.971drop = true;972}974last_sequence_for_key = ikey.sequence;975}976#if 0977Log(options_.info_log,978" Compact: %s, seq %d, type: %d %d, drop: %d, is_base: %d, "979"%d smallest_snapshot: %d",980ikey.user_key.ToString().c_str(),981(int)ikey.sequence, ikey.type, kTypeValue, drop,982compact->compaction->IsBaseLevelForKey(ikey.user_key),983(int)last_sequence_for_key, (int)compact->smallest_snapshot);984#endif986if (!drop) {987// Open output file if necessary988if (compact->builder == nullptr) {989status = OpenCompactionOutputFile(compact);990if (!status.ok()) {991break;992}993}994if (compact->builder->NumEntries() == 0) {995compact->current_output()->smallest.DecodeFrom(key);996}997compact->current_output()->largest.DecodeFrom(key);998compact->builder->Add(key, input->value());1000// Close output file if it is big enough
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.