dovecot: Use separate idle timeouts to avoid unneededly checking...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Jan 4 00:36:36 EET 2008
details: http://hg.dovecot.org/dovecot/rev/284dd5f2777d
changeset: 7103:284dd5f2777d
user: Timo Sirainen <tss at iki.fi>
date: Fri Jan 04 00:36:32 2008 +0200
description:
Use separate idle timeouts to avoid unneededly checking them every n seconds.
diffstat:
7 files changed, 77 insertions(+), 84 deletions(-)
src/imap/client.c | 88 +++++++++++++++++++++++++------------------------
src/imap/client.h | 2 +
src/imap/cmd-append.c | 7 +--
src/imap/cmd-search.c | 7 +--
src/imap/common.h | 6 +--
src/pop3/client.c | 50 ++++++++++-----------------
src/pop3/client.h | 1
diffs (truncated from 371 to 300 lines):
diff -r 75f4e7ce8151 -r 284dd5f2777d src/imap/client.c
--- 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,9 +16,15 @@ extern struct mail_storage_callbacks mai
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 @@ struct client *client_create(int fd_in,
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 @@ void client_destroy(struct client *clien
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 @@ void client_command_free(struct client_c
/* 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 @@ static bool client_skip_line(struct clie
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 @@ static bool client_command_input(struct
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 @@ void client_input(struct client *client)
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 @@ void client_input(struct client *client)
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 @@ int client_output(struct client *client)
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 @@ int client_output(struct client *client)
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 @@ void clients_deinit(void)
client_send_line(my_client, "* BYE Server shutting down.");
client_destroy(my_client, "Server shutting down");
}
-
- timeout_remove(&to_idle);
-}
+}
diff -r 75f4e7ce8151 -r 284dd5f2777d src/imap/client.h
--- 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 client {
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
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);
diff -r 75f4e7ce8151 -r 284dd5f2777d src/imap/cmd-append.c
--- 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 @@ static void client_input_append(struct c
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);
}
}
diff -r 75f4e7ce8151 -r 284dd5f2777d src/imap/cmd-search.c
--- 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 @@ static void cmd_search_more_callback(str
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);
}
}
diff -r 75f4e7ce8151 -r 284dd5f2777d src/imap/common.h
--- 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
diff -r 75f4e7ce8151 -r 284dd5f2777d src/pop3/client.c
--- 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,20 +23,27 @@
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)
{
@@ -152,6 +159,8 @@ struct client *client_create(int fd_in,
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 @@ void client_destroy(struct client *clien
if (client->io != NULL)
io_remove(&client->io);
More information about the dovecot-cvs
mailing list