dovecot-2.2: lib-storage: Saving/copying no longer discards priv...

dovecot at dovecot.org dovecot at dovecot.org
Tue Feb 19 08:27:50 EET 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/02529503c59c
changeset: 15835:02529503c59c
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Feb 19 08:27:40 2013 +0200
description:
lib-storage: Saving/copying no longer discards private message flags.

diffstat:

 src/lib-storage/index/index-sync-private.h |   14 +-
 src/lib-storage/index/index-sync-pvt.c     |  266 ++++++++++++++++++++--------
 src/lib-storage/index/index-sync.c         |    9 +-
 src/lib-storage/index/index-transaction.c  |   17 +
 src/lib-storage/mail-storage-private.h     |   13 +
 src/lib-storage/mail-storage.c             |   51 ++++-
 src/plugins/acl/acl-mailbox.c              |   20 +-
 src/plugins/virtual/virtual-save.c         |    3 +-
 8 files changed, 293 insertions(+), 100 deletions(-)

diffs (truncated from 716 to 300 lines):

diff -r be857a95b381 -r 02529503c59c src/lib-storage/index/index-sync-private.h
--- a/src/lib-storage/index/index-sync-private.h	Tue Feb 19 08:17:50 2013 +0200
+++ b/src/lib-storage/index/index-sync-private.h	Tue Feb 19 08:27:40 2013 +0200
@@ -3,6 +3,8 @@
 
 #include "index-storage.h"
 
+struct index_mailbox_sync_pvt_context;
+
 struct index_mailbox_sync_context {
 	struct mailbox_sync_context ctx;
 
@@ -22,8 +24,14 @@
 void index_sync_search_results_update(struct index_mailbox_sync_context *ctx);
 void index_sync_search_results_expunge(struct index_mailbox_sync_context *ctx);
 
-int index_storage_mailbox_sync_pvt(struct mailbox *box,
-				   ARRAY_TYPE(seq_range) *flag_updates,
-				   ARRAY_TYPE(seq_range) *hidden_updates);
+/* Returns 1 = ok, 0 = no private indexes, -1 = error */
+int index_mailbox_sync_pvt_init(struct mailbox *box, bool lock,
+				struct index_mailbox_sync_pvt_context **ctx_r);
+int index_mailbox_sync_pvt_newmails(struct index_mailbox_sync_pvt_context *ctx,
+				    struct mailbox_transaction_context *trans);
+int index_mailbox_sync_pvt_view(struct index_mailbox_sync_pvt_context *ctx,
+				ARRAY_TYPE(seq_range) *flag_updates,
+				ARRAY_TYPE(seq_range) *hidden_updates);
+void index_mailbox_sync_pvt_deinit(struct index_mailbox_sync_pvt_context **ctx);
 
 #endif
diff -r be857a95b381 -r 02529503c59c src/lib-storage/index/index-sync-pvt.c
--- a/src/lib-storage/index/index-sync-pvt.c	Tue Feb 19 08:17:50 2013 +0200
+++ b/src/lib-storage/index/index-sync-pvt.c	Tue Feb 19 08:27:40 2013 +0200
@@ -4,31 +4,37 @@
 #include "mailbox-list-private.h"
 #include "index-sync-private.h"
 
-static int sync_pvt_expunges(struct mailbox *box,
-			     struct mail_index_view *view_pvt,
-			     struct mail_index_transaction *trans_pvt,
-			     struct mail_index_view *view_shared)
+struct index_mailbox_sync_pvt_context {
+	struct mailbox *box;
+
+	struct mail_index_sync_ctx *sync_ctx;
+	struct mail_index_view *view_pvt;
+	struct mail_index_transaction *trans_pvt;
+	struct mail_index_view *view_shared;
+};
+
+static int sync_pvt_expunges(struct index_mailbox_sync_pvt_context *ctx)
 {
 	uint32_t seq_shared, seq_pvt, count_shared, count_pvt;
 	uint32_t uid_shared, uid_pvt;
 
-	count_shared = mail_index_view_get_messages_count(view_shared);
-	count_pvt = mail_index_view_get_messages_count(view_pvt);
+	count_shared = mail_index_view_get_messages_count(ctx->view_shared);
+	count_pvt = mail_index_view_get_messages_count(ctx->view_pvt);
 	seq_shared = seq_pvt = 1;
 	while (seq_pvt <= count_pvt && seq_shared <= count_shared) {
-		mail_index_lookup_uid(view_pvt, seq_pvt, &uid_pvt);
-		mail_index_lookup_uid(view_shared, seq_shared, &uid_shared);
+		mail_index_lookup_uid(ctx->view_pvt, seq_pvt, &uid_pvt);
+		mail_index_lookup_uid(ctx->view_shared, seq_shared, &uid_shared);
 		if (uid_pvt == uid_shared) {
 			seq_pvt++;
 			seq_shared++;
 		} else if (uid_pvt < uid_shared) {
 			/* message expunged */
-			mail_index_expunge(trans_pvt, seq_pvt);
+			mail_index_expunge(ctx->trans_pvt, seq_pvt);
 			seq_pvt++;
 		} else {
-			mail_storage_set_critical(box->storage,
+			mail_storage_set_critical(ctx->box->storage,
 				"%s: Message UID=%u unexpectedly inserted to mailbox",
-				box->index_pvt->filepath, uid_shared);
+				ctx->box->index_pvt->filepath, uid_shared);
 			return -1;
 		}
 	}
@@ -36,78 +42,122 @@
 }
 
 static void
-sync_pvt_copy_self_flags(struct mailbox *box,
-			 struct mail_index_view *view,
-			 struct mail_index_transaction *trans,
+sync_pvt_copy_self_flags(struct index_mailbox_sync_pvt_context *ctx,
 			 ARRAY_TYPE(keyword_indexes) *keywords,
 			 uint32_t seq_old, uint32_t seq_new)
 {
 	const struct mail_index_record *old_rec;
 
-	old_rec = mail_index_lookup(view, seq_old);
-	mail_index_lookup_keywords(view, seq_old, keywords);
+	old_rec = mail_index_lookup(ctx->view_pvt, seq_old);
+	mail_index_lookup_keywords(ctx->view_pvt, seq_old, keywords);
 	if (old_rec->flags != 0) {
-		mail_index_update_flags(trans, seq_new,
+		mail_index_update_flags(ctx->trans_pvt, seq_new,
 					MODIFY_ADD, old_rec->flags);
 	}
 	if (array_count(keywords) > 0) {
 		struct mail_keywords *kw;
 
-		kw = mail_index_keywords_create_from_indexes(box->index_pvt,
+		kw = mail_index_keywords_create_from_indexes(ctx->box->index_pvt,
 							     keywords);
-		mail_index_update_keywords(trans, seq_new, MODIFY_ADD, kw);
+		mail_index_update_keywords(ctx->trans_pvt, seq_new,
+					   MODIFY_ADD, kw);
 		mail_index_keywords_unref(&kw);
 	}
 }
 
 static int
-index_storage_mailbox_sync_pvt_index(struct mailbox *box)
+index_mailbox_sync_view_refresh(struct index_mailbox_sync_pvt_context *ctx)
 {
-	struct mail_index_sync_ctx *sync_ctx;
-	struct mail_index_view *view_pvt;
-	struct mail_index_transaction *trans_pvt;
+	/* open a view for the latest version of the index */
+	if (mail_index_refresh(ctx->box->index_pvt) < 0 ||
+	    mail_index_refresh(ctx->box->index) < 0) {
+		mailbox_set_index_error(ctx->box);
+		return -1;
+	}
+	if (ctx->view_shared != NULL)
+		mail_index_view_close(&ctx->view_shared);
+	ctx->view_shared = mail_index_view_open(ctx->box->index);
+	return 0;
+}
+
+static int
+index_mailbox_sync_open(struct index_mailbox_sync_pvt_context *ctx, bool force)
+{
 	const struct mail_index_header *hdr_shared, *hdr_pvt;
-	struct mail_index_view *view_shared;
+
+	if (index_mailbox_sync_view_refresh(ctx) < 0)
+		return -1;
+
+	hdr_shared = mail_index_get_header(ctx->view_shared);
+	if (hdr_shared->uid_validity == 0 && !force) {
+		/* the mailbox hasn't been fully created yet,
+		   no need for a private index yet */
+		return 0;
+	}
+	hdr_pvt = mail_index_get_header(ctx->box->view_pvt);
+	if (hdr_pvt->next_uid == hdr_shared->next_uid &&
+	    hdr_pvt->messages_count == hdr_shared->messages_count && !force) {
+		/* no new or expunged mails, don't bother syncing */
+		return 0;
+	}
+	if (mail_index_sync_begin(ctx->box->index_pvt, &ctx->sync_ctx,
+				  &ctx->view_pvt, &ctx->trans_pvt, 0) < 0) {
+		mailbox_set_index_error(ctx->box);
+		return -1;
+	}
+	/* refresh once more now that we're locked */
+	if (index_mailbox_sync_view_refresh(ctx) < 0)
+		return -1;
+	return 1;
+}
+
+int index_mailbox_sync_pvt_init(struct mailbox *box, bool lock,
+				struct index_mailbox_sync_pvt_context **ctx_r)
+{
+	struct index_mailbox_sync_pvt_context *ctx;
+	int ret;
+
+	*ctx_r = NULL;
+
+	if ((ret = mailbox_open_index_pvt(box)) <= 0)
+		return ret;
+
+	ctx = i_new(struct index_mailbox_sync_pvt_context, 1);
+	ctx->box = box;
+	if (lock) {
+		if (index_mailbox_sync_open(ctx, TRUE) < 0) {
+			index_mailbox_sync_pvt_deinit(&ctx);
+			return -1;
+		}
+	}
+
+	*ctx_r = ctx;
+	return 1;
+}
+
+static int
+index_mailbox_sync_pvt_index(struct index_mailbox_sync_pvt_context *ctx,
+			     const struct mail_save_private_changes *pvt_changes,
+			     unsigned int pvt_changes_count)
+{
+	const struct mail_index_header *hdr_shared, *hdr_pvt;
 	ARRAY_TYPE(keyword_indexes) keywords;
 	uint32_t seq_shared, seq_pvt, seq_old_pvt, seq2, count_shared, uid;
+	unsigned int pc_idx = 0;
 	bool reset = FALSE, preserve_old_flags = FALSE;
 	int ret;
 
-	/* open a view for the latest version of the index */
-	if (mail_index_refresh(box->index) < 0 ||
-	    mail_index_refresh(box->index_pvt) < 0) {
-		mailbox_set_index_error(box);
-		return -1;
+	if (ctx->sync_ctx == NULL) {
+		if ((ret = index_mailbox_sync_open(ctx, FALSE)) <= 0)
+			return ret;
 	}
-	view_shared = mail_index_view_open(box->index);
-	hdr_shared = mail_index_get_header(view_shared);
-	if (hdr_shared->uid_validity == 0) {
-		/* the mailbox hasn't been fully created yet,
-		   no need for a private index yet */
-		mail_index_view_close(&view_shared);
-		return 0;
-	}
-	hdr_pvt = mail_index_get_header(box->view_pvt);
-	if (hdr_pvt->next_uid == hdr_shared->next_uid &&
-	    hdr_pvt->messages_count == hdr_shared->messages_count) {
-		/* no new or expunged mails, don't bother syncing */
-		mail_index_view_close(&view_shared);
-		return 0;
-	}
-
-	if (mail_index_sync_begin(box->index_pvt, &sync_ctx,
-				  &view_pvt, &trans_pvt, 0) < 0) {
-		mailbox_set_index_error(box);
-		mail_index_view_close(&view_shared);
-		return -1;
-	}
-	/* get an updated private header */
-	hdr_pvt = mail_index_get_header(view_pvt);
+	hdr_pvt = mail_index_get_header(ctx->view_pvt);
+	hdr_shared = mail_index_get_header(ctx->view_shared);
 
 	if (hdr_shared->uid_validity == hdr_pvt->uid_validity) {
 		/* same mailbox. expunge messages from private index that
 		   no longer exist. */
-		if (sync_pvt_expunges(box, view_pvt, trans_pvt, view_shared) < 0) {
+		if (sync_pvt_expunges(ctx) < 0) {
 			reset = TRUE;
 			preserve_old_flags = TRUE;
 			t_array_init(&keywords, 32);
@@ -117,17 +167,18 @@
 		reset = TRUE;
 	}
 
-	count_shared = mail_index_view_get_messages_count(view_shared);
+	count_shared = mail_index_view_get_messages_count(ctx->view_shared);
 	if (!reset) {
-		if (!mail_index_lookup_seq_range(view_shared, hdr_pvt->next_uid,
+		if (!mail_index_lookup_seq_range(ctx->view_shared,
+						 hdr_pvt->next_uid,
 						 hdr_shared->next_uid,
 						 &seq_shared, &seq2)) {
 			/* no new messages */
 			seq_shared = count_shared+1;
 		}
 	} else {
-		mail_index_reset(trans_pvt);
-		mail_index_update_header(trans_pvt,
+		mail_index_reset(ctx->trans_pvt);
+		mail_index_update_header(ctx->trans_pvt,
 			offsetof(struct mail_index_header, uid_validity),
 			&hdr_shared->uid_validity,
 			sizeof(hdr_shared->uid_validity), TRUE);
@@ -136,56 +187,100 @@
 
 	uid = 0;
 	for (; seq_shared <= count_shared; seq_shared++) {
-		mail_index_lookup_uid(view_shared, seq_shared, &uid);
-		mail_index_append(trans_pvt, uid, &seq_pvt);
+		mail_index_lookup_uid(ctx->view_shared, seq_shared, &uid);
+		mail_index_append(ctx->trans_pvt, uid, &seq_pvt);
 		if (preserve_old_flags &&
-		    mail_index_lookup_seq(view_pvt, uid, &seq_old_pvt)) {
-			/* copy flags from the original index */
-			sync_pvt_copy_self_flags(box, view_pvt, trans_pvt,
-						 &keywords,
+		    mail_index_lookup_seq(ctx->view_pvt, uid, &seq_old_pvt)) {
+			/* copy flags from the original private index */
+			sync_pvt_copy_self_flags(ctx, &keywords,
 						 seq_old_pvt, seq_pvt);
 		}
+		/* add private flags for the recently saved/copied messages */
+		while (pc_idx < pvt_changes_count &&
+		       pvt_changes[pc_idx].mailnum <= uid) {
+			if (pvt_changes[pc_idx].mailnum == uid) {
+				mail_index_update_flags(ctx->trans_pvt, seq_pvt,
+					MODIFY_ADD, pvt_changes[pc_idx].flags);
+			}
+			pc_idx++;
+		}
 	}
 


More information about the dovecot-cvs mailing list