Mercurial > dovecot > core-2.2
changeset 13252:32315c24992c
Replaced "ioloop log" with a more generic "ioloop context".
The context can call multiple callbacks that can do anything they want,
including setting the log prefix.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 16 Aug 2011 18:33:27 +0300 |
parents | 390f69281fb8 |
children | 69cf3bb0b8e8 |
files | src/lib-storage/mail-storage-service.c src/lib/ioloop-internal.h src/lib/ioloop-notify-dn.c src/lib/ioloop-notify-inotify.c src/lib/ioloop-notify-kqueue.c src/lib/ioloop.c src/lib/ioloop.h |
diffstat | 7 files changed, 181 insertions(+), 94 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/mail-storage-service.c Tue Aug 16 18:27:40 2011 +0300 +++ b/src/lib-storage/mail-storage-service.c Tue Aug 16 18:33:27 2011 +0300 @@ -41,6 +41,8 @@ struct mail_storage_service_ctx { pool_t pool; struct master_service *service; + const char *default_log_prefix; + struct auth_master_connection *conn; struct auth_master_user_list_ctx *auth_list; const struct setting_parser_info **set_roots; @@ -55,9 +57,13 @@ struct mail_storage_service_user { pool_t pool; + struct mail_storage_service_ctx *service_ctx; struct mail_storage_service_input input; enum mail_storage_service_flags flags; + struct ioloop_context *ioloop_ctx; + const char *log_prefix; + const char *system_groups_user, *uid_source, *gid_source; const struct mail_user_settings *user_set; const struct setting_parser_info *user_info; @@ -564,6 +570,20 @@ return str_c(ret); } +static void mail_storage_service_io_activate(void *context) +{ + struct mail_storage_service_user *user = context; + + i_set_failure_prefix(user->log_prefix); +} + +static void mail_storage_service_io_deactivate(void *context) +{ + struct mail_storage_service_user *user = context; + + i_set_failure_prefix(user->service_ctx->default_log_prefix); +} + static void mail_storage_service_init_log(struct mail_storage_service_ctx *ctx, struct mail_storage_service_user *user) @@ -571,17 +591,20 @@ ctx->log_initialized = TRUE; T_BEGIN { string_t *str; - struct ioloop_log *log; str = t_str_new(256); var_expand(str, user->user_set->mail_log_prefix, get_var_expand_table(ctx->service, &user->input)); - master_service_init_log(ctx->service, str_c(str)); + user->log_prefix = p_strdup(user->pool, str_c(str)); + } T_END; + + master_service_init_log(ctx->service, user->log_prefix); - log = io_loop_log_new(current_ioloop); - io_loop_log_set_prefix(log, str_c(str)); - io_loop_log_unref(&log); - } T_END; + user->ioloop_ctx = io_loop_context_new(current_ioloop); + io_loop_context_add_callbacks(user->ioloop_ctx, + mail_storage_service_io_activate, + mail_storage_service_io_deactivate, + user); } static void mail_storage_service_time_moved(time_t old_time, time_t new_time) @@ -657,10 +680,9 @@ if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0) { /* note: we may not have read any settings yet, so this logging may still be going to wrong location */ - const char *log_prefix = t_strconcat(service->name, ": ", NULL); - - master_service_init_log(service, log_prefix); - io_loop_set_default_log_prefix(current_ioloop, log_prefix); + ctx->default_log_prefix = + p_strconcat(pool, service->name, ": ", NULL); + master_service_init_log(service, ctx->default_log_prefix); } dict_drivers_register_builtin(); return ctx; @@ -871,6 +893,7 @@ user = p_new(user_pool, struct mail_storage_service_user, 1); memset(user_r, 0, sizeof(user_r)); + user->service_ctx = ctx; user->pool = user_pool; user->input = *input; user->input.userdb_fields = NULL; @@ -1050,6 +1073,9 @@ struct mail_storage_service_user *user = *_user; *_user = NULL; + + io_loop_context_remove_callbacks(user->ioloop_ctx, user); + io_loop_context_unref(&user->ioloop_ctx); settings_parser_deinit(&user->set_parser); pool_unref(&user->pool); }
--- a/src/lib/ioloop-internal.h Tue Aug 16 18:27:40 2011 +0300 +++ b/src/lib/ioloop-internal.h Tue Aug 16 18:33:27 2011 +0300 @@ -11,8 +11,7 @@ struct ioloop { struct ioloop *prev; - struct ioloop_log *cur_log; - char *default_log_prefix; + struct ioloop_context *cur_ctx; struct io_file *io_files; struct io_file *next_io_file; @@ -35,7 +34,7 @@ void *context; struct ioloop *ioloop; - struct ioloop_log *log; + struct ioloop_context *ctx; }; struct io_file { @@ -58,13 +57,19 @@ void *context; struct ioloop *ioloop; - struct ioloop_log *log; + struct ioloop_context *ctx; }; -struct ioloop_log { +struct ioloop_context_callback { + io_callback_t *activate; + io_callback_t *deactivate; + void *context; +}; + +struct ioloop_context { int refcount; - char *prefix; struct ioloop *ioloop; + ARRAY_DEFINE(callbacks, struct ioloop_context_callback); }; int io_loop_get_wait_time(struct ioloop *ioloop, struct timeval *tv_r); @@ -81,4 +86,7 @@ void io_loop_notify_remove(struct io *io); void io_loop_notify_handler_deinit(struct ioloop *ioloop); +void io_loop_context_activate(struct ioloop_context *ctx); +void io_loop_context_deactivate(struct ioloop_context *ctx); + #endif
--- a/src/lib/ioloop-notify-dn.c Tue Aug 16 18:27:40 2011 +0300 +++ b/src/lib/ioloop-notify-dn.c Tue Aug 16 18:33:27 2011 +0300 @@ -87,7 +87,7 @@ for (i = 0; i < ret; i++) { io = io_notify_fd_find(&ctx->fd_ctx, fd_buf[i]); if (io != NULL) - io->io.callback(io->io.context); + io_loop_call_io(&io->io); } }
--- a/src/lib/ioloop-notify-inotify.c Tue Aug 16 18:27:40 2011 +0300 +++ b/src/lib/ioloop-notify-inotify.c Tue Aug 16 18:33:27 2011 +0300 @@ -70,7 +70,7 @@ EINVAL */ io->fd = -1; } - io->io.callback(io->io.context); + io_loop_call_io(&io->io); } } if (pos != ret)
--- a/src/lib/ioloop-notify-kqueue.c Tue Aug 16 18:27:40 2011 +0300 +++ b/src/lib/ioloop-notify-kqueue.c Tue Aug 16 18:33:27 2011 +0300 @@ -71,7 +71,7 @@ /* there can be multiple events for a single io. call the callback only once if that happens. */ if (io->refcount == 2 && io->io.callback != NULL) - io->io.callback(io->io.context); + io_loop_call_io(&io->io); if (--io->refcount == 0) i_free(io);
--- a/src/lib/ioloop.c Tue Aug 16 18:27:40 2011 +0300 +++ b/src/lib/ioloop.c Tue Aug 16 18:33:27 2011 +0300 @@ -1,6 +1,7 @@ /* Copyright (c) 2002-2011 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "array.h" #include "time-util.h" #include "ioloop-internal.h" @@ -44,9 +45,9 @@ 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->cur_ctx != NULL) { + io->io.ctx = io->io.ioloop->cur_ctx; + io_loop_context_ref(io->io.ctx); } if (io->io.ioloop->handler_context == NULL) @@ -89,8 +90,8 @@ kqueue code relies on this. */ io->callback = NULL; - if (io->log != NULL) - io_loop_log_unref(&io->log); + if (io->ctx != NULL) + io_loop_context_unref(&io->ctx); if ((io->condition & IO_NOTIFY) != 0) io_loop_notify_remove(io); @@ -150,9 +151,9 @@ timeout->callback = callback; timeout->context = context; - if (timeout->ioloop->cur_log != NULL) { - timeout->log = timeout->ioloop->cur_log; - io_loop_log_ref(timeout->log); + if (timeout->ioloop->cur_ctx != NULL) { + timeout->ctx = timeout->ioloop->cur_ctx; + io_loop_context_ref(timeout->ctx); } timeout_update_next(timeout, timeout->ioloop->running ? @@ -163,8 +164,8 @@ static void timeout_free(struct timeout *timeout) { - if (timeout->log != NULL) - io_loop_log_unref(&timeout->log); + if (timeout->ctx != NULL) + io_loop_context_unref(&timeout->ctx); i_free(timeout); } @@ -345,21 +346,16 @@ /* 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); - } + if (timeout->ctx != NULL) + io_loop_context_activate(timeout->ctx); 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); - } + if (ioloop->cur_ctx != NULL) + io_loop_context_activate(ioloop->cur_ctx); } } @@ -375,21 +371,16 @@ 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); - } + if (io->ctx != NULL) + io_loop_context_activate(io->ctx); 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); - } + if (ioloop->cur_ctx != NULL) + io_loop_context_deactivate(ioloop->cur_ctx); } void io_loop_run(struct ioloop *ioloop) @@ -397,8 +388,8 @@ if (ioloop->handler_context == NULL) io_loop_initialize_handler(ioloop); - if (ioloop->cur_log != NULL) - io_loop_log_unref(&ioloop->cur_log); + if (ioloop->cur_ctx != NULL) + io_loop_context_unref(&ioloop->cur_ctx); ioloop->running = TRUE; while (ioloop->running) @@ -480,7 +471,6 @@ i_assert(ioloop == current_ioloop); current_ioloop = current_ioloop->prev; - i_free(ioloop->default_log_prefix); i_free(ioloop); } @@ -495,59 +485,117 @@ current_ioloop = ioloop; } -struct ioloop_log *io_loop_log_new(struct ioloop *ioloop) +struct ioloop_context *io_loop_context_new(struct ioloop *ioloop) { - struct ioloop_log *log; + struct ioloop_context *ctx; - i_assert(ioloop->default_log_prefix != NULL); + ctx = i_new(struct ioloop_context, 1); + ctx->refcount = 2; + ctx->ioloop = ioloop; + i_array_init(&ctx->callbacks, 4); - log = i_new(struct ioloop_log, 1); - log->refcount = 2; - log->prefix = i_strdup(""); + if (ioloop->cur_ctx != NULL) + io_loop_context_unref(&ioloop->cur_ctx); + ioloop->cur_ctx = ctx; + return ctx; +} - log->ioloop = ioloop; - if (ioloop->cur_log != NULL) - io_loop_log_unref(&ioloop->cur_log); - ioloop->cur_log = log; - return log; +void io_loop_context_ref(struct ioloop_context *ctx) +{ + i_assert(ctx->refcount > 0); + + ctx->refcount++; } -void io_loop_log_ref(struct ioloop_log *log) +void io_loop_context_unref(struct ioloop_context **_ctx) { - i_assert(log->refcount > 0); + struct ioloop_context *ctx = *_ctx; + + *_ctx = NULL; + + i_assert(ctx->refcount > 0); + if (--ctx->refcount > 0) + return; + + /* cur_ctx itself keeps a reference */ + i_assert(ctx->ioloop->cur_ctx != ctx); - log->refcount++; + array_free(&ctx->callbacks); + i_free(ctx); +} + +void io_loop_context_add_callbacks(struct ioloop_context *ctx, + io_callback_t *activate, + io_callback_t *deactivate, void *context) +{ + struct ioloop_context_callback cb; + + memset(&cb, 0, sizeof(cb)); + cb.activate = activate; + cb.deactivate = deactivate; + cb.context = context; + + array_append(&ctx->callbacks, &cb, 1); } -void io_loop_log_unref(struct ioloop_log **_log) +void io_loop_context_remove_callbacks(struct ioloop_context *ctx, + void *context) { - struct ioloop_log *log = *_log; - - *_log = NULL; + struct ioloop_context_callback *cb; - 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); + array_foreach_modifiable(&ctx->callbacks, cb) { + if (cb->context == context) { + /* simply mark it as deleted, since we could get + here from activate/deactivate loop */ + cb->activate = NULL; + cb->deactivate = NULL; + cb->context = NULL; + return; + } + } + i_panic("io_loop_context_remove_callbacks() context not found"); } -void io_loop_log_set_prefix(struct ioloop_log *log, const char *prefix) +static void +io_loop_context_remove_deleted_callbacks(struct ioloop_context *ctx) { - i_free(log->prefix); - log->prefix = i_strdup(prefix); + const struct ioloop_context_callback *cbs; + unsigned int i, count; + + cbs = array_get(&ctx->callbacks, &count); + for (i = 0; i < count; ) { + if (cbs[i].activate != NULL) + i++; + else { + array_delete(&ctx->callbacks, i, 1); + cbs = array_get(&ctx->callbacks, &count); + } + } } -void io_loop_set_default_log_prefix(struct ioloop *ioloop, const char *prefix) +void io_loop_context_activate(struct ioloop_context *ctx) { - i_assert(prefix != NULL); + const struct ioloop_context_callback *cb; + + ctx->ioloop->cur_ctx = ctx; + io_loop_context_ref(ctx); + array_foreach(&ctx->callbacks, cb) { + if (cb->activate != NULL) + cb->activate(cb->context); + } +} - i_free(ioloop->default_log_prefix); - ioloop->default_log_prefix = i_strdup(prefix); +void io_loop_context_deactivate(struct ioloop_context *ctx) +{ + const struct ioloop_context_callback *cb; + + array_foreach(&ctx->callbacks, cb) { + if (cb->deactivate != NULL) + cb->deactivate(cb->context); + } + ctx->ioloop->cur_ctx = NULL; + io_loop_context_remove_deleted_callbacks(ctx); + io_loop_context_unref(&ctx); } struct io *io_loop_move_io(struct io **_io)
--- a/src/lib/ioloop.h Tue Aug 16 18:27:40 2011 +0300 +++ b/src/lib/ioloop.h Tue Aug 16 18:33:27 2011 +0300 @@ -100,16 +100,21 @@ /* 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); +/* This context is used for all further I/O and timeout callbacks that are + added until returning to ioloop. When a callback is called, this context is + again activated. */ +struct ioloop_context *io_loop_context_new(struct ioloop *ioloop); +void io_loop_context_ref(struct ioloop_context *ctx); +void io_loop_context_unref(struct ioloop_context **ctx); +/* Call the activate callback when this context is activated (I/O callback is + about to be called), and the deactivate callback when the context is + deactivated (I/O callback has returned). You can add multiple callbacks. */ +void io_loop_context_add_callbacks(struct ioloop_context *ctx, + io_callback_t *activate, + io_callback_t *deactivate, void *context); +/* Remove callbacks with the given context. */ +void io_loop_context_remove_callbacks(struct ioloop_context *ctx, + void *context); /* Move the given I/O into the current I/O loop if it's not already there. New I/O is returned, while the old one is freed. */