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 <dirent.h>6#include <fcntl.h>7#include <pthread.h>8#include <sys/mman.h>9#include <sys/resource.h>10#include <sys/stat.h>11#include <sys/time.h>12#include <sys/types.h>13#include <unistd.h>15#include <atomic>16#include <cerrno>17#include <cstddef>18#include <cstdint>19#include <cstdio>20#include <cstdlib>21#include <cstring>22#include <limits>23#include <queue>24#include <set>25#include <string>26#include <thread>27#include <type_traits>28#include <utility>30#include "leveldb/env.h"31#include "leveldb/slice.h"32#include "leveldb/status.h"33#include "port/port.h"34#include "port/thread_annotations.h"35#include "util/env_posix_test_helper.h"36#include "util/posix_logger.h"38namespace leveldb {40namespace {42// Set by EnvPosixTestHelper::SetReadOnlyMMapLimit() and MaxOpenFiles().43int g_open_read_only_file_limit = -1;45// Up to 1000 mmap regions for 64-bit binaries; none for 32-bit.46constexpr const int kDefaultMmapLimit = (sizeof(void*) >= 8) ? 1000 : 0;48// Can be set using EnvPosixTestHelper::SetReadOnlyMMapLimit().49int g_mmap_limit = kDefaultMmapLimit;51// Common flags defined for all posix open operations52#if HAVE_O_CLOEXEC53constexpr const int kOpenBaseFlags = O_CLOEXEC;54#else55constexpr const int kOpenBaseFlags = 0;56#endif // defined(HAVE_O_CLOEXEC)58constexpr const size_t kWritableFileBufferSize = 65536;60Status PosixError(const std::string& context, int error_number) {61if (error_number == ENOENT) {62return Status::NotFound(context, std::strerror(error_number));63} else {64return Status::IOError(context, std::strerror(error_number));65}66}68// Helper class to limit resource usage to avoid exhaustion.69// Currently used to limit read-only file descriptors and mmap file usage70// so that we do not run out of file descriptors or virtual memory, or run into71// kernel performance problems for very large databases.72class Limiter {73public:74// Limit maximum number of resources to |max_acquires|.75Limiter(int max_acquires) : acquires_allowed_(max_acquires) {}77Limiter(const Limiter&) = delete;78Limiter operator=(const Limiter&) = delete;80// If another resource is available, acquire it and return true.81// Else return false.82bool Acquire() {83int old_acquires_allowed =84acquires_allowed_.fetch_sub(1, std::memory_order_relaxed);86if (old_acquires_allowed > 0) return true;88acquires_allowed_.fetch_add(1, std::memory_order_relaxed);89return false;90}92// Release a resource acquired by a previous call to Acquire() that returned93// true.94void Release() { acquires_allowed_.fetch_add(1, std::memory_order_relaxed); }96private:97// The number of available resources.98//99// This is a counter and is not tied to the invariants of any other class, so100// it can be operated on safely using std::memory_order_relaxed.101std::atomic<int> acquires_allowed_;102};104// Implements sequential read access in a file using read().105//106// Instances of this class are thread-friendly but not thread-safe, as required107// by the SequentialFile API.108class PosixSequentialFile final : public SequentialFile {109public:110PosixSequentialFile(std::string filename, int fd)111: fd_(fd), filename_(filename) {}112~PosixSequentialFile() override { close(fd_); }114Status Read(size_t n, Slice* result, char* scratch) override {115Status status;116while (true) {117::ssize_t read_size = ::read(fd_, scratch, n);118if (read_size < 0) { // Read error.119if (errno == EINTR) {120continue; // Retry121}122status = PosixError(filename_, errno);123break;124}125*result = Slice(scratch, read_size);126break;127}128return status;129}131Status Skip(uint64_t n) override {132if (::lseek(fd_, n, SEEK_CUR) == static_cast<off_t>(-1)) {133return PosixError(filename_, errno);134}135return Status::OK();136}138virtual std::string GetName() const override { return filename_; }140private:141const int fd_;142const std::string filename_;143};145// Implements random read access in a file using pread().146//147// Instances of this class are thread-safe, as required by the RandomAccessFile148// API. Instances are immutable and Read() only calls thread-safe library149// functions.150class PosixRandomAccessFile final : public RandomAccessFile {151public:152// The new instance takes ownership of |fd|. |fd_limiter| must outlive this153// instance, and will be used to determine if .154PosixRandomAccessFile(std::string filename, int fd, Limiter* fd_limiter)155: has_permanent_fd_(fd_limiter->Acquire()),156fd_(has_permanent_fd_ ? fd : -1),157fd_limiter_(fd_limiter),158filename_(std::move(filename)) {159if (!has_permanent_fd_) {160assert(fd_ == -1);161::close(fd); // The file will be opened on every read.162}163}165~PosixRandomAccessFile() override {166if (has_permanent_fd_) {167assert(fd_ != -1);168::close(fd_);169fd_limiter_->Release();170}171}173Status Read(uint64_t offset, size_t n, Slice* result,174char* scratch) const override {175int fd = fd_;176if (!has_permanent_fd_) {177fd = ::open(filename_.c_str(), O_RDONLY | kOpenBaseFlags);178if (fd < 0) {179return PosixError(filename_, errno);180}181}183assert(fd != -1);185Status status;186ssize_t read_size = ::pread(fd, scratch, n, static_cast<off_t>(offset));187*result = Slice(scratch, (read_size < 0) ? 0 : read_size);188if (read_size < 0) {189// An error: return a non-ok status.190status = PosixError(filename_, errno);191}192if (!has_permanent_fd_) {193// Close the temporary file descriptor opened earlier.194assert(fd != fd_);195::close(fd);196}197return status;198}200virtual std::string GetName() const override { return filename_; }202private:203const bool has_permanent_fd_; // If false, the file is opened on every read.204const int fd_; // -1 if has_permanent_fd_ is false.205Limiter* const fd_limiter_;206const std::string filename_;207};209// Implements random read access in a file using mmap().210//211// Instances of this class are thread-safe, as required by the RandomAccessFile212// API. Instances are immutable and Read() only calls thread-safe library213// functions.214class PosixMmapReadableFile final : public RandomAccessFile {215public:216// mmap_base[0, length-1] points to the memory-mapped contents of the file. It217// must be the result of a successful call to mmap(). This instances takes218// over the ownership of the region.219//220// |mmap_limiter| must outlive this instance. The caller must have already221// acquired the right to use one mmap region, which will be released when this222// instance is destroyed.223PosixMmapReadableFile(std::string filename, char* mmap_base, size_t length,224Limiter* mmap_limiter)225: mmap_base_(mmap_base),226length_(length),227mmap_limiter_(mmap_limiter),228filename_(std::move(filename)) {}230~PosixMmapReadableFile() override {231::munmap(static_cast<void*>(mmap_base_), length_);232mmap_limiter_->Release();233}235Status Read(uint64_t offset, size_t n, Slice* result,236char* scratch) const override {237if (offset + n > length_) {238*result = Slice();239return PosixError(filename_, EINVAL);240}242*result = Slice(mmap_base_ + offset, n);243return Status::OK();244}246virtual std::string GetName() const override { return filename_; }248private:249char* const mmap_base_;250const size_t length_;
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.