remove atomics and add dynamic log target
This commit is contained in:
parent
356a166b19
commit
71d05b9ae4
2 changed files with 111 additions and 40 deletions
122
common/log.h
122
common/log.h
|
@ -5,8 +5,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <atomic>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
// Specifies a log target.
|
// Specifies a log target.
|
||||||
// default uses log_handler() with "llama.log" log file
|
// default uses log_handler() with "llama.log" log file
|
||||||
|
@ -86,64 +87,127 @@
|
||||||
|
|
||||||
#define _LOG(str, ...) \
|
#define _LOG(str, ...) \
|
||||||
{ \
|
{ \
|
||||||
|
/*fprintf(stderr, "DBG:" str, ##__VA_ARGS__);*/ \
|
||||||
fprintf(LOG_TARGET, LOG_TIMESTAMP_FMT LOG_FLF_FMT str "%c" LOG_TIMESTAMP_VAL LOG_FLF_VAL, ##__VA_ARGS__); \
|
fprintf(LOG_TARGET, LOG_TIMESTAMP_FMT LOG_FLF_FMT str "%c" LOG_TIMESTAMP_VAL LOG_FLF_VAL, ##__VA_ARGS__); \
|
||||||
fflush(LOG_TARGET); \
|
fflush(LOG_TARGET); /*fprintf(stderr, "DBGEND\n");*/ \
|
||||||
}
|
}
|
||||||
|
|
||||||
// This us a trick to bypass the silly
|
// This is a trick to bypass the silly
|
||||||
// "warning: ISO C++11 requires at least one argument for the "..." in a variadic macro"
|
// "warning: ISO C++11 requires at least one argument for the "..." in a variadic macro"
|
||||||
// so we can gave a single macro which can be called just like printf.
|
// so we can gave a single macro which can be called just like printf.
|
||||||
#define LOG(...) _LOG(__VA_ARGS__, '\0')
|
#define LOG(...) _LOG(__VA_ARGS__, '\0')
|
||||||
|
|
||||||
inline FILE *log_handler(std::string s = "llama.log")
|
inline std::string log_get_pid()
|
||||||
{
|
{
|
||||||
static std::atomic_bool _initialized{false};
|
static std::string pid;
|
||||||
static std::atomic_bool _logfileopened{false};
|
if (pid.empty()) [[unlikely]]
|
||||||
|
{
|
||||||
|
// std::this_thread::get_id() is the most portable way of obtaining a "process id"
|
||||||
|
// it's not the same as "pid" but is unique enough to solve multiple instances
|
||||||
|
// trying to write to the same log.
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::this_thread::get_id();
|
||||||
|
pid = ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LOG_DEFAULT_FILE_NAME std::string().append("llama.").append(log_get_pid()).append(".log")
|
||||||
|
|
||||||
|
inline FILE *_log_handler1(bool change = false, std::string filename = LOG_DEFAULT_FILE_NAME, FILE *target = nullptr)
|
||||||
|
{
|
||||||
|
// std::cerr << "\tFNM:" << filename << "TGT:" << (uint64_t)target << std::endl;
|
||||||
|
static bool _initialized{false};
|
||||||
|
static std::string log_current_filename{filename};
|
||||||
|
static FILE *log_current_target{target};
|
||||||
static FILE *logfile = nullptr;
|
static FILE *logfile = nullptr;
|
||||||
|
|
||||||
|
if (change && log_current_filename.compare(filename) != 0) [[unlikely]]
|
||||||
|
{
|
||||||
|
// std::cerr << "\t\tFNM changed, deinit" << std::endl;
|
||||||
|
_initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (change && log_current_target != target) [[unlikely]]
|
||||||
|
{
|
||||||
|
// std::cerr << "\t\tTGT changed, deinit" << std::endl;
|
||||||
|
_initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::cerr << "\tINIT:" << (_initialized ? "true" : "false") << std::endl;
|
||||||
|
|
||||||
if (_initialized) [[likely]]
|
if (_initialized) [[likely]]
|
||||||
{
|
{
|
||||||
|
// std::cerr << "\t\tIS Inited" << std::endl;
|
||||||
// with fallback in case something went wrong
|
// with fallback in case something went wrong
|
||||||
|
// std::cerr << "\t\tEarly Done" << std::endl;
|
||||||
return logfile ? logfile : stderr;
|
return logfile ? logfile : stderr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Mutex-less threadsafe synchronisation.
|
// std::cerr << "\t\tIS NOT Inited" << std::endl;
|
||||||
// we need to make sure not more than one invocation of this function
|
if (target != nullptr)
|
||||||
// attempts to open a file at once.
|
|
||||||
// compare_exchange_strong checks and updates a flag
|
|
||||||
// in a single atomic operation.
|
|
||||||
bool expected{false};
|
|
||||||
if( _logfileopened.compare_exchange_strong(expected,true) )
|
|
||||||
{
|
{
|
||||||
// If the flag was previously false, and we managed to turn it true
|
// std::cerr << "\t\t\tTGT not nullptr" << std::endl;
|
||||||
// ew are now responsible for opening the log file
|
if (logfile != nullptr && logfile != stdout && logfile != stderr)
|
||||||
logfile = fopen( s.c_str(), "wa" );
|
{
|
||||||
|
// std::cerr << "\t\t\t\tF close" << std::endl;
|
||||||
|
fclose(logfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_current_filename = LOG_DEFAULT_FILE_NAME;
|
||||||
|
log_current_target = target;
|
||||||
|
|
||||||
|
// std::cerr << "\t\t\tTGT set to new target" << std::endl;
|
||||||
|
logfile = target;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// std::cerr << "\t\t\tTGT IS nullptr" << std::endl;
|
||||||
|
if (log_current_filename.compare(filename) != 0) [[likely]]
|
||||||
|
{
|
||||||
|
// std::cerr << "\t\t\t\tFNM changed" << std::endl;
|
||||||
|
|
||||||
|
if (logfile != nullptr && logfile != stdout && logfile != stderr)
|
||||||
|
{
|
||||||
|
// std::cerr << "\t\t\t\t\tF close 2" << std::endl;
|
||||||
|
fclose(logfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::cerr << "\t\t\t\tF reopen" << std::endl;
|
||||||
|
logfile = nullptr;
|
||||||
|
logfile = fopen(filename.c_str(), "a");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// std::cerr << "\t\t\t\tF open" << std::endl;
|
||||||
|
// logfile = fopen(filename.c_str(), "wa");
|
||||||
|
logfile = fopen(filename.c_str(), "a");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!logfile)
|
if (!logfile)
|
||||||
{
|
{
|
||||||
|
// std::cerr << "\t\t\tF invalid" << std::endl;
|
||||||
// Verify whether the file was opened, otherwise fallback to stderr
|
// Verify whether the file was opened, otherwise fallback to stderr
|
||||||
logfile = stderr;
|
logfile = stderr;
|
||||||
|
|
||||||
fprintf(stderr, "Failed to open logfile '%s' with error '%s'\n", s.c_str(), std::strerror(errno));
|
fprintf(stderr, "Failed to open logfile '%s' with error '%s'\n", filename.c_str(), std::strerror(errno));
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
_initialized.store(true);
|
_initialized = true;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// We are not first to open the log file
|
|
||||||
//
|
|
||||||
// TODO: Better thread-safe option, possibly std::condition_variable
|
|
||||||
|
|
||||||
return stderr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// with fallback in case something went wrong
|
// std::cerr << "\tDone" << std::endl;
|
||||||
return logfile ? logfile : stderr;
|
return logfile ? logfile : stderr;
|
||||||
}
|
}
|
||||||
|
inline FILE *_log_handler2(bool change = false, FILE *target = nullptr, std::string filename = LOG_DEFAULT_FILE_NAME)
|
||||||
return stderr;
|
{
|
||||||
|
return _log_handler1(change, filename, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline FILE *log_set_target(std::string filename) { return _log_handler1(true, filename); }
|
||||||
|
inline FILE *log_set_target(FILE *target) { return _log_handler2(true, target); }
|
||||||
|
inline FILE *log_handler() { return _log_handler1(); }
|
|
@ -61,8 +61,15 @@ void sigint_handler(int signo) {
|
||||||
int main(int argc, char ** argv) {
|
int main(int argc, char ** argv) {
|
||||||
gpt_params params;
|
gpt_params params;
|
||||||
|
|
||||||
LOG("Hello World!\n")
|
LOG("Hello World to default output!\n")
|
||||||
LOG("Hello Again!\n")
|
log_set_target(stderr);
|
||||||
|
LOG("Hello World to stderr!\n")
|
||||||
|
log_set_target(LOG_DEFAULT_FILE_NAME);
|
||||||
|
LOG("Hello World to default log file!\n")
|
||||||
|
log_set_target(stdout);
|
||||||
|
LOG("Hello World to stdout!\n")
|
||||||
|
log_set_target(LOG_DEFAULT_FILE_NAME);
|
||||||
|
LOG("Hello World to default log file again!\n")
|
||||||
|
|
||||||
if (gpt_params_parse(argc, argv, params) == false) {
|
if (gpt_params_parse(argc, argv, params) == false) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue