changeset 2121:0840edf34f37 HEAD

Locking fixes. use less memory
author Timo Sirainen <tss@iki.fi>
date Mon, 14 Jun 2004 08:22:51 +0300
parents f434ecc6ef83
children db5807f350ca
files src/lib-storage/index/maildir/maildir-sync.c src/lib-storage/index/maildir/maildir-uidlist.c
diffstat 2 files changed, 32 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/maildir/maildir-sync.c	Mon Jun 14 08:16:10 2004 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync.c	Mon Jun 14 08:22:51 2004 +0300
@@ -424,9 +424,6 @@
         enum maildir_uidlist_rec_flag flags;
 	int move_new, ret = 1;
 
-	src = t_str_new(1024);
-	dest = t_str_new(1024);
-
 	dir = new_dir ? ctx->new_dir : ctx->cur_dir;
 	dirp = opendir(dir);
 	if (dirp == NULL) {
@@ -435,6 +432,10 @@
 		return -1;
 	}
 
+	t_push();
+	src = t_str_new(1024);
+	dest = t_str_new(1024);
+
 	move_new = new_dir && !mailbox_is_readonly(&ctx->ibox->box) &&
 		!ctx->ibox->keep_recent;
 	while ((dp = readdir(dirp)) != NULL) {
@@ -507,6 +508,8 @@
 		mail_storage_set_critical(storage,
 					  "closedir(%s) failed: %m", dir);
 	}
+
+	t_pop();
 	return ret < 0 ? -1 : 0;
 }
 
@@ -835,6 +838,15 @@
 	ctx->uidlist_sync_ctx =
 		maildir_uidlist_sync_init(ctx->ibox->uidlist, ctx->partial);
 
+	/* we have to lock uidlist immediately, otherwise there's race
+	   conditions with other processes who might write older maildir
+	   file list into uidlist.
+
+	   alternative would be to lock it when new files are found, but
+	   the directory scans _must_ be restarted then */
+	if (maildir_uidlist_try_lock(ctx->ibox->uidlist) < 0)
+		return -1;
+
 	if (maildir_scan_dir(ctx, TRUE) < 0)
 		return -1;
 	if (cur_changed) {
--- a/src/lib-storage/index/maildir/maildir-uidlist.c	Mon Jun 14 08:16:10 2004 +0300
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c	Mon Jun 14 08:22:51 2004 +0300
@@ -91,8 +91,12 @@
 			"file_dotlock_open(%s) failed: %m", path);
 		return -1;
 	}
+	uidlist->lock_fd = fd;
 
-	uidlist->lock_fd = fd;
+	/* our view of uidlist must be up-to-date if we plan on changing it */
+	if (maildir_uidlist_update(uidlist) < 0)
+		return -1;
+
 	return 1;
 }
 
@@ -463,8 +467,10 @@
 
 	iter = maildir_uidlist_iter_init(uidlist->ibox->uidlist);
 	while (maildir_uidlist_iter_next(iter, &uid, &flags, &filename)) {
+		/* avoid overflowing str buffer so we don't eat more memory
+		   than we need. */
 		if (str_len(str) + MAX_INT_STRLEN +
-		    strlen(filename) + 2 >= 4096) {
+		    strlen(filename) + 5 + 10 >= 4096) {
 			/* flush buffer */
 			if (write_full(uidlist->lock_fd,
 				       str_data(str), str_len(str)) < 0) {
@@ -592,6 +598,11 @@
 
 	i_assert(!ctx->synced);
 
+	if (UIDLIST_IS_LOCKED(ctx->uidlist)) {
+		ctx->synced = TRUE;
+		return 1;
+	}
+
 	if (!ctx->uidlist->initial_read) {
 		/* first time reading the uidlist,
 		   no locking yet */
@@ -612,10 +623,6 @@
 		ctx->failed = TRUE;
 		return -1;
 	}
-	if (maildir_uidlist_update(ctx->uidlist) < 0) {
-		ctx->failed = TRUE;
-		return -1;
-	}
 
 	ctx->synced = TRUE;
 	return 1;
@@ -842,8 +849,11 @@
 	if (!ctx->finished)
 		maildir_uidlist_sync_finish(ctx);
 
-	if (ctx->new_files_count != 0 && !ctx->failed && !ctx->locked)
+	if (ctx->new_files_count != 0 && !ctx->failed && !ctx->locked) {
+		t_push();
 		ret = maildir_uidlist_rewrite(ctx->uidlist);
+		t_pop();
+	}
 
 	if (ctx->partial)
 		maildir_uidlist_mark_all(ctx->uidlist, FALSE);