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 "leveldb/db.h"7#include <atomic>8#include <string>10#include "db/db_impl.h"11#include "db/filename.h"12#include "db/version_set.h"13#include "db/write_batch_internal.h"14#include "leveldb/cache.h"15#include "leveldb/env.h"16#include "leveldb/filter_policy.h"17#include "leveldb/table.h"18#include "port/port.h"19#include "port/thread_annotations.h"20#include "util/hash.h"21#include "util/logging.h"22#include "util/mutexlock.h"23#include "util/testharness.h"24#include "util/testutil.h"26namespace leveldb {28static std::string RandomString(Random* rnd, int len) {29std::string r;30test::RandomString(rnd, len, &r);31return r;32}34static std::string RandomKey(Random* rnd) {35int len =36(rnd->OneIn(3) ? 1 // Short sometimes to encourage collisions37: (rnd->OneIn(100) ? rnd->Skewed(10) : rnd->Uniform(10)));38return test::RandomKey(rnd, len);39}41namespace {42class AtomicCounter {43public:44AtomicCounter() : count_(0) {}45void Increment() { IncrementBy(1); }46void IncrementBy(int count) LOCKS_EXCLUDED(mu_) {47MutexLock l(&mu_);48count_ += count;49}50int Read() LOCKS_EXCLUDED(mu_) {51MutexLock l(&mu_);52return count_;53}54void Reset() LOCKS_EXCLUDED(mu_) {55MutexLock l(&mu_);56count_ = 0;57}59private:60port::Mutex mu_;61int count_ GUARDED_BY(mu_);62};64void DelayMilliseconds(int millis) {65Env::Default()->SleepForMicroseconds(millis * 1000);66}67} // namespace69// Test Env to override default Env behavior for testing.70class TestEnv : public EnvWrapper {71public:72explicit TestEnv(Env* base) : EnvWrapper(base), ignore_dot_files_(false) {}74void SetIgnoreDotFiles(bool ignored) { ignore_dot_files_ = ignored; }76Status GetChildren(const std::string& dir,77std::vector<std::string>* result) override {78Status s = target()->GetChildren(dir, result);79if (!s.ok() || !ignore_dot_files_) {80return s;81}83std::vector<std::string>::iterator it = result->begin();84while (it != result->end()) {85if ((*it == ".") || (*it == "..")) {86it = result->erase(it);87} else {88++it;89}90}92return s;93}95private:96bool ignore_dot_files_;97};99// Special Env used to delay background operations.100class SpecialEnv : public EnvWrapper {101public:102// sstable/log Sync() calls are blocked while this pointer is non-null.103std::atomic<bool> delay_data_sync_;105// sstable/log Sync() calls return an error.106std::atomic<bool> data_sync_error_;108// Simulate no-space errors while this pointer is non-null.109std::atomic<bool> no_space_;111// Simulate non-writable file system while this pointer is non-null.112std::atomic<bool> non_writable_;114// Force sync of manifest files to fail while this pointer is non-null.115std::atomic<bool> manifest_sync_error_;117// Force write to manifest files to fail while this pointer is non-null.118std::atomic<bool> manifest_write_error_;120bool count_random_reads_;121AtomicCounter random_read_counter_;123explicit SpecialEnv(Env* base)124: EnvWrapper(base),125delay_data_sync_(false),126data_sync_error_(false),127no_space_(false),128non_writable_(false),129manifest_sync_error_(false),130manifest_write_error_(false),131count_random_reads_(false) {}133Status NewWritableFile(const std::string& f, WritableFile** r) {134class DataFile : public WritableFile {135private:136SpecialEnv* const env_;137WritableFile* const base_;139public:140DataFile(SpecialEnv* env, WritableFile* base) : env_(env), base_(base) {}141~DataFile() { delete base_; }142Status Append(const Slice& data) override {143if (env_->no_space_.load(std::memory_order_acquire)) {144// Drop writes on the floor145return Status::OK();146} else {147return base_->Append(data);148}149}150Status Close() override { return base_->Close(); }151Status Flush() override { return base_->Flush(); }152Status Sync() override {153if (env_->data_sync_error_.load(std::memory_order_acquire)) {154return Status::IOError("simulated data sync error");155}156while (env_->delay_data_sync_.load(std::memory_order_acquire)) {157DelayMilliseconds(100);158}159return base_->Sync();160}161std::string GetName() const override { return ""; }162};163class ManifestFile : public WritableFile {164private:165SpecialEnv* env_;166WritableFile* base_;168public:169ManifestFile(SpecialEnv* env, WritableFile* b) : env_(env), base_(b) {}170~ManifestFile() { delete base_; }171Status Append(const Slice& data) override {172if (env_->manifest_write_error_.load(std::memory_order_acquire)) {173return Status::IOError("simulated writer error");174} else {175return base_->Append(data);176}177}178Status Close() override { return base_->Close(); }179Status Flush() override { return base_->Flush(); }180Status Sync() override {181if (env_->manifest_sync_error_.load(std::memory_order_acquire)) {182return Status::IOError("simulated sync error");183} else {184return base_->Sync();185}186}187std::string GetName() const override { return ""; }188};190if (non_writable_.load(std::memory_order_acquire)) {191return Status::IOError("simulated write error");192}194Status s = target()->NewWritableFile(f, r);195if (s.ok()) {196if (strstr(f.c_str(), ".ldb") != nullptr ||197strstr(f.c_str(), ".log") != nullptr) {198*r = new DataFile(this, *r);199} else if (strstr(f.c_str(), "MANIFEST") != nullptr) {200*r = new ManifestFile(this, *r);201}202}203return s;204}206Status NewRandomAccessFile(const std::string& f, RandomAccessFile** r) {207class CountingFile : public RandomAccessFile {208private:209RandomAccessFile* target_;210AtomicCounter* counter_;212public:213CountingFile(RandomAccessFile* target, AtomicCounter* counter)214: target_(target), counter_(counter) {}215~CountingFile() override { delete target_; }216Status Read(uint64_t offset, size_t n, Slice* result,217char* scratch) const override {218counter_->Increment();219return target_->Read(offset, n, result, scratch);220}221std::string GetName() const override { return ""; }222};224Status s = target()->NewRandomAccessFile(f, r);225if (s.ok() && count_random_reads_) {226*r = new CountingFile(*r, &random_read_counter_);227}228return s;229}230};232class DBTest {233public:234std::string dbname_;235SpecialEnv* env_;236DB* db_;238Options last_options_;240DBTest() : env_(new SpecialEnv(Env::Default())), option_config_(kDefault) {241filter_policy_ = NewBloomFilterPolicy(10);242dbname_ = test::TmpDir() + "/db_test";243DestroyDB(dbname_, Options());244db_ = nullptr;245Reopen();246}248~DBTest() {249delete db_;250DestroyDB(dbname_, Options());
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.