chenBright commented on code in PR #2413: URL: https://github.com/apache/brpc/pull/2413#discussion_r1368919859
########## src/butil/logging.cc: ########## @@ -399,8 +404,253 @@ void CloseLogFileUnlocked() { log_file = NULL; } +void Log2File(const std::string& log) { + // We can have multiple threads and/or processes, so try to prevent them + // from clobbering each other's writes. + // If the client app did not call InitLogging, and the lock has not + // been created do it now. We do this on demand, but if two threads try + // to do this at the same time, there will be a race condition to create + // the lock. This is why InitLogging should be called from the main + // thread at the beginning of execution. + LoggingLock::Init(LOCK_LOG_FILE, NULL); + LoggingLock logging_lock; + if (InitializeLogFileHandle()) { +#if defined(OS_WIN) + SetFilePointer(log_file, 0, 0, SEEK_END); + DWORD num_written; + WriteFile(log_file, + static_cast<const void*>(log.data()), + static_cast<DWORD>(log.size()), + &num_written, + NULL); +#else + fwrite(log.data(), log.size(), 1, log_file); + fflush(log_file); +#endif + } +} + } // namespace +struct BAIDU_CACHELINE_ALIGNMENT LogRequest { + static LogRequest* const UNCONNECTED; + + LogRequest* next{NULL}; + std::string data; +}; + +LogRequest* const LogRequest::UNCONNECTED = (LogRequest*)(intptr_t)-1; + +class AsyncLog : public butil::SimpleThread { +public: + static AsyncLog* GetInstance(); + + void Log(const std::string& log); + void Log(std::string&& log); + +private: +friend struct DefaultSingletonTraits<AsyncLog>; + + AsyncLog(); + ~AsyncLog() override; + + void LogImpl(LogRequest* log_req); + + void Run() override; + + void LogTask(); + + bool IsLogComplete(LogRequest* old_head, + bool singular_node, + LogRequest** new_tail); + + butil::atomic<LogRequest*> _log_head; + butil::Mutex _mutex; + butil::ConditionVariable _cond; + LogRequest* _current_log_request; + bool _stop; +}; + +AsyncLog* AsyncLog::GetInstance() { + return Singleton<AsyncLog, + LeakySingletonTraits<AsyncLog>>::get(); +} + +AsyncLog::AsyncLog() + : butil::SimpleThread("async_log_thread") + , _log_head(NULL) + , _cond(&_mutex) + , _current_log_request(NULL) + , _stop(false) { + Start(); +} + +AsyncLog::~AsyncLog() { + { + BAIDU_SCOPED_LOCK(_mutex); + _stop = true; + _cond.Signal(); + } + Join(); +} + +void AsyncLog::Log(const std::string& log) { + if (log.empty()) { + return; + } + + auto log_req = butil::get_object<LogRequest>(); + if (!log_req) { + // Async log failed, fallback to sync log. + Log2File(log); + return; + } + log_req->data = log; + LogImpl(log_req); +} + +void AsyncLog::Log(std::string&& log) { + if (log.empty()) { + return; + } + + auto log_req = butil::get_object<LogRequest>(); + if (!log_req) { + // Async log failed, fallback to sync log. Review Comment: done -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: dev-unsubscr...@brpc.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@brpc.apache.org For additional commands, e-mail: dev-h...@brpc.apache.org