From 88f6a30274103d1e2e154b45f4c29d86373dcb7a Mon Sep 17 00:00:00 2001 From: Thomas Porzelt Date: Sat, 19 Jul 2008 00:11:08 +0200 Subject: [PATCH] introduced a logging thread --- src/base.h | 3 ++ src/lighttpd.c | 7 ++++ src/log.c | 105 ++++++++++++++++++++++++++++++++++--------------- src/log.h | 10 +++++ src/server.c | 4 ++ src/wscript | 2 +- wscript | 4 ++ 7 files changed, 102 insertions(+), 33 deletions(-) diff --git a/src/base.h b/src/base.h index 8300c5c..acd0e91 100644 --- a/src/base.h +++ b/src/base.h @@ -26,9 +26,12 @@ struct server { GHashTable *options; gpointer *option_def_values; + gboolean exiting; GMutex *mutex; GArray *logs; + GAsyncQueue *log_queue; + GThread *log_thread; }; struct connection { diff --git a/src/lighttpd.c b/src/lighttpd.c index 75d859c..5dc4afa 100644 --- a/src/lighttpd.c +++ b/src/lighttpd.c @@ -39,8 +39,13 @@ int main(int argc, char *argv[]) { return 0; } + /* initialize threading */ + g_thread_init(NULL); + srv = server_new(); + log_init(srv); + /* if no path is specified for the config, read lighttpd.conf from current directory */ if (config_path == NULL) config_path = "lighttpd.conf"; @@ -64,5 +69,7 @@ int main(int argc, char *argv[]) { TRACE("%s", "Test!"); + g_thread_join(srv->log_thread); + return 0; } diff --git a/src/log.c b/src/log.c index 17bed8f..6c4e96a 100644 --- a/src/log.c +++ b/src/log.c @@ -33,11 +33,9 @@ int log_write(server* UNUSED_PARAM(srv), connection* UNUSED_PARAM(con), const ch gboolean log_write_(server *srv, connection *con, const char *fmt, ...) { va_list ap; GString *log_line; - static GStaticMutex log_mutex = G_STATIC_MUTEX_INIT; log_t *log; guint log_ndx; - gssize bytes_written; - gssize write_res; + log_entry_t *log_entry; if (con != NULL) { /* get log index from connection */ @@ -73,36 +71,11 @@ gboolean log_write_(server *srv, connection *con, const char *fmt, ...) { g_string_append_len(log_line, CONST_STR_LEN("\r\n")); - bytes_written = 0; - - /* lock to ensure that multiple threads don't mess up the logs */ - g_static_mutex_lock(&log_mutex); - while (bytes_written < (gssize)log_line->len) { - write_res = write(log->fd, log_line->str + bytes_written, log_line->len - bytes_written); - - assert(write_res <= (gssize) log_line->len); - - /* write() failed, check why */ - if (write_res == -1) { - switch (errno) { - case EAGAIN: - case EINTR: - continue; - } - - /* the error is serious, unlock mutex and return as we can't seem to write to the log */ - g_static_mutex_unlock(&log_mutex); - g_string_free(log_line, TRUE); - return FALSE; - } - else { - bytes_written += write_res; - assert(bytes_written <= (gssize) log_line->len); - } - } - g_static_mutex_unlock(&log_mutex); - g_string_free(log_line, TRUE); + log_entry = g_slice_new(log_entry_t); + log_entry->fd = log->fd; + log_entry->msg = log_line; + g_async_queue_push(srv->log_queue, log_entry); return TRUE; } @@ -132,3 +105,71 @@ void log_free(log_t *log) { g_mutex_free(log->mutex); g_string_free(log->lastmsg, TRUE); } + + +gpointer log_thread(server *srv) { + GAsyncQueue *queue; + gboolean exiting; + log_entry_t *log_entry; + GTimeVal *timeout; + gssize bytes_written; + gssize write_res; + + queue = srv->log_queue; + + while (TRUE) { + /* check if we need to exit */ + g_mutex_lock(srv->mutex); + exiting = srv->exiting; + g_mutex_unlock(srv->mutex); + if (exiting) + break; + + /* 1 second timeout */ + g_get_current_time(timeout); + g_time_val_add(timeout, 1000 * 1000 * 1); + log_entry = g_async_queue_timed_pop(srv->log_queue, timeout); + + g_print("log_thread ping\n"); + + if (log_entry == NULL) + continue; + + while (bytes_written < (gssize)log_entry->msg->len) { + write_res = write(log_entry->fd, log_entry->msg->str + bytes_written, log_entry->msg->len - bytes_written); + + assert(write_res <= (gssize) log_entry->msg->len); + + /* write() failed, check why */ + if (write_res == -1) { + switch (errno) { + case EAGAIN: + case EINTR: + continue; + } + } + else { + bytes_written += write_res; + assert(bytes_written <= (gssize) log_entry->msg->len); + } + } + + g_string_free(log_entry->msg, TRUE); + g_slice_free(log_entry_t, log_entry); + } + + return NULL; +} + +void log_init(server *srv) { + GError *err = NULL; + + srv->log_thread = g_thread_create((GThreadFunc)log_thread, srv, TRUE, &err); + + if (srv->log_thread == NULL) { + g_printerr("could not create loggin thread: %s\n", err->message); + assert(NULL); + } +} + + diff --git a/src/log.h b/src/log.h index c8e71f9..79f2d0d 100644 --- a/src/log.h +++ b/src/log.h @@ -49,6 +49,9 @@ LI_API int log_write(server *srv, connection *con, const char *fmt, ...) __ATTRI struct log_t; typedef struct log_t log_t; +struct log_entry_t; +typedef struct log_entry_t log_entry_t; + struct log_t { gint fd; GMutex *mutex; @@ -56,7 +59,14 @@ struct log_t { guint lastmsg_count; }; +struct log_entry_t { + gint fd; + GString *msg; +}; + log_t *log_new(const gchar* filename); void log_free(log_t *log); +gpointer log_thread(server *srv); +void log_init(server *srv); #endif diff --git a/src/server.c b/src/server.c index d9ca2a9..738628d 100644 --- a/src/server.c +++ b/src/server.c @@ -10,6 +10,8 @@ server* server_new() { srv->mutex = g_mutex_new(); srv->logs = g_array_new(FALSE, FALSE, sizeof(log_t)); + srv->log_queue = g_async_queue_new(); + srv->exiting = FALSE; return srv; } @@ -29,5 +31,7 @@ void server_free(server* srv) { } g_array_free(srv->logs, TRUE); + g_async_queue_unref(srv->log_queue); + g_slice_free(server, srv); } diff --git a/src/wscript b/src/wscript index f2c4f9b..28ba2aa 100644 --- a/src/wscript +++ b/src/wscript @@ -4,7 +4,7 @@ #import Object, Params, os, sys import Options -common_uselib = 'glib ' +common_uselib = 'glib gthread' common_source=''' actions.c diff --git a/wscript b/wscript index 9381593..0616874 100644 --- a/wscript +++ b/wscript @@ -382,6 +382,10 @@ def configure(conf): conf.env['CPPPATH_glib'] += [ incdir+'/glib-2.0/', incdir + '/glib-2.0/include/' ] CHECK_INCLUDE_FILES(conf, "glib.h", "HAVE_GLIB_H", uselib = 'glib', use = ['glib'], mandatory = 1) + PKGCONFIG(conf, "gthread-2.0", uselib = 'gthread', mandatory = 1) + incdir = conf.env['CPPPATH_gthread'][0] + conf.env['CPPPATH_gthread'] += [ incdir+'/glib-2.0/', incdir + '/glib-2.0/include/' ] + #if opts.libfcgi: #CHECK_INCLUDE_FILES(conf, "fastcgi.h", "HAVE_FASTCGI_H", uselib = 'libfcgi') #if not conf.is_defined("HAVE_FASTCGI_H"):