Commit 790e6aef authored by François Grisez's avatar François Grisez

Add bctbx_file_log_handler_reopen() function

parent 994394bc
...@@ -98,7 +98,15 @@ BCTBX_PUBLIC bctbx_log_handler_t* bctbx_create_log_handler(BctbxLogHandlerFunc f ...@@ -98,7 +98,15 @@ BCTBX_PUBLIC bctbx_log_handler_t* bctbx_create_log_handler(BctbxLogHandlerFunc f
@param[in] FILE* f : the file where to write the logs @param[in] FILE* f : the file where to write the logs
@return a new bctbx_log_handler_t @return a new bctbx_log_handler_t
*/ */
BCTBX_PUBLIC bctbx_log_handler_t* bctbx_create_file_log_handler(uint64_t max_size, const char* path, const char* name, FILE* f); BCTBX_PUBLIC bctbx_log_handler_t* bctbx_create_file_log_handler(uint64_t max_size, const char* path, const char* name);
/**
* @brief Request reopening of the log file.
* @param[in] file_log_handler The log handler whose file will be reopened.
* @note This function is thread-safe and reopening is done asynchronously.
*/
BCTBX_PUBLIC void bctbx_file_log_handler_reopen(bctbx_log_handler_t *file_log_handler);
/* set domain the handler is limited to. NULL for ALL*/ /* set domain the handler is limited to. NULL for ALL*/
BCTBX_PUBLIC void bctbx_log_handler_set_domain(bctbx_log_handler_t * log_handler,const char *domain); BCTBX_PUBLIC void bctbx_log_handler_set_domain(bctbx_log_handler_t * log_handler,const char *domain);
BCTBX_PUBLIC void bctbx_log_handler_set_user_data(bctbx_log_handler_t*, void* user_data); BCTBX_PUBLIC void bctbx_log_handler_set_user_data(bctbx_log_handler_t*, void* user_data);
......
...@@ -373,16 +373,32 @@ BCTBX_PUBLIC char *bctbx_concat(const char *str, ...); ...@@ -373,16 +373,32 @@ BCTBX_PUBLIC char *bctbx_concat(const char *str, ...);
BCTBX_PUBLIC char *bctbx_replace(char *str, char c, char n); BCTBX_PUBLIC char *bctbx_replace(char *str, char c, char n);
/** /**
* Portable version of the dirname function from libgen.h * @brief Return the directory part of a file path.
* @param[in] path The full path for which we want to find the dirname *
* @return NULL if no dirname is found, otherwise a copy of the dirname of path that needs to be freed with bctbx_free(). * Find the last delimiting character ('/' or '\') and return a
* copy of the substring before. If no delimiter has been found,
* then "." string is returned.
*
* @param[in] path A string containing a file path. The behaviour
* is undefined if the string contains a path to a directoy. MUST be non-NULL.
* @return An allocated string containing the directory name.
*
* @warning This funciton isn't equivalent to libgen.h dirname().
*/ */
BCTBX_PUBLIC char *bctbx_dirname(const char *path); BCTBX_PUBLIC char *bctbx_dirname(const char *path);
/** /**
* Portable version of the basename function from libgen.h * @brief Return the name of a file from its path.
* @param[in] path The full path for which we want to find the basename *
* @return NULL if no basename is found, otherwise a copy of the basename of path that needs to be freed with bctbx_free(). * Find the last delimiting character ('/' or '\') and return a
* copy of the substring after. If no delimiter has been found,
* then a copy of 'path' is returned.
*
* @param[in] path A string containing a file path. The behaviour
* is undefined if the string contains a path to a directoy. MUST be non-NULL.
* @return An allocated string containing the file name.
*
* @warning This funciton isn't equivalent to libgen.h basename().
*/ */
BCTBX_PUBLIC char *bctbx_basename(const char *path); BCTBX_PUBLIC char *bctbx_basename(const char *path);
......
...@@ -114,6 +114,7 @@ typedef struct _bctbx_file_log_handler_t { ...@@ -114,6 +114,7 @@ typedef struct _bctbx_file_log_handler_t {
uint64_t max_size; uint64_t max_size;
uint64_t size; uint64_t size;
FILE* file; FILE* file;
bool_t reopen_requested;
} bctbx_file_log_handler_t; } bctbx_file_log_handler_t;
...@@ -194,16 +195,19 @@ void bctbx_log_handler_set_domain(bctbx_log_handler_t * log_handler, const char ...@@ -194,16 +195,19 @@ void bctbx_log_handler_set_domain(bctbx_log_handler_t * log_handler, const char
} }
} }
bctbx_log_handler_t* bctbx_create_file_log_handler(uint64_t max_size, const char* path, const char* name, FILE* f) { bctbx_log_handler_t* bctbx_create_file_log_handler(uint64_t max_size, const char* path, const char* name) {
bctbx_log_handler_t *handler = NULL; bctbx_log_handler_t *handler = NULL;
bctbx_file_log_handler_t *filehandler = NULL; bctbx_file_log_handler_t *filehandler = NULL;
char *full_name = bctbx_strdup_printf("%s/%s", path, name); char *full_name = bctbx_strdup_printf("%s/%s", path, name);
int res;
struct stat buf = {0}; struct stat buf = {0};
res = stat(full_name, &buf); FILE *f = fopen(full_name, "a");
if (!f && res != 0) { if (f == NULL) {
fprintf(stderr, "Error while creating file log handler. \n"); fprintf(stderr, "error while opening '%s': %s\n", full_name, strerror(errno));
goto end;
}
if (stat(full_name, &buf) != 0) {
fprintf(stderr, "error while gathering info about '%s': %s", full_name, strerror(errno));
goto end; goto end;
} }
...@@ -224,6 +228,14 @@ end: ...@@ -224,6 +228,14 @@ end:
return handler; return handler;
} }
void bctbx_file_log_handler_reopen(bctbx_log_handler_t *file_log_handler) {
bctbx_file_log_handler_t *filehandler = (bctbx_file_log_handler_t *)file_log_handler->user_info;
bctbx_logger_t *logger = bctbx_get_logger();
bctbx_mutex_lock(&logger->log_mutex);
filehandler->reopen_requested = TRUE;
bctbx_mutex_unlock(&logger->log_mutex);
}
/** /**
*@param func: your logging function, compatible with the BctoolboxLogFunc prototype. *@param func: your logging function, compatible with the BctoolboxLogFunc prototype.
* *
...@@ -723,11 +735,10 @@ void bctbx_logv_file(void* user_info, const char *domain, BctbxLogLevel lev, con ...@@ -723,11 +735,10 @@ void bctbx_logv_file(void* user_info, const char *domain, BctbxLogLevel lev, con
time_t tt; time_t tt;
int ret = -1; int ret = -1;
bctbx_file_log_handler_t *filehandler = (bctbx_file_log_handler_t *) user_info; bctbx_file_log_handler_t *filehandler = (bctbx_file_log_handler_t *) user_info;
FILE *f;
bctbx_logger_t *logger = bctbx_get_logger(); bctbx_logger_t *logger = bctbx_get_logger();
bctbx_mutex_lock(&logger->log_mutex); bctbx_mutex_lock(&logger->log_mutex);
f = filehandler ? filehandler->file : stdout; FILE *f = filehandler ? filehandler->file : stdout;
bctbx_gettimeofday(&tp,NULL); bctbx_gettimeofday(&tp,NULL);
tt = (time_t)tp.tv_sec; tt = (time_t)tp.tv_sec;
...@@ -779,11 +790,20 @@ void bctbx_logv_file(void* user_info, const char *domain, BctbxLogLevel lev, con ...@@ -779,11 +790,20 @@ void bctbx_logv_file(void* user_info, const char *domain, BctbxLogLevel lev, con
,1900+lt->tm_year,1+lt->tm_mon,lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_sec ,1900+lt->tm_year,1+lt->tm_mon,lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_sec
,(int)(tp.tv_usec/1000), (domain?domain:"bctoolbox"), lname, msg); ,(int)(tp.tv_usec/1000), (domain?domain:"bctoolbox"), lname, msg);
fflush(f); fflush(f);
if (filehandler && filehandler->max_size > 0 && ret > 0) {
filehandler->size += ret; /* reopen the log file when either the size limit has been exceeded, or reopen has been required
if (filehandler->size > filehandler->max_size) { by the user. Reopening a log file that has reached the size limit automatically trigger log rotation
while opening. */
if (filehandler) {
bool_t reopen_requested = filehandler->reopen_requested;
if (filehandler->max_size > 0 && ret > 0) {
filehandler->size += ret;
reopen_requested = reopen_requested || filehandler->size > filehandler->max_size;
}
if (reopen_requested) {
_close_log_collection_file(filehandler); _close_log_collection_file(filehandler);
_open_log_collection_file(filehandler); _open_log_collection_file(filehandler);
filehandler->reopen_requested = FALSE;
} }
} }
......
...@@ -81,7 +81,6 @@ static char *bc_current_suite_name = NULL; ...@@ -81,7 +81,6 @@ static char *bc_current_suite_name = NULL;
static char *bc_current_test_name = NULL; static char *bc_current_test_name = NULL;
static char *log_file_name = NULL; static char *log_file_name = NULL;
static FILE *log_file = NULL;
static int bc_printf_verbosity_info; static int bc_printf_verbosity_info;
static int bc_printf_verbosity_error; static int bc_printf_verbosity_error;
...@@ -1041,25 +1040,20 @@ int bc_tester_silent_handler(const char *arg) { ...@@ -1041,25 +1040,20 @@ int bc_tester_silent_handler(const char *arg) {
//Default function for the `--log-file`cli option //Default function for the `--log-file`cli option
int bc_tester_logfile_handler(const char *arg) { int bc_tester_logfile_handler(const char *arg) {
bctbx_log_handler_t *filehandler; int res = 0;
char* dir; char *dir = bctbx_dirname(arg);
char* base; char *base = bctbx_basename(arg);
bctbx_log_handler_t *filehandler = bctbx_create_file_log_handler(0, dir, base);
if (log_file) { if (filehandler == NULL) {
fclose(log_file); res = -1;
} goto end;
log_file = fopen(arg, "w");
if (!log_file) {
bc_tester_printf(bc_printf_verbosity_error, "Cannot open file [%s] for writing logs because [%s]", arg, strerror(errno));
return -1;
} }
dir = bctbx_dirname(arg);
base = bctbx_basename(arg);
filehandler = bctbx_create_file_log_handler(0, dir, base, log_file);
bctbx_add_log_handler(filehandler); bctbx_add_log_handler(filehandler);
if (dir) bctbx_free(dir);
if (base) bctbx_free(base); end:
return 0; bctbx_free(dir);
bctbx_free(base);
return res;
} }
void bc_tester_init(void (*ftester_printf)(int level, const char *format, va_list args), int iverbosity_info, int iverbosity_error, const char* aexpected_res) { void bc_tester_init(void (*ftester_printf)(int level, const char *format, va_list args), int iverbosity_info, int iverbosity_error, const char* aexpected_res) {
......
...@@ -108,33 +108,15 @@ char * bctbx_strdup(const char *tmp){ ...@@ -108,33 +108,15 @@ char * bctbx_strdup(const char *tmp){
} }
char * bctbx_dirname(const char *path) { char * bctbx_dirname(const char *path) {
char *ptr; char *ptr = strrchr(path, '/');
char *dname = bctbx_strdup(path); if (ptr == NULL) ptr = strrchr(path, '\\');
bool_t found = FALSE; return ptr ? bctbx_strndup(path, ptr-path) : bctbx_strdup(".");
ptr = strrchr(path, '/');
if (ptr != NULL) {
dname[ptr - path] = '\0';
found = TRUE;
} else {
ptr = strrchr(path, '\\');
if (ptr != NULL) {
dname[ptr - path] = '\0';
found = TRUE;
}
}
if (found == FALSE) {
bctbx_free(dname);
return NULL;
}
return dname;
} }
char * bctbx_basename(const char *path) { char * bctbx_basename(const char *path) {
char *ptr = strrchr(path, '/'); char *ptr = strrchr(path, '/');
if (ptr == NULL) ptr = strrchr(path, '\\'); if (ptr == NULL) ptr = strrchr(path, '\\');
if (ptr == NULL) return NULL; if (ptr == NULL) return bctbx_strdup(path);
return bctbx_strdup(ptr + 1); return bctbx_strdup(ptr + 1);
} }
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include "bctoolbox/logging.h" #include "bctoolbox/logging.h"
#include "bctoolbox_tester.h" #include "bctoolbox_tester.h"
static FILE * log_file = NULL;
static const char *log_domain = "bctoolbox-tester"; static const char *log_domain = "bctoolbox-tester";
static void log_handler(int lev, const char *fmt, va_list args) { static void log_handler(int lev, const char *fmt, va_list args) {
...@@ -36,9 +35,8 @@ static void log_handler(int lev, const char *fmt, va_list args) { ...@@ -36,9 +35,8 @@ static void log_handler(int lev, const char *fmt, va_list args) {
fprintf(lev == BCTBX_LOG_ERROR ? stderr : stdout, "\n"); fprintf(lev == BCTBX_LOG_ERROR ? stderr : stdout, "\n");
va_end(cap); va_end(cap);
#endif #endif
if (log_file){
bctbx_logv(log_domain,lev, fmt, args); bctbx_logv(log_domain,lev, fmt, args);
}
} }
...@@ -60,25 +58,21 @@ void bctoolbox_tester_before_each() { ...@@ -60,25 +58,21 @@ void bctoolbox_tester_before_each() {
} }
int bctoolbox_tester_set_log_file(const char *filename) { int bctoolbox_tester_set_log_file(const char *filename) {
bctbx_log_handler_t* filehandler; int res = 0;
char* dir; char* dir = bctbx_dirname(filename);
char* base; char* base = bctbx_basename(filename);
if (log_file) {
fclose(log_file);
}
log_file = fopen(filename, "a");
if (!log_file) {
bctbx_error("Cannot open file [%s] for writing logs because [%s]", filename, strerror(errno));
return -1;
}
dir = bctbx_dirname(filename);
base = bctbx_basename(filename);
bctbx_message("Redirecting traces to file [%s]", filename); bctbx_message("Redirecting traces to file [%s]", filename);
filehandler = bctbx_create_file_log_handler(0, dir, base, log_file); bctbx_log_handler_t *filehandler = bctbx_create_file_log_handler(0, dir, base);
if (filehandler == NULL) {
res = -1;
goto end;
}
bctbx_add_log_handler(filehandler); bctbx_add_log_handler(filehandler);
if (dir) bctbx_free(dir);
if (base) bctbx_free(base); end:
return 0; bctbx_free(dir);
bctbx_free(base);
return res;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment