dovecot: Added "command state" for running commands. Use it inst...

dovecot at dovecot.org dovecot at dovecot.org
Sat Jan 12 08:51:21 EET 2008


details:   http://hg.dovecot.org/dovecot/rev/5e3188213724
changeset: 7148:5e3188213724
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Jan 12 06:46:28 2008 +0200
description:
Added "command state" for running commands. Use it instead of some bitfields
to test for the current state.

diffstat:

7 files changed, 40 insertions(+), 31 deletions(-)
src/imap/client.c     |   45 +++++++++++++++++++++------------------------
src/imap/client.h     |   14 +++++++++++++-
src/imap/cmd-append.c |    2 +-
src/imap/cmd-fetch.c  |    2 +-
src/imap/cmd-idle.c   |    4 ++--
src/imap/cmd-list.c   |    2 +-
src/imap/imap-sync.c  |    2 +-

diffs (221 lines):

diff -r 740a17139b67 -r 5e3188213724 src/imap/client.c
--- a/src/imap/client.c	Fri Jan 11 07:07:09 2008 +0200
+++ b/src/imap/client.c	Sat Jan 12 06:46:28 2008 +0200
@@ -71,7 +71,7 @@ void client_command_cancel(struct client
 
 	cmd->cancel = TRUE;
 	cmd_ret = cmd->func == NULL ? TRUE : cmd->func(cmd);
-	if (!cmd_ret && !cmd->param_error) {
+	if (!cmd_ret && cmd->state != CLIENT_COMMAND_STATE_DONE) {
 		if (cmd->client->output->closed)
 			i_panic("command didn't cancel itself: %s", cmd->name);
 	} else {
@@ -258,10 +258,11 @@ void client_send_command_error(struct cl
 			"Too many invalid IMAP commands.");
 	}
 
+	cmd->param_error = TRUE;
 	/* client_read_args() failures rely on this being set, so that the
 	   command processing is stopped even while command function returns
 	   FALSE. */
-	cmd->param_error = TRUE;
+	cmd->state = CLIENT_COMMAND_STATE_DONE;
 }
 
 bool client_read_args(struct client_command_context *cmd, unsigned int count,
@@ -282,7 +283,7 @@ bool client_read_args(struct client_comm
 		/* need more data */
 		if (cmd->client->input->closed) {
 			/* disconnected */
-			cmd->param_error = TRUE;
+			cmd->state = CLIENT_COMMAND_STATE_DONE;
 		}
 		return FALSE;
 	} else {
@@ -479,6 +480,7 @@ void client_continue_pending_input(struc
 		if (client_command_check_ambiguity(client->input_lock))
 			return;
 		client->input_lock->waiting_unambiguity = FALSE;
+		client->input_lock->state = CLIENT_COMMAND_STATE_WAIT_INPUT;
 	}
 
 	client_add_missing_io(client);
@@ -518,10 +520,8 @@ static void client_idle_output_timeout(s
 
 bool client_handle_unfinished_cmd(struct client_command_context *cmd)
 {
-	if (!cmd->output_pending) {
-		/* need more input */
-		return FALSE;
-	}
+	if (cmd->state != CLIENT_COMMAND_STATE_WAIT_OUTPUT)
+		return FALSE;
 
 	/* output is blocking, we can execute more commands */
 	o_stream_set_flush_pending(cmd->client->output, TRUE);
@@ -537,10 +537,11 @@ static bool client_command_input(struct 
 static bool client_command_input(struct client_command_context *cmd)
 {
 	struct client *client = cmd->client;
+	struct command *command;
 
         if (cmd->func != NULL) {
 		/* command is being executed - continue it */
-		if (cmd->func(cmd) || cmd->param_error) {
+		if (cmd->func(cmd) || cmd->state == CLIENT_COMMAND_STATE_DONE) {
 			/* command execution was finished */
 			client_command_free(cmd);
 			client_add_missing_io(client);
@@ -568,20 +569,16 @@ static bool client_command_input(struct 
 
 	if (cmd->name == '\0') {
 		/* command not given - cmd_func is already NULL. */
-	} else {
-		/* find the command function */
-		struct command *command = command_find(cmd->name);
-
-		if (command != NULL) {
-			cmd->func = command->func;
-			cmd->cmd_flags = command->flags;
-			if (client_command_check_ambiguity(cmd)) {
-				/* do nothing until existing commands are
-				   finished */
-				cmd->waiting_unambiguity = TRUE;
-				io_remove(&client->io);
-				return FALSE;
-			}
+	} else if ((command = command_find(cmd->name)) != NULL) {
+		cmd->func = command->func;
+		cmd->cmd_flags = command->flags;
+		if (client_command_check_ambiguity(cmd)) {
+			/* do nothing until existing commands are finished */
+			i_assert(cmd->state == CLIENT_COMMAND_STATE_WAIT_INPUT);
+			cmd->waiting_unambiguity = TRUE;
+			cmd->state = CLIENT_COMMAND_STATE_WAIT;
+			io_remove(&client->io);
+			return FALSE;
 		}
 	}
 
@@ -701,7 +698,7 @@ static void client_output_cmd(struct cli
 	bool finished;
 
 	/* continue processing command */
-	finished = cmd->func(cmd) || cmd->param_error;
+	finished = cmd->func(cmd) || cmd->state == CLIENT_COMMAND_STATE_DONE;
 
 	if (!finished)
 		(void)client_handle_unfinished_cmd(cmd);
@@ -735,7 +732,7 @@ int client_output(struct client *client)
 		cmd = client->command_queue;
 		for (; cmd != NULL; cmd = next) {
 			next = cmd->next;
-			if (!cmd->waiting_unambiguity) {
+			if (cmd->state == CLIENT_COMMAND_STATE_WAIT_OUTPUT) {
 				client_output_cmd(cmd);
 				if (client->output_lock != NULL)
 					break;
diff -r 740a17139b67 -r 5e3188213724 src/imap/client.h
--- a/src/imap/client.h	Fri Jan 11 07:07:09 2008 +0200
+++ b/src/imap/client.h	Sat Jan 12 06:46:28 2008 +0200
@@ -20,6 +20,18 @@ struct mailbox_keywords {
 	unsigned int announce_count;
 };
 
+enum client_command_state {
+	/* Waiting for more input */
+	CLIENT_COMMAND_STATE_WAIT_INPUT,
+	/* Waiting to be able to send more output */
+	CLIENT_COMMAND_STATE_WAIT_OUTPUT,
+	/* Just waiting for execution to continue later. For example waiting
+	   for other commands to finish first. */
+	CLIENT_COMMAND_STATE_WAIT,
+	/* Command is finished */
+	CLIENT_COMMAND_STATE_DONE
+};
+
 struct client_command_context {
 	struct client_command_context *prev, *next;
 	struct client *client;
@@ -33,11 +45,11 @@ struct client_command_context {
 	void *context;
 
 	struct imap_parser *parser;
+	enum client_command_state state;
 
 	unsigned int uid:1; /* used UID command */
 	unsigned int cancel:1; /* command is wanted to be cancelled */
 	unsigned int param_error:1;
-	unsigned int output_pending:1;
 	unsigned int waiting_unambiguity:1;
 };
 
diff -r 740a17139b67 -r 5e3188213724 src/imap/cmd-append.c
--- a/src/imap/cmd-append.c	Fri Jan 11 07:07:09 2008 +0200
+++ b/src/imap/cmd-append.c	Sat Jan 12 06:46:28 2008 +0200
@@ -76,7 +76,7 @@ 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 && cmd->state != CLIENT_COMMAND_STATE_DONE)
 		(void)client_handle_unfinished_cmd(cmd);
 	else {
 		client_command_free(cmd);
diff -r 740a17139b67 -r 5e3188213724 src/imap/cmd-fetch.c
--- a/src/imap/cmd-fetch.c	Fri Jan 11 07:07:09 2008 +0200
+++ b/src/imap/cmd-fetch.c	Sat Jan 12 06:46:28 2008 +0200
@@ -153,7 +153,7 @@ bool cmd_fetch(struct client_command_con
 	imap_fetch_begin(ctx, search_arg);
 	if ((ret = imap_fetch(ctx)) == 0) {
 		/* unfinished */
-		cmd->output_pending = TRUE;
+		cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
 
 		cmd->func = cmd_fetch_continue;
 		cmd->context = ctx;
diff -r 740a17139b67 -r 5e3188213724 src/imap/cmd-idle.c
--- a/src/imap/cmd-idle.c	Fri Jan 11 07:07:09 2008 +0200
+++ b/src/imap/cmd-idle.c	Sat Jan 12 06:46:28 2008 +0200
@@ -151,7 +151,7 @@ static bool cmd_idle_continue(struct cli
 				ctx->manual_cork = FALSE;
 				o_stream_uncork(client->output);
 			}
-			cmd->output_pending = TRUE;
+			cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
 			return FALSE;
 		}
 
@@ -171,7 +171,7 @@ static bool cmd_idle_continue(struct cli
 		   so we return here instead of doing everything twice. */
 		return FALSE;
 	}
-        cmd->output_pending = FALSE;
+	cmd->state = CLIENT_COMMAND_STATE_WAIT;
 
 	if (ctx->manual_cork) {
 		ctx->manual_cork = FALSE;
diff -r 740a17139b67 -r 5e3188213724 src/imap/cmd-list.c
--- a/src/imap/cmd-list.c	Fri Jan 11 07:07:09 2008 +0200
+++ b/src/imap/cmd-list.c	Sat Jan 12 06:46:28 2008 +0200
@@ -852,7 +852,7 @@ bool cmd_list_full(struct client_command
 
 		if (!cmd_list_continue(cmd)) {
 			/* unfinished */
-			cmd->output_pending = TRUE;
+			cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
 			cmd->func = cmd_list_continue;
 			return FALSE;
 		}
diff -r 740a17139b67 -r 5e3188213724 src/imap/imap-sync.c
--- a/src/imap/imap-sync.c	Fri Jan 11 07:07:09 2008 +0200
+++ b/src/imap/imap-sync.c	Sat Jan 12 06:46:28 2008 +0200
@@ -246,7 +246,7 @@ bool cmd_sync(struct client_command_cont
 
 	cmd->func = cmd_sync_continue;
 	cmd->context = ctx;
-	cmd->output_pending = TRUE;
+	cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
 	if (client->input_lock == cmd)
 		client->input_lock = NULL;
 	client->output_lock = NULL;


More information about the dovecot-cvs mailing list