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.
1// Copyright (c) 2011 The LevelDB Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file. See the AUTHORS file for names of contributors.5#include "db/db_impl.h"7#include <stdint.h>8#include <stdio.h>10#include <algorithm>11#include <atomic>12#include <set>13#include <string>14#include <vector>16#include "db/builder.h"17#include "db/db_iter.h"18#include "db/dbformat.h"19#include "db/filename.h"20#include "db/log_reader.h"21#include "db/log_writer.h"22#include "db/memtable.h"23#include "db/table_cache.h"24#include "db/version_set.h"25#include "db/write_batch_internal.h"26#include "leveldb/db.h"27#include "leveldb/env.h"28#include "leveldb/status.h"29#include "leveldb/table.h"30#include "leveldb/table_builder.h"31#include "port/port.h"32#include "table/block.h"33#include "table/merger.h"34#include "table/two_level_iterator.h"35#include "util/coding.h"36#include "util/logging.h"37#include "util/mutexlock.h"39namespace leveldb {41const int kNumNonTableCacheFiles = 10;43// Information kept for every waiting writer44struct DBImpl::Writer {45explicit Writer(port::Mutex* mu)46: batch(nullptr), sync(false), done(false), cv(mu) {}48Status status;49WriteBatch* batch;50bool sync;51bool done;52port::CondVar cv;53};55struct DBImpl::CompactionState {56// Files produced by compaction57struct Output {58uint64_t number;59uint64_t file_size;60InternalKey smallest, largest;61};63Output* current_output() { return &outputs[outputs.size() - 1]; }65explicit CompactionState(Compaction* c)66: compaction(c),67smallest_snapshot(0),68outfile(nullptr),69builder(nullptr),70total_bytes(0) {}72Compaction* const compaction;74// Sequence numbers < smallest_snapshot are not significant since we75// will never have to service a snapshot below smallest_snapshot.76// Therefore if we have seen a sequence number S <= smallest_snapshot,77// we can drop all entries for the same key with sequence numbers < S.78SequenceNumber smallest_snapshot;80std::vector<Output> outputs;82// State kept for output being generated83WritableFile* outfile;84TableBuilder* builder;86uint64_t total_bytes;87};89// Fix user-supplied options to be reasonable90template <class T, class V>91static void ClipToRange(T* ptr, V minvalue, V maxvalue) {92if (static_cast<V>(*ptr) > maxvalue) *ptr = maxvalue;93if (static_cast<V>(*ptr) < minvalue) *ptr = minvalue;94}95Options SanitizeOptions(const std::string& dbname,96const InternalKeyComparator* icmp,97const InternalFilterPolicy* ipolicy,98const Options& src) {99Options result = src;100result.comparator = icmp;101result.filter_policy = (src.filter_policy != nullptr) ? ipolicy : nullptr;102ClipToRange(&result.max_open_files, 64 + kNumNonTableCacheFiles, 50000);103ClipToRange(&result.write_buffer_size, 64 << 10, 1 << 30);104ClipToRange(&result.max_file_size, 1 << 20, 1 << 30);105ClipToRange(&result.block_size, 1 << 10, 4 << 20);106if (result.info_log == nullptr) {107// Open a log file in the same directory as the db108src.env->CreateDir(dbname); // In case it does not exist109src.env->RenameFile(InfoLogFileName(dbname), OldInfoLogFileName(dbname));110Status s = src.env->NewLogger(InfoLogFileName(dbname), &result.info_log);111if (!s.ok()) {112// No place suitable for logging113result.info_log = nullptr;114}115}116if (result.block_cache == nullptr) {117result.block_cache = NewLRUCache(8 << 20);118}119return result;120}122static int TableCacheSize(const Options& sanitized_options) {123// Reserve ten files or so for other uses and give the rest to TableCache.124return sanitized_options.max_open_files - kNumNonTableCacheFiles;125}127DBImpl::DBImpl(const Options& raw_options, const std::string& dbname)128: env_(raw_options.env),129internal_comparator_(raw_options.comparator),130internal_filter_policy_(raw_options.filter_policy),131options_(SanitizeOptions(dbname, &internal_comparator_,132&internal_filter_policy_, raw_options)),133owns_info_log_(options_.info_log != raw_options.info_log),134owns_cache_(options_.block_cache != raw_options.block_cache),135dbname_(dbname),136table_cache_(new TableCache(dbname_, options_, TableCacheSize(options_))),137db_lock_(nullptr),138shutting_down_(false),139background_work_finished_signal_(&mutex_),140mem_(nullptr),141imm_(nullptr),142has_imm_(false),143logfile_(nullptr),144logfile_number_(0),145log_(nullptr),146seed_(0),147tmp_batch_(new WriteBatch),148background_compaction_scheduled_(false),149manual_compaction_(nullptr),150versions_(new VersionSet(dbname_, &options_, table_cache_,151&internal_comparator_)) {}153DBImpl::~DBImpl() {154// Wait for background work to finish.155mutex_.Lock();156shutting_down_.store(true, std::memory_order_release);157while (background_compaction_scheduled_) {158background_work_finished_signal_.Wait();159}160mutex_.Unlock();162if (db_lock_ != nullptr) {163env_->UnlockFile(db_lock_);164}166delete versions_;167if (mem_ != nullptr) mem_->Unref();168if (imm_ != nullptr) imm_->Unref();169delete tmp_batch_;170delete log_;171delete logfile_;172delete table_cache_;174if (owns_info_log_) {175delete options_.info_log;176}177if (owns_cache_) {178delete options_.block_cache;179}180}182Status DBImpl::NewDB() {183VersionEdit new_db;184new_db.SetComparatorName(user_comparator()->Name());185new_db.SetLogNumber(0);186new_db.SetNextFile(2);187new_db.SetLastSequence(0);189const std::string manifest = DescriptorFileName(dbname_, 1);190WritableFile* file;191Status s = env_->NewWritableFile(manifest, &file);192if (!s.ok()) {193return s;194}195{196log::Writer log(file);197std::string record;198new_db.EncodeTo(&record);199s = log.AddRecord(record);200if (s.ok()) {201s = file->Close();202}203}204delete file;205if (s.ok()) {206// Make "CURRENT" file that points to the new manifest file.207s = SetCurrentFile(env_, dbname_, 1);208} else {209env_->DeleteFile(manifest);210}211return s;212}214void DBImpl::MaybeIgnoreError(Status* s) const {215if (s->ok() || options_.paranoid_checks) {216// No change needed217} else {218Log(options_.info_log, "Ignoring error %s", s->ToString().c_str());219*s = Status::OK();220}221}223void DBImpl::DeleteObsoleteFiles() {224mutex_.AssertHeld();226if (!bg_error_.ok()) {227// After a background error, we don't know whether a new version may228// or may not have been committed, so we cannot safely garbage collect.229return;230}232// Make a set of all of the live files233std::set<uint64_t> live = pending_outputs_;234versions_->AddLiveFiles(&live);236std::vector<std::string> filenames;237env_->GetChildren(dbname_, &filenames); // Ignoring errors on purpose238uint64_t number;239FileType type;240std::vector<std::string> files_to_delete;241for (std::string& filename : filenames) {242if (ParseFileName(filename, &number, &type)) {243bool keep = true;244switch (type) {245case kLogFile:246keep = ((number >= versions_->LogNumber()) ||247(number == versions_->PrevLogNumber()));248break;249case kDescriptorFile:250// Keep my manifest file, and any newer incarnations'
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.