Index: main/logger.c =================================================================== --- main/logger.c (revision 42010) +++ main/logger.c (working copy) @@ -124,10 +124,18 @@ const char *file; int line; const char *function; - char *str; + struct ast_dynamic_str *buf; AST_LIST_ENTRY(logmsg) list; }; +static void logmsg_cache_cleanup(void *data); + +/*! \brief A per-thread cache of logmsg structs */ +AST_THREADSTORAGE_CUSTOM(logmsg_cache, logmsg_cache_init, logmsg_cache_cleanup); + +/*! Default buffer length for a logmsg */ +#define LOGMSG_INIT_LEN 80 + static AST_LIST_HEAD_STATIC(logmsgs, logmsg); static pthread_t logthread = AST_PTHREADT_NULL; static ast_cond_t logcond; @@ -631,7 +639,7 @@ AST_LIST_LOCK(&logchannels); if (logfiles.event_log && logmsg->level == __LOG_EVENT) { - fprintf(eventlog, "%s asterisk[%ld]: %s", logmsg->date, (long)getpid(), logmsg->str); + fprintf(eventlog, "%s asterisk[%ld]: %s", logmsg->date, (long)getpid(), logmsg->buf->str); fflush(eventlog); AST_LIST_UNLOCK(&logchannels); return; @@ -644,7 +652,7 @@ continue; /* Check syslog channels */ if (chan->type == LOGTYPE_SYSLOG && (chan->logmask & (1 << logmsg->level))) { - ast_log_vsyslog(logmsg->level, logmsg->file, logmsg->line, logmsg->function, logmsg->str); + ast_log_vsyslog(logmsg->level, logmsg->file, logmsg->line, logmsg->function, logmsg->buf->str); /* Console channels */ } else if (chan->type == LOGTYPE_CONSOLE && (chan->logmask & (1 << logmsg->level))) { char linestr[128]; @@ -664,7 +672,7 @@ term_color(tmp2, logmsg->file, COLOR_BRWHITE, 0, sizeof(tmp2)), term_color(tmp3, linestr, COLOR_BRWHITE, 0, sizeof(tmp3)), term_color(tmp4, logmsg->function, COLOR_BRWHITE, 0, sizeof(tmp4)), - logmsg->str); + logmsg->buf->str); /* Print out */ ast_console_puts_mutable(buf); /* File channels */ @@ -677,8 +685,8 @@ /* Print out to the file */ res = fprintf(chan->fileptr, "[%s] %s[%ld] %s: %s", - logmsg->date, levels[logmsg->level], (long)GETTID(), logmsg->file, logmsg->str); - if (res <= 0 && !ast_strlen_zero(logmsg->str)) { + logmsg->date, levels[logmsg->level], (long)GETTID(), logmsg->file, logmsg->buf->str); + if (res <= 0 && !ast_strlen_zero(logmsg->buf->str)) { fprintf(stderr, "**** Asterisk Logging Error: ***********\n"); if (errno == ENOMEM || errno == ENOSPC) fprintf(stderr, "Asterisk logging error: Out of disk space, can't log to log file %s\n", chan->filename); @@ -690,7 +698,7 @@ } } } else if (logmsg->level != __LOG_VERBOSE) { - fputs(logmsg->str, stdout); + fputs(logmsg->buf->str, stdout); } AST_LIST_UNLOCK(&logchannels); @@ -706,6 +714,56 @@ return; } +static void logmsg_cache_cleanup(void *data) +{ + struct logmsgs *logmsgs = data; + struct logmsg *logmsg; + + while ((logmsg = AST_LIST_REMOVE_HEAD(logmsgs, list))) + free(logmsg); + + free(logmsgs); +} + +static void logmsg_free(struct logmsg *logmsg) +{ + struct logmsgs *logmsgs; + + if ((logmsgs = ast_threadstorage_get(&logmsg_cache, sizeof(*logmsgs)))) { + AST_LIST_INSERT_HEAD(logmsgs, logmsg, list); + return; + } + + free(logmsg->buf); + free(logmsg); +} + +static struct logmsg *logmsg_new(void) +{ + struct logmsgs *logmsgs; + struct logmsg *logmsg; + + if ((logmsgs = ast_threadstorage_get(&logmsg_cache, sizeof(*logmsgs)))) { + if ((logmsg = AST_LIST_REMOVE_HEAD(logmsgs, list))) { + struct ast_dynamic_str *buf = logmsg->buf; + memset(logmsg, 0, sizeof(*logmsg)); + logmsg->buf = buf; + ast_dynamic_str_set(&logmsg->buf, 0, "%s", ""); + return logmsg; + } + } + + if (!(logmsg = ast_calloc(1, sizeof(*logmsg)))) + return NULL; + + if (!(logmsg->buf = ast_dynamic_str_create(LOGMSG_INIT_LEN))) { + free(logmsg); + return NULL; + } + + return logmsg; +} + /* Print a verbose message to the verbosers */ static void logger_print_verbose(struct logmsg *logmsg) { @@ -714,7 +772,7 @@ /* Iterate through the list of verbosers and pass them the log message string */ AST_LIST_LOCK(&verbosers); AST_LIST_TRAVERSE(&verbosers, v, list) - v->verboser(logmsg->str); + v->verboser(logmsg->buf->str); AST_LIST_UNLOCK(&verbosers); return; @@ -749,9 +807,7 @@ else if (msg->type == LOGMSG_VERBOSE) logger_print_verbose(msg); - /* Free the data since we are done */ - free(msg->str); - free(msg); + logmsg_free(msg); } } @@ -875,7 +931,7 @@ return; /* Create a new logging message */ - if (!(logmsg = ast_calloc(1, sizeof(*logmsg)))) + if (!(logmsg = logmsg_new())) return; /* Set type to be normal */ @@ -899,12 +955,12 @@ /* If the build failed, then abort and free this structure */ if (res == AST_DYNSTR_BUILD_FAILED) { - free(logmsg); + logmsg_free(logmsg); return; } /* Copy string over */ - logmsg->str = ast_strdup(buf->str); + ast_dynamic_str_set(&logmsg->buf, 0, buf->str); /* Add it to the list at the tail end, and prod the logging thread */ AST_LIST_LOCK(&logmsgs); @@ -954,7 +1010,7 @@ if (!(buf = ast_dynamic_str_thread_get(&verbose_buf, VERBOSE_BUF_INIT_SIZE))) return; - if (!(logmsg = ast_calloc(1, sizeof(*logmsg)))) + if (!(logmsg = logmsg_new())) return; if (ast_opt_timestamp) { @@ -981,13 +1037,11 @@ /* If the build failed then we can drop this allocated message */ if (res == AST_DYNSTR_BUILD_FAILED) { - free(logmsg); + logmsg_free(logmsg); return; } - /* Duplicate it in the logging message */ - logmsg->str = ast_strdup(buf->str); - ast_log(LOG_VERBOSE, "%s", buf->str); + ast_dynamic_str_set(&logmsg->buf, 0, buf->str); /* Add to the list and poke the thread */ AST_LIST_LOCK(&logmsgs);