From b43bc048eb4c2c0855d4d7c4ad6b0b3c14e50eb2 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 27 Jun 2011 10:29:17 +0200 Subject: logging: introduce library-internal logging categories We do this by using a trick: library-internal log categories use negative subsystem numbers, which are converted into positive array indexes at the time of logging. library-internal log categories need to be knwo at compile-time, while application-specified categories now are of unlimited number, as they are dynamically allocated. --- src/logging.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 20 deletions(-) (limited to 'src/logging.c') diff --git a/src/logging.c b/src/logging.c index 3c9dc03f..def13b3b 100644 --- a/src/logging.c +++ b/src/logging.c @@ -40,7 +40,7 @@ #include /* for LOGGING_STR. */ -const struct log_info *osmo_log_info; +struct log_info *osmo_log_info; static struct log_context log_context; static void *tall_log_ctx = NULL; @@ -58,6 +58,16 @@ static const struct value_string loglevel_strs[LOGLEVEL_DEFS+1] = { { 0, NULL }, }; +#define INT2IDX(x) (-1*(x)-1) +static const struct log_info_cat internal_cat[OSMO_NUM_DLIB] = { + [INT2IDX(DLGLOBAL)] = { /* -1 becomes 0 */ + .name = "DLGLOBAL", + .description = "Library-internal global log family", + .loglevel = LOGL_NOTICE, + .enabled = 1, + }, +}; + /* You have to keep this in sync with the structure loglevel_strs. */ const char *loglevel_descriptions[LOGLEVEL_DEFS+1] = { "Log simply everything", @@ -69,6 +79,12 @@ const char *loglevel_descriptions[LOGLEVEL_DEFS+1] = { NULL, }; +/* special magic for negative (library-internal) log subsystem numbers */ +static int subsys_lib2index(int subsys) +{ + return (subsys * -1) + (osmo_log_info->num_cat_user-1); +} + int log_parse_level(const char *lvl) { return get_string_value(loglevel_strs, lvl); @@ -84,6 +100,8 @@ int log_parse_category(const char *category) int i; for (i = 0; i < osmo_log_info->num_cat; ++i) { + if (osmo_log_info->cat[i].name == NULL) + continue; if (!strcasecmp(osmo_log_info->cat[i].name+1, category)) return i; } @@ -103,7 +121,7 @@ void log_parse_category_mask(struct log_target* target, const char *_mask) char *category_token = NULL; /* Disable everything to enable it afterwards */ - for (i = 0; i < ARRAY_SIZE(target->categories); ++i) + for (i = 0; i < osmo_log_info->num_cat; ++i) target->categories[i].enabled = 0; category_token = strtok(mask, ":"); @@ -112,6 +130,9 @@ void log_parse_category_mask(struct log_target* target, const char *_mask) char* colon = strstr(category_token, ","); int length = strlen(category_token); + if (!osmo_log_info->cat[i].name) + continue; + if (colon) length = colon - category_token; @@ -189,12 +210,17 @@ err: target->output(target, level, buf); } - -static void _logp(unsigned int subsys, int level, char *file, int line, +static void _logp(int subsys, int level, char *file, int line, int cont, const char *format, va_list ap) { struct log_target *tar; + if (subsys < 0) + subsys = subsys_lib2index(subsys); + + if (subsys > osmo_log_info->num_cat) + subsys = DLGLOBAL; + llist_for_each_entry(tar, &osmo_log_target_list, entry) { struct log_category *category; int output = 0; @@ -234,7 +260,7 @@ static void _logp(unsigned int subsys, int level, char *file, int line, } } -void logp(unsigned int subsys, char *file, int line, int cont, +void logp(int subsys, char *file, int line, int cont, const char *format, ...) { va_list ap; @@ -244,7 +270,7 @@ void logp(unsigned int subsys, char *file, int line, int cont, va_end(ap); } -void logp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) +void logp2(int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) { va_list ap; @@ -326,6 +352,14 @@ struct log_target *log_target_create(void) if (!target) return NULL; + target->categories = talloc_zero_array(target, + struct log_category, + osmo_log_info->num_cat); + if (!target->categories) { + talloc_free(target); + return NULL; + } + INIT_LLIST_HEAD(&target->entry); /* initialize the per-category enabled/loglevel from defaults */ @@ -441,8 +475,11 @@ const char *log_vty_command_string(const struct log_info *info) int size = strlen("logging level () ()") + 1; char *str; - for (i = 0; i < info->num_cat; i++) + for (i = 0; i < info->num_cat; i++) { + if (info->cat[i].name == NULL) + continue; size += strlen(info->cat[i].name) + 1; + } for (i = 0; i < LOGLEVEL_DEFS; i++) size += strlen(loglevel_strs[i].str) + 1; @@ -458,17 +495,19 @@ const char *log_vty_command_string(const struct log_info *info) OSMO_SNPRINTF_RET(ret, rem, offset, len); for (i = 0; i < info->num_cat; i++) { - int j, name_len = strlen(info->cat[i].name)+1; - char name[name_len]; + if (info->cat[i].name) { + int j, name_len = strlen(info->cat[i].name)+1; + char name[name_len]; - for (j = 0; j < name_len; j++) - name[j] = tolower(info->cat[i].name[j]); + for (j = 0; j < name_len; j++) + name[j] = tolower(info->cat[i].name[j]); - name[name_len-1] = '\0'; - ret = snprintf(str + offset, rem, "%s|", name+1); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); + name[name_len-1] = '\0'; + ret = snprintf(str + offset, rem, "%s|", name+1); + if (ret < 0) + goto err; + OSMO_SNPRINTF_RET(ret, rem, offset, len); + } } offset--; /* to remove the trailing | */ rem++; @@ -512,8 +551,11 @@ const char *log_vty_command_description(const struct log_info *info) strlen(LOGGING_STR "Set the log level for a specified category\n") + 1; - for (i = 0; i < info->num_cat; i++) + for (i = 0; i < info->num_cat; i++) { + if (info->cat[i].name == NULL) + continue; size += strlen(info->cat[i].description) + 1; + } for (i = 0; i < LOGLEVEL_DEFS; i++) size += strlen(loglevel_descriptions[i]) + 1; @@ -537,6 +579,8 @@ const char *log_vty_command_description(const struct log_info *info) OSMO_SNPRINTF_RET(ret, rem, offset, len); for (i = 0; i < info->num_cat; i++) { + if (info->cat[i].name == NULL) + continue; ret = snprintf(str + offset, rem, "%s\n", info->cat[i].description); if (ret < 0) @@ -555,8 +599,36 @@ err: return str; } -void log_init(const struct log_info *cat) +int log_init(const struct log_info *inf, void *ctx) { - tall_log_ctx = talloc_named_const(NULL, 1, "logging"); - osmo_log_info = cat; + int i; + + tall_log_ctx = talloc_named_const(ctx, 1, "logging"); + if (!tall_log_ctx) + return -ENOMEM; + + osmo_log_info = talloc_zero(tall_log_ctx, struct log_info); + if (!osmo_log_info) + return -ENOMEM; + + osmo_log_info->num_cat_user = inf->num_cat; + /* total number = number of user cat + library cat */ + osmo_log_info->num_cat = inf->num_cat + OSMO_NUM_DLIB; + + osmo_log_info->cat = talloc_zero_array(osmo_log_info, + struct log_info_cat, + osmo_log_info->num_cat); + if (!osmo_log_info->cat) { + talloc_free(osmo_log_info); + osmo_log_info = NULL; + return -ENOMEM; + } + + /* copy over the user part */ + for (i = 0; i < inf->num_cat; i++) { + memcpy(&osmo_log_info->cat[i], &inf->cat[i], + sizeof(struct log_info_cat)); + } + + /* copy over the library part */ } -- cgit v1.2.3