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#ifndef STORAGE_LEVELDB_DB_DBFORMAT_H_6#define STORAGE_LEVELDB_DB_DBFORMAT_H_8#include <cstddef>9#include <cstdint>10#include <string>12#include "leveldb/comparator.h"13#include "leveldb/db.h"14#include "leveldb/filter_policy.h"15#include "leveldb/slice.h"16#include "leveldb/table_builder.h"17#include "util/coding.h"18#include "util/logging.h"20namespace leveldb {22// Grouping of constants. We may want to make some of these23// parameters set via options.24namespace config {25static const int kNumLevels = 7;27// Level-0 compaction is started when we hit this many files.28static const int kL0_CompactionTrigger = 4;30// Soft limit on number of level-0 files. We slow down writes at this point.31static const int kL0_SlowdownWritesTrigger = 8;33// Maximum number of level-0 files. We stop writes at this point.34static const int kL0_StopWritesTrigger = 12;36// Maximum level to which a new compacted memtable is pushed if it37// does not create overlap. We try to push to level 2 to avoid the38// relatively expensive level 0=>1 compactions and to avoid some39// expensive manifest file operations. We do not push all the way to40// the largest level since that can generate a lot of wasted disk41// space if the same key space is being repeatedly overwritten.42static const int kMaxMemCompactLevel = 2;44// Approximate gap in bytes between samples of data read during iteration.45static const int kReadBytesPeriod = 1048576;47} // namespace config49class InternalKey;51// Value types encoded as the last component of internal keys.52// DO NOT CHANGE THESE ENUM VALUES: they are embedded in the on-disk53// data structures.54enum ValueType { kTypeDeletion = 0x0, kTypeValue = 0x1 };55// kValueTypeForSeek defines the ValueType that should be passed when56// constructing a ParsedInternalKey object for seeking to a particular57// sequence number (since we sort sequence numbers in decreasing order58// and the value type is embedded as the low 8 bits in the sequence59// number in internal keys, we need to use the highest-numbered60// ValueType, not the lowest).61static const ValueType kValueTypeForSeek = kTypeValue;63typedef uint64_t SequenceNumber;65// We leave eight bits empty at the bottom so a type and sequence#66// can be packed together into 64-bits.67static const SequenceNumber kMaxSequenceNumber = ((0x1ull << 56) - 1);69struct ParsedInternalKey {70Slice user_key;71SequenceNumber sequence;72ValueType type;74ParsedInternalKey() {} // Intentionally left uninitialized (for speed)75ParsedInternalKey(const Slice& u, const SequenceNumber& seq, ValueType t)76: user_key(u), sequence(seq), type(t) {}77std::string DebugString() const;78};80// Return the length of the encoding of "key".81inline size_t InternalKeyEncodingLength(const ParsedInternalKey& key) {82return key.user_key.size() + 8;83}85// Append the serialization of "key" to *result.86void AppendInternalKey(std::string* result, const ParsedInternalKey& key);88// Attempt to parse an internal key from "internal_key". On success,89// stores the parsed data in "*result", and returns true.90//91// On error, returns false, leaves "*result" in an undefined state.92bool ParseInternalKey(const Slice& internal_key, ParsedInternalKey* result);94// Returns the user key portion of an internal key.95inline Slice ExtractUserKey(const Slice& internal_key) {96assert(internal_key.size() >= 8);97return Slice(internal_key.data(), internal_key.size() - 8);98}100// A comparator for internal keys that uses a specified comparator for101// the user key portion and breaks ties by decreasing sequence number.102class InternalKeyComparator : public Comparator {103private:104const Comparator* user_comparator_;106public:107explicit InternalKeyComparator(const Comparator* c) : user_comparator_(c) {}108const char* Name() const override;109int Compare(const Slice& a, const Slice& b) const override;110void FindShortestSeparator(std::string* start,111const Slice& limit) const override;112void FindShortSuccessor(std::string* key) const override;114const Comparator* user_comparator() const { return user_comparator_; }116int Compare(const InternalKey& a, const InternalKey& b) const;117};119// Filter policy wrapper that converts from internal keys to user keys120class InternalFilterPolicy : public FilterPolicy {121private:122const FilterPolicy* const user_policy_;124public:125explicit InternalFilterPolicy(const FilterPolicy* p) : user_policy_(p) {}126const char* Name() const override;127void CreateFilter(const Slice* keys, int n, std::string* dst) const override;128bool KeyMayMatch(const Slice& key, const Slice& filter) const override;129};131// Modules in this directory should keep internal keys wrapped inside132// the following class instead of plain strings so that we do not133// incorrectly use string comparisons instead of an InternalKeyComparator.134class InternalKey {135private:136std::string rep_;138public:139InternalKey() {} // Leave rep_ as empty to indicate it is invalid140InternalKey(const Slice& user_key, SequenceNumber s, ValueType t) {141AppendInternalKey(&rep_, ParsedInternalKey(user_key, s, t));142}144bool DecodeFrom(const Slice& s) {145rep_.assign(s.data(), s.size());146return !rep_.empty();147}149Slice Encode() const {150assert(!rep_.empty());151return rep_;152}154Slice user_key() const { return ExtractUserKey(rep_); }156void SetFrom(const ParsedInternalKey& p) {157rep_.clear();158AppendInternalKey(&rep_, p);159}161void Clear() { rep_.clear(); }163std::string DebugString() const;164};166inline int InternalKeyComparator::Compare(const InternalKey& a,167const InternalKey& b) const {168return Compare(a.Encode(), b.Encode());169}171inline bool ParseInternalKey(const Slice& internal_key,172ParsedInternalKey* result) {173const size_t n = internal_key.size();174if (n < 8) return false;175uint64_t num = DecodeFixed64(internal_key.data() + n - 8);176uint8_t c = num & 0xff;177result->sequence = num >> 8;178result->type = static_cast<ValueType>(c);179result->user_key = Slice(internal_key.data(), n - 8);180return (c <= static_cast<uint8_t>(kTypeValue));181}183// A helper class useful for DBImpl::Get()184class LookupKey {185public:186// Initialize *this for looking up user_key at a snapshot with187// the specified sequence number.188LookupKey(const Slice& user_key, SequenceNumber sequence);190LookupKey(const LookupKey&) = delete;191LookupKey& operator=(const LookupKey&) = delete;193~LookupKey();195// Return a key suitable for lookup in a MemTable.196Slice memtable_key() const { return Slice(start_, end_ - start_); }198// Return an internal key (suitable for passing to an internal iterator)199Slice internal_key() const { return Slice(kstart_, end_ - kstart_); }201// Return the user key202Slice user_key() const { return Slice(kstart_, end_ - kstart_ - 8); }204private:205// We construct a char array of the form:206// klength varint32 <-- start_207// userkey char[klength] <-- kstart_208// tag uint64209// <-- end_210// The array is a suitable MemTable key.211// The suffix starting with "userkey" can be used as an InternalKey.212const char* start_;213const char* kstart_;214const char* end_;215char space_[200]; // Avoid allocation for short keys216};218inline LookupKey::~LookupKey() {219if (start_ != space_) delete[] start_;220}222} // namespace leveldb224#endif // STORAGE_LEVELDB_DB_DBFORMAT_H_
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.