dovecot-1.1: Syncing supports now calling a callback after sync ...
dovecot at dovecot.org
dovecot at dovecot.org
Wed Mar 5 02:54:36 EET 2008
details: http://hg.dovecot.org/dovecot-1.1/rev/33304b5f6070
changeset: 7353:33304b5f6070
user: Timo Sirainen <tss at iki.fi>
date: Wed Mar 05 02:54:33 2008 +0200
description:
Syncing supports now calling a callback after sync instead of just sending a
tagged reply. Use it with EXPUNGE to retry EXPUNGE in case the syncing had
seen new \Deleted flags (Outlook workaround).
diffstat:
4 files changed, 92 insertions(+), 32 deletions(-)
src/imap/client.h | 10 ++---
src/imap/cmd-expunge.c | 18 ++++++++-
src/imap/imap-sync.c | 90 +++++++++++++++++++++++++++++++++++-------------
src/imap/imap-sync.h | 6 +++
diffs (255 lines):
diff -r 4f63124e756e -r 33304b5f6070 src/imap/client.h
--- a/src/imap/client.h Wed Mar 05 02:53:05 2008 +0200
+++ b/src/imap/client.h Wed Mar 05 02:54:33 2008 +0200
@@ -48,12 +48,7 @@ struct client_command_context {
struct imap_parser *parser;
enum client_command_state state;
- /* if multiple commands are in progress, we may need to wait for them
- to finish before syncing mailbox. */
- unsigned int sync_counter;
- enum mailbox_sync_flags sync_flags;
- enum imap_sync_flags sync_imap_flags;
- const char *sync_tagline;
+ struct client_sync_context *sync;
unsigned int uid:1; /* used UID command */
unsigned int cancel:1; /* command is wanted to be cancelled */
@@ -89,6 +84,9 @@ struct client {
struct client_command_context *input_lock;
struct client_command_context *output_lock;
+ /* syncing marks this TRUE when it sees \Deleted flags. this is by
+ EXPUNGE for Outlook-workaround. */
+ unsigned int sync_seen_deletes:1;
unsigned int disconnected:1;
unsigned int destroyed:1;
unsigned int handling_input:1;
diff -r 4f63124e756e -r 33304b5f6070 src/imap/cmd-expunge.c
--- a/src/imap/cmd-expunge.c Wed Mar 05 02:53:05 2008 +0200
+++ b/src/imap/cmd-expunge.c Wed Mar 05 02:54:33 2008 +0200
@@ -38,6 +38,19 @@ bool cmd_uid_expunge(struct client_comma
}
}
+static bool cmd_expunge_callback(struct client_command_context *cmd)
+{
+ if (cmd->client->sync_seen_deletes) {
+ /* Outlook workaround: session 1 set \Deleted flag and
+ session 2 tried to expunge without having seen it yet.
+ expunge again. */
+ return cmd_expunge(cmd);
+ }
+
+ client_send_tagline(cmd, "OK Expunge completed.");
+ return TRUE;
+}
+
bool cmd_expunge(struct client_command_context *cmd)
{
struct client *client = cmd->client;
@@ -45,9 +58,10 @@ bool cmd_expunge(struct client_command_c
if (!client_verify_open_mailbox(cmd))
return TRUE;
+ cmd->client->sync_seen_deletes = FALSE;
if (imap_expunge(client->mailbox, NULL)) {
- return cmd_sync(cmd, 0, IMAP_SYNC_FLAG_SAFE,
- "OK Expunge completed.");
+ return cmd_sync_callback(cmd, 0, IMAP_SYNC_FLAG_SAFE,
+ cmd_expunge_callback);
} else {
client_send_storage_error(cmd,
mailbox_get_storage(client->mailbox));
diff -r 4f63124e756e -r 33304b5f6070 src/imap/imap-sync.c
--- a/src/imap/imap-sync.c Wed Mar 05 02:53:05 2008 +0200
+++ b/src/imap/imap-sync.c Wed Mar 05 02:54:33 2008 +0200
@@ -8,6 +8,16 @@
#include "imap-sync.h"
#include "commands.h"
+struct client_sync_context {
+ /* if multiple commands are in progress, we may need to wait for them
+ to finish before syncing mailbox. */
+ unsigned int counter;
+ enum mailbox_sync_flags flags;
+ enum imap_sync_flags imap_flags;
+ const char *tagline;
+ imap_sync_callback_t *callback;
+};
+
struct imap_sync_context {
struct client *client;
struct mailbox *box;
@@ -102,6 +112,9 @@ static int imap_sync_send_flags(struct i
flags = mail_get_flags(ctx->mail);
keywords = client_get_keyword_names(ctx->client, &ctx->tmp_keywords,
mail_get_keyword_indexes(ctx->mail));
+
+ if ((flags & MAIL_DELETED) != 0)
+ ctx->client->sync_seen_deletes = TRUE;
str_truncate(str, 0);
str_printfa(str, "* %u FETCH (", ctx->seq);
@@ -185,6 +198,16 @@ int imap_sync_more(struct imap_sync_cont
return ret;
}
+static bool cmd_finish_sync(struct client_command_context *cmd)
+{
+ if (cmd->sync->callback != NULL)
+ return cmd->sync->callback(cmd);
+ else {
+ client_send_tagline(cmd, cmd->sync->tagline);
+ return TRUE;
+ }
+}
+
static bool cmd_sync_continue(struct client_command_context *sync_cmd)
{
struct client_command_context *cmd;
@@ -210,13 +233,12 @@ static bool cmd_sync_continue(struct cli
for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next) {
if (cmd->state == CLIENT_COMMAND_STATE_WAIT_SYNC &&
cmd != sync_cmd &&
- cmd->sync_counter+1 == client->sync_counter) {
- client_send_tagline(cmd, cmd->sync_tagline);
- client_command_free(cmd);
- }
- }
- client_send_tagline(sync_cmd, sync_cmd->sync_tagline);
- return TRUE;
+ cmd->sync->counter+1 == client->sync_counter) {
+ if (cmd_finish_sync(cmd))
+ client_command_free(cmd);
+ }
+ }
+ return cmd_finish_sync(sync_cmd);
}
static void get_common_sync_flags(struct client *client,
@@ -230,14 +252,14 @@ static void get_common_sync_flags(struct
*imap_flags_r = 0;
for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next) {
- if (cmd->sync_tagline != NULL &&
- cmd->sync_counter == client->sync_counter) {
- if ((cmd->sync_flags & MAILBOX_SYNC_FLAG_FAST) != 0)
+ if (cmd->sync != NULL &&
+ cmd->sync->counter == client->sync_counter) {
+ if ((cmd->sync->flags & MAILBOX_SYNC_FLAG_FAST) != 0)
fast_count++;
- if (cmd->sync_flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES)
+ if (cmd->sync->flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES)
noexpunges_count++;
- *flags_r |= cmd->sync_flags;
- *imap_flags_r |= cmd->sync_imap_flags;
+ *flags_r |= cmd->sync->flags;
+ *imap_flags_r |= cmd->sync->imap_flags;
count++;
}
}
@@ -290,8 +312,10 @@ static bool cmd_sync_client(struct clien
return TRUE;
}
-bool cmd_sync(struct client_command_context *cmd, enum mailbox_sync_flags flags,
- enum imap_sync_flags imap_flags, const char *tagline)
+static bool
+cmd_sync_full(struct client_command_context *cmd, enum mailbox_sync_flags flags,
+ enum imap_sync_flags imap_flags, const char *tagline,
+ imap_sync_callback_t *callback)
{
struct client *client = cmd->client;
@@ -302,14 +326,17 @@ bool cmd_sync(struct client_command_cont
if (client->mailbox == NULL) {
/* no mailbox selected, no point in delaying the sync */
+ i_assert(callback == NULL);
client_send_tagline(cmd, tagline);
return TRUE;
}
- cmd->sync_counter = client->sync_counter;
- cmd->sync_flags = flags;
- cmd->sync_imap_flags = imap_flags;
- cmd->sync_tagline = p_strdup(cmd->pool, tagline);
+ cmd->sync = p_new(cmd->pool, struct client_sync_context, 1);
+ cmd->sync->counter = client->sync_counter;
+ cmd->sync->flags = flags;
+ cmd->sync->imap_flags = imap_flags;
+ cmd->sync->tagline = p_strdup(cmd->pool, tagline);
+ cmd->sync->callback = callback;
cmd->state = CLIENT_COMMAND_STATE_WAIT_SYNC;
cmd->func = NULL;
@@ -321,6 +348,20 @@ bool cmd_sync(struct client_command_cont
return FALSE;
}
+bool cmd_sync(struct client_command_context *cmd, enum mailbox_sync_flags flags,
+ enum imap_sync_flags imap_flags, const char *tagline)
+{
+ return cmd_sync_full(cmd, flags, imap_flags, tagline, NULL);
+}
+
+bool cmd_sync_callback(struct client_command_context *cmd,
+ enum mailbox_sync_flags flags,
+ enum imap_sync_flags imap_flags,
+ imap_sync_callback_t *callback)
+{
+ return cmd_sync_full(cmd, flags, imap_flags, NULL, callback);
+}
+
static bool cmd_sync_drop_fast(struct client *client)
{
struct client_command_context *cmd, *next;
@@ -330,10 +371,11 @@ static bool cmd_sync_drop_fast(struct cl
next = cmd->next;
if (cmd->state == CLIENT_COMMAND_STATE_WAIT_SYNC &&
- (cmd->sync_flags & MAILBOX_SYNC_FLAG_FAST) != 0) {
- client_send_tagline(cmd, cmd->sync_tagline);
- client_command_free(cmd);
- ret = TRUE;
+ (cmd->sync->flags & MAILBOX_SYNC_FLAG_FAST) != 0) {
+ if (cmd_finish_sync(cmd)) {
+ client_command_free(cmd);
+ ret = TRUE;
+ }
}
}
return ret;
@@ -358,7 +400,7 @@ bool cmd_sync_delayed(struct client *cli
/* find a command that we can sync */
for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next) {
if (cmd->state == CLIENT_COMMAND_STATE_WAIT_SYNC) {
- if (cmd->sync_counter == client->sync_counter)
+ if (cmd->sync->counter == client->sync_counter)
break;
}
}
diff -r 4f63124e756e -r 33304b5f6070 src/imap/imap-sync.h
--- a/src/imap/imap-sync.h Wed Mar 05 02:53:05 2008 +0200
+++ b/src/imap/imap-sync.h Wed Mar 05 02:54:33 2008 +0200
@@ -5,6 +5,8 @@ enum imap_sync_flags {
IMAP_SYNC_FLAG_SEND_UID = 0x01,
IMAP_SYNC_FLAG_SAFE = 0x02
};
+
+typedef bool imap_sync_callback_t(struct client_command_context *cmd);
struct client;
@@ -16,6 +18,10 @@ int imap_sync_more(struct imap_sync_cont
bool cmd_sync(struct client_command_context *cmd, enum mailbox_sync_flags flags,
enum imap_sync_flags imap_flags, const char *tagline);
+bool cmd_sync_callback(struct client_command_context *cmd,
+ enum mailbox_sync_flags flags,
+ enum imap_sync_flags imap_flags,
+ imap_sync_callback_t *callback);
bool cmd_sync_delayed(struct client *client);
#endif
More information about the dovecot-cvs
mailing list