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.4//5// Logger implementation for the Windows platform.7#ifndef STORAGE_LEVELDB_UTIL_WINDOWS_LOGGER_H_8#define STORAGE_LEVELDB_UTIL_WINDOWS_LOGGER_H_10#include <cassert>11#include <cstdarg>12#include <cstdio>13#include <ctime>14#include <sstream>15#include <thread>17#include "leveldb/env.h"19namespace leveldb {21class WindowsLogger final : public Logger {22public:23// Creates a logger that writes to the given file.24//25// The PosixLogger instance takes ownership of the file handle.26explicit WindowsLogger(std::FILE* fp) : fp_(fp) { assert(fp != nullptr); }28~WindowsLogger() override { std::fclose(fp_); }30void Logv(const char* format, va_list arguments) override {31// Record the time as close to the Logv() call as possible.32SYSTEMTIME now_components;33::GetLocalTime(&now_components);35// Record the thread ID.36constexpr const int kMaxThreadIdSize = 32;37std::ostringstream thread_stream;38thread_stream << std::this_thread::get_id();39std::string thread_id = thread_stream.str();40if (thread_id.size() > kMaxThreadIdSize) {41thread_id.resize(kMaxThreadIdSize);42}44// We first attempt to print into a stack-allocated buffer. If this attempt45// fails, we make a second attempt with a dynamically allocated buffer.46constexpr const int kStackBufferSize = 512;47char stack_buffer[kStackBufferSize];48static_assert(sizeof(stack_buffer) == static_cast<size_t>(kStackBufferSize),49"sizeof(char) is expected to be 1 in C++");51int dynamic_buffer_size = 0; // Computed in the first iteration.52for (int iteration = 0; iteration < 2; ++iteration) {53const int buffer_size =54(iteration == 0) ? kStackBufferSize : dynamic_buffer_size;55char* const buffer =56(iteration == 0) ? stack_buffer : new char[dynamic_buffer_size];58// Print the header into the buffer.59int buffer_offset = snprintf(60buffer, buffer_size, "%04d/%02d/%02d-%02d:%02d:%02d.%06d %s ",61now_components.wYear, now_components.wMonth, now_components.wDay,62now_components.wHour, now_components.wMinute, now_components.wSecond,63static_cast<int>(now_components.wMilliseconds * 1000),64thread_id.c_str());66// The header can be at most 28 characters (10 date + 15 time +67// 3 delimiters) plus the thread ID, which should fit comfortably into the68// static buffer.69assert(buffer_offset <= 28 + kMaxThreadIdSize);70static_assert(28 + kMaxThreadIdSize < kStackBufferSize,71"stack-allocated buffer may not fit the message header");72assert(buffer_offset < buffer_size);74// Print the message into the buffer.75std::va_list arguments_copy;76va_copy(arguments_copy, arguments);77buffer_offset +=78std::vsnprintf(buffer + buffer_offset, buffer_size - buffer_offset,79format, arguments_copy);80va_end(arguments_copy);82// The code below may append a newline at the end of the buffer, which83// requires an extra character.84if (buffer_offset >= buffer_size - 1) {85// The message did not fit into the buffer.86if (iteration == 0) {87// Re-run the loop and use a dynamically-allocated buffer. The buffer88// will be large enough for the log message, an extra newline and a89// null terminator.90dynamic_buffer_size = buffer_offset + 2;91continue;92}94// The dynamically-allocated buffer was incorrectly sized. This should95// not happen, assuming a correct implementation of (v)snprintf. Fail96// in tests, recover by truncating the log message in production.97assert(false);98buffer_offset = buffer_size - 1;99}101// Add a newline if necessary.102if (buffer[buffer_offset - 1] != '\n') {103buffer[buffer_offset] = '\n';104++buffer_offset;105}107assert(buffer_offset <= buffer_size);108std::fwrite(buffer, 1, buffer_offset, fp_);109std::fflush(fp_);111if (iteration != 0) {112delete[] buffer;113}114break;115}116}118private:119std::FILE* const fp_;120};122} // namespace leveldb124#endif // STORAGE_LEVELDB_UTIL_WINDOWS_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.