diff src/lib-storage/index/maildir/maildir-sync.c @ 4848:967de900c73a HEAD

Mailbox list indexing and related changes. Currently works only with maildir and mmap_disable=no. This allows doing STATUS to synced mailboxes without opening their index files at all.
author Timo Sirainen <tss@iki.fi>
date Sun, 26 Nov 2006 00:17:39 +0200
parents 615b7738a62f
children 24afafbfe47b
line wrap: on
line diff
--- a/src/lib-storage/index/maildir/maildir-sync.c	Sun Nov 26 00:12:11 2006 +0200
+++ b/src/lib-storage/index/maildir/maildir-sync.c	Sun Nov 26 00:17:39 2006 +0200
@@ -179,6 +179,7 @@
 #include "maildir-storage.h"
 #include "maildir-uidlist.h"
 #include "maildir-keywords.h"
+#include "maildir-sync.h"
 
 #include <stdio.h>
 #include <stddef.h>
@@ -186,8 +187,6 @@
 #include <dirent.h>
 #include <sys/stat.h>
 
-#define MAILDIR_SYNC_SECS 1
-
 #define MAILDIR_FILENAME_FLAG_FOUND 128
 
 /* When rename()ing many files from new/ to cur/, it's possible that next
@@ -774,17 +773,29 @@
 }
 
 static void
-maildir_sync_update_from_header(struct maildir_mailbox *mbox)
+maildir_sync_update_from_header(struct maildir_mailbox *mbox,
+				struct mail_index_header *hdr_r)
 {
-	uint64_t value;
+	struct mail_index_view *view;
+	const struct mail_index_header *hdr;
+
+	/* open a new view so we get the latest header */
+	view = mail_index_view_open(mbox->ibox.index);
+	hdr = mail_index_get_header(view);
 
 	/* FIXME: ugly, replace with extension header */
-	value = mail_index_get_header(mbox->ibox.view)->sync_size;
-	mbox->last_new_mtime = value & 0xffffffff;
-	mbox->last_new_sync_time = value >> 32;
+	mbox->last_new_mtime = hdr->sync_size & 0xffffffff;
+	mbox->last_dirty_flags = (hdr->sync_size >> 32) &
+		(MAILDIR_DIRTY_NEW | MAILDIR_DIRTY_CUR);
+
+	mbox->last_cur_mtime = hdr->sync_stamp;
 
-	mbox->last_cur_mtime =
-		mail_index_get_header(mbox->ibox.view)->sync_stamp;
+	if ((mbox->last_dirty_flags & MAILDIR_DIRTY_CUR) != 0 &&
+	    mbox->dirty_cur_time < mbox->last_cur_mtime)
+		mbox->dirty_cur_time = mbox->last_cur_mtime;
+
+	*hdr_r = *hdr;
+	mail_index_view_close(&view);
 }
 
 static int
@@ -793,6 +804,7 @@
 			 bool *new_changed_r, bool *cur_changed_r)
 {
 	struct index_mailbox *ibox = &mbox->ibox;
+	struct mail_index_header hdr;
 	struct stat st;
 	time_t new_mtime, cur_mtime;
 
@@ -817,7 +829,7 @@
 
 	   FIXME: For now we're using sync_size field as the new/ dir's stamp.
 	   Pretty ugly.. */
-        maildir_sync_update_from_header(mbox);
+        maildir_sync_update_from_header(mbox, &hdr);
 	if ((mbox->dirty_cur_time == 0 && cur_mtime != mbox->last_cur_mtime) ||
 	    (new_mtime != mbox->last_new_mtime)) {
 		/* check if the index has been updated.. */
@@ -826,18 +838,22 @@
 			return -1;
 		}
 
-		maildir_sync_update_from_header(mbox);
+		maildir_sync_update_from_header(mbox, &hdr);
 	}
 
 	/* If we're removing recent flags, always sync new/ directory if
 	   it has mails. */
 	if (new_mtime != mbox->last_new_mtime ||
-	    new_mtime >= mbox->last_new_sync_time - MAILDIR_SYNC_SECS ||
-	    (!ibox->keep_recent &&
-	     mail_index_get_header(ibox->view)->recent_messages_count > 0)) {
+	    ((mbox->last_dirty_flags & MAILDIR_DIRTY_NEW) != 0 &&
+	     new_mtime < ioloop_time - MAILDIR_SYNC_SECS) ||
+	    (!ibox->keep_recent && hdr.recent_messages_count > 0)) {
 		*new_changed_r = TRUE;
 		mbox->last_new_mtime = new_mtime;
-		mbox->last_new_sync_time = ioloop_time;
+
+		if (new_mtime < ioloop_time - MAILDIR_SYNC_SECS)
+			mbox->last_dirty_flags &= ~MAILDIR_DIRTY_NEW;
+		else
+			mbox->last_dirty_flags |= MAILDIR_DIRTY_NEW;
 	}
 
 	if (cur_mtime != mbox->last_cur_mtime ||
@@ -847,9 +863,13 @@
 		*cur_changed_r = TRUE;
 		mbox->last_cur_mtime = cur_mtime;
 
-		mbox->dirty_cur_time =
-			cur_mtime >= ioloop_time - MAILDIR_SYNC_SECS ?
-			cur_mtime : 0;
+		if (cur_mtime < ioloop_time - MAILDIR_SYNC_SECS) {
+			mbox->last_dirty_flags &= ~MAILDIR_DIRTY_CUR;
+			mbox->dirty_cur_time = 0;
+		} else {
+			mbox->last_dirty_flags |= MAILDIR_DIRTY_CUR;
+			mbox->dirty_cur_time = cur_mtime;
+		}
 	}
 
 	return 0;
@@ -947,7 +967,6 @@
 	ARRAY_TYPE(keyword_indexes) idx_keywords;
 	uint32_t uid_validity, next_uid;
 	uint64_t value;
-	time_t old_new_sync_time;
 	int ret = 0;
 	bool full_rescan = FALSE;
 
@@ -1179,8 +1198,10 @@
 		mbox->syncing_commit = FALSE;
 	}
 
-	if (mbox->dirty_cur_time == 0 &&
-	    mbox->last_cur_mtime != (time_t)hdr->sync_stamp) {
+	if (mbox->dirty_cur_time != 0)
+		mbox->last_dirty_flags |= MAILDIR_DIRTY_CUR;
+
+	if (mbox->last_cur_mtime != (time_t)hdr->sync_stamp) {
 		uint32_t sync_stamp = mbox->last_cur_mtime;
 
 		mail_index_update_header(trans,
@@ -1189,20 +1210,12 @@
 	}
 
 	/* FIXME: use a header extension instead of sync_size.. */
-	value = mbox->last_new_mtime;
-	old_new_sync_time = hdr->sync_size >> 32;
-	if (mbox->last_new_mtime >= old_new_sync_time - MAILDIR_SYNC_SECS) {
-		value |= (uint64_t)mbox->last_new_sync_time << 32;
-	} else {
-		value |= (uint64_t)old_new_sync_time << 32;
-	}
+	value = mbox->last_new_mtime |
+		((uint64_t)mbox->last_dirty_flags << 32);
 	if (value != hdr->sync_size) {
-		uint64_t sync_stamp = mbox->last_new_mtime |
-			((uint64_t)mbox->last_new_sync_time << 32);
-
 		mail_index_update_header(trans,
 			offsetof(struct mail_index_header, sync_size),
-			&sync_stamp, sizeof(sync_stamp), TRUE);
+			&value, sizeof(value), TRUE);
 	}
 
 	if (hdr->uid_validity == 0) {
@@ -1384,6 +1397,11 @@
 	struct maildir_sync_context *ctx;
 	int ret = 0;
 
+	if (!box->opened) {
+		if (index_storage_mailbox_open(&mbox->ibox) < 0)
+			return index_mailbox_sync_init(box, 0, TRUE);
+	}
+
 	if ((flags & MAILBOX_SYNC_FLAG_FAST) == 0 ||
 	    mbox->ibox.sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <=
 	    ioloop_time) {