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) 2018 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// Prevent Windows headers from defining min/max macros and instead6// use STL.7#ifndef NOMINMAX8#define NOMINMAX9#endif // ifndef NOMINMAX10#include <windows.h>12#include <algorithm>13#include <atomic>14#include <chrono>15#include <condition_variable>16#include <cstddef>17#include <cstdint>18#include <cstdlib>19#include <cstring>20#include <memory>21#include <mutex>22#include <queue>23#include <sstream>24#include <string>25#include <vector>27#include "leveldb/env.h"28#include "leveldb/slice.h"29#include "port/port.h"30#include "port/thread_annotations.h"31#include "util/env_windows_test_helper.h"32#include "util/logging.h"33#include "util/mutexlock.h"34#include "util/windows_logger.h"36#if defined(DeleteFile)37#undef DeleteFile38#endif // defined(DeleteFile)40namespace leveldb {42namespace {44constexpr const size_t kWritableFileBufferSize = 65536;46// Up to 1000 mmaps for 64-bit binaries; none for 32-bit.47constexpr int kDefaultMmapLimit = (sizeof(void*) >= 8) ? 1000 : 0;49// Can be set by by EnvWindowsTestHelper::SetReadOnlyMMapLimit().50int g_mmap_limit = kDefaultMmapLimit;52std::string GetWindowsErrorMessage(DWORD error_code) {53std::string message;54char* error_text = nullptr;55// Use MBCS version of FormatMessage to match return value.56size_t error_text_size = ::FormatMessageA(57FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER |58FORMAT_MESSAGE_IGNORE_INSERTS,59nullptr, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),60reinterpret_cast<char*>(&error_text), 0, nullptr);61if (!error_text) {62return message;63}64message.assign(error_text, error_text_size);65::LocalFree(error_text);66return message;67}69Status WindowsError(const std::string& context, DWORD error_code) {70if (error_code == ERROR_FILE_NOT_FOUND || error_code == ERROR_PATH_NOT_FOUND)71return Status::NotFound(context, GetWindowsErrorMessage(error_code));72return Status::IOError(context, GetWindowsErrorMessage(error_code));73}75class ScopedHandle {76public:77ScopedHandle(HANDLE handle) : handle_(handle) {}78ScopedHandle(const ScopedHandle&) = delete;79ScopedHandle(ScopedHandle&& other) noexcept : handle_(other.Release()) {}80~ScopedHandle() { Close(); }82ScopedHandle& operator=(const ScopedHandle&) = delete;84ScopedHandle& operator=(ScopedHandle&& rhs) = delete;86bool Close() {87if (!is_valid()) {88return true;89}90HANDLE h = handle_;91handle_ = INVALID_HANDLE_VALUE;92return ::CloseHandle(h);93}95bool is_valid() const {96return handle_ != INVALID_HANDLE_VALUE && handle_ != nullptr;97}99HANDLE get() const { return handle_; }101HANDLE Release() {102HANDLE h = handle_;103handle_ = INVALID_HANDLE_VALUE;104return h;105}107private:108HANDLE handle_;109};111// Helper class to limit resource usage to avoid exhaustion.112// Currently used to limit read-only file descriptors and mmap file usage113// so that we do not run out of file descriptors or virtual memory, or run into114// kernel performance problems for very large databases.115class Limiter {116public:117// Limit maximum number of resources to |max_acquires|.118Limiter(int max_acquires) : acquires_allowed_(max_acquires) {}120Limiter(const Limiter&) = delete;121Limiter operator=(const Limiter&) = delete;123// If another resource is available, acquire it and return true.124// Else return false.125bool Acquire() {126int old_acquires_allowed =127acquires_allowed_.fetch_sub(1, std::memory_order_relaxed);129if (old_acquires_allowed > 0) return true;131acquires_allowed_.fetch_add(1, std::memory_order_relaxed);132return false;133}135// Release a resource acquired by a previous call to Acquire() that returned136// true.137void Release() { acquires_allowed_.fetch_add(1, std::memory_order_relaxed); }139private:140// The number of available resources.141//142// This is a counter and is not tied to the invariants of any other class, so143// it can be operated on safely using std::memory_order_relaxed.144std::atomic<int> acquires_allowed_;145};147class WindowsSequentialFile : public SequentialFile {148public:149WindowsSequentialFile(std::string filename, ScopedHandle handle)150: handle_(std::move(handle)), filename_(std::move(filename)) {}151~WindowsSequentialFile() override {}153Status Read(size_t n, Slice* result, char* scratch) override {154DWORD bytes_read;155// DWORD is 32-bit, but size_t could technically be larger. However leveldb156// files are limited to leveldb::Options::max_file_size which is clamped to157// 1<<30 or 1 GiB.158assert(n <= std::numeric_limits<DWORD>::max());159if (!::ReadFile(handle_.get(), scratch, static_cast<DWORD>(n), &bytes_read,160nullptr)) {161return WindowsError(filename_, ::GetLastError());162}164*result = Slice(scratch, bytes_read);165return Status::OK();166}168Status Skip(uint64_t n) override {169LARGE_INTEGER distance;170distance.QuadPart = n;171if (!::SetFilePointerEx(handle_.get(), distance, nullptr, FILE_CURRENT)) {172return WindowsError(filename_, ::GetLastError());173}174return Status::OK();175}177std::string GetName() const override { return filename_; }179private:180const ScopedHandle handle_;181const std::string filename_;182};184class WindowsRandomAccessFile : public RandomAccessFile {185public:186WindowsRandomAccessFile(std::string filename, ScopedHandle handle)187: handle_(std::move(handle)), filename_(std::move(filename)) {}189~WindowsRandomAccessFile() override = default;191Status Read(uint64_t offset, size_t n, Slice* result,192char* scratch) const override {193DWORD bytes_read = 0;194OVERLAPPED overlapped = {};196overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);197overlapped.Offset = static_cast<DWORD>(offset);198if (!::ReadFile(handle_.get(), scratch, static_cast<DWORD>(n), &bytes_read,199&overlapped)) {200DWORD error_code = ::GetLastError();201if (error_code != ERROR_HANDLE_EOF) {202*result = Slice(scratch, 0);203return Status::IOError(filename_, GetWindowsErrorMessage(error_code));204}205}207*result = Slice(scratch, bytes_read);208return Status::OK();209}211std::string GetName() const override { return filename_; }213private:214const ScopedHandle handle_;215const std::string filename_;216};218class WindowsMmapReadableFile : public RandomAccessFile {219public:220// base[0,length-1] contains the mmapped contents of the file.221WindowsMmapReadableFile(std::string filename, char* mmap_base, size_t length,222Limiter* mmap_limiter)223: mmap_base_(mmap_base),224length_(length),225mmap_limiter_(mmap_limiter),226filename_(std::move(filename)) {}228~WindowsMmapReadableFile() override {229::UnmapViewOfFile(mmap_base_);230mmap_limiter_->Release();231}233Status Read(uint64_t offset, size_t n, Slice* result,234char* scratch) const override {235if (offset + n > length_) {236*result = Slice();237return WindowsError(filename_, ERROR_INVALID_PARAMETER);238}240*result = Slice(mmap_base_ + offset, n);241return Status::OK();242}244std::string GetName() const override { return filename_; }246private:247char* const mmap_base_;248const size_t length_;249Limiter* const mmap_limiter_;250const std::string filename_;
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.