bitcoinleveldb_log/posix_logger.rs
1/*!
2 | Logger implementation that can be shared
3 | by all environments where enough posix
4 | functionality is available.
5 |
6 */
7
8crate::ix!();
9
10
11
12//-------------------------------------------[.cpp/bitcoin/src/leveldb/util/posix_logger.h]
13
14pub struct PosixLogger {
15 fp: *const libc::FILE,
16}
17
18impl Logger for PosixLogger {
19
20}
21
22impl Logv for PosixLogger {
23
24 fn logv(&mut self,
25 format: *const u8,
26 arguments: &[&str]) {
27
28 todo!();
29 /*
30 // Record the time as close to the Logv() call as possible.
31 struct ::timeval now_timeval;
32 ::gettimeofday(&now_timeval, nullptr);
33 const std::time_t now_seconds = now_timeval.tv_sec;
34 struct std::tm now_components;
35 ::localtime_r(&now_seconds, &now_components);
36
37 // Record the thread ID.
38 constexpr const int kMaxThreadIdSize = 32;
39 std::ostringstream thread_stream;
40 thread_stream << std::this_thread::get_id();
41 std::string thread_id = thread_stream.str();
42 if (thread_id.size() > kMaxThreadIdSize) {
43 thread_id.resize(kMaxThreadIdSize);
44 }
45
46 // We first attempt to print into a stack-allocated buffer. If this attempt
47 // fails, we make a second attempt with a dynamically allocated buffer.
48 constexpr const int kStackBufferSize = 512;
49 char stack_buffer[kStackBufferSize];
50 const_assert(sizeof(stack_buffer) == static_cast<size_t>(kStackBufferSize),
51 "sizeof(char) is expected to be 1 in C++");
52
53 int dynamic_buffer_size = 0; // Computed in the first iteration.
54 for (int iteration = 0; iteration < 2; ++iteration) {
55 const int buffer_size =
56 (iteration == 0) ? kStackBufferSize : dynamic_buffer_size;
57 char* const buffer =
58 (iteration == 0) ? stack_buffer : new char[dynamic_buffer_size];
59
60 // Print the header into the buffer.
61 int buffer_offset = snprintf(
62 buffer, buffer_size, "%04d/%02d/%02d-%02d:%02d:%02d.%06d %s ",
63 now_components.tm_year + 1900, now_components.tm_mon + 1,
64 now_components.tm_mday, now_components.tm_hour, now_components.tm_min,
65 now_components.tm_sec, static_cast<int>(now_timeval.tv_usec),
66 thread_id.c_str());
67
68 // The header can be at most 28 characters (10 date + 15 time +
69 // 3 delimiters) plus the thread ID, which should fit comfortably into the
70 // static buffer.
71 assert(buffer_offset <= 28 + kMaxThreadIdSize);
72 const_assert(28 + kMaxThreadIdSize < kStackBufferSize,
73 "stack-allocated buffer may not fit the message header");
74 assert(buffer_offset < buffer_size);
75
76 // Print the message into the buffer.
77 std::va_list arguments_copy;
78 va_copy(arguments_copy, arguments);
79 buffer_offset +=
80 std::vsnprintf(buffer + buffer_offset, buffer_size - buffer_offset,
81 format, arguments_copy);
82 va_end(arguments_copy);
83
84 // The code below may append a newline at the end of the buffer, which
85 // requires an extra character.
86 if (buffer_offset >= buffer_size - 1) {
87 // The message did not fit into the buffer.
88 if (iteration == 0) {
89 // Re-run the loop and use a dynamically-allocated buffer. The buffer
90 // will be large enough for the log message, an extra newline and a
91 // null terminator.
92 dynamic_buffer_size = buffer_offset + 2;
93 continue;
94 }
95
96 // The dynamically-allocated buffer was incorrectly sized. This should
97 // not happen, assuming a correct implementation of (v)snprintf. Fail
98 // in tests, recover by truncating the log message in production.
99 assert(false);
100 buffer_offset = buffer_size - 1;
101 }
102
103 // Add a newline if necessary.
104 if (buffer[buffer_offset - 1] != '\n') {
105 buffer[buffer_offset] = '\n';
106 ++buffer_offset;
107 }
108
109 assert(buffer_offset <= buffer_size);
110 std::fwrite(buffer, 1, buffer_offset, fp_);
111 std::fflush(fp_);
112
113 if (iteration != 0) {
114 delete[] buffer;
115 }
116 break;
117 }
118 */
119 }
120}
121
122impl Drop for PosixLogger {
123 fn drop(&mut self) {
124 todo!();
125 /*
126 std::fclose(fp_);
127 */
128 }
129}
130
131impl PosixLogger {
132
133 /**
134 | Creates a logger that writes to the given
135 | file.
136 |
137 | The PosixLogger instance takes ownership of
138 | the file handle.
139 */
140 pub fn new(fp: *mut libc::FILE) -> Self {
141
142 todo!();
143 /*
144 : fp(fp),
145
146 assert(fp != nullptr);
147 */
148 }
149}