Add log_remove_target

Don't need to deinit+init struct log any more just to switch log target
:)

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2019-02-07 21:48:39 +00:00
parent 049cc94e7a
commit 68c77cd7d8
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
3 changed files with 37 additions and 17 deletions

View File

@ -2654,12 +2654,12 @@ session_init(session_t *ps_old, int argc, char **argv) {
}; };
log_init_tls(); log_init_tls();
struct log_target *log_target = stderr_logger_new(); auto stderr_logger = stderr_logger_new();
if (!log_target) { if (!stderr_logger) {
fprintf(stderr, "Cannot create any logger, giving up.\n"); fprintf(stderr, "Cannot create any logger, giving up.\n");
abort(); abort();
} }
log_add_target_tls(log_target); log_add_target_tls(stderr_logger);
// Allocate a session and copy default values into it // Allocate a session and copy default values into it
session_t *ps = cmalloc(session_t); session_t *ps = cmalloc(session_t);
@ -2788,14 +2788,11 @@ session_init(session_t *ps_old, int argc, char **argv) {
get_cfg(&ps->o, argc, argv, shadow_enabled, fading_enable, hasneg, winopt_mask); get_cfg(&ps->o, argc, argv, shadow_enabled, fading_enable, hasneg, winopt_mask);
if (ps->o.logpath) { if (ps->o.logpath) {
log_target = file_logger_new(ps->o.logpath); auto l = file_logger_new(ps->o.logpath);
if (log_target) { if (l) {
auto level = log_get_level_tls();
log_info("Switching to log file: %s", ps->o.logpath); log_info("Switching to log file: %s", ps->o.logpath);
log_deinit_tls(); log_remove_target_tls(stderr_logger);
log_init_tls(); log_add_target_tls(l);
log_set_level_tls(level);
log_add_target_tls(log_target);
} else { } else {
log_error("Failed to setup log file %s, I will keep using stderr", ps->o.logpath); log_error("Failed to setup log file %s, I will keep using stderr", ps->o.logpath);
} }

View File

@ -103,7 +103,22 @@ void log_add_target(struct log *l, struct log_target *tgt) {
l->head = tgt; l->head = tgt;
} }
/// Destroy a log struct /// Remove a previously added log target for a log struct. If the log target was never
/// added, nothing happens.
void log_remove_target(struct log *l, struct log_target *tgt) {
struct log_target *now = l->head, **prev = &l->head;
while (now) {
if (now == tgt) {
*prev = now->next;
tgt->ops->destroy(tgt);
break;
}
prev = &now->next;
now = now->next;
}
}
/// Destroy a log struct and every log target added to it
void log_destroy(struct log *l) { void log_destroy(struct log *l) {
// free all tgt // free all tgt
struct log_target *head = l->head; struct log_target *head = l->head;

View File

@ -17,12 +17,11 @@ enum log_level {
LOG_LEVEL_FATAL, LOG_LEVEL_FATAL,
}; };
#define LOG(level, x, ...) \ #define LOG(level, x, ...) \
do { \ do { \
if (LOG_LEVEL_##level >= log_get_level_tls()) { \ if (LOG_LEVEL_##level >= log_get_level_tls()) { \
log_printf(tls_logger, LOG_LEVEL_##level, __func__, x, \ log_printf(tls_logger, LOG_LEVEL_##level, __func__, x, ##__VA_ARGS__); \
##__VA_ARGS__); \ } \
} \
} while (0) } while (0)
#define log_trace(x, ...) LOG(TRACE, x, ##__VA_ARGS__) #define log_trace(x, ...) LOG(TRACE, x, ##__VA_ARGS__)
#define log_debug(x, ...) LOG(DEBUG, x, ##__VA_ARGS__) #define log_debug(x, ...) LOG(DEBUG, x, ##__VA_ARGS__)
@ -38,11 +37,15 @@ attr_printf(4, 5) void log_printf(struct log *, int level, const char *func,
const char *fmt, ...); const char *fmt, ...);
attr_malloc struct log *log_new(void); attr_malloc struct log *log_new(void);
/// Destroy a log struct and every log target added to it
attr_nonnull_all void log_destroy(struct log *); attr_nonnull_all void log_destroy(struct log *);
attr_nonnull(1) void log_set_level(struct log *l, int level); attr_nonnull(1) void log_set_level(struct log *l, int level);
attr_pure enum log_level log_get_level(const struct log *l); attr_pure enum log_level log_get_level(const struct log *l);
attr_nonnull_all void log_add_target(struct log *, struct log_target *); attr_nonnull_all void log_add_target(struct log *, struct log_target *);
attr_const enum log_level string_to_log_level(const char *); attr_const enum log_level string_to_log_level(const char *);
/// Remove a previously added log target for a log struct, and destroy it. If the log
/// target was never added, nothing happens.
void log_remove_target(struct log *l, struct log_target *tgt);
extern thread_local struct log *tls_logger; extern thread_local struct log *tls_logger;
@ -60,6 +63,11 @@ static inline attr_nonnull_all void log_add_target_tls(struct log_target *tgt) {
log_add_target(tls_logger, tgt); log_add_target(tls_logger, tgt);
} }
static inline attr_nonnull_all void log_remove_target_tls(struct log_target *tgt) {
assert(tls_logger);
log_remove_target(tls_logger, tgt);
}
static inline attr_pure enum log_level log_get_level_tls(void) { static inline attr_pure enum log_level log_get_level_tls(void) {
assert(tls_logger); assert(tls_logger);
return log_get_level(tls_logger); return log_get_level(tls_logger);