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