diff --git a/f8/jsonlog.cc b/f8/jsonlog.cc new file mode 100644 index 0000000..61e08eb --- /dev/null +++ b/f8/jsonlog.cc @@ -0,0 +1,133 @@ +#include +#include +#include + +#include + +#include +#include + +namespace f8 +{ + struct JsonLogMsgNode + { + a8::XObject* xobj = nullptr; + JsonLogMsgNode* next = nullptr; + }; + + struct JsonLogImpl + { + std::string log_filename; + + std::thread* save_thread = nullptr; + bool save_thread_shutdown = false; + + std::mutex msg_mutex; + JsonLogMsgNode* top_node = nullptr; + JsonLogMsgNode* bot_node = nullptr; + JsonLogMsgNode* work_node = nullptr; + std::mutex *save_cond_mutex = nullptr; + std::condition_variable *save_cond = nullptr; + }; + + JsonLog::JsonLog() + { + impl_ = new JsonLogImpl(); + impl_->save_cond_mutex = new std::mutex(); + impl_->save_cond = new std::condition_variable(); + + impl_->top_node = nullptr; + impl_->bot_node = nullptr; + impl_->work_node = nullptr; + } + + JsonLog::~JsonLog() + { + delete impl_->save_cond_mutex; + impl_->save_cond_mutex = nullptr; + delete impl_->save_cond; + impl_->save_cond = nullptr; + delete impl_; + impl_ = nullptr; + } + + void JsonLog::Init() + { + impl_->save_thread_shutdown = false; + impl_->save_thread = new std::thread(&JsonLog::SaveToFileThreadProc, this); + } + + void JsonLog::UnInit() + { + impl_->save_thread_shutdown = true; + impl_->save_thread->join(); + delete impl_->save_thread; + impl_->save_thread = nullptr; + } + + void JsonLog::SetLogFileName(const std::string& filename) + { + impl_->log_filename = filename; + } + + void JsonLog::AddLog(a8::XObject* xobj) + { + JsonLogMsgNode *p = new JsonLogMsgNode(); + p->xobj = xobj; + impl_->msg_mutex.lock(); + if (impl_->bot_node) { + impl_->bot_node->next = p; + impl_->bot_node = p; + } else { + impl_->top_node = p; + impl_->bot_node = p; + } + impl_->msg_mutex.unlock(); + { + std::unique_lock lk(*impl_->save_cond_mutex); + impl_->save_cond->notify_all(); + } + } + + void JsonLog::SaveToFileThreadProc() + { + while (!impl_->save_thread_shutdown) { + if (!impl_->work_node && impl_->top_node) { + impl_->msg_mutex.lock(); + impl_->work_node = impl_->top_node; + impl_->top_node = nullptr; + impl_->bot_node = nullptr; + impl_->msg_mutex.unlock(); + } + + if (impl_->work_node) { + time_t nowtime = time(nullptr); + struct tm tm_nowtime = {0}; + localtime_r(&nowtime, &tm_nowtime); + + char szfilename[256]; + strftime(szfilename, a8::ArraySize(szfilename), impl_->log_filename.c_str(), &tm_nowtime); + std::string filename((char*)szfilename); + FILE *logfile = fopen(filename.c_str(), "a+"); + if (logfile) { + while (impl_->work_node) { + JsonLogMsgNode *nextnode = impl_->work_node->next; + std::string logmsg; + impl_->work_node->xobj->ToJsonStr(logmsg); + logmsg.push_back('\n'); + fwrite(logmsg.c_str(), 1, logmsg.size(), logfile); + delete impl_->work_node->xobj; + delete impl_->work_node; + impl_->work_node = nextnode; + } + fclose(logfile); + } + } + { + std::unique_lock lk(*impl_->save_cond_mutex); + impl_->save_cond->wait_for(lk, std::chrono::seconds(10)); + } + } + } + +} diff --git a/f8/jsonlog.h b/f8/jsonlog.h new file mode 100644 index 0000000..30e51f6 --- /dev/null +++ b/f8/jsonlog.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +namespace f8 +{ + + class JsonLog : public a8::Singleton + { + private: + JsonLog(); + friend class a8::Singleton; + + public: + ~JsonLog(); + + void Init(); + void UnInit(); + + void SetLogFileName(const std::string& filename); + + void AddLog(a8::XObject* logobj); + + private: + void SaveToFileThreadProc(); + + private: + struct JsonLogImpl* impl_ = nullptr; + }; + +}