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.
251source_ = nullptr;252}254StringSource* source_;255Table* table_;257TableConstructor();258};260// A helper class that converts internal format keys into user keys261class KeyConvertingIterator : public Iterator {262public:263explicit KeyConvertingIterator(Iterator* iter) : iter_(iter) {}265KeyConvertingIterator(const KeyConvertingIterator&) = delete;266KeyConvertingIterator& operator=(const KeyConvertingIterator&) = delete;268~KeyConvertingIterator() override { delete iter_; }270bool Valid() const override { return iter_->Valid(); }271void Seek(const Slice& target) override {272ParsedInternalKey ikey(target, kMaxSequenceNumber, kTypeValue);273std::string encoded;274AppendInternalKey(&encoded, ikey);275iter_->Seek(encoded);276}277void SeekToFirst() override { iter_->SeekToFirst(); }278void SeekToLast() override { iter_->SeekToLast(); }279void Next() override { iter_->Next(); }280void Prev() override { iter_->Prev(); }282Slice key() const override {283assert(Valid());284ParsedInternalKey key;285if (!ParseInternalKey(iter_->key(), &key)) {286status_ = Status::Corruption("malformed internal key");287return Slice("corrupted key");288}289return key.user_key;290}292Slice value() const override { return iter_->value(); }293Status status() const override {294return status_.ok() ? iter_->status() : status_;295}297private:298mutable Status status_;299Iterator* iter_;300};302class MemTableConstructor : public Constructor {303public:304explicit MemTableConstructor(const Comparator* cmp)305: Constructor(cmp), internal_comparator_(cmp) {306memtable_ = new MemTable(internal_comparator_);307memtable_->Ref();308}309~MemTableConstructor() override { memtable_->Unref(); }310Status FinishImpl(const Options& options, const KVMap& data) override {311memtable_->Unref();312memtable_ = new MemTable(internal_comparator_);313memtable_->Ref();314int seq = 1;315for (const auto& kvp : data) {316memtable_->Add(seq, kTypeValue, kvp.first, kvp.second);317seq++;318}319return Status::OK();320}321Iterator* NewIterator() const override {322return new KeyConvertingIterator(memtable_->NewIterator());323}325private:326const InternalKeyComparator internal_comparator_;327MemTable* memtable_;328};330class DBConstructor : public Constructor {331public:332explicit DBConstructor(const Comparator* cmp)333: Constructor(cmp), comparator_(cmp) {334db_ = nullptr;335NewDB();336}337~DBConstructor() override { delete db_; }338Status FinishImpl(const Options& options, const KVMap& data) override {339delete db_;340db_ = nullptr;341NewDB();342for (const auto& kvp : data) {343WriteBatch batch;344batch.Put(kvp.first, kvp.second);345ASSERT_TRUE(db_->Write(WriteOptions(), &batch).ok());346}347return Status::OK();348}349Iterator* NewIterator() const override {350return db_->NewIterator(ReadOptions());351}353DB* db() const override { return db_; }355private:356void NewDB() {357std::string name = test::TmpDir() + "/table_testdb";359Options options;360options.comparator = comparator_;361Status status = DestroyDB(name, options);362ASSERT_TRUE(status.ok()) << status.ToString();364options.create_if_missing = true;365options.error_if_exists = true;366options.write_buffer_size = 10000; // Something small to force merging367status = DB::Open(options, name, &db_);368ASSERT_TRUE(status.ok()) << status.ToString();369}371const Comparator* const comparator_;372DB* db_;373};375enum TestType { TABLE_TEST, BLOCK_TEST, MEMTABLE_TEST, DB_TEST };377struct TestArgs {378TestType type;379bool reverse_compare;380int restart_interval;381};383static const TestArgs kTestArgList[] = {384{TABLE_TEST, false, 16},385{TABLE_TEST, false, 1},386{TABLE_TEST, false, 1024},387{TABLE_TEST, true, 16},388{TABLE_TEST, true, 1},389{TABLE_TEST, true, 1024},391{BLOCK_TEST, false, 16},392{BLOCK_TEST, false, 1},393{BLOCK_TEST, false, 1024},394{BLOCK_TEST, true, 16},395{BLOCK_TEST, true, 1},396{BLOCK_TEST, true, 1024},398// Restart interval does not matter for memtables399{MEMTABLE_TEST, false, 16},400{MEMTABLE_TEST, true, 16},402// Do not bother with restart interval variations for DB403{DB_TEST, false, 16},404{DB_TEST, true, 16},405};406static const int kNumTestArgs = sizeof(kTestArgList) / sizeof(kTestArgList[0]);408class Harness {409public:410Harness() : constructor_(nullptr) {}412void Init(const TestArgs& args) {413delete constructor_;414constructor_ = nullptr;415options_ = Options();417options_.block_restart_interval = args.restart_interval;418// Use shorter block size for tests to exercise block boundary419// conditions more.420options_.block_size = 256;421if (args.reverse_compare) {422options_.comparator = &reverse_key_comparator;423}424switch (args.type) {425case TABLE_TEST:426constructor_ = new TableConstructor(options_.comparator);427break;428case BLOCK_TEST:429constructor_ = new BlockConstructor(options_.comparator);430break;431case MEMTABLE_TEST:432constructor_ = new MemTableConstructor(options_.comparator);433break;434case DB_TEST:435constructor_ = new DBConstructor(options_.comparator);436break;437}438}440~Harness() { delete constructor_; }442void Add(const std::string& key, const std::string& value) {443constructor_->Add(key, value);444}446void Test(Random* rnd) {447std::vector<std::string> keys;448KVMap data;449constructor_->Finish(options_, &keys, &data);451TestForwardScan(keys, data);452TestBackwardScan(keys, data);453TestRandomAccess(rnd, keys, data);454}456void TestForwardScan(const std::vector<std::string>& keys,457const KVMap& data) {458Iterator* iter = constructor_->NewIterator();459ASSERT_TRUE(!iter->Valid());460iter->SeekToFirst();461for (KVMap::const_iterator model_iter = data.begin();462model_iter != data.end(); ++model_iter) {463ASSERT_EQ(ToString(data, model_iter), ToString(iter));464iter->Next();465}466ASSERT_TRUE(!iter->Valid());467delete iter;468}470void TestBackwardScan(const std::vector<std::string>& keys,471const KVMap& data) {472Iterator* iter = constructor_->NewIterator();473ASSERT_TRUE(!iter->Valid());474iter->SeekToLast();475for (KVMap::const_reverse_iterator model_iter = data.rbegin();476model_iter != data.rend(); ++model_iter) {477ASSERT_EQ(ToString(data, model_iter), ToString(iter));478iter->Prev();479}480ASSERT_TRUE(!iter->Valid());481delete iter;482}484void TestRandomAccess(Random* rnd, const std::vector<std::string>& keys,485const KVMap& data) {486static const bool kVerbose = false;487Iterator* iter = constructor_->NewIterator();488ASSERT_TRUE(!iter->Valid());489KVMap::const_iterator model_iter = data.begin();490if (kVerbose) fprintf(stderr, "---\n");491for (int i = 0; i < 200; i++) {492const int toss = rnd->Uniform(5);493switch (toss) {494case 0: {495if (iter->Valid()) {496if (kVerbose) fprintf(stderr, "Next\n");497iter->Next();498++model_iter;499ASSERT_EQ(ToString(data, model_iter), ToString(iter));500}
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.