]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
ioloop: Added support for per-io/timeout callback log prefix automation.
authorTimo Sirainen <tss@iki.fi>
Fri, 3 Dec 2010 06:58:38 +0000 (06:58 +0000)
committerTimo Sirainen <tss@iki.fi>
Fri, 3 Dec 2010 06:58:38 +0000 (06:58 +0000)
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

index 5f7095b7dcdcbf7a4f52b7d4feb7278d25dce6b2..4ef5a14ebfb8109606871c1e1c238dcbafff0458 100644 (file)
@@ -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);
                }
        }
 }
index 9666445ffce72d44b91100b57d8a7210c7f5afb8..e4ae3f0b270158f9a81da4cff8fc5a2c3ef0e236 100644 (file)
@@ -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);
index 9f202588ebf58aaeddfec9460707d3646b1e1b92..b194f7b47b09bff36c2829f49a3c10731400a2f6 100644 (file)
@@ -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)
index c856eca27ee23f9bed090ba4421a05af290e42a2..cb6e79fd3e939d3304e918af0535e0e8b6bd6046 100644 (file)
@@ -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);
                }
        }
 }
index a480f130fbfbcacbdcd99664339de29e6c3c2205..6a44c26ff4b921a1417f58399a57c5ebeba08ac2 100644 (file)
@@ -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);
                }
        }
 }
index e877d7bfa7fd405770ceb152eb23d33f1dce7bcf..1c38ca3abcebf0ffb9bf003b2dcefdbebadaea44 100644 (file)
@@ -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);
+}
index fcdb869b01f78ba835313cf3597968ad26175a8d..41ff6f76af9b0182006dde9e26b0e8bfc4a4dcb9 100644 (file)
@@ -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