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.
252Cache::Handle* LRUCache::Lookup(const Slice& key, uint32_t hash) {253MutexLock l(&mutex_);254LRUHandle* e = table_.Lookup(key, hash);255if (e != nullptr) {256Ref(e);257}258return reinterpret_cast<Cache::Handle*>(e);259}261void LRUCache::Release(Cache::Handle* handle) {262MutexLock l(&mutex_);263Unref(reinterpret_cast<LRUHandle*>(handle));264}266Cache::Handle* LRUCache::Insert(const Slice& key, uint32_t hash, void* value,267size_t charge,268void (*deleter)(const Slice& key,269void* value)) {270MutexLock l(&mutex_);272LRUHandle* e =273reinterpret_cast<LRUHandle*>(malloc(sizeof(LRUHandle) - 1 + key.size()));274e->value = value;275e->deleter = deleter;276e->charge = charge;277e->key_length = key.size();278e->hash = hash;279e->in_cache = false;280e->refs = 1; // for the returned handle.281memcpy(e->key_data, key.data(), key.size());283if (capacity_ > 0) {284e->refs++; // for the cache's reference.285e->in_cache = true;286LRU_Append(&in_use_, e);287usage_ += charge;288FinishErase(table_.Insert(e));289} else { // don't cache. (capacity_==0 is supported and turns off caching.)290// next is read by key() in an assert, so it must be initialized291e->next = nullptr;292}293while (usage_ > capacity_ && lru_.next != &lru_) {294LRUHandle* old = lru_.next;295assert(old->refs == 1);296bool erased = FinishErase(table_.Remove(old->key(), old->hash));297if (!erased) { // to avoid unused variable when compiled NDEBUG298assert(erased);299}300}302return reinterpret_cast<Cache::Handle*>(e);303}305// If e != nullptr, finish removing *e from the cache; it has already been306// removed from the hash table. Return whether e != nullptr.307bool LRUCache::FinishErase(LRUHandle* e) {308if (e != nullptr) {309assert(e->in_cache);310LRU_Remove(e);311e->in_cache = false;312usage_ -= e->charge;313Unref(e);314}315return e != nullptr;316}318void LRUCache::Erase(const Slice& key, uint32_t hash) {319MutexLock l(&mutex_);320FinishErase(table_.Remove(key, hash));321}323void LRUCache::Prune() {324MutexLock l(&mutex_);325while (lru_.next != &lru_) {326LRUHandle* e = lru_.next;327assert(e->refs == 1);328bool erased = FinishErase(table_.Remove(e->key(), e->hash));329if (!erased) { // to avoid unused variable when compiled NDEBUG330assert(erased);331}332}333}335static const int kNumShardBits = 4;336static const int kNumShards = 1 << kNumShardBits;338class ShardedLRUCache : public Cache {339private:340LRUCache shard_[kNumShards];341port::Mutex id_mutex_;342uint64_t last_id_;344static inline uint32_t HashSlice(const Slice& s) {345return Hash(s.data(), s.size(), 0);346}348static uint32_t Shard(uint32_t hash) { return hash >> (32 - kNumShardBits); }350public:351explicit ShardedLRUCache(size_t capacity) : last_id_(0) {352const size_t per_shard = (capacity + (kNumShards - 1)) / kNumShards;353for (int s = 0; s < kNumShards; s++) {354shard_[s].SetCapacity(per_shard);355}356}357~ShardedLRUCache() override {}358Handle* Insert(const Slice& key, void* value, size_t charge,359void (*deleter)(const Slice& key, void* value)) override {360const uint32_t hash = HashSlice(key);361return shard_[Shard(hash)].Insert(key, hash, value, charge, deleter);362}363Handle* Lookup(const Slice& key) override {364const uint32_t hash = HashSlice(key);365return shard_[Shard(hash)].Lookup(key, hash);366}367void Release(Handle* handle) override {368LRUHandle* h = reinterpret_cast<LRUHandle*>(handle);369shard_[Shard(h->hash)].Release(handle);370}371void Erase(const Slice& key) override {372const uint32_t hash = HashSlice(key);373shard_[Shard(hash)].Erase(key, hash);374}375void* Value(Handle* handle) override {376return reinterpret_cast<LRUHandle*>(handle)->value;377}378uint64_t NewId() override {379MutexLock l(&id_mutex_);380return ++(last_id_);381}382void Prune() override {383for (int s = 0; s < kNumShards; s++) {384shard_[s].Prune();385}386}387size_t TotalCharge() const override {388size_t total = 0;389for (int s = 0; s < kNumShards; s++) {390total += shard_[s].TotalCharge();391}392return total;393}394};396} // end anonymous namespace398Cache* NewLRUCache(size_t capacity) { return new ShardedLRUCache(capacity); }400} // 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.