Mercurial > dovecot > core-2.2
changeset 12497:1bac1c09201a
ioloop: Added support for per-io/timeout callback log prefix automation.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 03 Dec 2010 06:58:38 +0000 |
parents | 841f56ea9d54 |
children | 1d1cd60d5429 |
files | src/lib/ioloop-epoll.c src/lib/ioloop-internal.h src/lib/ioloop-kqueue.c src/lib/ioloop-poll.c src/lib/ioloop-select.c src/lib/ioloop.c src/lib/ioloop.h |
diffstat | 7 files changed, 138 insertions(+), 40 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/ioloop-epoll.c Fri Dec 03 06:57:58 2010 +0000 +++ b/src/lib/ioloop-epoll.c Fri Dec 03 06:58:38 2010 +0000 @@ -170,7 +170,7 @@ struct io_list *list; struct io_file *io; struct timeval tv; - unsigned int events_count, t_id; + unsigned int events_count; int msecs, ret, i, j; bool call; @@ -209,15 +209,8 @@ else if ((io->io.condition & IO_ERROR) != 0) call = (event->events & IO_EPOLL_ERROR) != 0; - if (call) { - t_id = t_push(); - io->io.callback(io->io.context); - if (t_pop() != t_id) { - i_panic("Leaked a t_pop() call in " - "I/O handler %p", - (void *)io->io.callback); - } - } + if (call) + io_loop_call_io(&io->io); } } }
--- a/src/lib/ioloop-internal.h Fri Dec 03 06:57:58 2010 +0000 +++ b/src/lib/ioloop-internal.h Fri Dec 03 06:58:38 2010 +0000 @@ -11,6 +11,9 @@ struct ioloop { struct ioloop *prev; + struct ioloop_log *cur_log; + char *default_log_prefix; + struct io_file *io_files; struct io_file *next_io_file; struct priorityq *timeouts; @@ -32,6 +35,7 @@ void *context; struct ioloop *ioloop; + struct ioloop_log *log; }; struct io_file { @@ -54,10 +58,18 @@ void *context; struct ioloop *ioloop; + struct ioloop_log *log; +}; + +struct ioloop_log { + int refcount; + char *prefix; + struct ioloop *ioloop; }; int io_loop_get_wait_time(struct ioloop *ioloop, struct timeval *tv_r); void io_loop_handle_timeouts(struct ioloop *ioloop); +void io_loop_call_io(struct io *io); /* I/O handler calls */ void io_loop_handle_add(struct io_file *io);
--- a/src/lib/ioloop-kqueue.c Fri Dec 03 06:57:58 2010 +0000 +++ b/src/lib/ioloop-kqueue.c Fri Dec 03 06:58:38 2010 +0000 @@ -114,7 +114,7 @@ struct timeval tv; struct timespec ts; struct io_file *io; - unsigned int events_count, t_id; + unsigned int events_count; int ret, i; /* get the time left for next timeout task */ @@ -144,15 +144,8 @@ io = (void *)event->udata; /* callback is NULL if io_remove() was already called */ - if (io->io.callback != NULL) { - t_id = t_push(); - io->io.callback(io->io.context); - if (t_pop() != t_id) { - i_panic("Leaked a t_pop() call in " - "I/O handler %p", - (void *)io->io.callback); - } - } + if (io->io.callback != NULL) + io_loop_call_io(&io->io); i_assert(io->refcount > 0); if (--io->refcount == 0)
--- a/src/lib/ioloop-poll.c Fri Dec 03 06:57:58 2010 +0000 +++ b/src/lib/ioloop-poll.c Fri Dec 03 06:58:38 2010 +0000 @@ -149,7 +149,6 @@ struct pollfd *pollfd; struct timeval tv; struct io_file *io; - unsigned int t_id; int msecs, ret; bool call; @@ -208,15 +207,8 @@ if (pollfd->revents == 0) ret--; - if (call) { - t_id = t_push(); - io->io.callback(io->io.context); - if (t_pop() != t_id) { - i_panic("Leaked a t_pop() call in " - "I/O handler %p", - (void *)io->io.callback); - } - } + if (call) + io_loop_call_io(&io->io); } } }
--- a/src/lib/ioloop-select.c Fri Dec 03 06:57:58 2010 +0000 +++ b/src/lib/ioloop-select.c Fri Dec 03 06:58:38 2010 +0000 @@ -108,7 +108,6 @@ struct ioloop_handler_context *ctx = ioloop->handler_context; struct timeval tv; struct io_file *io; - unsigned int t_id; int ret; /* get the time left for next timeout task */ @@ -137,14 +136,7 @@ if (io_check_condition(ctx, io->fd, io->io.condition)) { ret--; - - t_id = t_push(); - io->io.callback(io->io.context); - if (t_pop() != t_id) { - i_panic("Leaked a t_pop() call in " - "I/O handler %p", - (void *)io->io.callback); - } + io_loop_call_io(&io->io); } } }
--- a/src/lib/ioloop.c Fri Dec 03 06:57:58 2010 +0000 +++ b/src/lib/ioloop.c Fri Dec 03 06:58:38 2010 +0000 @@ -44,6 +44,11 @@ io->refcount = 1; io->fd = fd; + if (io->io.ioloop->cur_log != NULL) { + io->io.log = io->io.ioloop->cur_log; + io_loop_log_ref(io->io.log); + } + if (io->io.ioloop->handler_context == NULL) io_loop_initialize_handler(io->io.ioloop); io_loop_handle_add(io); @@ -84,6 +89,9 @@ kqueue code relies on this. */ io->callback = NULL; + if (io->log != NULL) + io_loop_log_unref(&io->log); + if ((io->condition & IO_NOTIFY) != 0) io_loop_notify_remove(io); else { @@ -142,19 +150,31 @@ timeout->callback = callback; timeout->context = context; + if (timeout->ioloop->cur_log != NULL) { + timeout->log = timeout->ioloop->cur_log; + io_loop_log_ref(timeout->log); + } + timeout_update_next(timeout, timeout->ioloop->running ? NULL : &ioloop_timeval); priorityq_add(timeout->ioloop->timeouts, &timeout->item); return timeout; } +static void timeout_free(struct timeout *timeout) +{ + if (timeout->log != NULL) + io_loop_log_unref(&timeout->log); + i_free(timeout); +} + void timeout_remove(struct timeout **_timeout) { struct timeout *timeout = *_timeout; *_timeout = NULL; priorityq_remove(timeout->ioloop->timeouts, &timeout->item); - i_free(timeout); + timeout_free(timeout); } static void @@ -324,12 +344,21 @@ /* update timeout's next_run and reposition it in the queue */ timeout_reset_timeval(timeout, &tv_call); + if (timeout->log != NULL) { + ioloop->cur_log = timeout->log; + io_loop_log_ref(ioloop->cur_log); + i_set_failure_prefix(timeout->log->prefix); + } t_id = t_push(); timeout->callback(timeout->context); if (t_pop() != t_id) { i_panic("Leaked a t_pop() call in timeout handler %p", (void *)timeout->callback); } + if (ioloop->cur_log != NULL) { + io_loop_log_unref(&ioloop->cur_log); + i_set_failure_prefix(ioloop->default_log_prefix); + } } } @@ -340,11 +369,36 @@ } T_END; } +void io_loop_call_io(struct io *io) +{ + struct ioloop *ioloop = io->ioloop; + unsigned int t_id; + + if (io->log != NULL) { + ioloop->cur_log = io->log; + io_loop_log_ref(ioloop->cur_log); + i_set_failure_prefix(io->log->prefix); + } + t_id = t_push(); + io->callback(io->context); + if (t_pop() != t_id) { + i_panic("Leaked a t_pop() call in I/O handler %p", + (void *)io->callback); + } + if (ioloop->cur_log != NULL) { + io_loop_log_unref(&ioloop->cur_log); + i_set_failure_prefix(ioloop->default_log_prefix); + } +} + void io_loop_run(struct ioloop *ioloop) { if (ioloop->handler_context == NULL) io_loop_initialize_handler(ioloop); + if (ioloop->cur_log != NULL) + io_loop_log_unref(&ioloop->cur_log); + ioloop->running = TRUE; while (ioloop->running) io_loop_handler_run(ioloop); @@ -438,3 +492,54 @@ { current_ioloop = ioloop; } + +struct ioloop_log *io_loop_log_new(struct ioloop *ioloop) +{ + struct ioloop_log *log; + + log = i_new(struct ioloop_log, 1); + log->refcount = 2; + log->prefix = i_strdup(""); + + log->ioloop = ioloop; + if (ioloop->cur_log != NULL) + io_loop_log_unref(&ioloop->cur_log); + ioloop->cur_log = log; + return log; +} + +void io_loop_log_ref(struct ioloop_log *log) +{ + i_assert(log->refcount > 0); + + log->refcount++; +} + +void io_loop_log_unref(struct ioloop_log **_log) +{ + struct ioloop_log *log = *_log; + + *_log = NULL; + + i_assert(log->refcount > 0); + if (--log->refcount > 0) + return; + + /* cur_log itself keeps a reference */ + i_assert(log->ioloop->cur_log != log); + + i_free(log->prefix); + i_free(log); +} + +void io_loop_log_set_prefix(struct ioloop_log *log, const char *prefix) +{ + i_free(log->prefix); + log->prefix = i_strdup(prefix); +} + +void io_loop_set_default_log_prefix(struct ioloop *ioloop, const char *prefix) +{ + i_free(ioloop->default_log_prefix); + ioloop->default_log_prefix = i_strdup(prefix); +}
--- a/src/lib/ioloop.h Fri Dec 03 06:57:58 2010 +0000 +++ b/src/lib/ioloop.h Fri Dec 03 06:58:38 2010 +0000 @@ -100,4 +100,15 @@ /* Change the current_ioloop. */ void io_loop_set_current(struct ioloop *ioloop); +/* This log is used for all further I/O and timeout callbacks that are added + until returning to ioloop. */ +struct ioloop_log *io_loop_log_new(struct ioloop *ioloop); +void io_loop_log_ref(struct ioloop_log *log); +void io_loop_log_unref(struct ioloop_log **log); +/* Set the log's prefix. Note that this doesn't immediately call + i_set_failure_prefix(). */ +void io_loop_log_set_prefix(struct ioloop_log *log, const char *prefix); +/* Set the default log prefix to use outside callbacks. */ +void io_loop_set_default_log_prefix(struct ioloop *ioloop, const char *prefix); + #endif