dovecot-2.2: imap: FETCH API updated to allow using the same par...

dovecot at dovecot.org dovecot at dovecot.org
Mon Aug 13 02:51:20 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/00be97a2139a
changeset: 14889:00be97a2139a
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Aug 13 02:51:09 2012 +0300
description:
imap: FETCH API updated to allow using the same parsed FETCH in multiple mailboxes.
This is in preparation for NOTIFY extension.

diffstat:

 src/imap/cmd-fetch.c       |   79 +++++++++++-----
 src/imap/cmd-select.c      |   41 +++++---
 src/imap/imap-fetch-body.c |   33 +++---
 src/imap/imap-fetch.c      |  216 ++++++++++++++++++++++++++------------------
 src/imap/imap-fetch.h      |   38 +++++--
 5 files changed, 246 insertions(+), 161 deletions(-)

diffs (truncated from 858 to 300 lines):

diff -r cf79ab812651 -r 00be97a2139a src/imap/cmd-fetch.c
--- a/src/imap/cmd-fetch.c	Mon Aug 13 02:41:08 2012 +0300
+++ b/src/imap/cmd-fetch.c	Mon Aug 13 02:51:09 2012 +0300
@@ -21,6 +21,28 @@
 };
 
 static bool
+imap_fetch_cmd_init_handler(struct imap_fetch_context *ctx,
+			    struct client_command_context *cmd,
+			    const char *name, const struct imap_arg **args)
+{
+	struct imap_fetch_init_context init_ctx;
+
+	memset(&init_ctx, 0, sizeof(init_ctx));
+	init_ctx.fetch_ctx = ctx;
+	init_ctx.pool = ctx->ctx_pool;
+	init_ctx.name = name;
+	init_ctx.args = *args;
+
+	if (!imap_fetch_init_handler(&init_ctx)) {
+		i_assert(init_ctx.error != NULL);
+		client_send_command_error(cmd, init_ctx.error);
+		return FALSE;
+	}
+	*args = init_ctx.args;
+	return TRUE;
+}
+
+static bool
 fetch_parse_args(struct imap_fetch_context *ctx,
 		 struct client_command_context *cmd,
 		 const struct imap_arg *arg, const struct imap_arg **next_arg_r)
@@ -81,7 +103,8 @@
 static bool
 fetch_parse_modifier(struct imap_fetch_context *ctx,
 		     struct client_command_context *cmd,
-		     const char *name, const struct imap_arg **args)
+		     const char *name, const struct imap_arg **args,
+		     bool *send_vanished)
 {
 	const char *str;
 	uint64_t modseq;
@@ -103,7 +126,7 @@
 			client_send_command_error(cmd, "QRESYNC not enabled");
 			return FALSE;
 		}
-		ctx->send_vanished = TRUE;
+		*send_vanished = TRUE;
 		return TRUE;
 	}
 
@@ -114,10 +137,12 @@
 static bool
 fetch_parse_modifiers(struct imap_fetch_context *ctx,
 		      struct client_command_context *cmd,
-		      const struct imap_arg *args)
+		      const struct imap_arg *args, bool *send_vanished_r)
 {
 	const char *name;
 
+	*send_vanished_r = FALSE;
+
 	while (!IMAP_ARG_IS_EOL(args)) {
 		if (!imap_arg_get_atom(args, &name)) {
 			client_send_command_error(cmd,
@@ -125,10 +150,11 @@
 			return FALSE;
 		}
 		args++;
-		if (!fetch_parse_modifier(ctx, cmd, t_str_ucase(name), &args))
+		if (!fetch_parse_modifier(ctx, cmd, t_str_ucase(name),
+					  &args, send_vanished_r))
 			return FALSE;
 	}
-	if (ctx->send_vanished &&
+	if (*send_vanished_r &&
 	    (ctx->search_args->args->next == NULL ||
 	     ctx->search_args->args->next->type != SEARCH_MODSEQ)) {
 		client_send_command_error(cmd,
@@ -144,17 +170,17 @@
 	static const char *ok_message = "OK Fetch completed.";
 	const char *tagged_reply = ok_message;
 	enum mail_error error;
-	bool seen_flags_changed = ctx->state.seen_flags_changed;
+	bool failed, seen_flags_changed = ctx->state.seen_flags_changed;
 
 	if (ctx->state.skipped_expunged_msgs) {
 		tagged_reply = "OK ["IMAP_RESP_CODE_EXPUNGEISSUED"] "
 			"Some messages were already expunged.";
 	}
 
-	if (imap_fetch_deinit(ctx) < 0)
-		ctx->state.failed = TRUE;
+	failed = imap_fetch_end(ctx) < 0;
+	imap_fetch_free(&ctx);
 
-	if (ctx->state.failed) {
+	if (failed) {
 		const char *errstr;
 
 		if (cmd->client->output->closed) {
@@ -198,7 +224,9 @@
 	struct imap_fetch_context *ctx;
 	const struct imap_arg *args, *next_arg, *list_arg;
 	struct mail_search_args *search_args;
+	struct imap_fetch_qresync_args qresync_args;
 	const char *messageset;
+	bool send_vanished = FALSE;
 	int ret;
 
 	if (!client_read_args(cmd, 0, 0, &args))
@@ -221,29 +249,32 @@
 	if (ret <= 0)
 		return ret < 0;
 
-	ctx = imap_fetch_init(cmd, client->mailbox);
-	if (ctx == NULL) {
-		mail_search_args_unref(&search_args);
-		return TRUE;
-	}
+	ctx = imap_fetch_alloc(client, cmd->pool);
 	ctx->search_args = search_args;
 
 	if (!fetch_parse_args(ctx, cmd, &args[1], &next_arg) ||
 	    (imap_arg_get_list(next_arg, &list_arg) &&
-	     !fetch_parse_modifiers(ctx, cmd, list_arg))) {
-		(void)imap_fetch_deinit(ctx);
+	     !fetch_parse_modifiers(ctx, cmd, list_arg, &send_vanished))) {
+		imap_fetch_free(&ctx);
 		return TRUE;
 	}
 
-	if (imap_fetch_begin(ctx) == 0) {
-		if (imap_fetch_more(ctx, cmd) == 0) {
-			/* unfinished */
-			cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
+	if (send_vanished) {
+		memset(&qresync_args, 0, sizeof(qresync_args));
+		if (imap_fetch_send_vanished(client, client->mailbox,
+					     search_args, &qresync_args) < 0)
+			return cmd_fetch_finish(ctx, cmd);
+	}
 
-			cmd->func = cmd_fetch_continue;
-			cmd->context = ctx;
-			return FALSE;
-		}
+	imap_fetch_begin_once(ctx, client->mailbox);
+
+	if (imap_fetch_more(ctx, cmd) == 0) {
+		/* unfinished */
+		cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
+
+		cmd->func = cmd_fetch_continue;
+		cmd->context = ctx;
+		return FALSE;
 	}
 	return cmd_fetch_finish(ctx, cmd);
 }
diff -r cf79ab812651 -r 00be97a2139a src/imap/cmd-select.c
--- a/src/imap/cmd-select.c	Mon Aug 13 02:41:08 2012 +0300
+++ b/src/imap/cmd-select.c	Mon Aug 13 02:51:09 2012 +0300
@@ -219,11 +219,12 @@
 		return FALSE;
 	}
 
-	ret = imap_fetch_deinit(ctx->fetch_ctx);
+	ret = imap_fetch_end(ctx->fetch_ctx);
 	if (ret < 0) {
 		client_send_storage_error(ctx->cmd,
 					  mailbox_get_storage(ctx->box));
 	}
+	imap_fetch_free(&ctx->fetch_ctx);
 	cmd_select_finish(ctx, ret);
 	return TRUE;
 }
@@ -232,39 +233,45 @@
 {
 	struct imap_fetch_context *fetch_ctx;
 	struct mail_search_args *search_args;
+	struct imap_fetch_qresync_args qresync_args;
 
 	search_args = mail_search_build_init();
 	search_args->args = p_new(search_args->pool, struct mail_search_arg, 1);
 	search_args->args->type = SEARCH_UIDSET;
 	search_args->args->value.seqset = ctx->qresync_known_uids;
 
-	fetch_ctx = imap_fetch_init(ctx->cmd, ctx->box);
-	if (fetch_ctx == NULL)
+	memset(&qresync_args, 0, sizeof(qresync_args));
+	qresync_args.qresync_sample_seqset = &ctx->qresync_sample_seqset;
+	qresync_args.qresync_sample_uidset = &ctx->qresync_sample_uidset;
+
+	if (imap_fetch_send_vanished(ctx->cmd->client, ctx->box,
+				     search_args, &qresync_args) < 0) {
+		mail_search_args_unref(&search_args);
 		return -1;
+	}
 
+	fetch_ctx = imap_fetch_alloc(ctx->cmd->client, ctx->cmd->pool);
 	fetch_ctx->search_args = search_args;
-	fetch_ctx->send_vanished = TRUE;
-	fetch_ctx->qresync_sample_seqset = &ctx->qresync_sample_seqset;
-	fetch_ctx->qresync_sample_uidset = &ctx->qresync_sample_uidset;
 
 	imap_fetch_add_changed_since(fetch_ctx, ctx->qresync_modseq);
 	imap_fetch_init_nofail_handler(fetch_ctx, imap_fetch_uid_init);
 	imap_fetch_init_nofail_handler(fetch_ctx, imap_fetch_flags_init);
 	imap_fetch_init_nofail_handler(fetch_ctx, imap_fetch_modseq_init);
 
-	if (imap_fetch_begin(fetch_ctx) == 0) {
-		if (imap_fetch_more(fetch_ctx, ctx->cmd) == 0) {
-			/* unfinished */
-			ctx->fetch_ctx = fetch_ctx;
-			ctx->cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
+	imap_fetch_begin_once(fetch_ctx, ctx->box);
+	if (imap_fetch_more(fetch_ctx, ctx->cmd) == 0) {
+		/* unfinished */
+		ctx->fetch_ctx = fetch_ctx;
+		ctx->cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
 
-			ctx->cmd->func = cmd_select_continue;
-			ctx->cmd->context = ctx;
-			return 0;
-		}
+		ctx->cmd->func = cmd_select_continue;
+		ctx->cmd->context = ctx;
+		return 0;
 	}
-
-	return imap_fetch_deinit(fetch_ctx) < 0 ? -1 : 1;
+	if (imap_fetch_end(fetch_ctx) < 0)
+		return -1;
+	imap_fetch_free(&fetch_ctx);
+	return 1;
 }
 
 static int
diff -r cf79ab812651 -r 00be97a2139a src/imap/imap-fetch-body.c
--- a/src/imap/imap-fetch-body.c	Mon Aug 13 02:41:08 2012 +0300
+++ b/src/imap/imap-fetch-body.c	Mon Aug 13 02:51:09 2012 +0300
@@ -33,7 +33,7 @@
 	struct imap_fetch_state *state = &ctx->state;
 
 	errno = state->cur_input->stream_errno;
-	mail_storage_set_critical(ctx->box->storage,
+	mail_storage_set_critical(state->cur_mail->box->storage,
 		"read(%s) failed: %m (FETCH for mailbox %s UID %u)",
 		i_stream_get_name(state->cur_input),
 		mailbox_get_vname(state->cur_mail->box), state->cur_mail->uid);
@@ -58,15 +58,15 @@
 	return str_c(str);
 }
 
-static string_t *get_prefix(struct imap_fetch_context *ctx,
+static string_t *get_prefix(struct imap_fetch_state *state,
 			    const struct imap_fetch_body_data *body,
 			    uoff_t size, bool has_nuls)
 {
 	string_t *str;
 
 	str = t_str_new(128);
-	if (ctx->state.cur_first)
-		ctx->state.cur_first = FALSE;
+	if (state->cur_first)
+		state->cur_first = FALSE;
 	else
 		str_append_c(str, ' ');
 
@@ -136,10 +136,9 @@
 	ctx->state.cur_input = result.input;
 	ctx->state.cur_size = result.size;
 	ctx->state.cur_size_field = result.size_field;
-	ctx->state.cur_human_name =
-		p_strconcat(ctx->pool, "[", body->section, "]", NULL);
+	ctx->state.cur_human_name = body->section;
 
-	str = get_prefix(ctx, body, ctx->state.cur_size,
+	str = get_prefix(&ctx->state, body, ctx->state.cur_size,
 			 result.binary_decoded_input_has_nuls);
 	o_stream_nsend(ctx->client->output, str_data(str), str_len(str));
 
@@ -196,7 +195,7 @@
 	const char *value;
 	size_t i;
 
-	str = str_new(ctx->fetch_ctx->pool, 128);
+	str = str_new(ctx->pool, 128);
 	str_append(str, prefix);
 	str_append(str, " (");
 
@@ -277,7 +276,7 @@
 	i_assert(strncmp(ctx->name, "BODY", 4) == 0);
 	p = ctx->name + 4;
 
-	body = p_new(ctx->fetch_ctx->pool, struct imap_fetch_body_data, 1);
+	body = p_new(ctx->pool, struct imap_fetch_body_data, 1);
 
 	if (strncmp(p, ".PEEK", 5) == 0)
 		p += 5;


More information about the dovecot-cvs mailing list