changeset 3435:6f7ce690358e HEAD

If we have rename()d more than 5 files from new/ to cur/, rescan the directory again to make sure we didn't skip any files.
author Timo Sirainen <tss@iki.fi>
date Thu, 16 Jun 2005 22:46:18 +0300
parents 3a98900070ee
children 3c51658d6846
files src/lib-storage/index/maildir/maildir-sync.c
diffstat 1 files changed, 20 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/maildir/maildir-sync.c	Thu Jun 16 22:26:46 2005 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync.c	Thu Jun 16 22:46:18 2005 +0300
@@ -188,6 +188,14 @@
 
 #define MAILDIR_FILENAME_FLAG_FOUND 128
 
+/* When rename()ing many files from new/ to cur/, it's possible that next
+   readdir() skips some files. we don't of course wish to lose them, so we
+   go and rescan the new/ directory again from beginning until no files are
+   left. This value is just an optimization to avoid checking the directory
+   twice unneededly. usually only NFS is the problem case. 1 is the safest
+   bet here, but I guess 5 will do just fine too. */
+#define MAILDIR_RENAME_RESCAN_COUNT 5
+
 struct maildir_sync_context {
         struct maildir_mailbox *mbox;
 	const char *new_dir, *cur_dir;
@@ -420,7 +428,8 @@
 	DIR *dirp;
 	string_t *src, *dest;
 	struct dirent *dp;
-        enum maildir_uidlist_rec_flag flags;
+	enum maildir_uidlist_rec_flag flags;
+	unsigned int moves = 0;
 	int move_new, ret = 1;
 
 	dir = new_dir ? ctx->new_dir : ctx->cur_dir;
@@ -466,11 +475,13 @@
 			}
 			if (rename(str_c(src), str_c(dest)) == 0) {
 				/* we moved it - it's \Recent for us */
-                                ctx->mbox->dirty_cur_time = ioloop_time;
+				moves++;
+				ctx->mbox->dirty_cur_time = ioloop_time;
 				flags |= MAILDIR_UIDLIST_REC_FLAG_MOVED |
 					MAILDIR_UIDLIST_REC_FLAG_RECENT;
 			} else if (ENOTFOUND(errno)) {
 				/* someone else moved it already */
+				moves++;
 				flags |= MAILDIR_UIDLIST_REC_FLAG_MOVED;
 			} else if (ENOSPACE(errno)) {
 				/* not enough disk space, leave here */
@@ -510,7 +521,7 @@
 	}
 
 	t_pop();
-	return ret < 0 ? -1 : 0;
+	return ret < 0 ? -1 : (moves <= MAILDIR_RENAME_RESCAN_COUNT ? 0 : 1);
 }
 
 static int maildir_sync_quick_check(struct maildir_sync_context *ctx,
@@ -937,7 +948,12 @@
 	ctx->uidlist_sync_ctx =
 		maildir_uidlist_sync_init(ctx->mbox->uidlist, ctx->partial);
 
-	if (maildir_scan_dir(ctx, TRUE) < 0)
+	while ((ret = maildir_scan_dir(ctx, TRUE)) > 0) {
+		/* rename()d at least some files, which might have caused some
+		   other files to be missed. check again (see
+		   MAILDIR_RENAME_RESCAN_COUNT). */
+	}
+	if (ret < 0)
 		return -1;
 	if (cur_changed) {
 		if (maildir_scan_dir(ctx, FALSE) < 0)