From: Timo Sirainen Date: Fri, 3 Dec 2010 06:58:38 +0000 (+0000) Subject: ioloop: Added support for per-io/timeout callback log prefix automation. X-Git-Tag: 2.0.8~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b9a13c136b7c5803a8271878fcbbf5328f6e7f2a;p=thirdparty%2Fdovecot%2Fcore.git ioloop: Added support for per-io/timeout callback log prefix automation. --- diff --git a/src/lib/ioloop-epoll.c b/src/lib/ioloop-epoll.c index 5f7095b7dc..4ef5a14ebf 100644 --- a/src/lib/ioloop-epoll.c +++ b/src/lib/ioloop-epoll.c @@ -170,7 +170,7 @@ void io_loop_handler_run(struct ioloop *ioloop) 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 @@ void io_loop_handler_run(struct ioloop *ioloop) 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); } } } diff --git a/src/lib/ioloop-internal.h b/src/lib/ioloop-internal.h index 9666445ffc..e4ae3f0b27 100644 --- a/src/lib/ioloop-internal.h +++ b/src/lib/ioloop-internal.h @@ -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 @@ struct io { void *context; struct ioloop *ioloop; + struct ioloop_log *log; }; struct io_file { @@ -54,10 +58,18 @@ struct timeout { 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); diff --git a/src/lib/ioloop-kqueue.c b/src/lib/ioloop-kqueue.c index 9f202588eb..b194f7b47b 100644 --- a/src/lib/ioloop-kqueue.c +++ b/src/lib/ioloop-kqueue.c @@ -114,7 +114,7 @@ void io_loop_handler_run(struct ioloop *ioloop) 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 @@ void io_loop_handler_run(struct ioloop *ioloop) 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) diff --git a/src/lib/ioloop-poll.c b/src/lib/ioloop-poll.c index c856eca27e..cb6e79fd3e 100644 --- a/src/lib/ioloop-poll.c +++ b/src/lib/ioloop-poll.c @@ -149,7 +149,6 @@ void io_loop_handler_run(struct ioloop *ioloop) struct pollfd *pollfd; struct timeval tv; struct io_file *io; - unsigned int t_id; int msecs, ret; bool call; @@ -208,15 +207,8 @@ void io_loop_handler_run(struct ioloop *ioloop) 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); } } } diff --git a/src/lib/ioloop-select.c b/src/lib/ioloop-select.c index a480f130fb..6a44c26ff4 100644 --- a/src/lib/ioloop-select.c +++ b/src/lib/ioloop-select.c @@ -108,7 +108,6 @@ void io_loop_handler_run(struct ioloop *ioloop) 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 @@ void io_loop_handler_run(struct ioloop *ioloop) 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); } } } diff --git a/src/lib/ioloop.c b/src/lib/ioloop.c index e877d7bfa7..1c38ca3abc 100644 --- a/src/lib/ioloop.c +++ b/src/lib/ioloop.c @@ -44,6 +44,11 @@ struct io *io_add(int fd, enum io_condition condition, 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 @@ static void io_remove_full(struct io **_io, bool closed) 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 @@ struct timeout *timeout_add(unsigned int msecs, timeout_callback_t *callback, 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 @@ static void io_loop_handle_timeouts_real(struct ioloop *ioloop) /* 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 @@ void io_loop_handle_timeouts(struct ioloop *ioloop) } 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 @@ void io_loop_set_current(struct ioloop *ioloop) { 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); +} diff --git a/src/lib/ioloop.h b/src/lib/ioloop.h index fcdb869b01..41ff6f76af 100644 --- a/src/lib/ioloop.h +++ b/src/lib/ioloop.h @@ -100,4 +100,15 @@ void io_loop_set_time_moved_callback(struct ioloop *ioloop, /* 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