dovecot: Store syncing information to maildir extension header i...

dovecot at dovecot.org dovecot at dovecot.org
Mon Jul 9 05:44:45 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/b9865213da42
changeset: 5927:b9865213da42
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Jul 09 01:33:30 2007 +0300
description:
Store syncing information to maildir extension header instead of kludging
them into base header. Also we're now using nanoseconds to check for changes
if they're available.

diffstat:

4 files changed, 188 insertions(+), 136 deletions(-)
src/lib-storage/index/maildir/maildir-storage.c    |    4 
src/lib-storage/index/maildir/maildir-storage.h    |   16 -
src/lib-storage/index/maildir/maildir-sync-index.c |   48 +--
src/lib-storage/index/maildir/maildir-sync.c       |  256 +++++++++++---------

diffs (truncated from 472 to 300 lines):

diff -r 095b3adc537b -r b9865213da42 src/lib-storage/index/maildir/maildir-storage.c
--- a/src/lib-storage/index/maildir/maildir-storage.c	Mon Jul 09 00:52:04 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Mon Jul 09 01:33:30 2007 +0300
@@ -464,6 +464,10 @@ maildir_open(struct maildir_storage *sto
 
 	mbox->uidlist = maildir_uidlist_init(mbox);
 	mbox->keywords = maildir_keywords_init(mbox);
+
+	mbox->maildir_ext_id =
+		mail_index_ext_register(index, "maildir",
+					sizeof(mbox->maildir_hdr), 0, 0);
 
 	if (!shared) {
 		mbox->mail_create_mode = 0600;
diff -r 095b3adc537b -r b9865213da42 src/lib-storage/index/maildir/maildir-storage.h
--- a/src/lib-storage/index/maildir/maildir-storage.h	Mon Jul 09 00:52:04 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.h	Mon Jul 09 01:33:30 2007 +0300
@@ -49,6 +49,11 @@ struct maildir_save_context;
 struct maildir_save_context;
 struct maildir_copy_context;
 
+struct maildir_index_header {
+	uint32_t new_check_time, new_mtime, new_mtime_nsecs;
+	uint32_t cur_check_time, cur_mtime, cur_mtime_nsecs;
+};
+
 struct maildir_storage {
 	struct mail_storage storage;
 
@@ -61,11 +66,6 @@ struct maildir_storage {
 	unsigned int stat_dirs:1;
 };
 
-enum maildir_dirty_flags {
-	MAILDIR_DIRTY_NEW = 0x01,
-	MAILDIR_DIRTY_CUR = 0x02
-};
-
 struct maildir_mailbox {
 	struct index_mailbox ibox;
 	struct maildir_storage *storage;
@@ -76,9 +76,9 @@ struct maildir_mailbox {
 	/* maildir sync: */
 	struct maildir_uidlist *uidlist;
 	struct maildir_keywords *keywords;
-	time_t last_new_mtime, last_cur_mtime;
-	time_t dirty_cur_time;
-	enum maildir_dirty_flags last_dirty_flags;
+
+	struct maildir_index_header maildir_hdr;
+	uint32_t maildir_ext_id;
 
 	mode_t mail_create_mode;
 	gid_t mail_create_gid;
diff -r 095b3adc537b -r b9865213da42 src/lib-storage/index/maildir/maildir-sync-index.c
--- a/src/lib-storage/index/maildir/maildir-sync-index.c	Mon Jul 09 00:52:04 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c	Mon Jul 09 01:33:30 2007 +0300
@@ -120,7 +120,7 @@ static void maildir_handle_uid_insertion
 	   shouldn't actually exist. */
 	if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RACING) == 0) {
 		/* mark it racy and check in next sync */
-		ctx->mbox->dirty_cur_time = ioloop_time;
+		ctx->mbox->maildir_hdr.cur_check_time = 0;
 		maildir_uidlist_add_flags(ctx->mbox->uidlist, filename,
 					  MAILDIR_UIDLIST_REC_FLAG_RACING);
 		return;
@@ -212,6 +212,27 @@ int maildir_sync_index_finish(struct mai
 	index_sync_changes_deinit(&ctx->sync_changes);
 	i_free(ctx);
 	return ret;
+}
+
+static void
+maildir_index_update_ext_header(struct maildir_mailbox *mbox,
+				struct mail_index_transaction *trans)
+{
+	const void *data;
+	size_t data_size;
+
+	if (mail_index_get_header_ext(mbox->ibox.view, mbox->maildir_ext_id,
+				      &data, &data_size) < 0)
+		data_size = 0;
+
+	if (data_size == sizeof(mbox->maildir_hdr) &&
+	    memcmp(data, &mbox->maildir_hdr, data_size) == 0) {
+		/* nothing changed */
+	} else {
+		mail_index_update_header_ext(trans, mbox->maildir_ext_id, 0,
+					     &mbox->maildir_hdr,
+					     sizeof(mbox->maildir_hdr));
+	}
 }
 
 int maildir_sync_index(struct maildir_index_sync_context *ctx,
@@ -229,7 +250,6 @@ int maildir_sync_index(struct maildir_in
 	const char *filename;
 	ARRAY_TYPE(keyword_indexes) idx_keywords;
 	uint32_t uid_validity, next_uid;
-	uint64_t value;
 	unsigned int changes = 0;
 	int ret = 0;
 	bool expunged, full_rescan = FALSE;
@@ -439,31 +459,11 @@ int maildir_sync_index(struct maildir_in
 	}
 
 	if (ctx->changed)
-		mbox->dirty_cur_time = ioloop_time;
-	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,
-			offsetof(struct mail_index_header, sync_stamp),
-			&sync_stamp, sizeof(sync_stamp), TRUE);
-	}
-
-	/* FIXME: use a header extension instead of sync_size.. */
-	value = mbox->last_new_mtime |
-		((uint64_t)mbox->last_dirty_flags << 32);
-	if (value != hdr->sync_size) {
-		mail_index_update_header(trans,
-			offsetof(struct mail_index_header, sync_size),
-			&value, sizeof(value), TRUE);
-	}
+		ctx->mbox->maildir_hdr.cur_mtime = time(NULL);
+	maildir_index_update_ext_header(ctx->mbox, trans);
 
 	if (hdr->uid_validity == 0) {
 		/* get the initial uidvalidity */
-		if (maildir_uidlist_refresh(mbox->uidlist) < 0)
-			ret = -1;
 		uid_validity = maildir_uidlist_get_uid_validity(mbox->uidlist);
 		if (uid_validity == 0) {
 			uid_validity = ioloop_time;
diff -r 095b3adc537b -r b9865213da42 src/lib-storage/index/maildir/maildir-sync.c
--- a/src/lib-storage/index/maildir/maildir-sync.c	Mon Jul 09 00:52:04 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync.c	Mon Jul 09 01:33:30 2007 +0300
@@ -354,25 +354,60 @@ static int maildir_scan_dir(struct maild
 static int maildir_scan_dir(struct maildir_sync_context *ctx, bool new_dir)
 {
 	struct mail_storage *storage = &ctx->mbox->storage->storage;
-	const char *dir;
+	const char *path;
 	DIR *dirp;
 	string_t *src, *dest;
 	struct dirent *dp;
+	struct stat st;
 	enum maildir_uidlist_rec_flag flags;
 	unsigned int i = 0, move_count = 0;
+	time_t now;
 	int ret = 1;
-	bool move_new, check_touch;
-
-	dir = new_dir ? ctx->new_dir : ctx->cur_dir;
-	dirp = opendir(dir);
+	bool move_new, check_touch, dir_changed = FALSE;
+
+	path = new_dir ? ctx->new_dir : ctx->cur_dir;
+	dirp = opendir(path);
 	if (dirp == NULL) {
 		if (errno == ENOENT) {
 			ctx->mbox->ibox.mailbox_deleted = TRUE;
 			return -1;
 		}
 		mail_storage_set_critical(storage,
-					  "opendir(%s) failed: %m", dir);
+					  "opendir(%s) failed: %m", path);
 		return -1;
+	}
+
+#ifdef HAVE_DIRFD
+	if (fstat(dirfd(dirp), &st) < 0) {
+		mail_storage_set_critical(storage,
+			"fstat(%s) failed: %m", path);
+		(void)closedir(dirp);
+		return -1;
+	}
+#else
+	if (maildir_stat(ctx->mbox, path, &st) < 0) {
+		(void)closedir(dirp);
+		return -1;
+	}
+#endif
+
+	now = time(NULL);
+	if (new_dir) {
+		ctx->mbox->maildir_hdr.new_check_time = now;
+		ctx->mbox->maildir_hdr.new_mtime = st.st_mtime;
+#ifdef HAVE_STAT_TV_NSEC
+		ctx->mbox->maildir_hdr.new_mtime_nsecs = st.st_mtim.tv_nsec;
+#else
+		ctx->mbox->maildir_hdr.new_mtime_nsecs = 0;
+#endif
+	} else {
+		ctx->mbox->maildir_hdr.cur_check_time = now;
+		ctx->mbox->maildir_hdr.cur_mtime = st.st_mtime;
+#ifdef HAVE_STAT_TV_NSEC
+		ctx->mbox->maildir_hdr.cur_mtime_nsecs = st.st_mtim.tv_nsec;
+#else
+		ctx->mbox->maildir_hdr.cur_mtime_nsecs = 0;
+#endif
 	}
 
 	t_push();
@@ -392,10 +427,7 @@ static int maildir_scan_dir(struct maild
 		if (ret == 0) {
 			/* new file and we couldn't lock uidlist, check this
 			   later in next sync. */
-			if (new_dir)
-				ctx->mbox->last_new_mtime = 0;
-			else
-				ctx->mbox->dirty_cur_time = ioloop_time;
+			dir_changed = TRUE;
 			continue;
 		}
 		if (ret < 0)
@@ -413,12 +445,13 @@ static int maildir_scan_dir(struct maild
 			}
 			if (rename(str_c(src), str_c(dest)) == 0) {
 				/* we moved it - it's \Recent for us */
+				dir_changed = TRUE;
 				move_count++;
-				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 */
+				dir_changed = TRUE;
 				move_count++;
 				flags |= MAILDIR_UIDLIST_REC_FLAG_MOVED;
 			} else if (ENOSPACE(errno) || errno == EACCES) {
@@ -452,7 +485,7 @@ static int maildir_scan_dir(struct maild
 				break;
 
 			/* possibly duplicate - try fixing it */
-			if (maildir_fix_duplicate(ctx, dir, dp->d_name) < 0) {
+			if (maildir_fix_duplicate(ctx, path, dp->d_name) < 0) {
 				ret = -1;
 				break;
 			}
@@ -461,14 +494,21 @@ static int maildir_scan_dir(struct maild
 
 	if (errno != 0) {
 		mail_storage_set_critical(storage,
-					  "readdir(%s) failed: %m", dir);
+					  "readdir(%s) failed: %m", path);
 		ret = -1;
 	}
 
 	if (closedir(dirp) < 0) {
 		mail_storage_set_critical(storage,
-					  "closedir(%s) failed: %m", dir);
+					  "closedir(%s) failed: %m", path);
 		ret = -1;
+	}
+
+	if (dir_changed) {
+		if (new_dir)
+			ctx->mbox->maildir_hdr.new_mtime = now;
+		else
+			ctx->mbox->maildir_hdr.cur_mtime = now;
 	}
 
 	t_pop();
@@ -476,98 +516,107 @@ static int maildir_scan_dir(struct maild
 		(move_count <= MAILDIR_RENAME_RESCAN_COUNT ? 0 : 1);
 }
 
-static void
-maildir_sync_update_from_header(struct maildir_mailbox *mbox,
-				struct mail_index_header *hdr_r)
-{
-	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 */
-	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;
-
-	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
-maildir_sync_quick_check(struct maildir_mailbox *mbox,
-			 const char *new_dir, const char *cur_dir,
-			 bool *new_changed_r, bool *cur_changed_r)


More information about the dovecot-cvs mailing list