Skip to content

Commit 1bf2307

Browse files
committed
another approach
1 parent 354aac5 commit 1bf2307

File tree

4 files changed

+81
-40
lines changed

4 files changed

+81
-40
lines changed

src/bitcoind.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,5 @@ int main(int argc, char* argv[])
193193

194194
int status = AppInit(argc, argv);
195195

196-
if (!status) {
197-
async_logging::Shutdown();
198-
}
199196
return (status ? EXIT_SUCCESS : EXIT_FAILURE);
200197
}

src/init.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,6 @@ void Shutdown()
291291
globalVerifyHandle.reset();
292292
ECC_Stop();
293293
LogPrintf("%s: done\n", __func__);
294-
async_logging::Shutdown();
295294
}
296295

297296
/**
@@ -1216,6 +1215,8 @@ bool AppInitMain()
12161215
return InitError(strprintf("Could not open debug log file %s",
12171216
g_logger->m_file_path.string()));
12181217
}
1218+
1219+
async_logging::Init();
12191220
}
12201221

12211222
if (!g_logger->m_log_timestamps)

src/logging.cpp

Lines changed: 74 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
#include <logging.h>
77
#include <utiltime.h>
88
#include <ringbuffer.h>
9+
#include <reverselock.h>
910

11+
#include <chrono>
1012
#include <mutex>
1113

1214
const char * const DEFAULT_DEBUGLOGFILE = "debug.log";
@@ -45,7 +47,7 @@ bool BCLog::Logger::OpenDebugLog()
4547
return false;
4648
}
4749

48-
setbuf(m_fileout, nullptr); // unbuffered
50+
//setbuf(m_fileout, nullptr); // unbuffered
4951
// dump buffered messages from before we opened the log
5052
while (!m_msgs_before_open.empty()) {
5153
FileWriteStr(m_msgs_before_open.front(), m_fileout);
@@ -211,7 +213,7 @@ void BCLog::Logger::LogPrintStr(const std::string &str)
211213
fflush(stdout);
212214
}
213215
if (m_print_to_file) {
214-
std::lock_guard<std::mutex> scoped_lock(m_file_mutex);
216+
//std::lock_guard<std::mutex> scoped_lock(m_file_mutex);
215217

216218
// buffer if we haven't opened the log yet
217219
if (m_fileout == nullptr) {
@@ -226,14 +228,19 @@ void BCLog::Logger::LogPrintStr(const std::string &str)
226228
if (!m_fileout) {
227229
return;
228230
}
229-
setbuf(m_fileout, nullptr); // unbuffered
231+
//setbuf(m_fileout, nullptr); // unbuffered
230232
}
231233

232234
FileWriteStr(strTimestamped, m_fileout);
233235
}
234236
}
235237
}
236238

239+
void BCLog::Logger::FlushFile()
240+
{
241+
fflush(m_fileout);
242+
}
243+
237244
void BCLog::Logger::ShrinkDebugFile()
238245
{
239246
// Amount of debug.log to save at end when shrinking (must fit in memory)
@@ -275,43 +282,82 @@ void BCLog::Logger::ShrinkDebugFile()
275282
fclose(file);
276283
}
277284

278-
namespace async_logging {
279-
using LogArgs = std::string;
280-
RingBuffer<LogArgs, 1024> log_buffer;
281-
std::unique_ptr<std::thread> flush_logs_thread;
282-
std::once_flag flush_logs_thread_started;
285+
class AsyncLogger
286+
{
287+
public:
288+
AsyncLogger() : m_size(0) {}
289+
~AsyncLogger() {}
283290

284-
static void ConsumeLogs()
291+
void Push(std::string&& line)
285292
{
286-
std::unique_ptr<LogArgs> next_log_line;
287-
while (next_log_line = log_buffer.PollForOne()) {
288-
g_logger->LogPrintStr(*next_log_line);
293+
{
294+
std::unique_lock<std::mutex> l(m_lock);
295+
296+
m_buffer_accumulating[m_end()] = std::forward<std::string>(line);
297+
m_size = std::min(m_size + 1, m_capacity);
289298
}
299+
300+
// doesnt matter that much if we slightly over or undernotify
301+
if(m_size > 100)
302+
m_cv.notify_one();
290303
}
291304

292-
void FlushAll()
305+
void Thread(void)
293306
{
294-
for (LogArgs& s : log_buffer.PopAll()) {
295-
g_logger->LogPrintStr(s);
307+
std::unique_lock<std::mutex> l(m_lock);
308+
while(true)
309+
{
310+
// if theres still a lot to do don't wait
311+
if(m_size < 100) {
312+
// sleep until there's a lot to do or some time has passed
313+
m_cv.wait_for(l, std::chrono::milliseconds(100));
314+
}
315+
316+
if(m_size > 0) {
317+
std::swap(m_buffer_accumulating, m_buffer_flushing);
318+
319+
unsigned int size = m_size;
320+
m_size = 0;
321+
322+
{
323+
// drop the lock while flushing
324+
reverse_lock<std::unique_lock<std::mutex>> release(l);
325+
326+
g_logger->LogPrintStr("flushing\n");
327+
for(size_t i = 0; i < size; ++i) {
328+
g_logger->LogPrintStr(std::move(m_buffer_flushing[i]));
329+
}
330+
g_logger->FlushFile();
331+
}
332+
}
296333
}
297334
}
298335

299-
void Queue(const std::string& str)
336+
private:
337+
std::mutex m_lock;
338+
std::condition_variable m_cv;
339+
340+
static constexpr long unsigned int m_capacity = 1024;
341+
342+
std::array<std::string, m_capacity> m_buffer_accumulating;
343+
std::array<std::string, m_capacity> m_buffer_flushing;
344+
345+
size_t m_size;
346+
inline size_t m_end(){ return m_size; }
347+
};
348+
349+
namespace async_logging {
350+
AsyncLogger log_buffer;
351+
std::thread flush_logs_thread;
352+
353+
void Init(void)
300354
{
301-
std::call_once(flush_logs_thread_started, [](){
302-
flush_logs_thread.reset(new std::thread(ConsumeLogs));
303-
});
304-
log_buffer.PushBack(std::move(str));
355+
flush_logs_thread = std::thread(&AsyncLogger::Thread, &log_buffer);
356+
LogPrintf("If you are seeing this message the async logger has started\n");
305357
}
306358

307-
void Shutdown()
359+
void Queue(std::string&& str)
308360
{
309-
if (flush_logs_thread) {
310-
log_buffer.SignalStopWaiting();
311-
FlushAll();
312-
if (flush_logs_thread->joinable()) {
313-
flush_logs_thread->join();
314-
}
315-
}
361+
log_buffer.Push(std::forward<std::string>(str));
316362
}
317363
}

src/logging.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ namespace BCLog {
9393

9494
bool OpenDebugLog();
9595
void ShrinkDebugFile();
96+
void FlushFile();
9697

9798
uint32_t GetCategoryMask() const { return m_categories.load(); }
9899

@@ -152,7 +153,7 @@ template<typename T, typename... Args> static inline void MarkUsed(const T& t, c
152153
/* Original format string will have newline so don't add one here */ \
153154
_log_msg_ = "Error \"" + std::string(fmterr.what()) + "\" while formatting log message: " + FormatStringFromLogArgs(__VA_ARGS__); \
154155
} \
155-
async_logging::Queue(_log_msg_); \
156+
async_logging::Queue(std::move(_log_msg_)); \
156157
} \
157158
} while(0)
158159

@@ -164,14 +165,10 @@ template<typename T, typename... Args> static inline void MarkUsed(const T& t, c
164165
#endif
165166

166167
namespace async_logging {
167-
/** Queue a log message to be written. */
168-
void Queue(const std::string& str);
169-
170-
/** Write all log messages currently buffered. Used during shutdown. */
171-
void FlushAll();
168+
void Init(void);
172169

173-
/** Shutdown the logging thread. */
174-
void Shutdown();
170+
/** Queue a log message to be written. */
171+
void Queue(std::string&& str);
175172
}
176173

177174
#endif // BITCOIN_LOGGING_H

0 commit comments

Comments
 (0)