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.4//5// Logger implementation that can be shared by all environments6// where enough posix functionality is available.8#ifndef STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_9#define STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_11#include <sys/time.h>13#include <cassert>14#include <cstdarg>15#include <cstdio>16#include <ctime>17#include <sstream>18#include <thread>20#include "leveldb/env.h"22namespace leveldb {24class PosixLogger final : public Logger {25public:26// Creates a logger that writes to the given file.27//28// The PosixLogger instance takes ownership of the file handle.29explicit PosixLogger(std::FILE* fp) : fp_(fp) { assert(fp != nullptr); }31~PosixLogger() override { std::fclose(fp_); }33void Logv(const char* format, va_list arguments) override {34// Record the time as close to the Logv() call as possible.35struct ::timeval now_timeval;36::gettimeofday(&now_timeval, nullptr);37const std::time_t now_seconds = now_timeval.tv_sec;38struct std::tm now_components;39::localtime_r(&now_seconds, &now_components);41// Record the thread ID.42constexpr const int kMaxThreadIdSize = 32;43std::ostringstream thread_stream;44thread_stream << std::this_thread::get_id();45std::string thread_id = thread_stream.str();46if (thread_id.size() > kMaxThreadIdSize) {47thread_id.resize(kMaxThreadIdSize);48}50// We first attempt to print into a stack-allocated buffer. If this attempt51// fails, we make a second attempt with a dynamically allocated buffer.52constexpr const int kStackBufferSize = 512;53char stack_buffer[kStackBufferSize];54static_assert(sizeof(stack_buffer) == static_cast<size_t>(kStackBufferSize),55"sizeof(char) is expected to be 1 in C++");57int dynamic_buffer_size = 0; // Computed in the first iteration.58for (int iteration = 0; iteration < 2; ++iteration) {59const int buffer_size =60(iteration == 0) ? kStackBufferSize : dynamic_buffer_size;61char* const buffer =62(iteration == 0) ? stack_buffer : new char[dynamic_buffer_size];64// Print the header into the buffer.65int buffer_offset = snprintf(66buffer, buffer_size, "%04d/%02d/%02d-%02d:%02d:%02d.%06d %s ",67now_components.tm_year + 1900, now_components.tm_mon + 1,68now_components.tm_mday, now_components.tm_hour, now_components.tm_min,69now_components.tm_sec, static_cast<int>(now_timeval.tv_usec),70thread_id.c_str());72// The header can be at most 28 characters (10 date + 15 time +73// 3 delimiters) plus the thread ID, which should fit comfortably into the74// static buffer.75assert(buffer_offset <= 28 + kMaxThreadIdSize);76static_assert(28 + kMaxThreadIdSize < kStackBufferSize,77"stack-allocated buffer may not fit the message header");78assert(buffer_offset < buffer_size);80// Print the message into the buffer.81std::va_list arguments_copy;82va_copy(arguments_copy, arguments);83buffer_offset +=84std::vsnprintf(buffer + buffer_offset, buffer_size - buffer_offset,85format, arguments_copy);86va_end(arguments_copy);88// The code below may append a newline at the end of the buffer, which89// requires an extra character.90if (buffer_offset >= buffer_size - 1) {91// The message did not fit into the buffer.92if (iteration == 0) {93// Re-run the loop and use a dynamically-allocated buffer. The buffer94// will be large enough for the log message, an extra newline and a95// null terminator.96dynamic_buffer_size = buffer_offset + 2;97continue;98}100// The dynamically-allocated buffer was incorrectly sized. This should101// not happen, assuming a correct implementation of (v)snprintf. Fail102// in tests, recover by truncating the log message in production.103assert(false);104buffer_offset = buffer_size - 1;105}107// Add a newline if necessary.108if (buffer[buffer_offset - 1] != '\n') {109buffer[buffer_offset] = '\n';110++buffer_offset;111}113assert(buffer_offset <= buffer_size);114std::fwrite(buffer, 1, buffer_offset, fp_);115std::fflush(fp_);117if (iteration != 0) {118delete[] buffer;119}120break;121}122}124private:125std::FILE* const fp_;126};128} // namespace leveldb130#endif // STORAGE_LEVELDB_UTIL_POSIX_LOGGER_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.