dovecot-1.2: QRESYNC: Send HIGHESTMODSEQ automatically in all ta...
dovecot at dovecot.org
dovecot at dovecot.org
Wed Jun 11 15:45:04 EEST 2008
details: http://hg.dovecot.org/dovecot-1.2/rev/ffaf1ea49704
changeset: 7817:ffaf1ea49704
user: Timo Sirainen <tss at iki.fi>
date: Wed Jun 11 15:44:35 2008 +0300
description:
QRESYNC: Send HIGHESTMODSEQ automatically in all tagged replies whenever it
seems useful.
diffstat:
7 files changed, 81 insertions(+), 60 deletions(-)
src/imap/client.h | 1
src/imap/cmd-close.c | 17 +--------
src/imap/cmd-expunge.c | 21 +----------
src/imap/cmd-idle.c | 4 +-
src/imap/imap-fetch.c | 8 +++-
src/imap/imap-sync.c | 87 ++++++++++++++++++++++++++++++++++++------------
src/imap/imap-sync.h | 3 +
diffs (282 lines):
diff -r ea6727a1220e -r ffaf1ea49704 src/imap/client.h
--- a/src/imap/client.h Wed Jun 11 15:43:12 2008 +0300
+++ b/src/imap/client.h Wed Jun 11 15:44:35 2008 +0300
@@ -94,6 +94,7 @@ struct client {
unsigned int command_queue_size;
uint64_t sync_last_full_modseq;
+ uint64_t highest_fetch_modseq;
/* SEARCHRES extension: Last saved SEARCH result */
ARRAY_TYPE(seq_range) search_saved_uidset;
diff -r ea6727a1220e -r ffaf1ea49704 src/imap/cmd-close.c
--- a/src/imap/cmd-close.c Wed Jun 11 15:43:12 2008 +0300
+++ b/src/imap/cmd-close.c Wed Jun 11 15:44:35 2008 +0300
@@ -12,19 +12,6 @@ static void cmd_close_finish(struct clie
mailbox_get_storage(client->mailbox));
}
client_update_mailbox_flags(client, NULL);
-}
-
-static bool cmd_close_callback(struct client_command_context *cmd)
-{
- struct mailbox_status status;
-
- mailbox_get_status(cmd->client->mailbox,
- STATUS_HIGHESTMODSEQ, &status);
- cmd_close_finish(cmd->client);
- client_send_tagline(cmd, t_strdup_printf(
- "OK [HIGHESTMODSEQ %llu] Close completed.",
- (unsigned long long)status.highest_modseq));
- return TRUE;
}
bool cmd_close(struct client_command_context *cmd)
@@ -51,8 +38,8 @@ bool cmd_close(struct client_command_con
it by syncing the mailbox one last time. We wouldn't need
to include our own expunge in there, but it's too much
trouble to hide it. */
- return cmd_sync_callback(cmd, 0, IMAP_SYNC_FLAG_SAFE,
- cmd_close_callback);
+ return cmd_sync(cmd, 0, IMAP_SYNC_FLAG_SAFE,
+ "OK Close completed.");
} else {
if (mailbox_sync(mailbox, 0, 0, NULL) < 0)
client_send_untagged_storage_error(client, storage);
diff -r ea6727a1220e -r ffaf1ea49704 src/imap/cmd-expunge.c
--- a/src/imap/cmd-expunge.c Wed Jun 11 15:43:12 2008 +0300
+++ b/src/imap/cmd-expunge.c Wed Jun 11 15:44:35 2008 +0300
@@ -19,22 +19,6 @@ static bool cmd_expunge_callback(struct
return TRUE;
}
-static bool cmd_expunge_callback_qresync(struct client_command_context *cmd)
-{
- struct mailbox_status status;
-
- if (!cmd->client->sync_seen_expunges)
- client_send_tagline(cmd, "OK Expunge completed.");
- else {
- mailbox_get_status(cmd->client->mailbox,
- STATUS_HIGHESTMODSEQ, &status);
- client_send_tagline(cmd, t_strdup_printf(
- "OK [HIGHESTMODSEQ %llu] Expunge completed.",
- (unsigned long long)status.highest_modseq));
- }
- return TRUE;
-}
-
static bool cmd_expunge_finish(struct client_command_context *cmd,
struct mail_search_args *search_args)
{
@@ -52,9 +36,8 @@ static bool cmd_expunge_finish(struct cl
client->sync_seen_deletes = FALSE;
client->sync_seen_expunges = FALSE;
if ((client->enabled_features & MAILBOX_FEATURE_QRESYNC) != 0) {
- return cmd_sync_callback(cmd, MAILBOX_SYNC_FLAG_EXPUNGE,
- IMAP_SYNC_FLAG_SAFE,
- cmd_expunge_callback_qresync);
+ return cmd_sync(cmd, MAILBOX_SYNC_FLAG_EXPUNGE,
+ IMAP_SYNC_FLAG_SAFE, "OK Expunge completed.");
} else {
return cmd_sync_callback(cmd, MAILBOX_SYNC_FLAG_EXPUNGE,
IMAP_SYNC_FLAG_SAFE,
diff -r ea6727a1220e -r ffaf1ea49704 src/imap/cmd-idle.c
--- a/src/imap/cmd-idle.c Wed Jun 11 15:43:12 2008 +0300
+++ b/src/imap/cmd-idle.c Wed Jun 11 15:44:35 2008 +0300
@@ -37,7 +37,7 @@ idle_finish(struct cmd_idle_context *ctx
if (ctx->sync_ctx != NULL) {
/* we're here only in connection failure cases */
- (void)imap_sync_deinit(ctx->sync_ctx);
+ (void)imap_sync_deinit(ctx->sync_ctx, ctx->cmd);
}
o_stream_cork(client->output);
@@ -157,7 +157,7 @@ static bool cmd_idle_continue(struct cli
return FALSE;
}
- if (imap_sync_deinit(ctx->sync_ctx) < 0) {
+ if (imap_sync_deinit(ctx->sync_ctx, ctx->cmd) < 0) {
client_send_untagged_storage_error(client,
mailbox_get_storage(client->mailbox));
mailbox_notify_changes_stop(client->mailbox);
diff -r ea6727a1220e -r ffaf1ea49704 src/imap/imap-fetch.c
--- a/src/imap/imap-fetch.c Wed Jun 11 15:43:12 2008 +0300
+++ b/src/imap/imap-fetch.c Wed Jun 11 15:44:35 2008 +0300
@@ -740,8 +740,13 @@ static int fetch_modseq(struct imap_fetc
static int fetch_modseq(struct imap_fetch_context *ctx, struct mail *mail,
void *context ATTR_UNUSED)
{
+ uint64_t modseq;
+
+ modseq = mail_get_modseq(mail);
+ if (ctx->client->highest_fetch_modseq < modseq)
+ ctx->client->highest_fetch_modseq = modseq;
str_printfa(ctx->cur_str, "MODSEQ %llu ",
- (unsigned long long)mail_get_modseq(mail));
+ (unsigned long long)modseq);
return 1;
}
@@ -752,7 +757,6 @@ fetch_modseq_init(struct imap_fetch_cont
client_enable(ctx->client, MAILBOX_FEATURE_CONDSTORE);
imap_fetch_add_handler(ctx, TRUE, FALSE, name, NULL,
fetch_modseq, NULL);
- ctx->client->modseqs_sent_since_sync = TRUE;
return TRUE;
}
diff -r ea6727a1220e -r ffaf1ea49704 src/imap/imap-sync.c
--- a/src/imap/imap-sync.c Wed Jun 11 15:43:12 2008 +0300
+++ b/src/imap/imap-sync.c Wed Jun 11 15:44:35 2008 +0300
@@ -158,7 +158,54 @@ imap_sync_init(struct client *client, st
return ctx;
}
-int imap_sync_deinit(struct imap_sync_context *ctx)
+static void
+imap_sync_send_highestmodseq(struct imap_sync_context *ctx,
+ const struct mailbox_status *status,
+ struct client_command_context *sync_cmd)
+{
+ struct client *client = ctx->client;
+ uint64_t send_modseq = 0;
+
+ if (status->sync_delayed_expunges &&
+ client->highest_fetch_modseq > client->sync_last_full_modseq) {
+ /* if client updates highest-modseq using returned MODSEQs
+ it loses expunges. try to avoid this by sending it a lower
+ pre-expunge HIGHESTMODSEQ reply. */
+ send_modseq = client->sync_last_full_modseq;
+ } else if (!status->sync_delayed_expunges &&
+ status->highest_modseq > client->sync_last_full_modseq &&
+ status->highest_modseq > client->highest_fetch_modseq) {
+ /* we've probably send some VANISHED or EXISTS replies which
+ increased the highest-modseq. notify the client about
+ this. */
+ send_modseq = status->highest_modseq;
+ }
+
+ if (send_modseq == 0) {
+ /* no sending */
+ } else if (strncmp(sync_cmd->sync->tagline, "OK ", 3) == 0 &&
+ sync_cmd->sync->tagline[3] != '[') {
+ /* modify the tagged reply directly */
+ sync_cmd->sync->tagline = p_strdup_printf(sync_cmd->pool,
+ "OK [HIGHESTMODSEQ %llu] %s",
+ (unsigned long long)send_modseq,
+ sync_cmd->sync->tagline + 3);
+ } else {
+ /* send an untagged OK reply */
+ client_send_line(client, t_strdup_printf(
+ "* OK [HIGHESTMODSEQ %llu]",
+ (unsigned long long)send_modseq));
+ }
+
+ if (!status->sync_delayed_expunges) {
+ /* no delayed expunges, remember this for future */
+ client->sync_last_full_modseq = status->highest_modseq;
+ }
+ client->highest_fetch_modseq = 0;
+}
+
+int imap_sync_deinit(struct imap_sync_context *ctx,
+ struct client_command_context *sync_cmd)
{
struct client *client = ctx->client;
struct mailbox_status status;
@@ -178,19 +225,6 @@ int imap_sync_deinit(struct imap_sync_co
return -1;
}
- if (!status.sync_delayed_expunges || status.highest_modseq == 0)
- client->sync_last_full_modseq = status.highest_modseq;
- else if (client->modseqs_sent_since_sync &&
- (client->enabled_features & MAILBOX_FEATURE_QRESYNC) != 0) {
- /* if client updates highest-modseq using returned MODSEQs
- it loses expunges. try to avoid this by sending it a lower
- pre-expunge HIGHESTMODSEQ reply. */
- client_send_line(client, t_strdup_printf(
- "* OK [HIGHESTMODSEQ %llu]",
- (unsigned long long)client->sync_last_full_modseq));
- }
- client->modseqs_sent_since_sync = FALSE;
-
ret = mailbox_transaction_commit(&ctx->t);
if (status.uidvalidity != client->uidvalidity) {
@@ -217,6 +251,9 @@ int imap_sync_deinit(struct imap_sync_co
now it contains added/removed messages. */
imap_sync_send_search_updates(ctx);
+ if ((client->enabled_features & MAILBOX_FEATURE_QRESYNC) != 0)
+ imap_sync_send_highestmodseq(ctx, &status, sync_cmd);
+
if (array_is_created(&ctx->search_removes)) {
array_free(&ctx->search_removes);
array_free(&ctx->search_adds);
@@ -225,6 +262,16 @@ int imap_sync_deinit(struct imap_sync_co
array_free(&ctx->tmp_keywords);
i_free(ctx);
return ret;
+}
+
+static void imap_sync_add_modseq(struct imap_sync_context *ctx, string_t *str)
+{
+ uint64_t modseq;
+
+ modseq = mail_get_modseq(ctx->mail);
+ if (ctx->client->highest_fetch_modseq < modseq)
+ ctx->client->highest_fetch_modseq = modseq;
+ str_printfa(str, "MODSEQ %llu", (unsigned long long)modseq);
}
static int imap_sync_send_flags(struct imap_sync_context *ctx, string_t *str)
@@ -246,9 +293,8 @@ static int imap_sync_send_flags(struct i
str_printfa(str, "UID %u ", ctx->mail->uid);
if ((mailbox_get_enabled_features(ctx->box) &
MAILBOX_FEATURE_CONDSTORE) != 0) {
- ctx->client->modseqs_sent_since_sync = TRUE;
- str_printfa(str, "MODSEQ %llu ",
- (unsigned long long)mail_get_modseq(ctx->mail));
+ imap_sync_add_modseq(ctx, str);
+ str_append_c(str, ' ');
}
str_append(str, "FLAGS (");
imap_write_flags(str, flags, keywords);
@@ -264,9 +310,8 @@ static int imap_sync_send_modseq(struct
str_printfa(str, "* %u FETCH (", ctx->seq);
if (ctx->imap_flags & IMAP_SYNC_FLAG_SEND_UID)
str_printfa(str, "UID %u ", ctx->mail->uid);
- str_printfa(str, "MODSEQ %llu)",
- (unsigned long long)mail_get_modseq(ctx->mail));
- ctx->client->modseqs_sent_since_sync = TRUE;
+ imap_sync_add_modseq(ctx, str);
+ str_append_c(str, ')');
return client_send_line(ctx->client, str_c(str));
}
@@ -446,7 +491,7 @@ static bool cmd_sync_continue(struct cli
ctx->failed = TRUE;
client->syncing = FALSE;
- if (imap_sync_deinit(ctx) < 0) {
+ if (imap_sync_deinit(ctx, sync_cmd) < 0) {
client_send_untagged_storage_error(client,
mailbox_get_storage(client->mailbox));
}
diff -r ea6727a1220e -r ffaf1ea49704 src/imap/imap-sync.h
--- a/src/imap/imap-sync.h Wed Jun 11 15:43:12 2008 +0300
+++ b/src/imap/imap-sync.h Wed Jun 11 15:44:35 2008 +0300
@@ -13,7 +13,8 @@ struct imap_sync_context *
struct imap_sync_context *
imap_sync_init(struct client *client, struct mailbox *box,
enum imap_sync_flags imap_flags, enum mailbox_sync_flags flags);
-int imap_sync_deinit(struct imap_sync_context *ctx);
+int imap_sync_deinit(struct imap_sync_context *ctx,
+ struct client_command_context *sync_cmd);
int imap_sync_more(struct imap_sync_context *ctx);
bool cmd_sync(struct client_command_context *cmd, enum mailbox_sync_flags flags,
More information about the dovecot-cvs
mailing list