#include "precompile.h" #include "log_redirect.h" #include "log_base.h" #include "log.h" #include "spinlock.h" #include "array.h" #include typedef struct redirectlogfactory_t redirectlogfactory_t; typedef struct redirectlog_t { logbase_t base; array_header_t *arr_dst; LONG file_lock; spinlock_t internal_lock; }redirectlog_t; struct redirectlogfactory_t { logfactory_t base; }; static void redirectlogfactory_destroy(void *self) { redirectlogfactory_t *fac = (redirectlogfactory_t *)self; if (fac) { if (fac->base.name) free(fac->base.name); free(fac); } } static void* redirectlogfactory_create_log(void *self, const char* inst) { redirectlogfactory_t *fac = (redirectlogfactory_t *)self; redirectlog_t *log = MALLOC_T(redirectlog_t); log->base.level = XLOG_LEVEL_ALL; log->base.factory = self; log->base.inst_name = _strdup(inst); log->arr_dst = array_make(8, sizeof(char*)); log->file_lock = 0; spinlock_init(&log->internal_lock); return log; } static int redirectlogfactory_set_log_param(void *self, void *log, const char *key, const char *value) { redirectlogfactory_t *fac = (redirectlogfactory_t *)self; redirectlog_t *slog = (redirectlog_t*)log; if (_stricmp(key, "destination") == 0) { char *p = _strdup(value); char *q; char *delim = ", "; q = strtok(p, delim); while (q != NULL) { ARRAY_PUSH(slog->arr_dst, char*) = _strdup(q); q = strtok(NULL, delim); } } else if (_stricmp(key, "use_lock") == 0) { if (_stricmp(value, "true") == 0 || _stricmp(value, "1") == 0) { slog->file_lock = 1; } else { slog->file_lock = 0; } } else if (_stricmp(key, "level") == 0) { if (_stricmp(value, "all") == 0) { slog->base.level = 0; } else if (_stricmp(value, "trace") == 0) { slog->base.level = 1; } else if (_stricmp(value, "debug") == 0) { slog->base.level = 2; } else if (_stricmp(value, "info") == 0) { slog->base.level = 3; } else if (_stricmp(value, "warn") == 0) { slog->base.level = 4; } else if (_stricmp(value, "error") == 0) { slog->base.level = 5; } else if (_stricmp(value, "fatal") == 0) { slog->base.level = 6; } else if (_stricmp(value, "none") == 0) { slog->base.level = 7; } else { return -1; } } else { return -1; } return 0; } static int redirectlogfactory_init_log(void *self, void *log) { redirectlogfactory_t *fac = (redirectlogfactory_t *)self; redirectlog_t *slog = (redirectlog_t*)log; return 0; } static int redirectlogfactory_term_log(void *self, void *log) { redirectlogfactory_t *fac = (redirectlogfactory_t *)self; redirectlog_t *slog = (redirectlog_t*)log; int i; char *pos; slog->file_lock = 0; ARRAY_FOR_EACH_ENTRY(pos, i, slog->arr_dst, char*) { free(pos); } array_clear(slog->arr_dst); return 0; } static void redirectlogfactory_destroy_log(void *self, void *log) { redirectlog_t *slog = (redirectlog_t*)log; if (slog) { if (slog->arr_dst) array_free(slog->arr_dst); if (slog->base.inst_name) free(slog->base.inst_name); free(slog); } } logbase_t *xlog_find_log(const char *inst); static int redirectlogfactory_record_log(void *self, void *log, int level, unsigned long ts_low, unsigned long ts_high, const char *s, int sn) { redirectlogfactory_t *fac = (redirectlogfactory_t *)self; redirectlog_t *slog = (redirectlog_t*)log; if (slog->arr_dst->nelts > 0) { int i; char *inst; if (slog->file_lock) spinlock_enter(&slog->internal_lock, -1); ARRAY_FOR_EACH_ENTRY(inst, i, slog->arr_dst, char*) { logbase_t *log = xlog_find_log(inst); if (log) { logfactory_log_record(log->factory, log, level, ts_low, ts_high, s, sn); } else { OutputDebugStringA("log inst "); OutputDebugStringA(inst); OutputDebugStringA("not found\n"); } } if (slog->file_lock) spinlock_leave(&slog->internal_lock); } return 0; } int redirectlogfactory_create(logfactory_t **p_fac) { redirectlogfactory_t *fac; if (!p_fac) return -1; fac = MALLOC_T(redirectlogfactory_t); fac->base.name = _strdup("redirect"); fac->base.record_log = &redirectlogfactory_record_log; fac->base.init_log = &redirectlogfactory_init_log; fac->base.set_log_param = &redirectlogfactory_set_log_param; fac->base.term_log = &redirectlogfactory_term_log; fac->base.create_log = &redirectlogfactory_create_log; fac->base.destroy_log = &redirectlogfactory_destroy_log; fac->base.destroy = &redirectlogfactory_destroy; *p_fac = &fac->base; return 0; }