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_iter.h"7#include "db/db_impl.h"8#include "db/dbformat.h"9#include "db/filename.h"10#include "leveldb/env.h"11#include "leveldb/iterator.h"12#include "port/port.h"13#include "util/logging.h"14#include "util/mutexlock.h"15#include "util/random.h"17namespace leveldb {19#if 020static void DumpInternalIter(Iterator* iter) {21for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {22ParsedInternalKey k;23if (!ParseInternalKey(iter->key(), &k)) {24fprintf(stderr, "Corrupt '%s'\n", EscapeString(iter->key()).c_str());25} else {26fprintf(stderr, "@ '%s'\n", k.DebugString().c_str());27}28}29}30#endif32namespace {34// Memtables and sstables that make the DB representation contain35// (userkey,seq,type) => uservalue entries. DBIter36// combines multiple entries for the same userkey found in the DB37// representation into a single entry while accounting for sequence38// numbers, deletion markers, overwrites, etc.39class DBIter : public Iterator {40public:41// Which direction is the iterator currently moving?42// (1) When moving forward, the internal iterator is positioned at43// the exact entry that yields this->key(), this->value()44// (2) When moving backwards, the internal iterator is positioned45// just before all entries whose user key == this->key().46enum Direction { kForward, kReverse };48DBIter(DBImpl* db, const Comparator* cmp, Iterator* iter, SequenceNumber s,49uint32_t seed)50: db_(db),51user_comparator_(cmp),52iter_(iter),53sequence_(s),54direction_(kForward),55valid_(false),56rnd_(seed),57bytes_until_read_sampling_(RandomCompactionPeriod()) {}59DBIter(const DBIter&) = delete;60DBIter& operator=(const DBIter&) = delete;62~DBIter() override { delete iter_; }63bool Valid() const override { return valid_; }64Slice key() const override {65assert(valid_);66return (direction_ == kForward) ? ExtractUserKey(iter_->key()) : saved_key_;67}68Slice value() const override {69assert(valid_);70return (direction_ == kForward) ? iter_->value() : saved_value_;71}72Status status() const override {73if (status_.ok()) {74return iter_->status();75} else {76return status_;77}78}80void Next() override;81void Prev() override;82void Seek(const Slice& target) override;83void SeekToFirst() override;84void SeekToLast() override;86private:87void FindNextUserEntry(bool skipping, std::string* skip);88void FindPrevUserEntry();89bool ParseKey(ParsedInternalKey* key);91inline void SaveKey(const Slice& k, std::string* dst) {92dst->assign(k.data(), k.size());93}95inline void ClearSavedValue() {96if (saved_value_.capacity() > 1048576) {97std::string empty;98swap(empty, saved_value_);99} else {100saved_value_.clear();101}102}104// Picks the number of bytes that can be read until a compaction is scheduled.105size_t RandomCompactionPeriod() {106return rnd_.Uniform(2 * config::kReadBytesPeriod);107}109DBImpl* db_;110const Comparator* const user_comparator_;111Iterator* const iter_;112SequenceNumber const sequence_;113Status status_;114std::string saved_key_; // == current key when direction_==kReverse115std::string saved_value_; // == current raw value when direction_==kReverse116Direction direction_;117bool valid_;118Random rnd_;119size_t bytes_until_read_sampling_;120};122inline bool DBIter::ParseKey(ParsedInternalKey* ikey) {123Slice k = iter_->key();125size_t bytes_read = k.size() + iter_->value().size();126while (bytes_until_read_sampling_ < bytes_read) {127bytes_until_read_sampling_ += RandomCompactionPeriod();128db_->RecordReadSample(k);129}130assert(bytes_until_read_sampling_ >= bytes_read);131bytes_until_read_sampling_ -= bytes_read;133if (!ParseInternalKey(k, ikey)) {134status_ = Status::Corruption("corrupted internal key in DBIter");135return false;136} else {137return true;138}139}141void DBIter::Next() {142assert(valid_);144if (direction_ == kReverse) { // Switch directions?145direction_ = kForward;146// iter_ is pointing just before the entries for this->key(),147// so advance into the range of entries for this->key() and then148// use the normal skipping code below.149if (!iter_->Valid()) {150iter_->SeekToFirst();151} else {152iter_->Next();153}154if (!iter_->Valid()) {155valid_ = false;156saved_key_.clear();157return;158}159// saved_key_ already contains the key to skip past.160} else {161// Store in saved_key_ the current key so we skip it below.162SaveKey(ExtractUserKey(iter_->key()), &saved_key_);164// iter_ is pointing to current key. We can now safely move to the next to165// avoid checking current key.166iter_->Next();167if (!iter_->Valid()) {168valid_ = false;169saved_key_.clear();170return;171}172}174FindNextUserEntry(true, &saved_key_);175}177void DBIter::FindNextUserEntry(bool skipping, std::string* skip) {178// Loop until we hit an acceptable entry to yield179assert(iter_->Valid());180assert(direction_ == kForward);181do {182ParsedInternalKey ikey;183if (ParseKey(&ikey) && ikey.sequence <= sequence_) {184switch (ikey.type) {185case kTypeDeletion:186// Arrange to skip all upcoming entries for this key since187// they are hidden by this deletion.188SaveKey(ikey.user_key, skip);189skipping = true;190break;191case kTypeValue:192if (skipping &&193user_comparator_->Compare(ikey.user_key, *skip) <= 0) {194// Entry hidden195} else {196valid_ = true;197saved_key_.clear();198return;199}200break;201}202}203iter_->Next();204} while (iter_->Valid());205saved_key_.clear();206valid_ = false;207}209void DBIter::Prev() {210assert(valid_);212if (direction_ == kForward) { // Switch directions?213// iter_ is pointing at the current entry. Scan backwards until214// the key changes so we can use the normal reverse scanning code.215assert(iter_->Valid()); // Otherwise valid_ would have been false216SaveKey(ExtractUserKey(iter_->key()), &saved_key_);217while (true) {218iter_->Prev();219if (!iter_->Valid()) {220valid_ = false;221saved_key_.clear();222ClearSavedValue();223return;224}225if (user_comparator_->Compare(ExtractUserKey(iter_->key()), saved_key_) <2260) {227break;228}229}230direction_ = kReverse;231}233FindPrevUserEntry();234}236void DBIter::FindPrevUserEntry() {237assert(direction_ == kReverse);239ValueType value_type = kTypeDeletion;240if (iter_->Valid()) {241do {242ParsedInternalKey ikey;243if (ParseKey(&ikey) && ikey.sequence <= sequence_) {244if ((value_type != kTypeDeletion) &&245user_comparator_->Compare(ikey.user_key, saved_key_) < 0) {246// We encountered a non-deleted value in entries for previous keys,247break;248}249value_type = ikey.type;250if (value_type == kTypeDeletion) {
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.