Mercurial > dovecot > original-hg > dovecot-1.2
changeset 7103:284dd5f2777d HEAD
Use separate idle timeouts to avoid unneededly checking them every n seconds.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 04 Jan 2008 00:36:32 +0200 |
parents | 75f4e7ce8151 |
children | db5f55daa002 |
files | src/imap/client.c src/imap/client.h src/imap/cmd-append.c src/imap/cmd-search.c src/imap/common.h src/pop3/client.c src/pop3/client.h |
diffstat | 7 files changed, 75 insertions(+), 82 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/client.c Fri Jan 04 00:02:06 2008 +0200 +++ b/src/imap/client.c Fri Jan 04 00:36:32 2008 +0200 @@ -16,10 +16,16 @@ extern struct mail_storage_callbacks mail_storage_callbacks; static struct client *my_client; /* we don't need more than one currently */ -static struct timeout *to_idle; static bool client_handle_input(struct client *client); +static void client_idle_timeout(struct client *client) +{ + if (client->output_lock == NULL) + client_send_line(client, "* BYE Disconnected for inactivity."); + client_destroy(client, "Disconnected for inactivity"); +} + struct client *client_create(int fd_in, int fd_out, struct mail_namespace *namespaces) { @@ -39,6 +45,8 @@ client->io = io_add(fd_in, IO_READ, client_input, client); client->last_input = ioloop_time; + client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS, + client_idle_timeout, client); client->command_pool = pool_alloconly_create("client command", 8192); client->namespaces = namespaces; @@ -132,6 +140,9 @@ imap_parser_destroy(&client->free_parser); if (client->io != NULL) io_remove(&client->io); + if (client->to_idle_output != NULL) + timeout_remove(&client->to_idle_output); + timeout_remove(&client->to_idle); i_stream_destroy(&client->input); o_stream_destroy(&client->output); @@ -397,6 +408,7 @@ /* reset input idle time because command output might have taken a long time and we don't want to disconnect client immediately then */ client->last_input = ioloop_time; + timeout_reset(client->to_idle); if (cmd->cancel) { cmd->cancel = FALSE; @@ -496,6 +508,30 @@ return !client->input_skip_line; } +static void client_idle_output_timeout(struct client *client) +{ + client_destroy(client, + "Disconnected for inactivity in reading our output"); +} + +bool client_handle_unfinished_cmd(struct client_command_context *cmd) +{ + if (!cmd->output_pending) { + /* need more input */ + return FALSE; + } + + /* output is blocking, we can execute more commands */ + o_stream_set_flush_pending(cmd->client->output, TRUE); + if (cmd->client->to_idle_output == NULL) { + /* disconnect sooner if client isn't reading our output */ + cmd->client->to_idle_output = + timeout_add(CLIENT_OUTPUT_TIMEOUT_MSECS, + client_idle_output_timeout, cmd->client); + } + return TRUE; +} + static bool client_command_input(struct client_command_context *cmd) { struct client *client = cmd->client; @@ -509,13 +545,7 @@ return TRUE; } - if (cmd->output_pending) { - /* output is blocking, we can execute more commands */ - o_stream_set_flush_pending(client->output, TRUE); - return TRUE; - } - /* need more input */ - return FALSE; + return client_handle_unfinished_cmd(cmd); } if (cmd->tag == NULL) { @@ -641,6 +671,7 @@ i_assert(client->io != NULL); client->last_input = ioloop_time; + timeout_reset(client->to_idle); bytes = i_stream_read(client->input); if (bytes == -1) { @@ -665,16 +696,14 @@ static void client_output_cmd(struct client_command_context *cmd) { - struct client *client = cmd->client; bool finished; /* continue processing command */ finished = cmd->func(cmd) || cmd->param_error; - if (!finished) { - if (cmd->output_pending) - o_stream_set_flush_pending(client->output, TRUE); - } else { + if (!finished) + (void)client_handle_unfinished_cmd(cmd); + else { /* command execution was finished */ client_command_free(cmd); } @@ -688,6 +717,9 @@ i_assert(!client->destroyed); client->last_output = ioloop_time; + timeout_reset(client->to_idle); + if (client->to_idle_output != NULL) + timeout_reset(client->to_idle_output); if ((ret = o_stream_flush(client->output)) < 0) { client_destroy(client, NULL); @@ -719,35 +751,9 @@ return ret; } -static void idle_timeout(void *context ATTR_UNUSED) -{ - time_t idle_time, last_change; - - if (my_client == NULL) - return; - - last_change = I_MAX(my_client->last_input, my_client->last_output); - idle_time = ioloop_time - last_change; - - if (o_stream_get_buffer_used_size(my_client->output) > 0 && - idle_time >= CLIENT_OUTPUT_TIMEOUT) { - /* client isn't reading our output */ - client_destroy(my_client, "Disconnected for inactivity " - "in reading our output"); - } else if (idle_time >= CLIENT_IDLE_TIMEOUT) { - /* client isn't sending us anything */ - if (my_client->output_lock == NULL) { - client_send_line(my_client, - "* BYE Disconnected for inactivity."); - } - client_destroy(my_client, "Disconnected for inactivity"); - } -} - void clients_init(void) { my_client = NULL; - to_idle = timeout_add(10000, idle_timeout, NULL); } void clients_deinit(void) @@ -756,6 +762,4 @@ client_send_line(my_client, "* BYE Server shutting down."); client_destroy(my_client, "Server shutting down"); } - - timeout_remove(&to_idle); }
--- a/src/imap/client.h Fri Jan 04 00:02:06 2008 +0200 +++ b/src/imap/client.h Fri Jan 04 00:36:32 2008 +0200 @@ -46,6 +46,7 @@ struct io *io; struct istream *input; struct ostream *output; + struct timeout *to_idle, *to_idle_output; struct mail_namespace *namespaces; struct mailbox *mailbox; @@ -110,6 +111,7 @@ void client_command_cancel(struct client_command_context *cmd); void client_command_free(struct client_command_context *cmd); +bool client_handle_unfinished_cmd(struct client_command_context *cmd); void client_continue_pending_input(struct client **_client); void client_input(struct client *client);
--- a/src/imap/cmd-append.c Fri Jan 04 00:02:06 2008 +0200 +++ b/src/imap/cmd-append.c Fri Jan 04 00:36:32 2008 +0200 @@ -75,12 +75,11 @@ o_stream_cork(client->output); finished = cmd->func(cmd); o_stream_uncork(client->output); - if (finished) { + if (!finished) + (void)client_handle_unfinished_cmd(cmd); + else { client_command_free(cmd); client_continue_pending_input(&client); - } else if (cmd->output_pending) { - /* syncing didn't send everything */ - o_stream_set_flush_pending(client->output, TRUE); } }
--- a/src/imap/cmd-search.c Fri Jan 04 00:02:06 2008 +0200 +++ b/src/imap/cmd-search.c Fri Jan 04 00:36:32 2008 +0200 @@ -132,12 +132,11 @@ finished = cmd_search_more(cmd); o_stream_uncork(client->output); - if (finished) { + if (!finished) + (void)client_handle_unfinished_cmd(cmd); + else { client_command_free(cmd); client_continue_pending_input(&client); - } else { - if (cmd->output_pending) - o_stream_set_flush_pending(client->output, TRUE); } }
--- a/src/imap/common.h Fri Jan 04 00:02:06 2008 +0200 +++ b/src/imap/common.h Fri Jan 04 00:36:32 2008 +0200 @@ -4,11 +4,11 @@ #include "lib.h" #include "client.h" -/* Disconnect client after idling this many seconds */ -#define CLIENT_IDLE_TIMEOUT (60*30) +/* Disconnect client after idling this many milliseconds */ +#define CLIENT_IDLE_TIMEOUT_MSECS (60*30*1000) /* If we can't send anything to client for this long, disconnect the client */ -#define CLIENT_OUTPUT_TIMEOUT (5*60) +#define CLIENT_OUTPUT_TIMEOUT_MSECS (5*60*1000) /* Stop buffering more data into output stream after this many bytes */ #define CLIENT_OUTPUT_OPTIMAL_SIZE 2048
--- a/src/pop3/client.c Fri Jan 04 00:02:06 2008 +0200 +++ b/src/pop3/client.c Fri Jan 04 00:36:32 2008 +0200 @@ -23,21 +23,28 @@ size has dropped to half of it, start reading input again. */ #define OUTBUF_THROTTLE_SIZE 4096 -/* If we can't send anything for 10 minutes, disconnect the client */ -#define CLIENT_OUTPUT_TIMEOUT (10*60) - /* Disconnect client when it sends too many bad commands in a row */ #define CLIENT_MAX_BAD_COMMANDS 20 -/* Disconnect client after idling this many seconds */ -#define CLIENT_IDLE_TIMEOUT (10*60) +/* Disconnect client after idling this many milliseconds */ +#define CLIENT_IDLE_TIMEOUT_MSECS (10*60*1000) static struct client *my_client; /* we don't need more than one currently */ -static struct timeout *to_idle; static void client_input(struct client *client); static int client_output(struct client *client); +static void client_idle_timeout(struct client *client) +{ + if (client->cmd != NULL) { + client_destroy(client, + "Disconnected for inactivity in reading our output"); + } else { + client_send_line(client, "-ERR Disconnected for inactivity."); + client_destroy(client, "Disconnected for inactivity"); + } +} + static bool init_mailbox(struct client *client, const char **error_r) { struct mail_search_arg search_arg; @@ -152,6 +159,8 @@ client->io = io_add(fd_in, IO_READ, client_input, client); client->last_input = ioloop_time; + client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS, + client_idle_timeout, client); client->namespaces = namespaces; @@ -260,6 +269,7 @@ if (client->io != NULL) io_remove(&client->io); + timeout_remove(&client->to_idle); i_stream_destroy(&client->input); o_stream_destroy(&client->output); @@ -369,6 +379,7 @@ client->waiting_input = FALSE; client->last_input = ioloop_time; + timeout_reset(client->to_idle); switch (i_stream_read(client->input)) { case -1: @@ -422,6 +433,7 @@ } client->last_output = ioloop_time; + timeout_reset(client->to_idle); if (client->cmd != NULL) { o_stream_cork(client->output); @@ -443,31 +455,9 @@ return client->cmd == NULL; } -static void idle_timeout(void *context ATTR_UNUSED) -{ - if (my_client == NULL) - return; - - if (my_client->cmd != NULL) { - if (ioloop_time - my_client->last_output >= - CLIENT_OUTPUT_TIMEOUT) { - client_destroy(my_client, "Disconnected for inactivity " - "in reading our output"); - } - } else { - if (ioloop_time - my_client->last_input >= - CLIENT_IDLE_TIMEOUT) { - client_send_line(my_client, - "-ERR Disconnected for inactivity."); - client_destroy(my_client, "Disconnected for inactivity"); - } - } -} - void clients_init(void) { my_client = NULL; - to_idle = timeout_add(10000, idle_timeout, NULL); } void clients_deinit(void) @@ -476,6 +466,4 @@ client_send_line(my_client, "-ERR Server shutting down."); client_destroy(my_client, "Server shutting down"); } - - timeout_remove(&to_idle); }