dovecot-2.1: imapc: Don't crash if a newly seen uncommitted mess...
dovecot at dovecot.org
dovecot at dovecot.org
Wed Sep 7 10:01:47 EEST 2011
details: http://hg.dovecot.org/dovecot-2.1/rev/3ae5d7e0a4b4
changeset: 13414:3ae5d7e0a4b4
user: Timo Sirainen <tss at iki.fi>
date: Wed Sep 07 10:01:36 2011 +0300
description:
imapc: Don't crash if a newly seen uncommitted message is expunged.
diffstat:
src/lib-storage/index/imapc/imapc-mailbox.c | 42 ++++++++++++++++++++++++++--
src/lib-storage/index/imapc/imapc-storage.c | 1 +
src/lib-storage/index/imapc/imapc-storage.h | 1 +
src/lib-storage/index/imapc/imapc-sync.c | 7 ++++
4 files changed, 48 insertions(+), 3 deletions(-)
diffs (113 lines):
diff -r 3828fa3b8fd4 -r 3ae5d7e0a4b4 src/lib-storage/index/imapc/imapc-mailbox.c
--- a/src/lib-storage/index/imapc/imapc-mailbox.c Wed Sep 07 09:40:16 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-mailbox.c Wed Sep 07 10:01:36 2011 +0300
@@ -46,6 +46,27 @@
mail_index_transaction_open_updated_view(mbox->delayed_sync_trans);
}
+static int imapc_mailbox_commit_delayed_expunges(struct imapc_mailbox *mbox)
+{
+ struct mail_index_view *view = imapc_mailbox_get_sync_view(mbox);
+ struct mail_index_transaction *trans;
+ const uint32_t *uidp;
+ uint32_t lseq;
+ int ret;
+
+ trans = mail_index_transaction_begin(view,
+ MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
+ array_foreach(&mbox->delayed_expunged_uids, uidp) {
+ if (mail_index_lookup_seq(view, *uidp, &lseq))
+ mail_index_expunge(trans, lseq);
+ }
+ array_clear(&mbox->delayed_expunged_uids);
+ ret = mail_index_transaction_commit(&trans);
+ if (ret < 0)
+ mail_storage_set_index_error(&mbox->box);
+ return ret;
+}
+
int imapc_mailbox_commit_delayed_trans(struct imapc_mailbox *mbox,
bool *changes_r)
{
@@ -64,6 +85,13 @@
}
if (mbox->sync_view != NULL)
mail_index_view_close(&mbox->sync_view);
+
+ if (array_count(&mbox->delayed_expunged_uids) > 0) {
+ /* delayed expunges - commit them now in a separate
+ transaction */
+ if (imapc_mailbox_commit_delayed_expunges(mbox) < 0)
+ ret = -1;
+ }
return ret;
}
@@ -289,10 +317,18 @@
imapc_msgmap_expunge(msgmap, rseq);
imapc_mailbox_init_delayed_trans(mbox);
- if (!mail_index_lookup_seq(mbox->delayed_sync_view, uid, &lseq)) {
+ if (mail_index_lookup_seq(mbox->sync_view, uid, &lseq))
+ mail_index_expunge(mbox->delayed_sync_trans, lseq);
+ else if (mail_index_lookup_seq(mbox->delayed_sync_view, uid, &lseq)) {
+ /* this message exists only in this transaction. lib-index
+ can't currently handle expunging anything except the last
+ appended message in a transaction, and fixing it would be
+ quite a lot of trouble. so instead we'll just delay doing
+ this expunge until after the current transaction has been
+ committed. */
+ array_append(&mbox->delayed_expunged_uids, &uid, 1);
+ } else {
/* already expunged by another session */
- } else {
- mail_index_expunge(mbox->delayed_sync_trans, lseq);
}
imapc_mailbox_idle_notify(mbox);
}
diff -r 3828fa3b8fd4 -r 3ae5d7e0a4b4 src/lib-storage/index/imapc/imapc-storage.c
--- a/src/lib-storage/index/imapc/imapc-storage.c Wed Sep 07 09:40:16 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-storage.c Wed Sep 07 10:01:36 2011 +0300
@@ -305,6 +305,7 @@
p_array_init(&mbox->resp_text_callbacks, pool, 16);
p_array_init(&mbox->fetch_mails, pool, 16);
p_array_init(&mbox->permanent_keywords, pool, 32);
+ p_array_init(&mbox->delayed_expunged_uids, pool, 16);
imapc_mailbox_register_callbacks(mbox);
return &mbox->box;
}
diff -r 3828fa3b8fd4 -r 3ae5d7e0a4b4 src/lib-storage/index/imapc/imapc-storage.h
--- a/src/lib-storage/index/imapc/imapc-storage.h Wed Sep 07 09:40:16 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-storage.h Wed Sep 07 10:01:36 2011 +0300
@@ -57,6 +57,7 @@
enum mail_flags permanent_flags;
ARRAY_TYPE(keywords) permanent_keywords;
+ ARRAY_TYPE(uint32_t) delayed_expunged_uids;
uint32_t sync_uid_validity;
uint32_t sync_uid_next;
uint32_t sync_fetch_first_uid;
diff -r 3828fa3b8fd4 -r 3ae5d7e0a4b4 src/lib-storage/index/imapc/imapc-sync.c
--- a/src/lib-storage/index/imapc/imapc-sync.c Wed Sep 07 09:40:16 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-sync.c Wed Sep 07 10:01:36 2011 +0300
@@ -331,6 +331,7 @@
static int imapc_sync_finish(struct imapc_sync_context **_ctx)
{
struct imapc_sync_context *ctx = *_ctx;
+ bool changes;
int ret = ctx->failed ? -1 : 0;
*_ctx = NULL;
@@ -343,6 +344,12 @@
mail_index_sync_rollback(&ctx->index_sync_ctx);
}
ctx->mbox->syncing = FALSE;
+
+ /* this is done simply to commit delayed expunges if there are any
+ (has to be done after sync is committed) */
+ if (imapc_mailbox_commit_delayed_trans(ctx->mbox, &changes) < 0)
+ ctx->failed = TRUE;
+
i_free(ctx);
return ret;
}
More information about the dovecot-cvs
mailing list