dovecot-1.2: maildir: Allow opening mailbox and expunging messag...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Dec 15 10:58:06 EET 2008
details: http://hg.dovecot.org/dovecot-1.2/rev/c438437b709a
changeset: 8554:c438437b709a
user: Timo Sirainen <tss at iki.fi>
date: Mon Dec 15 10:58:02 2008 +0200
description:
maildir: Allow opening mailbox and expunging messages when uidlist couldn't be locked (e.g. out of quota).
diffstat:
5 files changed, 80 insertions(+), 33 deletions(-)
src/lib-storage/index/maildir/maildir-keywords.c | 9 +---
src/lib-storage/index/maildir/maildir-sync-index.c | 26 +++++++------
src/lib-storage/index/maildir/maildir-sync.c | 37 ++++++++++++++++---
src/lib-storage/index/maildir/maildir-uidlist.c | 38 +++++++++++++++-----
src/lib-storage/index/maildir/maildir-uidlist.h | 3 +
diffs (260 lines):
diff -r e8a8383895df -r c438437b709a src/lib-storage/index/maildir/maildir-keywords.c
--- a/src/lib-storage/index/maildir/maildir-keywords.c Sun Dec 14 08:36:10 2008 +0200
+++ b/src/lib-storage/index/maildir/maildir-keywords.c Mon Dec 15 10:58:02 2008 +0200
@@ -194,9 +194,6 @@ maildir_keywords_lookup(struct maildir_k
{
void *p;
- i_assert(mk->mbox == NULL ||
- maildir_uidlist_is_locked(mk->mbox->uidlist));
-
p = hash_lookup(mk->hash, name);
if (p == NULL) {
if (mk->synced)
@@ -256,6 +253,9 @@ maildir_keywords_lookup_or_create(struct
if (i == count && count >= MAILDIR_MAX_KEYWORDS)
return -1;
+ if (!maildir_uidlist_is_locked(mk->mbox->uidlist))
+ return -1;
+
maildir_keywords_create(mk, name, i);
return i;
}
@@ -265,9 +265,6 @@ maildir_keywords_idx(struct maildir_keyw
{
const char *const *keywords;
unsigned int count;
-
- i_assert(mk->mbox == NULL ||
- maildir_uidlist_is_locked(mk->mbox->uidlist));
keywords = array_get(&mk->list, &count);
if (idx >= count) {
diff -r e8a8383895df -r c438437b709a src/lib-storage/index/maildir/maildir-sync-index.c
--- a/src/lib-storage/index/maildir/maildir-sync-index.c Sun Dec 14 08:36:10 2008 +0200
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c Mon Dec 15 10:58:02 2008 +0200
@@ -105,15 +105,15 @@ static int maildir_sync_flags(struct mai
return -1;
}
-static void maildir_handle_uid_insertion(struct maildir_index_sync_context *ctx,
- enum maildir_uidlist_rec_flag uflags,
- const char *filename, uint32_t uid)
+static int maildir_handle_uid_insertion(struct maildir_index_sync_context *ctx,
+ enum maildir_uidlist_rec_flag uflags,
+ const char *filename, uint32_t uid)
{
int ret;
if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) {
/* partial syncing */
- return;
+ return 0;
}
/* most likely a race condition: we read the maildir, then someone else
@@ -124,7 +124,7 @@ static void maildir_handle_uid_insertion
ctx->mbox->maildir_hdr.cur_check_time = 0;
maildir_uidlist_add_flags(ctx->mbox->uidlist, filename,
MAILDIR_UIDLIST_REC_FLAG_RACING);
- return;
+ return 0;
}
if (ctx->uidlist_sync_ctx == NULL) {
@@ -132,7 +132,8 @@ static void maildir_handle_uid_insertion
MAILDIR_UIDLIST_SYNC_PARTIAL |
MAILDIR_UIDLIST_SYNC_KEEP_STATE,
&ctx->uidlist_sync_ctx);
- i_assert(ret > 0);
+ if (ret <= 0)
+ return -1;
}
uflags &= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR;
@@ -146,6 +147,7 @@ static void maildir_handle_uid_insertion
i_warning("Maildir %s: Expunged message reappeared, giving a new UID "
"(old uid=%u, file=%s)", ctx->mbox->path, uid, filename);
+ return 0;
}
int maildir_sync_index_begin(struct maildir_mailbox *mbox,
@@ -283,7 +285,6 @@ int maildir_sync_index(struct maildir_in
bool expunged, full_rescan = FALSE;
i_assert(!mbox->syncing_commit);
- i_assert(maildir_uidlist_is_locked(mbox->uidlist));
first_uid = 1;
hdr = mail_index_get_header(view);
@@ -328,8 +329,10 @@ int maildir_sync_index(struct maildir_in
if (seq > hdr->messages_count) {
if (uid < hdr_next_uid) {
- maildir_handle_uid_insertion(ctx, uflags,
- filename, uid);
+ if (maildir_handle_uid_insertion(ctx, uflags,
+ filename,
+ uid) < 0)
+ ret = -1;
seq--;
continue;
}
@@ -367,8 +370,9 @@ int maildir_sync_index(struct maildir_in
}
if (uid < rec->uid) {
- maildir_handle_uid_insertion(ctx, uflags,
- filename, uid);
+ if (maildir_handle_uid_insertion(ctx, uflags,
+ filename, uid) < 0)
+ ret = -1;
seq--;
continue;
}
diff -r e8a8383895df -r c438437b709a src/lib-storage/index/maildir/maildir-sync.c
--- a/src/lib-storage/index/maildir/maildir-sync.c Sun Dec 14 08:36:10 2008 +0200
+++ b/src/lib-storage/index/maildir/maildir-sync.c Mon Dec 15 10:58:02 2008 +0200
@@ -670,7 +670,7 @@ static int maildir_sync_context(struct m
{
enum maildir_uidlist_sync_flags sync_flags;
enum maildir_uidlist_rec_flag flags;
- bool new_changed, cur_changed;
+ bool new_changed, cur_changed, lock_failure;
int ret;
*lost_files_r = FALSE;
@@ -741,15 +741,39 @@ static int maildir_sync_context(struct m
}
ret = maildir_uidlist_sync_init(ctx->mbox->uidlist, sync_flags,
&ctx->uidlist_sync_ctx);
+ lock_failure = ret <= 0;
if (ret <= 0) {
- /* failure / timeout */
- return ret;
+ struct mail_storage *storage = ctx->mbox->ibox.box.storage;
+
+ if (ret == 0) {
+ /* timeout */
+ return 0;
+ }
+ /* locking failed. sync anyway without locking so that it's
+ possible to expunge messages when out of quota. */
+ if (forced) {
+ /* we're already forcing a sync, we're trying to find
+ a message that was probably already expunged, don't
+ loop for a long time trying to find it. */
+ return -1;
+ }
+ ret = maildir_uidlist_sync_init(ctx->mbox->uidlist, sync_flags |
+ MAILDIR_UIDLIST_SYNC_NOLOCK,
+ &ctx->uidlist_sync_ctx);
+ i_assert(ret > 0);
+
+ if (storage->callbacks->notify_no != NULL) {
+ storage->callbacks->notify_no(&ctx->mbox->ibox.box,
+ "Internal mailbox synchronization failure, "
+ "showing only old mails.",
+ storage->callback_context);
+ }
}
ctx->locked = maildir_uidlist_is_locked(ctx->mbox->uidlist);
if (!ctx->locked)
ctx->partial = TRUE;
- if (!ctx->mbox->syncing_commit && ctx->locked) {
+ if (!ctx->mbox->syncing_commit && (ctx->locked || lock_failure)) {
if (maildir_sync_index_begin(ctx->mbox, ctx,
&ctx->index_sync_ctx) < 0)
return -1;
@@ -787,7 +811,7 @@ static int maildir_sync_context(struct m
ctx->mbox->maildir_hdr.cur_mtime = 0;
}
- if (!ctx->mbox->syncing_commit && ctx->locked) {
+ if (ctx->index_sync_ctx != NULL) {
/* NOTE: index syncing here might cause a re-sync due to
files getting lost, so this function might be called
re-entrantly. */
@@ -801,7 +825,8 @@ static int maildir_sync_context(struct m
if (ret == 0)
*lost_files_r = TRUE;
- i_assert(maildir_uidlist_is_locked(ctx->mbox->uidlist));
+ i_assert(maildir_uidlist_is_locked(ctx->mbox->uidlist) ||
+ lock_failure);
}
if (find_uid != NULL && *find_uid != 0) {
diff -r e8a8383895df -r c438437b709a src/lib-storage/index/maildir/maildir-uidlist.c
--- a/src/lib-storage/index/maildir/maildir-uidlist.c Sun Dec 14 08:36:10 2008 +0200
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c Mon Dec 15 10:58:02 2008 +0200
@@ -1287,13 +1287,20 @@ static void maildir_uidlist_mark_all(str
}
}
-int maildir_uidlist_sync_init(struct maildir_uidlist *uidlist,
- enum maildir_uidlist_sync_flags sync_flags,
- struct maildir_uidlist_sync_ctx **sync_ctx_r)
-{
- struct maildir_uidlist_sync_ctx *ctx;
- bool nonblock, refresh, locked;
+static int maildir_uidlist_sync_lock(struct maildir_uidlist *uidlist,
+ enum maildir_uidlist_sync_flags sync_flags,
+ bool *locked_r)
+{
+ bool nonblock, refresh;
int ret;
+
+ *locked_r = FALSE;
+
+ if ((sync_flags & MAILDIR_UIDLIST_SYNC_NOLOCK) != 0) {
+ if (maildir_uidlist_refresh(uidlist) < 0)
+ return -1;
+ return 1;
+ }
nonblock = (sync_flags & MAILDIR_UIDLIST_SYNC_TRYLOCK) != 0;
refresh = (sync_flags & MAILDIR_UIDLIST_SYNC_NOREFRESH) == 0;
@@ -1309,10 +1316,23 @@ int maildir_uidlist_sync_init(struct mai
/* forcing the sync anyway */
if (maildir_uidlist_refresh(uidlist) < 0)
return -1;
- locked = FALSE;
} else {
- locked = TRUE;
- }
+ *locked_r = TRUE;
+ }
+ return 1;
+}
+
+int maildir_uidlist_sync_init(struct maildir_uidlist *uidlist,
+ enum maildir_uidlist_sync_flags sync_flags,
+ struct maildir_uidlist_sync_ctx **sync_ctx_r)
+{
+ struct maildir_uidlist_sync_ctx *ctx;
+ bool locked;
+ int ret;
+
+ ret = maildir_uidlist_sync_lock(uidlist, sync_flags, &locked);
+ if (ret <= 0)
+ return ret;
*sync_ctx_r = ctx = i_new(struct maildir_uidlist_sync_ctx, 1);
ctx->uidlist = uidlist;
diff -r e8a8383895df -r c438437b709a src/lib-storage/index/maildir/maildir-uidlist.h
--- a/src/lib-storage/index/maildir/maildir-uidlist.h Sun Dec 14 08:36:10 2008 +0200
+++ b/src/lib-storage/index/maildir/maildir-uidlist.h Mon Dec 15 10:58:02 2008 +0200
@@ -15,7 +15,8 @@ enum maildir_uidlist_sync_flags {
MAILDIR_UIDLIST_SYNC_KEEP_STATE = 0x02,
MAILDIR_UIDLIST_SYNC_FORCE = 0x04,
MAILDIR_UIDLIST_SYNC_TRYLOCK = 0x08,
- MAILDIR_UIDLIST_SYNC_NOREFRESH = 0x10
+ MAILDIR_UIDLIST_SYNC_NOREFRESH = 0x10,
+ MAILDIR_UIDLIST_SYNC_NOLOCK = 0x20
};
enum maildir_uidlist_rec_flag {
More information about the dovecot-cvs
mailing list