[asterisk-commits] russell: branch russell/ast_verbose_threadstorage r38405 - /team/russell/ast_...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Thu Jul 27 23:03:52 MST 2006


Author: russell
Date: Fri Jul 28 01:03:52 2006
New Revision: 38405

URL: http://svn.digium.com/view/asterisk?rev=38405&view=rev
Log:
Merge thread storage support for ast_log().  Previously, every call to the
function just allocated a buffer on the stack with size BUFSIZ (a standard I/O
constant) which on my system, is 8 kB.  Now, it uses a dynamically sized thread
local buffer that starts small but has the ability to grow up to BUFSIZ if
needed.

This has made it very clear to me that it's time to abstract this code to
handle dynamically sized thread local buffers, because it's pretty much the same
code that I'm using over and over again.

Modified:
    team/russell/ast_verbose_threadstorage/logger.c

Modified: team/russell/ast_verbose_threadstorage/logger.c
URL: http://svn.digium.com/view/asterisk/team/russell/ast_verbose_threadstorage/logger.c?rev=38405&r1=38404&r2=38405&view=diff
==============================================================================
--- team/russell/ast_verbose_threadstorage/logger.c (original)
+++ team/russell/ast_verbose_threadstorage/logger.c Fri Jul 28 01:03:52 2006
@@ -138,7 +138,12 @@
 static pthread_once_t verbose_buf_once = PTHREAD_ONCE_INIT;
 static pthread_key_t verbose_buf_key;
 
-#define VERBOSE_BUF_INIT_SIZE	128
+#define VERBOSE_BUF_INIT_SIZE   128
+
+static pthread_once_t log_buf_once = PTHREAD_ONCE_INIT;
+static pthread_key_t log_buf_key;
+
+#define LOG_BUF_INIT_SIZE       128
 
 static int make_components(char *s, int lineno)
 {
@@ -672,28 +677,43 @@
 	syslog(syslog_level_map[level], "%s", buf);
 }
 
-/*
- * send log messages to syslog and/or the console
+static void log_buf_key_create(void)
+{
+	pthread_key_create(&log_buf_key, FREE);
+}
+
+/*!
+ * \brief send log messages to syslog and/or the console
  */
 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
 {
 	struct logchannel *chan;
-	char buf[BUFSIZ];
 	time_t t;
 	struct tm tm;
 	char date[256];
+	struct {
+		size_t len;
+		char str[0];
+	} *buf;
 
 	va_list ap;
-	
+
+	pthread_once(&log_buf_once, log_buf_key_create);
+	if (!(buf = pthread_getspecific(log_buf_key))) {
+		if (!(buf = ast_malloc(LOG_BUF_INIT_SIZE + sizeof(*buf))))
+			return;
+		buf->len = LOG_BUF_INIT_SIZE;
+		pthread_setspecific(log_buf_key, buf);
+	}
+
 	/* don't display LOG_DEBUG messages unless option_verbose _or_ option_debug
 	   are non-zero; LOG_DEBUG messages can still be displayed if option_debug
 	   is zero, if option_verbose is non-zero (this allows for 'level zero'
 	   LOG_DEBUG messages to be displayed, if the logmask on any channel
 	   allows it)
 	*/
-	if (!option_verbose && !option_debug && (level == __LOG_DEBUG)) {
+	if (!option_verbose && !option_debug && (level == __LOG_DEBUG))
 		return;
-	}
 
 	/* Ignore anything that never gets logged anywhere */
 	if (!(global_logmask & (1 << level)))
@@ -736,28 +756,68 @@
 				char tmp1[80], tmp2[80], tmp3[80], tmp4[80];
 
 				if (level != __LOG_VERBOSE) {
+					int res;
 					sprintf(linestr, "%d", line);
-					snprintf(buf, sizeof(buf), ast_opt_timestamp ? "[%s] %s[%ld]: %s:%s %s: " : "%s %s[%ld]: %s:%s %s: ",
+
+					res = snprintf(buf->str, buf->len, ast_opt_timestamp ? "[%s] %s[%ld]: %s:%s %s: " : "%s %s[%ld]: %s:%s %s: ",
 						date,
 						term_color(tmp1, levels[level], colors[level], 0, sizeof(tmp1)),
 						(long)GETTID(),
 						term_color(tmp2, file, COLOR_BRWHITE, 0, sizeof(tmp2)),
 						term_color(tmp3, linestr, COLOR_BRWHITE, 0, sizeof(tmp3)),
 						term_color(tmp4, function, COLOR_BRWHITE, 0, sizeof(tmp4)));
+
+					while ((res >= buf->len) && (buf->len <= (BUFSIZ / 2))) {
+						if (!(buf = ast_realloc(buf, (buf->len * 2) + sizeof(*buf)))) {
+							AST_LIST_UNLOCK(&logchannels);
+							return;
+						}
+						buf->len *= 2;
+						pthread_setspecific(log_buf_key, buf);
+						res = snprintf(buf->str, buf->len, ast_opt_timestamp ? "[%s] %s[%ld]: %s:%s %s: " : "%s %s[%ld]: %s:%s %s: ",
+							date,
+							term_color(tmp1, levels[level], colors[level], 0, sizeof(tmp1)),
+							(long)GETTID(),
+							term_color(tmp2, file, COLOR_BRWHITE, 0, sizeof(tmp2)),
+							term_color(tmp3, linestr, COLOR_BRWHITE, 0, sizeof(tmp3)),
+							term_color(tmp4, function, COLOR_BRWHITE, 0, sizeof(tmp4)));
+					}
+					ast_console_puts_mutable(buf->str);
 					
-					ast_console_puts_mutable(buf);
 					va_start(ap, fmt);
-					vsnprintf(buf, sizeof(buf), fmt, ap);
+					res = vsnprintf(buf->str, buf->len, fmt, ap);
+					while ((res >= buf->len) && (buf->len <= (BUFSIZ / 2))) {
+						if (!(buf = ast_realloc(buf, (buf->len * 2) + sizeof(*buf)))) {
+							AST_LIST_UNLOCK(&logchannels);
+							va_end(ap);
+							return;
+						}
+						buf->len *= 2;
+						pthread_setspecific(log_buf_key, buf);
+						va_end(ap);
+						va_start(ap, fmt);
+						res = vsnprintf(buf->str, buf->len, fmt, ap);
+					}
 					va_end(ap);
-					ast_console_puts_mutable(buf);
+					ast_console_puts_mutable(buf->str);
 				}
 			/* File channels */
 			} else if ((chan->logmask & (1 << level)) && (chan->fileptr)) {
 				int res;
-				snprintf(buf, sizeof(buf), ast_opt_timestamp ? "[%s] %s[%ld]: " : "%s %s[%ld] %s: ", date,
+				res = snprintf(buf->str, buf->len, ast_opt_timestamp ? "[%s] %s[%ld]: " : "%s %s[%ld] %s: ", date,
 					levels[level], (long)GETTID(), file);
-				res = fprintf(chan->fileptr, buf);
-				if (res <= 0 && buf[0] != '\0') {	/* Error, no characters printed */
+				while ((res >= buf->len) && (buf->len <= (BUFSIZ / 2))) {
+					if (!(buf = ast_realloc(buf, (buf->len * 2) + sizeof(*buf)))) {
+						AST_LIST_UNLOCK(&logchannels);
+						return;
+					}
+					buf->len *= 2;
+					pthread_setspecific(log_buf_key, buf);
+					res = snprintf(buf->str, buf->len, ast_opt_timestamp ? "[%s] %s[%ld]: " : "%s %s[%ld] %s: ", date,
+						levels[level], (long)GETTID(), file);
+				}
+				res = fprintf(chan->fileptr, "%s", buf->str);
+				if (res <= 0 && !ast_strlen_zero(buf->str)) {	/* Error, no characters printed */
 					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);
@@ -768,10 +828,20 @@
 				} else {
 					/* No error message, continue printing */
 					va_start(ap, fmt);
-					vsnprintf(buf, sizeof(buf), fmt, ap);
+					vsnprintf(buf->str, buf->len, fmt, ap);
+					while ((res >= buf->len) && (buf->len <= (BUFSIZ / 2))) {
+						if (!(buf = ast_realloc(buf, (buf->len * 2) + sizeof(*buf)))) {
+							AST_LIST_UNLOCK(&logchannels);
+							va_end(ap);
+							return;
+						}
+						buf->len *= 2;
+						pthread_setspecific(log_buf_key, buf);
+						res = vsnprintf(buf->str, buf->len, fmt, ap);
+					}
 					va_end(ap);
-					term_strip(buf, buf, sizeof(buf));
-					fputs(buf, chan->fileptr);
+					term_strip(buf->str, buf->str, buf->len);
+					fputs(buf->str, chan->fileptr);
 					fflush(chan->fileptr);
 				}
 			}
@@ -782,10 +852,21 @@
 		 * so just log to stdout 
 		*/
 		if (level != __LOG_VERBOSE) {
+			int res;
 			va_start(ap, fmt);
-			vsnprintf(buf, sizeof(buf), fmt, ap);
+			res = vsnprintf(buf->str, buf->len, fmt, ap);
+			while ((res >= buf->len) && (buf->len <= (BUFSIZ / 2))) {
+				if (!(buf = ast_realloc(buf, (buf->len * 2) + sizeof(*buf)))) {
+					AST_LIST_UNLOCK(&logchannels);
+					va_end(ap);
+					return;
+				}
+				buf->len *= 2;
+				pthread_setspecific(log_buf_key, buf);
+				res = vsnprintf(buf->str, buf->len, fmt, ap);
+			}
 			va_end(ap);
-			fputs(buf, stdout);
+			fputs(buf->str, stdout);
 		}
 	}
 



More information about the asterisk-commits mailing list