changeset 12646:87f84a76fb1e

lib-storage: Return STATUS replies from mailbox list index only when it's fully up-to-date.
author Timo Sirainen <tss@iki.fi>
date Wed, 09 Feb 2011 01:31:40 +0200
parents d3d5f104ca40
children f02d429ff6bd
files src/lib-storage/index/cydir/cydir-storage.c src/lib-storage/index/dbox-multi/mdbox-storage.c src/lib-storage/index/dbox-single/sdbox-storage.c src/lib-storage/index/index-storage.h src/lib-storage/index/index-sync.c src/lib-storage/index/maildir/maildir-sync-index.c src/lib-storage/index/maildir/maildir-sync.h src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/index/raw/raw-storage.c src/lib-storage/list/index-mailbox-list-status.c src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.c
diffstat 12 files changed, 154 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/cydir/cydir-storage.c	Tue Feb 08 22:54:14 2011 +0200
+++ b/src/lib-storage/index/cydir/cydir-storage.c	Wed Feb 09 01:31:40 2011 +0200
@@ -146,8 +146,8 @@
 		index_storage_mailbox_rename,
 		index_storage_get_status,
 		NULL,
-		NULL,
-		NULL,
+		index_storage_list_index_has_changed,
+		index_storage_list_index_update_sync,
 		cydir_storage_sync_init,
 		index_mailbox_sync_next,
 		index_mailbox_sync_deinit,
--- a/src/lib-storage/index/dbox-multi/mdbox-storage.c	Tue Feb 08 22:54:14 2011 +0200
+++ b/src/lib-storage/index/dbox-multi/mdbox-storage.c	Wed Feb 09 01:31:40 2011 +0200
@@ -420,8 +420,8 @@
 		index_storage_mailbox_rename,
 		index_storage_get_status,
 		mdbox_mailbox_get_metadata,
-		NULL,
-		NULL,
+		index_storage_list_index_has_changed,
+		index_storage_list_index_update_sync,
 		mdbox_storage_sync_init,
 		index_mailbox_sync_next,
 		index_mailbox_sync_deinit,
--- a/src/lib-storage/index/dbox-single/sdbox-storage.c	Tue Feb 08 22:54:14 2011 +0200
+++ b/src/lib-storage/index/dbox-single/sdbox-storage.c	Wed Feb 09 01:31:40 2011 +0200
@@ -378,8 +378,8 @@
 		index_storage_mailbox_rename,
 		index_storage_get_status,
 		sdbox_mailbox_get_metadata,
-		NULL,
-		NULL,
+		index_storage_list_index_has_changed,
+		index_storage_list_index_update_sync,
 		sdbox_storage_sync_init,
 		index_mailbox_sync_next,
 		index_mailbox_sync_deinit,
--- a/src/lib-storage/index/index-storage.h	Tue Feb 08 22:54:14 2011 +0200
+++ b/src/lib-storage/index/index-storage.h	Wed Feb 09 01:31:40 2011 +0200
@@ -138,4 +138,11 @@
 bool index_keyword_array_cmp(const ARRAY_TYPE(keyword_indexes) *k1,
 			     const ARRAY_TYPE(keyword_indexes) *k2);
 
+int index_storage_list_index_has_changed(struct mailbox *box,
+					 struct mail_index_view *list_view,
+					 uint32_t seq);
+void index_storage_list_index_update_sync(struct mailbox *box,
+					  struct mail_index_transaction *trans,
+					  uint32_t seq);
+
 #endif
--- a/src/lib-storage/index/index-sync.c	Tue Feb 08 22:54:14 2011 +0200
+++ b/src/lib-storage/index/index-sync.c	Wed Feb 09 01:31:40 2011 +0200
@@ -6,6 +6,11 @@
 #include "array.h"
 #include "index-sync-private.h"
 
+struct index_storage_list_index_record {
+	uint32_t size;
+	uint32_t mtime;
+};
+
 enum mail_index_sync_flags index_storage_get_sync_flags(struct mailbox *box)
 {
 	enum mail_index_sync_flags sync_flags = 0;
@@ -430,3 +435,99 @@
 		ret |= MAILBOX_SYNC_TYPE_FLAGS;
 	return ret;
 }
+
+static unsigned int
+index_storage_list_get_ext_id(struct mail_storage *storage,
+			      struct mail_index_view *view)
+{
+	if (storage->list_sync_ext_id == (uint32_t)-1) {
+		storage->list_sync_ext_id =
+			mail_index_ext_register(mail_index_view_get_index(view),
+				"index sync", 0,
+				sizeof(struct index_storage_list_index_record),
+				sizeof(uint32_t));
+	}
+	return storage->list_sync_ext_id;
+}
+
+int index_storage_list_index_has_changed(struct mailbox *box,
+					 struct mail_index_view *list_view,
+					 uint32_t seq)
+{
+	const struct index_storage_list_index_record *rec;
+	const void *data;
+	const char *dir, *path;
+	struct stat st;
+	uint32_t ext_id;
+	bool expunged;
+
+	if (mail_index_is_in_memory(mail_index_view_get_index(list_view)))
+		return 1;
+
+	ext_id = index_storage_list_get_ext_id(box->storage, list_view);
+	mail_index_lookup_ext(list_view, seq, ext_id, &data, &expunged);
+	rec = data;
+
+	if (rec == NULL || expunged || rec->size == 0 || rec->mtime == 0) {
+		/* doesn't exist / not synced */
+		return 1;
+	}
+
+	dir = mailbox_list_get_path(box->list, box->name,
+				    MAILBOX_LIST_PATH_TYPE_INDEX);
+	path = t_strconcat(dir, "/", box->index_prefix, ".log", NULL);
+	if (stat(path, &st) < 0) {
+		mail_storage_set_critical(box->storage,
+					  "stat(%s) failed: %m", path);
+		return -1;
+	}
+	if (rec->size != (st.st_size & 0xffffffffU) ||
+	    rec->mtime != (st.st_mtime & 0xffffffffU))
+		return 1;
+	return 0;
+}
+
+void index_storage_list_index_update_sync(struct mailbox *box,
+					  struct mail_index_transaction *trans,
+					  uint32_t seq)
+{
+	struct mail_index_view *list_view;
+	const struct index_storage_list_index_record *old_rec;
+	struct index_storage_list_index_record new_rec;
+	const void *data;
+	const char *dir, *path;
+	struct stat st;
+	uint32_t ext_id;
+	bool expunged;
+
+	list_view = mail_index_transaction_get_view(trans);
+	if (mail_index_is_in_memory(mail_index_view_get_index(list_view)))
+		return;
+
+	/* get the current record */
+	ext_id = index_storage_list_get_ext_id(box->storage, list_view);
+	mail_index_lookup_ext(list_view, seq, ext_id, &data, &expunged);
+	if (expunged)
+		return;
+	old_rec = data;
+
+	dir = mailbox_list_get_path(box->list, box->name,
+				    MAILBOX_LIST_PATH_TYPE_INDEX);
+	path = t_strconcat(dir, "/", box->index_prefix, ".log", NULL);
+	if (stat(path, &st) < 0) {
+		mail_storage_set_critical(box->storage,
+					  "stat(%s) failed: %m", path);
+		return;
+	}
+
+	memset(&new_rec, 0, sizeof(new_rec));
+	new_rec.size = st.st_size & 0xffffffffU;
+	new_rec.mtime = st.st_mtime & 0xffffffffU;
+
+	if (old_rec == NULL ||
+	    memcmp(old_rec, &new_rec, sizeof(*old_rec)) != 0) {
+		mail_index_update_ext(trans, seq,
+				      box->storage->list_sync_ext_id,
+				      &new_rec, NULL);
+	}
+}
--- a/src/lib-storage/index/maildir/maildir-sync-index.c	Tue Feb 08 22:54:14 2011 +0200
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c	Wed Feb 09 01:31:40 2011 +0200
@@ -711,6 +711,9 @@
 	uint32_t ext_id;
 	bool expunged;
 
+	if (mbox->storage->set->maildir_very_dirty_syncs)
+		return index_storage_list_index_has_changed(box, list_view, seq);
+
 	ext_id = maildir_list_get_ext_id(mbox->storage, list_view);
 	mail_index_lookup_ext(list_view, seq, ext_id, &data, &expunged);
 	rec = data;
@@ -746,9 +749,9 @@
 	return 0;
 }
 
-int maildir_list_index_update_sync(struct mailbox *box,
-				   struct mail_index_transaction *trans,
-				   uint32_t seq)
+void maildir_list_index_update_sync(struct mailbox *box,
+				    struct mail_index_transaction *trans,
+				    uint32_t seq)
 {
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
 	struct mail_index_view *list_view;
@@ -759,12 +762,17 @@
 	uint32_t ext_id;
 	bool expunged;
 
+	if (mbox->storage->set->maildir_very_dirty_syncs) {
+		index_storage_list_index_update_sync(box, trans, seq);
+		return;
+	}
+
 	/* get the current record */
 	list_view = mail_index_transaction_get_view(trans);
 	ext_id = maildir_list_get_ext_id(mbox->storage, list_view);
 	mail_index_lookup_ext(list_view, seq, ext_id, &data, &expunged);
 	if (expunged)
-		return 0;
+		return;
 	old_rec = data;
 
 	memset(&new_rec, 0, sizeof(new_rec));
@@ -777,10 +785,9 @@
 	}
 
 	if (old_rec == NULL ||
-	    memcmp(old_rec, &new_rec, sizeof(old_rec)) != 0) {
+	    memcmp(old_rec, &new_rec, sizeof(*old_rec)) != 0) {
 		mail_index_update_ext(trans, seq,
 				      mbox->storage->maildir_list_ext_id,
 				      &new_rec, NULL);
 	}
-	return 0;
 }
--- a/src/lib-storage/index/maildir/maildir-sync.h	Tue Feb 08 22:54:14 2011 +0200
+++ b/src/lib-storage/index/maildir/maildir-sync.h	Wed Feb 09 01:31:40 2011 +0200
@@ -50,8 +50,8 @@
 int maildir_list_index_has_changed(struct mailbox *box,
 				   struct mail_index_view *list_view,
 				   uint32_t seq);
-int maildir_list_index_update_sync(struct mailbox *box,
-				   struct mail_index_transaction *trans,
-				   uint32_t seq);
+void maildir_list_index_update_sync(struct mailbox *box,
+				    struct mail_index_transaction *trans,
+				    uint32_t seq);
 
 #endif
--- a/src/lib-storage/index/mbox/mbox-storage.c	Tue Feb 08 22:54:14 2011 +0200
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Wed Feb 09 01:31:40 2011 +0200
@@ -764,8 +764,8 @@
 		index_storage_mailbox_rename,
 		index_storage_get_status,
 		mbox_mailbox_get_metadata,
-		NULL,
-		NULL,
+		index_storage_list_index_has_changed,
+		index_storage_list_index_update_sync,
 		mbox_storage_sync_init,
 		index_mailbox_sync_next,
 		index_mailbox_sync_deinit,
--- a/src/lib-storage/index/raw/raw-storage.c	Tue Feb 08 22:54:14 2011 +0200
+++ b/src/lib-storage/index/raw/raw-storage.c	Wed Feb 09 01:31:40 2011 +0200
@@ -146,8 +146,8 @@
 		index_storage_mailbox_rename,
 		index_storage_get_status,
 		NULL,
-		NULL,
-		NULL,
+		index_storage_list_index_has_changed,
+		index_storage_list_index_update_sync,
 		raw_storage_sync_init,
 		index_mailbox_sync_next,
 		index_mailbox_sync_deinit,
--- a/src/lib-storage/list/index-mailbox-list-status.c	Tue Feb 08 22:54:14 2011 +0200
+++ b/src/lib-storage/list/index-mailbox-list-status.c	Wed Feb 09 01:31:40 2011 +0200
@@ -27,6 +27,7 @@
 	struct index_mailbox_node *node;
 	struct mail_index_view *view;
 	uint32_t seq;
+	int ret;
 
 	if (index_mailbox_list_refresh(box->list) < 0)
 		return -1;
@@ -40,9 +41,17 @@
 	view = mail_index_view_open(ilist->index);
 	if (!mail_index_lookup_seq(view, node->uid, &seq)) {
 		/* our in-memory tree is out of sync */
+		ret = 1;
+	} else T_BEGIN {
+		ret = box->v.list_index_has_changed == NULL ? 0 :
+			box->v.list_index_has_changed(box, view, seq);
+	} T_END;
+
+	if (ret != 0) {
+		/* error / mailbox has changed. we'll need to sync it. */
 		index_mailbox_list_refresh_later(box->list);
 		mail_index_view_close(&view);
-		return 0;
+		return ret < 0 ? -1 : 0;
 	}
 
 	*view_r = view;
@@ -221,6 +230,9 @@
 				      &status->highest_modseq, NULL);
 	}
 
+	if (box->v.list_index_update_sync != NULL)
+		box->v.list_index_update_sync(box, trans, seq);
+
 	return mail_index_transaction_commit_full(&trans, &result);
 }
 
@@ -280,7 +292,7 @@
 		sizeof(uint32_t));
 
 	ilist->hmodseq_ext_id =
-		mail_index_ext_register(ilist->index, "msgs", 0,
+		mail_index_ext_register(ilist->index, "hmodseq", 0,
 					sizeof(uint64_t), sizeof(uint64_t));
 }
 
--- a/src/lib-storage/mail-storage-private.h	Tue Feb 08 22:54:14 2011 +0200
+++ b/src/lib-storage/mail-storage-private.h	Wed Feb 09 01:31:40 2011 +0200
@@ -85,6 +85,7 @@
 	struct mail_user *user;
 	const char *temp_path_prefix;
 	const struct mail_storage_settings *set;
+	uint32_t list_sync_ext_id;
 
 	enum mail_storage_flags flags;
 
@@ -128,10 +129,10 @@
 	int (*list_index_has_changed)(struct mailbox *box,
 				      struct mail_index_view *list_view,
 				      uint32_t seq);
-	/* Update the sync extension record. Returns 0 = ok, -1 = error. */
-	int (*list_index_update_sync)(struct mailbox *box,
-				      struct mail_index_transaction *trans,
-				      uint32_t seq);
+	/* Update the sync extension record. */
+	void (*list_index_update_sync)(struct mailbox *box,
+				       struct mail_index_transaction *trans,
+				       uint32_t seq);
 
 	struct mailbox_sync_context *
 		(*sync_init)(struct mailbox *box,
--- a/src/lib-storage/mail-storage.c	Tue Feb 08 22:54:14 2011 +0200
+++ b/src/lib-storage/mail-storage.c	Wed Feb 09 01:31:40 2011 +0200
@@ -349,6 +349,7 @@
 	storage->user = ns->user;
 	storage->set = ns->mail_set;
 	storage->flags = flags;
+	storage->list_sync_ext_id = (uint32_t)-1;
 	p_array_init(&storage->module_contexts, storage->pool, 5);
 
 	if (storage->v.create != NULL &&