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/table.h"7#include <map>8#include <string>10#include "db/dbformat.h"11#include "db/memtable.h"12#include "db/write_batch_internal.h"13#include "leveldb/db.h"14#include "leveldb/env.h"15#include "leveldb/iterator.h"16#include "leveldb/table_builder.h"17#include "table/block.h"18#include "table/block_builder.h"19#include "table/format.h"20#include "util/random.h"21#include "util/testharness.h"22#include "util/testutil.h"24namespace leveldb {26// Return reverse of "key".27// Used to test non-lexicographic comparators.28static std::string Reverse(const Slice& key) {29std::string str(key.ToString());30std::string rev("");31for (std::string::reverse_iterator rit = str.rbegin(); rit != str.rend();32++rit) {33rev.push_back(*rit);34}35return rev;36}38namespace {39class ReverseKeyComparator : public Comparator {40public:41const char* Name() const override {42return "leveldb.ReverseBytewiseComparator";43}45int Compare(const Slice& a, const Slice& b) const override {46return BytewiseComparator()->Compare(Reverse(a), Reverse(b));47}49void FindShortestSeparator(std::string* start,50const Slice& limit) const override {51std::string s = Reverse(*start);52std::string l = Reverse(limit);53BytewiseComparator()->FindShortestSeparator(&s, l);54*start = Reverse(s);55}57void FindShortSuccessor(std::string* key) const override {58std::string s = Reverse(*key);59BytewiseComparator()->FindShortSuccessor(&s);60*key = Reverse(s);61}62};63} // namespace64static ReverseKeyComparator reverse_key_comparator;66static void Increment(const Comparator* cmp, std::string* key) {67if (cmp == BytewiseComparator()) {68key->push_back('\0');69} else {70assert(cmp == &reverse_key_comparator);71std::string rev = Reverse(*key);72rev.push_back('\0');73*key = Reverse(rev);74}75}77// An STL comparator that uses a Comparator78namespace {79struct STLLessThan {80const Comparator* cmp;82STLLessThan() : cmp(BytewiseComparator()) {}83STLLessThan(const Comparator* c) : cmp(c) {}84bool operator()(const std::string& a, const std::string& b) const {85return cmp->Compare(Slice(a), Slice(b)) < 0;86}87};88} // namespace90class StringSink : public WritableFile {91public:92~StringSink() override = default;94const std::string& contents() const { return contents_; }96Status Close() override { return Status::OK(); }97Status Flush() override { return Status::OK(); }98Status Sync() override { return Status::OK(); }100Status Append(const Slice& data) override {101contents_.append(data.data(), data.size());102return Status::OK();103}105std::string GetName() const override { return ""; }106private:107std::string contents_;108};110class StringSource : public RandomAccessFile {111public:112StringSource(const Slice& contents)113: contents_(contents.data(), contents.size()) {}115~StringSource() override = default;117uint64_t Size() const { return contents_.size(); }119Status Read(uint64_t offset, size_t n, Slice* result,120char* scratch) const override {121if (offset >= contents_.size()) {122return Status::InvalidArgument("invalid Read offset");123}124if (offset + n > contents_.size()) {125n = contents_.size() - offset;126}127memcpy(scratch, &contents_[offset], n);128*result = Slice(scratch, n);129return Status::OK();130}132std::string GetName() const override { return ""; }133private:134std::string contents_;135};137typedef std::map<std::string, std::string, STLLessThan> KVMap;139// Helper class for tests to unify the interface between140// BlockBuilder/TableBuilder and Block/Table.141class Constructor {142public:143explicit Constructor(const Comparator* cmp) : data_(STLLessThan(cmp)) {}144virtual ~Constructor() = default;146void Add(const std::string& key, const Slice& value) {147data_[key] = value.ToString();148}150// Finish constructing the data structure with all the keys that have151// been added so far. Returns the keys in sorted order in "*keys"152// and stores the key/value pairs in "*kvmap"153void Finish(const Options& options, std::vector<std::string>* keys,154KVMap* kvmap) {155*kvmap = data_;156keys->clear();157for (const auto& kvp : data_) {158keys->push_back(kvp.first);159}160data_.clear();161Status s = FinishImpl(options, *kvmap);162ASSERT_TRUE(s.ok()) << s.ToString();163}165// Construct the data structure from the data in "data"166virtual Status FinishImpl(const Options& options, const KVMap& data) = 0;168virtual Iterator* NewIterator() const = 0;170const KVMap& data() const { return data_; }172virtual DB* db() const { return nullptr; } // Overridden in DBConstructor174private:175KVMap data_;176};178class BlockConstructor : public Constructor {179public:180explicit BlockConstructor(const Comparator* cmp)181: Constructor(cmp), comparator_(cmp), block_(nullptr) {}182~BlockConstructor() override { delete block_; }183Status FinishImpl(const Options& options, const KVMap& data) override {184delete block_;185block_ = nullptr;186BlockBuilder builder(&options);188for (const auto& kvp : data) {189builder.Add(kvp.first, kvp.second);190}191// Open the block192data_ = builder.Finish().ToString();193BlockContents contents;194contents.data = data_;195contents.cachable = false;196contents.heap_allocated = false;197block_ = new Block(contents);198return Status::OK();199}200Iterator* NewIterator() const override {201return block_->NewIterator(comparator_);202}204private:205const Comparator* const comparator_;206std::string data_;207Block* block_;209BlockConstructor();210};212class TableConstructor : public Constructor {213public:214TableConstructor(const Comparator* cmp)215: Constructor(cmp), source_(nullptr), table_(nullptr) {}216~TableConstructor() override { Reset(); }217Status FinishImpl(const Options& options, const KVMap& data) override {218Reset();219StringSink sink;220TableBuilder builder(options, &sink);222for (const auto& kvp : data) {223builder.Add(kvp.first, kvp.second);224ASSERT_TRUE(builder.status().ok());225}226Status s = builder.Finish();227ASSERT_TRUE(s.ok()) << s.ToString();229ASSERT_EQ(sink.contents().size(), builder.FileSize());231// Open the table232source_ = new StringSource(sink.contents());233Options table_options;234table_options.comparator = options.comparator;235return Table::Open(table_options, source_, sink.contents().size(), &table_);236}238Iterator* NewIterator() const override {239return table_->NewIterator(ReadOptions());240}242uint64_t ApproximateOffsetOf(const Slice& key) const {243return table_->ApproximateOffsetOf(key);244}246private:247void Reset() {248delete table_;249delete source_;250table_ = nullptr;
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.