Mercurial > dovecot > original-hg > dovecot-1.2
changeset 7815:2d62129a709b HEAD
QRESYNC: If MODSEQs were returned in FETCH replies but there are pending
expunges, send a low enough HIGHESTMODSEQ reply to make sure the client will
later see the expunges.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 11 Jun 2008 14:39:52 +0300 |
parents | 1ae3d4a5057b |
children | ea6727a1220e |
files | src/imap/client.h src/imap/cmd-select.c src/imap/imap-fetch.c src/imap/imap-sync.c src/lib-index/mail-index-view-sync.c src/lib-index/mail-index.h src/lib-storage/index/index-sync.c src/lib-storage/mail-storage.h |
diffstat | 8 files changed, 44 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/client.h Wed Jun 11 14:37:49 2008 +0300 +++ b/src/imap/client.h Wed Jun 11 14:39:52 2008 +0300 @@ -93,6 +93,8 @@ struct client_command_context *command_queue; unsigned int command_queue_size; + uint64_t sync_last_full_modseq; + /* SEARCHRES extension: Last saved SEARCH result */ ARRAY_TYPE(seq_range) search_saved_uidset; /* SEARCH=CONTEXT extension: Searches that get updated */ @@ -113,6 +115,7 @@ unsigned int changing_mailbox:1; unsigned int input_skip_line:1; /* skip all the data until we've found a new line */ + unsigned int modseqs_sent_since_sync:1; }; /* Create new client with specified input/output handles. socket specifies
--- a/src/imap/cmd-select.c Wed Jun 11 14:37:49 2008 +0300 +++ b/src/imap/cmd-select.c Wed Jun 11 14:39:52 2008 +0300 @@ -313,6 +313,7 @@ client_send_line(client, t_strdup_printf("* OK [HIGHESTMODSEQ %llu]", (unsigned long long)status.highest_modseq)); + client->sync_last_full_modseq = status.highest_modseq; } if (ctx->qresync_uid_validity == status.uidvalidity) {
--- a/src/imap/imap-fetch.c Wed Jun 11 14:37:49 2008 +0300 +++ b/src/imap/imap-fetch.c Wed Jun 11 14:39:52 2008 +0300 @@ -752,6 +752,7 @@ 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; }
--- a/src/imap/imap-sync.c Wed Jun 11 14:37:49 2008 +0300 +++ b/src/imap/imap-sync.c Wed Jun 11 14:39:52 2008 +0300 @@ -160,6 +160,7 @@ int imap_sync_deinit(struct imap_sync_context *ctx) { + struct client *client = ctx->client; struct mailbox_status status; int ret; @@ -168,7 +169,8 @@ array_free(&ctx->expunges); if (mailbox_sync_deinit(&ctx->sync_ctx, STATUS_UIDVALIDITY | - STATUS_MESSAGES | STATUS_RECENT, &status) < 0 || + STATUS_MESSAGES | STATUS_RECENT | + STATUS_HIGHESTMODSEQ, &status) < 0 || ctx->failed) { mailbox_transaction_rollback(&ctx->t); array_free(&ctx->tmp_keywords); @@ -176,25 +178,38 @@ 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 != ctx->client->uidvalidity) { + if (status.uidvalidity != client->uidvalidity) { /* most clients would get confused by this. disconnect them. */ - client_disconnect_with_error(ctx->client, + client_disconnect_with_error(client, "Mailbox UIDVALIDITY changed"); } if (!ctx->no_newmail) { if (status.messages < ctx->messages_count) i_panic("Message count decreased"); - ctx->client->messages_count = status.messages; + client->messages_count = status.messages; if (status.messages != ctx->messages_count) { - client_send_line(ctx->client, + client_send_line(client, t_strdup_printf("* %u EXISTS", status.messages)); } - if (status.recent != ctx->client->recent_count && + if (status.recent != client->recent_count && !ctx->no_newmail) { - ctx->client->recent_count = status.recent; - client_send_line(ctx->client, + client->recent_count = status.recent; + client_send_line(client, t_strdup_printf("* %u RECENT", status.recent)); } } @@ -231,6 +246,7 @@ 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)); } @@ -250,6 +266,7 @@ 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; return client_send_line(ctx->client, str_c(str)); }
--- a/src/lib-index/mail-index-view-sync.c Wed Jun 11 14:37:49 2008 +0300 +++ b/src/lib-index/mail-index-view-sync.c Wed Jun 11 14:39:52 2008 +0300 @@ -633,7 +633,8 @@ array_delete(&view->syncs_hidden, 0, i); } -int mail_index_view_sync_commit(struct mail_index_view_sync_ctx **_ctx) +int mail_index_view_sync_commit(struct mail_index_view_sync_ctx **_ctx, + bool *delayed_expunges_r) { struct mail_index_view_sync_ctx *ctx = *_ctx; struct mail_index_view *view = ctx->view; @@ -642,6 +643,7 @@ i_assert(view->syncing); *_ctx = NULL; + *delayed_expunges_r = ctx->skipped_expunges; if ((!ctx->last_read || view->inconsistent) && (ctx->flags & MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT) == 0) {
--- a/src/lib-index/mail-index.h Wed Jun 11 14:37:49 2008 +0300 +++ b/src/lib-index/mail-index.h Wed Jun 11 14:39:52 2008 +0300 @@ -314,7 +314,8 @@ void mail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx, const ARRAY_TYPE(seq_range) **expunges_r); -int mail_index_view_sync_commit(struct mail_index_view_sync_ctx **ctx); +int mail_index_view_sync_commit(struct mail_index_view_sync_ctx **ctx, + bool *delayed_expunges_r); /* Returns the index header. */ const struct mail_index_header *
--- a/src/lib-storage/index/index-sync.c Wed Jun 11 14:37:49 2008 +0300 +++ b/src/lib-storage/index/index-sync.c Wed Jun 11 14:39:52 2008 +0300 @@ -325,6 +325,7 @@ struct mailbox_sync_rec sync_rec; const struct mail_index_header *hdr; uint32_t seq1, seq2; + bool delayed_expunges = FALSE; int ret = ctx->failed ? -1 : 0; /* finish handling expunges, so we don't break when updating @@ -332,7 +333,8 @@ while (index_mailbox_sync_next_expunge(ctx, &sync_rec) > 0) ; if (ctx->sync_ctx != NULL) { - if (mail_index_view_sync_commit(&ctx->sync_ctx) < 0) { + if (mail_index_view_sync_commit(&ctx->sync_ctx, + &delayed_expunges) < 0) { mail_storage_set_index_error(ibox); ret = -1; } @@ -354,8 +356,10 @@ } } - if (ret == 0 && status_items != 0) + if (ret == 0 && status_items != 0) { mailbox_get_status(_ctx->box, status_items, status_r); + status_r->sync_delayed_expunges = delayed_expunges; + } index_sync_search_results_update(ctx);
--- a/src/lib-storage/mail-storage.h Wed Jun 11 14:37:49 2008 +0300 +++ b/src/lib-storage/mail-storage.h Wed Jun 11 14:39:52 2008 +0300 @@ -189,6 +189,9 @@ uint64_t highest_modseq; const ARRAY_TYPE(keywords) *keywords; + + /* There are expunges that haven't been synced yet */ + unsigned int sync_delayed_expunges:1; }; struct mailbox_sync_rec {