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 "table/two_level_iterator.h"7#include "leveldb/table.h"8#include "table/block.h"9#include "table/format.h"10#include "table/iterator_wrapper.h"12namespace leveldb {14namespace {16typedef Iterator* (*BlockFunction)(void*, const ReadOptions&, const Slice&);18class TwoLevelIterator : public Iterator {19public:20TwoLevelIterator(Iterator* index_iter, BlockFunction block_function,21void* arg, const ReadOptions& options);23~TwoLevelIterator() override;25void Seek(const Slice& target) override;26void SeekToFirst() override;27void SeekToLast() override;28void Next() override;29void Prev() override;31bool Valid() const override { return data_iter_.Valid(); }32Slice key() const override {33assert(Valid());34return data_iter_.key();35}36Slice value() const override {37assert(Valid());38return data_iter_.value();39}40Status status() const override {41// It'd be nice if status() returned a const Status& instead of a Status42if (!index_iter_.status().ok()) {43return index_iter_.status();44} else if (data_iter_.iter() != nullptr && !data_iter_.status().ok()) {45return data_iter_.status();46} else {47return status_;48}49}51private:52void SaveError(const Status& s) {53if (status_.ok() && !s.ok()) status_ = s;54}55void SkipEmptyDataBlocksForward();56void SkipEmptyDataBlocksBackward();57void SetDataIterator(Iterator* data_iter);58void InitDataBlock();60BlockFunction block_function_;61void* arg_;62const ReadOptions options_;63Status status_;64IteratorWrapper index_iter_;65IteratorWrapper data_iter_; // May be nullptr66// If data_iter_ is non-null, then "data_block_handle_" holds the67// "index_value" passed to block_function_ to create the data_iter_.68std::string data_block_handle_;69};71TwoLevelIterator::TwoLevelIterator(Iterator* index_iter,72BlockFunction block_function, void* arg,73const ReadOptions& options)74: block_function_(block_function),75arg_(arg),76options_(options),77index_iter_(index_iter),78data_iter_(nullptr) {}80TwoLevelIterator::~TwoLevelIterator() = default;82void TwoLevelIterator::Seek(const Slice& target) {83index_iter_.Seek(target);84InitDataBlock();85if (data_iter_.iter() != nullptr) data_iter_.Seek(target);86SkipEmptyDataBlocksForward();87}89void TwoLevelIterator::SeekToFirst() {90index_iter_.SeekToFirst();91InitDataBlock();92if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst();93SkipEmptyDataBlocksForward();94}96void TwoLevelIterator::SeekToLast() {97index_iter_.SeekToLast();98InitDataBlock();99if (data_iter_.iter() != nullptr) data_iter_.SeekToLast();100SkipEmptyDataBlocksBackward();101}103void TwoLevelIterator::Next() {104assert(Valid());105data_iter_.Next();106SkipEmptyDataBlocksForward();107}109void TwoLevelIterator::Prev() {110assert(Valid());111data_iter_.Prev();112SkipEmptyDataBlocksBackward();113}115void TwoLevelIterator::SkipEmptyDataBlocksForward() {116while (data_iter_.iter() == nullptr || !data_iter_.Valid()) {117// Move to next block118if (!index_iter_.Valid()) {119SetDataIterator(nullptr);120return;121}122index_iter_.Next();123InitDataBlock();124if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst();125}126}128void TwoLevelIterator::SkipEmptyDataBlocksBackward() {129while (data_iter_.iter() == nullptr || !data_iter_.Valid()) {130// Move to next block131if (!index_iter_.Valid()) {132SetDataIterator(nullptr);133return;134}135index_iter_.Prev();136InitDataBlock();137if (data_iter_.iter() != nullptr) data_iter_.SeekToLast();138}139}141void TwoLevelIterator::SetDataIterator(Iterator* data_iter) {142if (data_iter_.iter() != nullptr) SaveError(data_iter_.status());143data_iter_.Set(data_iter);144}146void TwoLevelIterator::InitDataBlock() {147if (!index_iter_.Valid()) {148SetDataIterator(nullptr);149} else {150Slice handle = index_iter_.value();151if (data_iter_.iter() != nullptr &&152handle.compare(data_block_handle_) == 0) {153// data_iter_ is already constructed with this iterator, so154// no need to change anything155} else {156Iterator* iter = (*block_function_)(arg_, options_, handle);157data_block_handle_.assign(handle.data(), handle.size());158SetDataIterator(iter);159}160}161}163} // namespace165Iterator* NewTwoLevelIterator(Iterator* index_iter,166BlockFunction block_function, void* arg,167const ReadOptions& options) {168return new TwoLevelIterator(index_iter, block_function, arg, options);169}171} // namespace leveldb
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.