Mercurial > dovecot > core-2.2
changeset 13348:fafbd108008c
stats plugin: Optimized to lookup statistics only when necessary.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 01 Sep 2011 06:36:34 +0300 |
parents | 4d8cec7a7496 |
children | ec6d171a54bd |
files | src/plugins/stats/stats-plugin.c |
diffstat | 1 files changed, 68 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/src/plugins/stats/stats-plugin.c Thu Sep 01 06:13:36 2011 +0300 +++ b/src/plugins/stats/stats-plugin.c Thu Sep 01 06:36:34 2011 +0300 @@ -17,7 +17,7 @@ MODULE_CONTEXT(obj, stats_storage_module) /* Refresh session every 10 seconds, if anything has changed */ -#define SESSION_STATS_REFRESH_MSECS (10*1000) +#define SESSION_STATS_REFRESH_SECS 10 /* If session isn't refreshed every 15 minutes, it's dropped. Must be smaller than MAIL_SESSION_IDLE_TIMEOUT_MSECS in stats server */ #define SESSION_STATS_FORCE_REFRESH_SECS (5*60) @@ -46,6 +46,8 @@ &mail_storage_module_register); static struct stats_connection *global_stats_conn = NULL; +static struct mail_user *stats_global_user = NULL; +static unsigned int stats_user_count = 0; static int process_io_buffer_parse(const char *buf, uint64_t *read_bytes_r, @@ -249,7 +251,16 @@ struct mail_user *user = context; struct stats_user *suser = STATS_USER_CONTEXT(user); - mail_stats_get(suser, &suser->pre_io_stats); + if (stats_user_count == 1) { + /* the first user sets the global user. the second user sets + it to NULL. when we get back to one user we'll need to set + the global user again somewhere. do it here. */ + stats_global_user = user; + } else { + i_assert(stats_global_user == NULL); + + mail_stats_get(suser, &suser->pre_io_stats); + } } static void timeval_add_diff(struct timeval *dest, @@ -311,15 +322,15 @@ str_printfa(str, "\tcache=%lu", tstats->cache_hit_count); } -static void stats_io_deactivate(void *context) +static void stats_add_session(struct mail_user *user) { - struct mail_user *user = context; struct stats_user *suser = STATS_USER_CONTEXT(user); struct mail_stats new_stats; mail_stats_get(suser, &new_stats); mail_stats_add_diff(&suser->session_stats, &suser->pre_io_stats, &new_stats); + suser->pre_io_stats = new_stats; } static bool session_stats_need_send(struct stats_user *suser) @@ -342,6 +353,36 @@ stats_connection_send_session(suser->stats_conn, user, &suser->session_stats); } + if (suser->to_stats_timeout != NULL) + timeout_remove(&suser->to_stats_timeout); +} + +static void session_stats_refresh_timeout(struct mail_user *user) +{ + if (stats_global_user != NULL) + stats_add_session(user); + session_stats_refresh(user); +} + +static void stats_io_deactivate(void *context) +{ + struct mail_user *user = context; + struct stats_user *suser = STATS_USER_CONTEXT(user); + unsigned int last_update_secs; + + if (stats_global_user == NULL) + stats_add_session(user); + + last_update_secs = ioloop_time - suser->last_session_update; + if (last_update_secs >= SESSION_STATS_REFRESH_SECS) { + if (stats_global_user != NULL) + stats_add_session(user); + session_stats_refresh(user); + } else if (suser->to_stats_timeout == NULL) { + suser->to_stats_timeout = + timeout_add(SESSION_STATS_REFRESH_SECS*1000, + session_stats_refresh_timeout, user); + } } static void stats_user_deinit(struct mail_user *user) @@ -349,6 +390,16 @@ struct stats_user *suser = STATS_USER_CONTEXT(user); struct stats_connection *stats_conn = suser->stats_conn; + i_assert(stats_user_count > 0); + if (--stats_user_count == 0) { + /* we were updating the session lazily. do one final update. */ + i_assert(stats_global_user == user); + stats_add_session(user); + stats_global_user = NULL; + } else { + i_assert(stats_global_user == NULL); + } + io_loop_context_remove_callbacks(suser->ioloop_ctx, stats_io_activate, stats_io_deactivate, user); @@ -356,7 +407,8 @@ session_stats_refresh(user); stats_connection_disconnect(stats_conn, user); - timeout_remove(&suser->to_stats_timeout); + if (suser->to_stats_timeout != NULL) + timeout_remove(&suser->to_stats_timeout); suser->module_ctx.super.deinit(user); stats_connection_unref(&stats_conn); @@ -388,6 +440,17 @@ } stats_connection_ref(global_stats_conn); + if (stats_user_count == 0) { + /* first user connection */ + stats_global_user = user; + } else if (stats_user_count == 1) { + /* second user connection. we'll need to start doing + per-io callback tracking now. */ + stats_add_session(stats_global_user); + stats_global_user = NULL; + } + stats_user_count++; + suser = p_new(user->pool, struct stats_user, 1); suser->module_ctx.super = *v; user->vlast = &suser->module_ctx.super; @@ -396,8 +459,6 @@ suser->stats_conn = global_stats_conn; guid_128_generate(suser->session_guid); suser->last_session_update = ioloop_time; - suser->to_stats_timeout = timeout_add(SESSION_STATS_REFRESH_MSECS, - session_stats_refresh, user); suser->ioloop_ctx = ioloop_ctx; io_loop_context_add_callbacks(ioloop_ctx,