changeset 2053:66f5d28f9b27 HEAD

race condition fixes
author Timo Sirainen <tss@iki.fi>
date Mon, 24 May 2004 05:47:23 +0300
parents 9d1ce6135d4f
children 02e066d4df9a
files src/lib-storage/index/maildir/maildir-sync.c src/lib-storage/index/maildir/maildir-uidlist.c src/lib-storage/index/maildir/maildir-uidlist.h
diffstat 3 files changed, 53 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/maildir/maildir-sync.c	Mon May 24 05:30:10 2004 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync.c	Mon May 24 05:47:23 2004 +0300
@@ -629,15 +629,33 @@
 
 		if (seq > hdr->messages_count) {
 			if (uid < hdr->next_uid) {
-				/* message not in index, but next_uid header
-				   is updated? shouldn't really happen.. */
-				mail_storage_set_critical(ibox->box.storage,
-					"Maildir sync: UID < next_uid "
-					"(%u < %u, file = %s)",
-					uid, hdr->next_uid, filename);
-				mail_index_mark_corrupted(ibox->index);
-				ret = -1;
-				break;
+				/* most likely a race condition: we read the
+				   maildir, then someone else expunged messages
+				   and committed changes to index. so, this
+				   message shouldn't actually exist. mark it
+				   racy and check in next sync.
+
+				   the difference between this and the later
+				   check is that this one happens when messages
+				   are expunged from the end */
+				if ((uflags &
+				     MAILDIR_UIDLIST_REC_FLAG_RACING) != 0) {
+					mail_storage_set_critical(
+						ibox->box.storage,
+						"Maildir sync: UID < next_uid "
+						"(%u < %u, file = %s)",
+						uid, hdr->next_uid, filename);
+					mail_index_mark_corrupted(ibox->index);
+					ret = -1;
+					break;
+				}
+				ibox->dirty_cur_time = ioloop_time;
+				maildir_uidlist_add_flags(ibox->uidlist,
+					filename,
+					MAILDIR_UIDLIST_REC_FLAG_RACING);
+
+				seq--;
+				continue;
 			}
 
 			mail_index_append(trans, uid, &seq);
@@ -661,20 +679,9 @@
 			/* most likely a race condition: we read the
 			   maildir, then someone else expunged messages and
 			   committed changes to index. so, this message
-			   shouldn't actually exist. check to be sure.
-
-			   FIXME: we could avoid this stat() and just mark
-			   this check in the uidlist and check it at next
-			   sync.. */
-			struct stat st;
-			const char *str;
-
-			t_push();
-			str = t_strdup_printf("%s/%s",
-				(uflags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) ?
-				ctx->new_dir : ctx->cur_dir, filename);
-			if (stat(str, &st) == 0) {
-				t_pop();
+			   shouldn't actually exist. mark it racy and check
+			   in next sync. */
+			if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RACING) != 0) {
 				mail_storage_set_critical(ibox->box.storage,
 					"Maildir sync: UID inserted in the "
 					"middle of mailbox "
@@ -683,8 +690,11 @@
 				mail_index_mark_corrupted(ibox->index);
 				ret = -1;
 				break;
-			}
-			t_pop();
+			 }
+
+			ibox->dirty_cur_time = ioloop_time;
+			maildir_uidlist_add_flags(ibox->uidlist, filename,
+				MAILDIR_UIDLIST_REC_FLAG_RACING);
 
 			seq--;
 			continue;
--- a/src/lib-storage/index/maildir/maildir-uidlist.c	Mon May 24 05:30:10 2004 +0300
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c	Mon May 24 05:47:23 2004 +0300
@@ -848,6 +848,18 @@
 	return ret;
 }
 
+void maildir_uidlist_add_flags(struct maildir_uidlist *uidlist,
+			       const char *filename,
+			       enum maildir_uidlist_rec_flag flags)
+{
+	struct maildir_uidlist_rec *rec;
+
+	rec = hash_lookup(uidlist->files, filename);
+	i_assert(rec != NULL);
+
+	rec->flags |= flags;
+}
+
 struct maildir_uidlist_iter_ctx *
 maildir_uidlist_iter_init(struct maildir_uidlist *uidlist)
 {
--- a/src/lib-storage/index/maildir/maildir-uidlist.h	Mon May 24 05:30:10 2004 +0300
+++ b/src/lib-storage/index/maildir/maildir-uidlist.h	Mon May 24 05:47:23 2004 +0300
@@ -7,7 +7,8 @@
 	MAILDIR_UIDLIST_REC_FLAG_NEW_DIR	= 0x01,
 	MAILDIR_UIDLIST_REC_FLAG_MOVED		= 0x02,
 	MAILDIR_UIDLIST_REC_FLAG_RECENT		= 0x04,
-	MAILDIR_UIDLIST_REC_FLAG_NONSYNCED	= 0x08
+	MAILDIR_UIDLIST_REC_FLAG_NONSYNCED	= 0x08,
+	MAILDIR_UIDLIST_REC_FLAG_RACING		= 0x10
 };
 
 int maildir_uidlist_try_lock(struct maildir_uidlist *uidlist);
@@ -47,6 +48,10 @@
 int maildir_uidlist_sync_finish(struct maildir_uidlist_sync_ctx *ctx);
 int maildir_uidlist_sync_deinit(struct maildir_uidlist_sync_ctx *ctx);
 
+void maildir_uidlist_add_flags(struct maildir_uidlist *uidlist,
+			       const char *filename,
+			       enum maildir_uidlist_rec_flag flags);
+
 /* List all maildir files. */
 struct maildir_uidlist_iter_ctx *
 maildir_uidlist_iter_init(struct maildir_uidlist *uidlist);