From 38e1eaa8a39d3622bafb087c7685571064540284 Mon Sep 17 00:00:00 2001 From: Takeshi Nakatani Date: Tue, 13 Oct 2020 14:00:11 +0000 Subject: [PATCH] Added logfile option for non-syslog logging --- doc/man/s3fs.1 | 5 + src/Makefile.am | 2 +- src/addhead.cpp | 2 +- src/curl.cpp | 2 +- src/s3fs.cpp | 40 +++--- src/s3fs_help.cpp | 9 ++ src/s3fs_logger.cpp | 200 +++++++++++++++++++++++++++++- src/s3fs_logger.h | 255 +++++++++++++++++++++++++-------------- src/sighandlers.cpp | 38 +++--- src/sighandlers.h | 6 +- src/test_string_util.cpp | 3 +- 11 files changed, 426 insertions(+), 136 deletions(-) diff --git a/doc/man/s3fs.1 b/doc/man/s3fs.1 index 4548036..bb9493b 100644 --- a/doc/man/s3fs.1 +++ b/doc/man/s3fs.1 @@ -337,6 +337,11 @@ Specify the path of the mime.types file. If this option is not specified, the existence of "/etc/mime.types" is checked, and that file is loaded as mime information. If this file does not exist on macOS, then "/etc/apache2/mime.types" is checked as well. .TP +\fB\-o\fR logfile - specify the log output file. +s3fs outputs the log file to syslog. Alternatively, if s3fs is started with the "-f" option specified, the log will be output to the stdout/stderr. +You can use this option to specify the log file that s3fs outputs. +If you specify a log file with this option, it will reopen the log file when s3fs receives a SIGHUP signal. You can use the SIGHUP signal for log rotation. +.TP \fB\-o\fR dbglevel (default="crit") Set the debug message level. set value as crit (critical), err (error), warn (warning), info (information) to debug level. default debug level is critical. If s3fs run with "-d" option, the debug level is set information. diff --git a/src/Makefile.am b/src/Makefile.am index 744b3ce..4e30965 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -65,7 +65,7 @@ s3fs_LDADD = $(DEPS_LIBS) noinst_PROGRAMS = test_string_util -test_string_util_SOURCES = string_util.cpp test_string_util.cpp +test_string_util_SOURCES = string_util.cpp test_string_util.cpp s3fs_logger.cpp TESTS = test_string_util diff --git a/src/addhead.cpp b/src/addhead.cpp index a113923..25b906c 100644 --- a/src/addhead.cpp +++ b/src/addhead.cpp @@ -233,7 +233,7 @@ struct curl_slist* AdditionalHeader::AddHeader(struct curl_slist* list, const ch bool AdditionalHeader::Dump() const { - if(!IS_S3FS_LOG_DBG()){ + if(!S3fsLog::IsS3fsLogDbg()){ return true; } diff --git a/src/curl.cpp b/src/curl.cpp index c72dfde..28e5f94 100644 --- a/src/curl.cpp +++ b/src/curl.cpp @@ -2203,7 +2203,7 @@ bool S3fsCurl::RemakeHandle() // int S3fsCurl::RequestPerform(bool dontAddAuthHeaders /*=false*/) { - if(IS_S3FS_LOG_DBG()){ + if(S3fsLog::IsS3fsLogDbg()){ char* ptr_url = NULL; curl_easy_getinfo(hCurl, CURLINFO_EFFECTIVE_URL , &ptr_url); S3FS_PRN_DBG("connecting to URL %s", SAFESTRPTR(ptr_url)); diff --git a/src/s3fs.cpp b/src/s3fs.cpp index 9f84da0..f0db045 100644 --- a/src/s3fs.cpp +++ b/src/s3fs.cpp @@ -2406,7 +2406,7 @@ static int s3fs_release(const char* _path, struct fuse_file_info* fi) } // check - for debug - if(IS_S3FS_LOG_DBG()){ + if(S3fsLog::IsS3fsLogDbg()){ AutoFdEntity autoent; FdEntity* ent; if(NULL != (ent = autoent.GetFdEntity(path, static_cast(fi->fh)))){ @@ -4619,20 +4619,31 @@ static int my_fuse_opt_proc(void* data, const char* arg, int key, struct fuse_ar return 0; } // - // debug option for s3fs + // log file option + // + if(is_prefix(arg, "logfile=")){ + const char* strlogfile = strchr(arg, '=') + sizeof(char); + if(!S3fsLog::SetLogfile(strlogfile)){ + S3FS_PRN_EXIT("The file(%s) specified by logfile option could not be opened.", strlogfile); + return -1; + } + return 0; + } + // + // debug level option // if(is_prefix(arg, "dbglevel=")){ const char* strlevel = strchr(arg, '=') + sizeof(char); if(0 == strcasecmp(strlevel, "silent") || 0 == strcasecmp(strlevel, "critical") || 0 == strcasecmp(strlevel, "crit")){ - S3fsSignals::SetLogLevel(S3FS_LOG_CRIT); + S3fsLog::SetLogLevel(S3fsLog::LEVEL_CRIT); }else if(0 == strcasecmp(strlevel, "error") || 0 == strcasecmp(strlevel, "err")){ - S3fsSignals::SetLogLevel(S3FS_LOG_ERR); + S3fsLog::SetLogLevel(S3fsLog::LEVEL_ERR); }else if(0 == strcasecmp(strlevel, "wan") || 0 == strcasecmp(strlevel, "warn") || 0 == strcasecmp(strlevel, "warning")){ - S3fsSignals::SetLogLevel(S3FS_LOG_WARN); + S3fsLog::SetLogLevel(S3fsLog::LEVEL_WARN); }else if(0 == strcasecmp(strlevel, "inf") || 0 == strcasecmp(strlevel, "info") || 0 == strcasecmp(strlevel, "information")){ - S3fsSignals::SetLogLevel(S3FS_LOG_INFO); + S3fsLog::SetLogLevel(S3fsLog::LEVEL_INFO); }else if(0 == strcasecmp(strlevel, "dbg") || 0 == strcasecmp(strlevel, "debug")){ - S3fsSignals::SetLogLevel(S3FS_LOG_DBG); + S3fsLog::SetLogLevel(S3fsLog::LEVEL_DBG); }else{ S3FS_PRN_EXIT("option dbglevel has unknown parameter(%s).", strlevel); return -1; @@ -4642,11 +4653,11 @@ static int my_fuse_opt_proc(void* data, const char* arg, int key, struct fuse_ar // // debug option // - // debug_level is S3FS_LOG_INFO, after second -d is passed to fuse. + // S3fsLog level is LEVEL_INFO, after second -d is passed to fuse. // if(0 == strcmp(arg, "-d") || 0 == strcmp(arg, "--debug")){ - if(!IS_S3FS_LOG_INFO() && !IS_S3FS_LOG_DBG()){ - S3fsSignals::SetLogLevel(S3FS_LOG_INFO); + if(!S3fsLog::IsS3fsLogInfo() && !S3fsLog::IsS3fsLogDbg()){ + S3fsLog::SetLogLevel(S3fsLog::LEVEL_INFO); return 0; } if(0 == strcmp(arg, "--debug")){ @@ -4656,9 +4667,9 @@ static int my_fuse_opt_proc(void* data, const char* arg, int key, struct fuse_ar } } // "f2" is not used no more. - // (set S3FS_LOG_DBG) + // (set S3fsLog::LEVEL_DBG) if(0 == strcmp(arg, "f2")){ - S3fsSignals::SetLogLevel(S3FS_LOG_DBG); + S3fsLog::SetLogLevel(S3fsLog::LEVEL_DBG); return 0; } if(0 == strcmp(arg, "curldbg")){ @@ -4734,6 +4745,7 @@ int main(int argc, char* argv[]) int option_index = 0; struct fuse_operations s3fs_oper; time_t incomp_abort_time = (24 * 60 * 60); + S3fsLog singletonLog; static const struct option long_opts[] = { {"help", no_argument, NULL, 'h'}, @@ -4744,10 +4756,6 @@ int main(int argc, char* argv[]) {NULL, 0, NULL, 0} }; - // init syslog(default CRIT) - openlog("s3fs", LOG_PID | LOG_ODELAY | LOG_NOWAIT, LOG_USER); - S3fsSignals::SetLogLevel(debug_level); - // init xml2 xmlInitParser(); LIBXML_TEST_VERSION diff --git a/src/s3fs_help.cpp b/src/s3fs_help.cpp index ceb60e0..15b0253 100644 --- a/src/s3fs_help.cpp +++ b/src/s3fs_help.cpp @@ -431,6 +431,15 @@ static const char help_string[] = " If this file does not exist on macOS, then \"/etc/apache2/mime.types\"\n" " is checked as well.\n" "\n" + " logfile - specify the log output file.\n" + " s3fs outputs the log file to syslog. Alternatively, if s3fs is\n" + " started with the \"-f\" option specified, the log will be output\n" + " to the stdout/stderr.\n" + " You can use this option to specify the log file that s3fs outputs.\n" + " If you specify a log file with this option, it will reopen the log\n" + " file when s3fs receives a SIGHUP signal. You can use the SIGHUP\n" + " signal for log rotation.\n" + "\n" " dbglevel (default=\"crit\")\n" " Set the debug message level. set value as crit (critical), err\n" " (error), warn (warning), info (information) to debug level.\n" diff --git a/src/s3fs_logger.cpp b/src/s3fs_logger.cpp index b520911..86055fd 100644 --- a/src/s3fs_logger.cpp +++ b/src/s3fs_logger.cpp @@ -18,13 +18,207 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include +#include + +#include "common.h" #include "s3fs_logger.h" //------------------------------------------------------------------- -// Global variables +// S3fsLog class : variables //------------------------------------------------------------------- -s3fs_log_level debug_level = S3FS_LOG_CRIT; -const char* s3fs_log_nest[S3FS_LOG_NEST_MAX] = {"", " ", " ", " "}; +const int S3fsLog::NEST_MAX; +const char* S3fsLog::nest_spaces[S3fsLog::NEST_MAX] = {"", " ", " ", " "}; +const char* S3fsLog::LOGFILEENV = "S3FS_LOGFILE"; +S3fsLog* S3fsLog::pSingleton = NULL; +S3fsLog::s3fs_log_level S3fsLog::debug_level = S3fsLog::LEVEL_CRIT; +FILE* S3fsLog::logfp = NULL; +std::string* S3fsLog::plogfile = NULL; + +//------------------------------------------------------------------- +// S3fsLog class : class methods +//------------------------------------------------------------------- +bool S3fsLog::IsS3fsLogLevel(s3fs_log_level level) +{ + return (level == (S3fsLog::debug_level & level)); +} + +bool S3fsLog::SetLogfile(const char* pfile) +{ + if(!S3fsLog::pSingleton){ + S3FS_PRN_CRIT("S3fsLog::pSingleton is NULL."); + return false; + } + return S3fsLog::pSingleton->LowSetLogfile(pfile); +} + +bool S3fsLog::ReopenLogfile() +{ + if(!S3fsLog::pSingleton){ + S3FS_PRN_CRIT("S3fsLog::pSingleton is NULL."); + return false; + } + if(!S3fsLog::logfp){ + S3FS_PRN_INFO("Currently the log file is output to stdout/stderr."); + return true; + } + if(!S3fsLog::plogfile){ + S3FS_PRN_ERR("There is a problem with the path to the log file being NULL."); + return false; + } + std::string tmp = *(S3fsLog::plogfile); + return S3fsLog::pSingleton->LowSetLogfile(tmp.c_str()); +} + +S3fsLog::s3fs_log_level S3fsLog::SetLogLevel(s3fs_log_level level) +{ + if(!S3fsLog::pSingleton){ + S3FS_PRN_CRIT("S3fsLog::pSingleton is NULL."); + return S3fsLog::debug_level; // Although it is an error, it returns the current value. + } + return S3fsLog::pSingleton->LowSetLogLevel(level); +} + +S3fsLog::s3fs_log_level S3fsLog::BumpupLogLevel() +{ + if(!S3fsLog::pSingleton){ + S3FS_PRN_CRIT("S3fsLog::pSingleton is NULL."); + return S3fsLog::debug_level; // Although it is an error, it returns the current value. + } + return S3fsLog::pSingleton->LowBumpupLogLevel(); +} + +//------------------------------------------------------------------- +// S3fsLog class : methods +//------------------------------------------------------------------- +S3fsLog::S3fsLog() +{ + if(!S3fsLog::pSingleton){ + S3fsLog::pSingleton = this; + + // init syslog(default CRIT) + openlog("s3fs", LOG_PID | LOG_ODELAY | LOG_NOWAIT, LOG_USER); + LowLoadEnv(); + }else{ + S3FS_PRN_ERR("Already set singleton object for S3fsLog."); + } +} + +S3fsLog::~S3fsLog() +{ + if(S3fsLog::pSingleton == this){ + FILE* oldfp = S3fsLog::logfp; + S3fsLog::logfp = NULL; + if(oldfp && 0 != fclose(oldfp)){ + S3FS_PRN_ERR("Could not close old log file(%s), but continue...", (S3fsLog::plogfile ? S3fsLog::plogfile->c_str() : "null")); + } + if(S3fsLog::plogfile){ + delete S3fsLog::plogfile; + S3fsLog::plogfile = NULL; + } + S3fsLog::pSingleton = NULL; + S3fsLog::debug_level = S3fsLog::LEVEL_CRIT; + + closelog(); + }else{ + S3FS_PRN_ERR("This object is not singleton S3fsLog object."); + } +} + +bool S3fsLog::LowLoadEnv() +{ + if(S3fsLog::pSingleton != this){ + S3FS_PRN_ERR("This object is not as same as S3fsLog::pSingleton."); + return false; + } + char* pEnvVal; + if(NULL == (pEnvVal = getenv(S3fsLog::LOGFILEENV))){ + return true; + } + if(!SetLogfile(pEnvVal)){ + return false; + } + return true; +} + +bool S3fsLog::LowSetLogfile(const char* pfile) +{ + if(S3fsLog::pSingleton != this){ + S3FS_PRN_ERR("This object is not as same as S3fsLog::pSingleton."); + return false; + } + + if(!pfile){ + // close log file if it is opened + if(S3fsLog::logfp && 0 != fclose(S3fsLog::logfp)){ + S3FS_PRN_ERR("Could not close log file(%s).", (S3fsLog::plogfile ? S3fsLog::plogfile->c_str() : "null")); + return false; + } + S3fsLog::logfp = NULL; + if(S3fsLog::plogfile){ + delete S3fsLog::plogfile; + S3fsLog::plogfile = NULL; + } + }else{ + // open new log file + // + // [NOTE] + // It will reopen even if it is the same file. + // + FILE* newfp; + if(NULL == (newfp = fopen(pfile, "a+"))){ + S3FS_PRN_ERR("Could not open log file(%s).", pfile); + return false; + } + + // switch new log file and close old log file if it is opened + FILE* oldfp = S3fsLog::logfp; + S3fsLog::logfp = newfp; + if(oldfp && 0 != fclose(oldfp)){ + S3FS_PRN_ERR("Could not close old log file(%s).", (S3fsLog::plogfile ? S3fsLog::plogfile->c_str() : "null")); + S3fsLog::logfp = oldfp; + fclose(newfp); + return false; + } + if(S3fsLog::plogfile){ + delete S3fsLog::plogfile; + } + S3fsLog::plogfile = new std::string(pfile); + } + return true; +} + +S3fsLog::s3fs_log_level S3fsLog::LowSetLogLevel(s3fs_log_level level) +{ + if(S3fsLog::pSingleton != this){ + S3FS_PRN_ERR("This object is not as same as S3fsLog::pSingleton."); + return S3fsLog::debug_level; // Although it is an error, it returns the current value. + } + if(level == S3fsLog::debug_level){ + return S3fsLog::debug_level; + } + s3fs_log_level old = S3fsLog::debug_level; + S3fsLog::debug_level = level; + setlogmask(LOG_UPTO(GetSyslogLevel(S3fsLog::debug_level))); + S3FS_PRN_CRIT("change debug level from %sto %s", GetLevelString(old), GetLevelString(S3fsLog::debug_level)); + return old; +} + +S3fsLog::s3fs_log_level S3fsLog::LowBumpupLogLevel() +{ + if(S3fsLog::pSingleton != this){ + S3FS_PRN_ERR("This object is not as same as S3fsLog::pSingleton."); + return S3fsLog::debug_level; // Although it is an error, it returns the current value. + } + s3fs_log_level old = S3fsLog::debug_level; + S3fsLog::debug_level = ( LEVEL_CRIT == S3fsLog::debug_level ? LEVEL_ERR : + LEVEL_ERR == S3fsLog::debug_level ? LEVEL_WARN : + LEVEL_WARN == S3fsLog::debug_level ? LEVEL_INFO : + LEVEL_INFO == S3fsLog::debug_level ? LEVEL_DBG : LEVEL_CRIT ); + setlogmask(LOG_UPTO(GetSyslogLevel(S3fsLog::debug_level))); + S3FS_PRN_CRIT("change debug level from %sto %s", GetLevelString(old), GetLevelString(S3fsLog::debug_level)); + return old; +} /* * Local variables: diff --git a/src/s3fs_logger.h b/src/s3fs_logger.h index a887376..d2036df 100644 --- a/src/s3fs_logger.h +++ b/src/s3fs_logger.h @@ -21,127 +21,200 @@ #ifndef S3FS_LOGGER_H_ #define S3FS_LOGGER_H_ +#include #include //------------------------------------------------------------------- -// Debug level +// S3fsLog class //------------------------------------------------------------------- -enum s3fs_log_level{ - S3FS_LOG_CRIT = 0, // LOG_CRIT - S3FS_LOG_ERR = 1, // LOG_ERR - S3FS_LOG_WARN = 3, // LOG_WARNING - S3FS_LOG_INFO = 7, // LOG_INFO - S3FS_LOG_DBG = 15 // LOG_DEBUG +class S3fsLog +{ + public: + enum s3fs_log_level{ + LEVEL_CRIT = 0, // LEVEL_CRIT + LEVEL_ERR = 1, // LEVEL_ERR + LEVEL_WARN = 3, // LEVEL_WARNING + LEVEL_INFO = 7, // LEVEL_INFO + LEVEL_DBG = 15 // LEVEL_DEBUG + }; + + protected: + static const int NEST_MAX = 4; + static const char* nest_spaces[NEST_MAX]; + static const char* LOGFILEENV; + static S3fsLog* pSingleton; + static s3fs_log_level debug_level; + static FILE* logfp; + static std::string* plogfile; + + protected: + bool LowLoadEnv(); + bool LowSetLogfile(const char* pfile); + s3fs_log_level LowSetLogLevel(s3fs_log_level level); + s3fs_log_level LowBumpupLogLevel(); + + public: + static bool IsS3fsLogLevel(s3fs_log_level level); + static bool IsS3fsLogCrit() { return IsS3fsLogLevel(LEVEL_CRIT); } + static bool IsS3fsLogErr() { return IsS3fsLogLevel(LEVEL_ERR); } + static bool IsS3fsLogWarn() { return IsS3fsLogLevel(LEVEL_WARN); } + static bool IsS3fsLogInfo() { return IsS3fsLogLevel(LEVEL_INFO); } + static bool IsS3fsLogDbg() { return IsS3fsLogLevel(LEVEL_DBG); } + + static int GetSyslogLevel(s3fs_log_level level) + { + return ( LEVEL_DBG == (level & LEVEL_DBG) ? LOG_DEBUG : + LEVEL_INFO == (level & LEVEL_DBG) ? LOG_INFO : + LEVEL_WARN == (level & LEVEL_DBG) ? LOG_WARNING : + LEVEL_ERR == (level & LEVEL_DBG) ? LOG_ERR : LOG_CRIT ); + } + + static const char* GetLevelString(s3fs_log_level level) + { + return ( LEVEL_DBG == (level & LEVEL_DBG) ? "[DBG] " : + LEVEL_INFO == (level & LEVEL_DBG) ? "[INF] " : + LEVEL_WARN == (level & LEVEL_DBG) ? "[WAN] " : + LEVEL_ERR == (level & LEVEL_DBG) ? "[ERR] " : "[CRT] " ); + } + + static const char* GetS3fsLogNest(int nest) + { + if(nest < NEST_MAX){ + return nest_spaces[nest]; + }else{ + return nest_spaces[NEST_MAX - 1]; + } + } + + static bool IsSetLogFile() + { + return (NULL != logfp); + } + + static FILE* GetOutputLogFile() + { + return (logfp ? logfp : stdout); + } + + static FILE* GetErrorLogFile() + { + return (logfp ? logfp : stderr); + } + + static void SeekEnd() + { + if(logfp){ + fseek(logfp, 0, SEEK_END); + } + } + + static void Flush() + { + if(logfp){ + fflush(logfp); + } + } + + static bool SetLogfile(const char* pfile); + static bool ReopenLogfile(); + static s3fs_log_level SetLogLevel(s3fs_log_level level); + static s3fs_log_level BumpupLogLevel(); + + explicit S3fsLog(); + ~S3fsLog(); }; //------------------------------------------------------------------- // Debug macros //------------------------------------------------------------------- -#define IS_S3FS_LOG_CRIT() (S3FS_LOG_CRIT == debug_level) -#define IS_S3FS_LOG_ERR() (S3FS_LOG_ERR == (debug_level & S3FS_LOG_DBG)) -#define IS_S3FS_LOG_WARN() (S3FS_LOG_WARN == (debug_level & S3FS_LOG_DBG)) -#define IS_S3FS_LOG_INFO() (S3FS_LOG_INFO == (debug_level & S3FS_LOG_DBG)) -#define IS_S3FS_LOG_DBG() (S3FS_LOG_DBG == (debug_level & S3FS_LOG_DBG)) - -#define S3FS_LOG_LEVEL_TO_SYSLOG(level) \ - ( S3FS_LOG_DBG == (level & S3FS_LOG_DBG) ? LOG_DEBUG : \ - S3FS_LOG_INFO == (level & S3FS_LOG_DBG) ? LOG_INFO : \ - S3FS_LOG_WARN == (level & S3FS_LOG_DBG) ? LOG_WARNING : \ - S3FS_LOG_ERR == (level & S3FS_LOG_DBG) ? LOG_ERR : LOG_CRIT ) - -#define S3FS_LOG_LEVEL_STRING(level) \ - ( S3FS_LOG_DBG == (level & S3FS_LOG_DBG) ? "[DBG] " : \ - S3FS_LOG_INFO == (level & S3FS_LOG_DBG) ? "[INF] " : \ - S3FS_LOG_WARN == (level & S3FS_LOG_DBG) ? "[WAN] " : \ - S3FS_LOG_ERR == (level & S3FS_LOG_DBG) ? "[ERR] " : "[CRT] " ) - -#define S3FS_LOG_NEST_MAX 4 -#define S3FS_LOG_NEST(nest) (nest < S3FS_LOG_NEST_MAX ? s3fs_log_nest[nest] : s3fs_log_nest[S3FS_LOG_NEST_MAX - 1]) - #define S3FS_LOW_LOGPRN(level, fmt, ...) \ - do{ \ - if(S3FS_LOG_CRIT == level || (S3FS_LOG_CRIT != debug_level && level == (debug_level & level))){ \ - if(foreground){ \ - fprintf(stdout, "%s%s:%s(%d): " fmt "%s\n", S3FS_LOG_LEVEL_STRING(level), __FILE__, __func__, __LINE__, __VA_ARGS__); \ - }else{ \ - syslog(S3FS_LOG_LEVEL_TO_SYSLOG(level), "%s%s:%s(%d): " fmt "%s", instance_name.c_str(), __FILE__, __func__, __LINE__, __VA_ARGS__); \ - } \ - } \ - }while(0) + do{ \ + if(S3fsLog::IsS3fsLogLevel(level)){ \ + if(foreground || S3fsLog::IsSetLogFile()){ \ + S3fsLog::SeekEnd(); \ + fprintf(S3fsLog::GetOutputLogFile(), "%s%s:%s(%d): " fmt "%s\n", S3fsLog::GetLevelString(level), __FILE__, __func__, __LINE__, __VA_ARGS__); \ + S3fsLog::Flush(); \ + }else{ \ + syslog(S3fsLog::GetSyslogLevel(level), "%s%s:%s(%d): " fmt "%s", instance_name.c_str(), __FILE__, __func__, __LINE__, __VA_ARGS__); \ + } \ + } \ + }while(0) #define S3FS_LOW_LOGPRN2(level, nest, fmt, ...) \ - do{ \ - if(S3FS_LOG_CRIT == level || (S3FS_LOG_CRIT != debug_level && level == (debug_level & level))){ \ - if(foreground){ \ - fprintf(stdout, "%s%s%s:%s(%d): " fmt "%s\n", S3FS_LOG_LEVEL_STRING(level), S3FS_LOG_NEST(nest), __FILE__, __func__, __LINE__, __VA_ARGS__); \ - }else{ \ - syslog(S3FS_LOG_LEVEL_TO_SYSLOG(level), "%s%s" fmt "%s", instance_name.c_str(), S3FS_LOG_NEST(nest), __VA_ARGS__); \ - } \ - } \ - }while(0) + do{ \ + if(S3fsLog::IsS3fsLogLevel(level)){ \ + if(foreground || S3fsLog::IsSetLogFile()){ \ + S3fsLog::SeekEnd(); \ + fprintf(S3fsLog::GetOutputLogFile(), "%s%s%s:%s(%d): " fmt "%s\n", S3fsLog::GetLevelString(level), S3fsLog::GetS3fsLogNest(nest), __FILE__, __func__, __LINE__, __VA_ARGS__); \ + S3fsLog::Flush(); \ + }else{ \ + syslog(S3fsLog::GetSyslogLevel(level), "%s%s" fmt "%s", instance_name.c_str(), S3fsLog::GetS3fsLogNest(nest), __VA_ARGS__); \ + } \ + } \ + }while(0) #define S3FS_LOW_CURLDBG(fmt, ...) \ - do{ \ - if(foreground){ \ - fprintf(stdout, "[CURL DBG] " fmt "%s\n", __VA_ARGS__); \ - }else{ \ - syslog(S3FS_LOG_LEVEL_TO_SYSLOG(S3FS_LOG_CRIT), "%s" fmt "%s", instance_name.c_str(), __VA_ARGS__); \ - } \ - }while(0) + do{ \ + if(foreground || S3fsLog::IsSetLogFile()){ \ + S3fsLog::SeekEnd(); \ + fprintf(S3fsLog::GetOutputLogFile(), "[CURL DBG] " fmt "%s\n", __VA_ARGS__); \ + S3fsLog::Flush(); \ + }else{ \ + syslog(S3fsLog::GetSyslogLevel(S3fsLog::LEVEL_CRIT), "%s" fmt "%s", instance_name.c_str(), __VA_ARGS__); \ + } \ + }while(0) #define S3FS_LOW_LOGPRN_EXIT(fmt, ...) \ - do{ \ - if(foreground){ \ - fprintf(stderr, "s3fs: " fmt "%s\n", __VA_ARGS__); \ - }else{ \ - fprintf(stderr, "s3fs: " fmt "%s\n", __VA_ARGS__); \ - syslog(S3FS_LOG_LEVEL_TO_SYSLOG(S3FS_LOG_CRIT), "%ss3fs: " fmt "%s", instance_name.c_str(), __VA_ARGS__); \ - } \ - }while(0) + do{ \ + if(foreground || S3fsLog::IsSetLogFile()){ \ + S3fsLog::SeekEnd(); \ + fprintf(S3fsLog::GetErrorLogFile(), "s3fs: " fmt "%s\n", __VA_ARGS__); \ + S3fsLog::Flush(); \ + }else{ \ + fprintf(S3fsLog::GetErrorLogFile(), "s3fs: " fmt "%s\n", __VA_ARGS__); \ + syslog(S3fsLog::GetSyslogLevel(S3fsLog::LEVEL_CRIT), "%ss3fs: " fmt "%s", instance_name.c_str(), __VA_ARGS__); \ + } \ + }while(0) // Special macro for init message #define S3FS_PRN_INIT_INFO(fmt, ...) \ - do{ \ - if(foreground){ \ - fprintf(stdout, "%s%s%s:%s(%d): " fmt "%s\n", S3FS_LOG_LEVEL_STRING(S3FS_LOG_INFO), S3FS_LOG_NEST(0), __FILE__, __func__, __LINE__, __VA_ARGS__, ""); \ - }else{ \ - syslog(S3FS_LOG_LEVEL_TO_SYSLOG(S3FS_LOG_INFO), "%s%s" fmt "%s", instance_name.c_str(), S3FS_LOG_NEST(0), __VA_ARGS__, ""); \ - } \ - }while(0) + do{ \ + if(foreground || S3fsLog::IsSetLogFile()){ \ + S3fsLog::SeekEnd(); \ + fprintf(S3fsLog::GetOutputLogFile(), "%s%s%s:%s(%d): " fmt "%s\n", S3fsLog::GetLevelString(S3fsLog::LEVEL_INFO), S3fsLog::GetS3fsLogNest(0), __FILE__, __func__, __LINE__, __VA_ARGS__, ""); \ + S3fsLog::Flush(); \ + }else{ \ + syslog(S3fsLog::GetSyslogLevel(S3fsLog::LEVEL_INFO), "%s%s" fmt "%s", instance_name.c_str(), S3fsLog::GetS3fsLogNest(0), __VA_ARGS__, ""); \ + } \ + }while(0) // Special macro for checking cache files #define S3FS_LOW_CACHE(fp, fmt, ...) \ - do{ \ - if(foreground){ \ - fprintf(fp, fmt "%s\n", __VA_ARGS__); \ - }else{ \ - syslog(S3FS_LOG_LEVEL_TO_SYSLOG(S3FS_LOG_INFO), "%s: " fmt "%s", instance_name.c_str(), __VA_ARGS__); \ - } \ - }while(0) + do{ \ + if(foreground || S3fsLog::IsSetLogFile()){ \ + S3fsLog::SeekEnd(); \ + fprintf(fp, fmt "%s\n", __VA_ARGS__); \ + S3fsLog::Flush(); \ + }else{ \ + syslog(S3fsLog::GetSyslogLevel(S3fsLog::LEVEL_INFO), "%s: " fmt "%s", instance_name.c_str(), __VA_ARGS__); \ + } \ + }while(0) // [NOTE] // small trick for VA_ARGS // #define S3FS_PRN_EXIT(fmt, ...) S3FS_LOW_LOGPRN_EXIT(fmt, ##__VA_ARGS__, "") -#define S3FS_PRN_CRIT(fmt, ...) S3FS_LOW_LOGPRN(S3FS_LOG_CRIT, fmt, ##__VA_ARGS__, "") -#define S3FS_PRN_ERR(fmt, ...) S3FS_LOW_LOGPRN(S3FS_LOG_ERR, fmt, ##__VA_ARGS__, "") -#define S3FS_PRN_WARN(fmt, ...) S3FS_LOW_LOGPRN(S3FS_LOG_WARN, fmt, ##__VA_ARGS__, "") -#define S3FS_PRN_DBG(fmt, ...) S3FS_LOW_LOGPRN(S3FS_LOG_DBG, fmt, ##__VA_ARGS__, "") -#define S3FS_PRN_INFO(fmt, ...) S3FS_LOW_LOGPRN2(S3FS_LOG_INFO, 0, fmt, ##__VA_ARGS__, "") -#define S3FS_PRN_INFO0(fmt, ...) S3FS_LOG_INFO(fmt, __VA_ARGS__) -#define S3FS_PRN_INFO1(fmt, ...) S3FS_LOW_LOGPRN2(S3FS_LOG_INFO, 1, fmt, ##__VA_ARGS__, "") -#define S3FS_PRN_INFO2(fmt, ...) S3FS_LOW_LOGPRN2(S3FS_LOG_INFO, 2, fmt, ##__VA_ARGS__, "") -#define S3FS_PRN_INFO3(fmt, ...) S3FS_LOW_LOGPRN2(S3FS_LOG_INFO, 3, fmt, ##__VA_ARGS__, "") +#define S3FS_PRN_CRIT(fmt, ...) S3FS_LOW_LOGPRN(S3fsLog::LEVEL_CRIT, fmt, ##__VA_ARGS__, "") +#define S3FS_PRN_ERR(fmt, ...) S3FS_LOW_LOGPRN(S3fsLog::LEVEL_ERR, fmt, ##__VA_ARGS__, "") +#define S3FS_PRN_WARN(fmt, ...) S3FS_LOW_LOGPRN(S3fsLog::LEVEL_WARN, fmt, ##__VA_ARGS__, "") +#define S3FS_PRN_DBG(fmt, ...) S3FS_LOW_LOGPRN(S3fsLog::LEVEL_DBG, fmt, ##__VA_ARGS__, "") +#define S3FS_PRN_INFO(fmt, ...) S3FS_LOW_LOGPRN2(S3fsLog::LEVEL_INFO, 0, fmt, ##__VA_ARGS__, "") +#define S3FS_PRN_INFO1(fmt, ...) S3FS_LOW_LOGPRN2(S3fsLog::LEVEL_INFO, 1, fmt, ##__VA_ARGS__, "") +#define S3FS_PRN_INFO2(fmt, ...) S3FS_LOW_LOGPRN2(S3fsLog::LEVEL_INFO, 2, fmt, ##__VA_ARGS__, "") +#define S3FS_PRN_INFO3(fmt, ...) S3FS_LOW_LOGPRN2(S3fsLog::LEVEL_INFO, 3, fmt, ##__VA_ARGS__, "") #define S3FS_PRN_CURL(fmt, ...) S3FS_LOW_CURLDBG(fmt, ##__VA_ARGS__, "") #define S3FS_PRN_CACHE(fp, ...) S3FS_LOW_CACHE(fp, ##__VA_ARGS__, "") -//------------------------------------------------------------------- -// Global variables -//------------------------------------------------------------------- -// TODO: namespace these -extern s3fs_log_level debug_level; -extern const char* s3fs_log_nest[S3FS_LOG_NEST_MAX]; - #endif // S3FS_LOGGER_H_ /* diff --git a/src/sighandlers.cpp b/src/sighandlers.cpp index c3a5dbd..91a6b64 100644 --- a/src/sighandlers.cpp +++ b/src/sighandlers.cpp @@ -123,7 +123,7 @@ void* S3fsSignals::CheckCacheWorker(void* arg) void S3fsSignals::HandlerUSR2(int sig) { if(SIGUSR2 == sig){ - S3fsSignals::BumpupLogLevel(); + S3fsLog::BumpupLogLevel(); }else{ S3FS_PRN_ERR("The handler for SIGUSR2 received signal(%d)", sig); } @@ -142,29 +142,26 @@ bool S3fsSignals::InitUsr2Handler() return true; } -s3fs_log_level S3fsSignals::SetLogLevel(s3fs_log_level level) +void S3fsSignals::HandlerHUP(int sig) { - if(level == debug_level){ - return debug_level; + if(SIGHUP == sig){ + S3fsLog::ReopenLogfile(); + }else{ + S3FS_PRN_ERR("The handler for SIGHUP received signal(%d)", sig); } - s3fs_log_level old = debug_level; - debug_level = level; - setlogmask(LOG_UPTO(S3FS_LOG_LEVEL_TO_SYSLOG(debug_level))); - S3FS_PRN_CRIT("change debug level from %sto %s", S3FS_LOG_LEVEL_STRING(old), S3FS_LOG_LEVEL_STRING(debug_level)); - return old; } -s3fs_log_level S3fsSignals::BumpupLogLevel() +bool S3fsSignals::InitHupHandler() { - s3fs_log_level old = debug_level; - debug_level = ( S3FS_LOG_CRIT == debug_level ? S3FS_LOG_ERR : - S3FS_LOG_ERR == debug_level ? S3FS_LOG_WARN : - S3FS_LOG_WARN == debug_level ? S3FS_LOG_INFO : - S3FS_LOG_INFO == debug_level ? S3FS_LOG_DBG : - S3FS_LOG_CRIT ); - setlogmask(LOG_UPTO(S3FS_LOG_LEVEL_TO_SYSLOG(debug_level))); - S3FS_PRN_CRIT("change debug level from %sto %s", S3FS_LOG_LEVEL_STRING(old), S3FS_LOG_LEVEL_STRING(debug_level)); - return old; + struct sigaction sa; + + memset(&sa, 0, sizeof(struct sigaction)); + sa.sa_handler = S3fsSignals::HandlerHUP; + sa.sa_flags = SA_RESTART; + if(0 != sigaction(SIGHUP, &sa, NULL)){ + return false; + } + return true; } //------------------------------------------------------------------- @@ -180,6 +177,9 @@ S3fsSignals::S3fsSignals() : pThreadUsr1(NULL), pSemUsr1(NULL) if(!S3fsSignals::InitUsr2Handler()){ S3FS_PRN_ERR("failed to initialize SIGUSR2 handler for bumping log level, but continue..."); } + if(!S3fsSignals::InitHupHandler()){ + S3FS_PRN_ERR("failed to initialize SIGHUP handler for reopen log file, but continue..."); + } } S3fsSignals::~S3fsSignals() diff --git a/src/sighandlers.h b/src/sighandlers.h index f8645a7..11ede73 100644 --- a/src/sighandlers.h +++ b/src/sighandlers.h @@ -44,6 +44,9 @@ class S3fsSignals static void HandlerUSR2(int sig); static bool InitUsr2Handler(); + static void HandlerHUP(int sig); + static bool InitHupHandler(); + S3fsSignals(); ~S3fsSignals(); @@ -56,9 +59,6 @@ class S3fsSignals static bool Destroy(); static bool SetUsr1Handler(const char* path); - - static s3fs_log_level SetLogLevel(s3fs_log_level level); - static s3fs_log_level BumpupLogLevel(); }; #endif // S3FS_SIGHANDLERS_H_ diff --git a/src/test_string_util.cpp b/src/test_string_util.cpp index b9fd3b3..7f5c442 100644 --- a/src/test_string_util.cpp +++ b/src/test_string_util.cpp @@ -34,7 +34,6 @@ // Global variables for test_string_util //------------------------------------------------------------------- bool foreground = false; -s3fs_log_level debug_level = S3FS_LOG_CRIT; std::string instance_name; void test_trim() @@ -141,6 +140,8 @@ void test_wtf8_encoding() int main(int argc, char *argv[]) { + S3fsLog singletonLog; + test_trim(); test_base64(); test_strtoofft();