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
@param[in] FILE* f : the file where to write the logs
@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*/
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);
......
......@@ -373,16 +373,32 @@ BCTBX_PUBLIC char *bctbx_concat(const char *str, ...);
BCTBX_PUBLIC char *bctbx_replace(char *str, char c, char n);
/**
* Portable version of the dirname function from libgen.h
* @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().
* @brief Return the directory part of a file path.
*
* 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);
/**
* Portable version of the basename function from libgen.h
* @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().
* @brief Return the name of a file from its path.
*
* 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);
......
......@@ -114,6 +114,7 @@ typedef struct _bctbx_file_log_handler_t {
uint64_t max_size;
uint64_t size;
FILE* file;
bool_t reopen_requested;
} bctbx_file_log_handler_t;
......@@ -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_file_log_handler_t *filehandler = NULL;
char *full_name = bctbx_strdup_printf("%s/%s", path, name);
int res;
struct stat buf = {0};
res = stat(full_name, &buf);
if (!f && res != 0) {
fprintf(stderr, "Error while creating file log handler. \n");
FILE *f = fopen(full_name, "a");
if (f == NULL) {
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;
}
......@@ -224,6 +228,14 @@ end:
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.
*
......@@ -723,11 +735,10 @@ void bctbx_logv_file(void* user_info, const char *domain, BctbxLogLevel lev, con
time_t tt;
int ret = -1;
bctbx_file_log_handler_t *filehandler = (bctbx_file_log_handler_t *) user_info;
FILE *f;
bctbx_logger_t *logger = bctbx_get_logger();
bctbx_mutex_lock(&logger->log_mutex);
f = filehandler ? filehandler->file : stdout;
FILE *f = filehandler ? filehandler->file : stdout;
bctbx_gettimeofday(&tp,NULL);
tt = (time_t)tp.tv_sec;
......@@ -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
,(int)(tp.tv_usec/1000), (domain?domain:"bctoolbox"), lname, msg);
fflush(f);
if (filehandler && filehandler->max_size > 0 && ret > 0) {
filehandler->size += ret;
if (filehandler->size > filehandler->max_size) {
/* reopen the log file when either the size limit has been exceeded, or reopen has been required
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);
_open_log_collection_file(filehandler);
filehandler->reopen_requested = FALSE;
}
}
......
......@@ -81,7 +81,6 @@ static char *bc_current_suite_name = NULL;
static char *bc_current_test_name = NULL;
static char *log_file_name = NULL;
static FILE *log_file = NULL;
static int bc_printf_verbosity_info;
static int bc_printf_verbosity_error;
......@@ -1041,25 +1040,20 @@ int bc_tester_silent_handler(const char *arg) {
//Default function for the `--log-file`cli option
int bc_tester_logfile_handler(const char *arg) {
bctbx_log_handler_t *filehandler;
char* dir;
char* base;
if (log_file) {
fclose(log_file);
}
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;
int res = 0;
char *dir = bctbx_dirname(arg);
char *base = bctbx_basename(arg);
bctbx_log_handler_t *filehandler = bctbx_create_file_log_handler(0, dir, base);
if (filehandler == NULL) {
res = -1;
goto end;
}
dir = bctbx_dirname(arg);
base = bctbx_basename(arg);
filehandler = bctbx_create_file_log_handler(0, dir, base, log_file);
bctbx_add_log_handler(filehandler);
if (dir) bctbx_free(dir);
if (base) bctbx_free(base);
return 0;
end:
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) {
......
......@@ -108,33 +108,15 @@ char * bctbx_strdup(const char *tmp){
}
char * bctbx_dirname(const char *path) {
char *ptr;
char *dname = bctbx_strdup(path);
bool_t found = FALSE;
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 *ptr = strrchr(path, '/');
if (ptr == NULL) ptr = strrchr(path, '\\');
return ptr ? bctbx_strndup(path, ptr-path) : bctbx_strdup(".");
}
char * bctbx_basename(const char *path) {
char *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);
}
......
......@@ -21,7 +21,6 @@
#include "bctoolbox/logging.h"
#include "bctoolbox_tester.h"
static FILE * log_file = NULL;
static const char *log_domain = "bctoolbox-tester";
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");
va_end(cap);
#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() {
}
int bctoolbox_tester_set_log_file(const char *filename) {
bctbx_log_handler_t* filehandler;
char* dir;
char* base;
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);
int res = 0;
char* dir = bctbx_dirname(filename);
char* base = bctbx_basename(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);
if (dir) bctbx_free(dir);
if (base) bctbx_free(base);
return 0;
end:
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