changeset 14580:2e7d718609fd

Don't write "keyword reset" records to transaction log anymore. These are a bit problematic for dsync's keyword merging to handle.
author Timo Sirainen <tss@iki.fi>
date Tue, 22 May 2012 17:03:20 +0300
parents fead3400c379
children 4b1309d171ff
files src/lib-index/mail-index-sync.c src/lib-index/mail-index-transaction-export.c src/lib-index/mail-index-transaction-finish.c src/lib-index/mail-index-transaction-private.h src/lib-index/mail-index-transaction-sort-appends.c src/lib-index/mail-index-transaction-update.c src/lib-index/mail-index-transaction-view.c src/lib-index/mail-index.h src/lib-index/test-mail-index-transaction-update.c src/lib-storage/index/cydir/cydir-sync.c src/lib-storage/index/imapc/imapc-sync.c src/lib-storage/index/index-sync-changes.c src/lib-storage/index/index-sync.c src/plugins/virtual/virtual-sync.c
diffstat 14 files changed, 84 insertions(+), 138 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-index-sync.c	Tue May 22 16:54:55 2012 +0300
+++ b/src/lib-index/mail-index-sync.c	Tue May 22 17:03:20 2012 +0300
@@ -242,12 +242,6 @@
 		synclist->array = (void *)&sync_trans->updates;
 	}
 
-	/* we must return resets before keyword additions or they get lost */
-	if (array_is_created(&sync_trans->keyword_resets)) {
-		synclist = array_append_space(&ctx->sync_list);
-		synclist->array = (void *)&sync_trans->keyword_resets;
-	}
-
 	keyword_updates = keyword_count == 0 ? NULL :
 		array_idx(&sync_trans->keyword_updates, 0);
 	for (i = 0; i < keyword_count; i++) {
@@ -655,14 +649,6 @@
 	rec->keyword_idx = sync_list->keyword_idx;
 }
 
-static void mail_index_sync_get_keyword_reset(struct mail_index_sync_rec *rec,
-					       const struct uid_range *range)
-{
-	rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET;
-	rec->uid1 = range->uid1;
-	rec->uid2 = range->uid2;
-}
-
 bool mail_index_sync_next(struct mail_index_sync_ctx *ctx,
 			  struct mail_index_sync_rec *sync_rec)
 {
@@ -720,8 +706,6 @@
 	} else if (sync_list[i].array == (void *)&sync_trans->updates) {
 		mail_index_sync_get_update(sync_rec,
 			(const struct mail_transaction_flag_update *)uid_range);
-	} else if (sync_list[i].array == (void *)&sync_trans->keyword_resets) {
-		mail_index_sync_get_keyword_reset(sync_rec, uid_range);
 	} else {
 		mail_index_sync_get_keyword_update(sync_rec, uid_range,
 						   &sync_list[i]);
@@ -921,12 +905,6 @@
 			}
 		}
 		return FALSE;
-	case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
-		if (array_count(keywords) == 0)
-			return FALSE;
-
-		array_clear(keywords);
-		return TRUE;
 	default:
 		i_unreached();
 		return FALSE;
--- a/src/lib-index/mail-index-transaction-export.c	Tue May 22 16:54:55 2012 +0300
+++ b/src/lib-index/mail-index-transaction-export.c	Tue May 22 17:03:20 2012 +0300
@@ -386,12 +386,6 @@
 				    MAIL_TRANSACTION_EXT_ATOMIC_INC);
 	}
 
-	/* keyword resets before updates */
-	if (array_is_created(&t->keyword_resets)) {
-		change_mask |= MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET;
-		log_append_buffer(&ctx, t->keyword_resets.arr.buffer,
-				  MAIL_TRANSACTION_KEYWORD_RESET);
-	}
 	if (array_is_created(&t->keyword_updates))
 		change_mask |= log_append_keyword_updates(&ctx);
 	/* keep modseq updates almost last */
--- a/src/lib-index/mail-index-transaction-finish.c	Tue May 22 16:54:55 2012 +0300
+++ b/src/lib-index/mail-index-transaction-finish.c	Tue May 22 17:03:20 2012 +0300
@@ -313,7 +313,6 @@
 	expunges_convert_to_uids(t);
 	mail_index_convert_to_uids(t, (void *)&t->modseq_updates);
 	mail_index_convert_to_uid_ranges(t, (void *)&t->updates);
-	mail_index_convert_to_uid_ranges(t, &t->keyword_resets);
 }
 
 void mail_index_transaction_finish(struct mail_index_transaction *t)
--- a/src/lib-index/mail-index-transaction-private.h	Tue May 22 16:54:55 2012 +0300
+++ b/src/lib-index/mail-index-transaction-private.h	Tue May 22 17:03:20 2012 +0300
@@ -66,7 +66,6 @@
 
 	ARRAY_DEFINE(keyword_updates,
 		     struct mail_index_transaction_keyword_update);
-	ARRAY_TYPE(seq_range) keyword_resets;
 
 	uint64_t min_highest_modseq;
 	uint64_t max_modseq;
--- a/src/lib-index/mail-index-transaction-sort-appends.c	Tue May 22 16:54:55 2012 +0300
+++ b/src/lib-index/mail-index-transaction-sort-appends.c	Tue May 22 17:03:20 2012 +0300
@@ -106,24 +106,20 @@
 {
 	struct mail_index_transaction_keyword_update *update;
 
-	if (array_is_created(&t->keyword_updates)) {
-		array_foreach_modifiable(&t->keyword_updates, update) {
-			if (array_is_created(&update->add_seq)) {
-				sort_appends_seq_range(&update->add_seq,
-						       t->first_new_seq,
-						       old_to_newseq_map);
-			}
-			if (array_is_created(&update->remove_seq)) {
-				sort_appends_seq_range(&update->remove_seq,
-						       t->first_new_seq,
-						       old_to_newseq_map);
-			}
+	if (!array_is_created(&t->keyword_updates))
+		return;
+
+	array_foreach_modifiable(&t->keyword_updates, update) {
+		if (array_is_created(&update->add_seq)) {
+			sort_appends_seq_range(&update->add_seq,
+					       t->first_new_seq,
+					       old_to_newseq_map);
 		}
-	}
-
-	if (array_is_created(&t->keyword_resets)) {
-		sort_appends_seq_range(&t->keyword_resets, t->first_new_seq,
-				       old_to_newseq_map);
+		if (array_is_created(&update->remove_seq)) {
+			sort_appends_seq_range(&update->remove_seq,
+					       t->first_new_seq,
+					       old_to_newseq_map);
+		}
 	}
 }
 
--- a/src/lib-index/mail-index-transaction-update.c	Tue May 22 16:54:55 2012 +0300
+++ b/src/lib-index/mail-index-transaction-update.c	Tue May 22 17:03:20 2012 +0300
@@ -59,8 +59,6 @@
 		}
 		array_free(&t->keyword_updates);
 	}
-	if (array_is_created(&t->keyword_resets))
-		array_free(&t->keyword_resets);
 
 	if (array_is_created(&t->appends))
 		array_free(&t->appends);
@@ -107,7 +105,6 @@
 	t->log_updates = array_is_created(&t->appends) ||
 		array_is_created(&t->modseq_updates) ||
 		array_is_created(&t->expunges) ||
-		array_is_created(&t->keyword_resets) ||
 		array_is_created(&t->keyword_updates) ||
 		t->pre_hdr_changed || t->post_hdr_changed ||
 		t->min_highest_modseq != 0;
@@ -304,8 +301,6 @@
 	t->log_ext_updates = mail_index_transaction_has_ext_changes(t);
 
 	/* remove keywords */
-	if (array_is_created(&t->keyword_resets))
-		seq_range_array_remove(&t->keyword_resets, seq);
 	if (array_is_created(&t->keyword_updates)) {
 		array_foreach_modifiable(&t->keyword_updates, kw_update) {
 			if (array_is_created(&kw_update->add_seq)) {
@@ -987,8 +982,12 @@
 		u = array_idx_modifiable(&t->keyword_updates,
 					 keywords->idx[i]);
 		if (array_is_created(&u->add_seq) ||
-		    array_is_created(&u->remove_seq))
+		    array_is_created(&u->remove_seq)) {
+			/* we've already modified this keyword in the
+			   transaction. don't bother checking it further,
+			   because we can't avoid the changes anyway. */
 			return TRUE;
+		}
 
 		found = FALSE;
 		for (j = 0; j < existing_count; j++) {
@@ -1012,11 +1011,25 @@
 	return FALSE;
 }
 
+static struct mail_keywords *
+keyword_update_remove_existing(struct mail_index_transaction *t, uint32_t seq)
+{
+	ARRAY_TYPE(keyword_indexes) keywords;
+
+	t_array_init(&keywords, 32);
+	mail_index_transaction_lookup_latest_keywords(t, seq, &keywords);
+	if (array_count(&keywords) == 0)
+		return NULL;
+	return mail_index_keywords_create_from_indexes(t->view->index,
+						       &keywords);
+}
+
 void mail_index_update_keywords(struct mail_index_transaction *t, uint32_t seq,
 				enum modify_type modify_type,
 				struct mail_keywords *keywords)
 {
 	struct mail_index_transaction_keyword_update *u;
+	struct mail_keywords *add_keywords = NULL, *remove_keywords = NULL;
 	unsigned int i;
 	bool changed;
 
@@ -1028,8 +1041,9 @@
 
 	update_minmax_flagupdate_seq(t, seq, seq);
 
-	if (!array_is_created(&t->keyword_updates) && keywords->count > 0) {
-		uint32_t max_idx = keywords->idx[keywords->count-1];
+	if (!array_is_created(&t->keyword_updates)) {
+		uint32_t max_idx = keywords->count == 0 ? 3 :
+			keywords->idx[keywords->count-1];
 
 		i_array_init(&t->keyword_updates, max_idx + 1);
 	}
@@ -1044,46 +1058,48 @@
 			return;
 	}
 
+	switch (modify_type) {
+	case MODIFY_REPLACE:
+		/* split this into add+remove. remove all existing keywords not
+		   included in the keywords list */
+		if (seq < t->first_new_seq) {
+			/* remove the ones currently in index */
+			remove_keywords = keyword_update_remove_existing(t, seq);
+		}
+		/* remove from all changes we've done in this transaction */
+		array_foreach_modifiable(&t->keyword_updates, u)
+			seq_range_array_remove(&u->add_seq, seq);
+		add_keywords = keywords;
+		break;
+	case MODIFY_ADD:
+		add_keywords = keywords;
+		break;
+	case MODIFY_REMOVE:
+		remove_keywords = keywords;
+		break;
+	}
+
 	/* Update add_seq and remove_seq arrays which describe the keyword
-	   changes. Don't bother updating remove_seq or keyword resets for
-	   newly added messages since they default to not having any
-	   keywords anyway. */
-	switch (modify_type) {
-	case MODIFY_ADD:
-		for (i = 0; i < keywords->count; i++) {
+	   changes. First do the removes, since replace removes everything
+	   first. */
+	if (remove_keywords != NULL) {
+		for (i = 0; i < remove_keywords->count; i++) {
 			u = array_idx_modifiable(&t->keyword_updates,
-						 keywords->idx[i]);
+						 remove_keywords->idx[i]);
+			seq_range_array_remove(&u->add_seq, seq);
+			/* Don't bother updating remove_seq for new messages,
+			   since their initial state is "no keyword" anyway */
+			if (seq < t->first_new_seq)
+				seq_range_array_add(&u->remove_seq, 16, seq);
+		}
+	}
+	if (add_keywords != NULL) {
+		for (i = 0; i < add_keywords->count; i++) {
+			u = array_idx_modifiable(&t->keyword_updates,
+						 add_keywords->idx[i]);
 			seq_range_array_add(&u->add_seq, 16, seq);
 			seq_range_array_remove(&u->remove_seq, seq);
 		}
-		break;
-	case MODIFY_REMOVE:
-		for (i = 0; i < keywords->count; i++) {
-			u = array_idx_modifiable(&t->keyword_updates,
-						 keywords->idx[i]);
-			seq_range_array_remove(&u->add_seq, seq);
-			if (seq < t->first_new_seq)
-				seq_range_array_add(&u->remove_seq, 16, seq);
-		}
-		break;
-	case MODIFY_REPLACE:
-		/* Remove sequence from all add/remove arrays */
-		if (array_is_created(&t->keyword_updates)) {
-			array_foreach_modifiable(&t->keyword_updates, u) {
-				seq_range_array_remove(&u->add_seq, seq);
-				seq_range_array_remove(&u->remove_seq, seq);
-			}
-		}
-		/* Add the wanted keyword back */
-		for (i = 0; i < keywords->count; i++) {
-			u = array_idx_modifiable(&t->keyword_updates,
-						 keywords->idx[i]);
-			seq_range_array_add(&u->add_seq, 16, seq);
-		}
-
-		if (seq < t->first_new_seq)
-			seq_range_array_add(&t->keyword_resets, 16, seq);
-		break;
 	}
 
 	t->log_updates = TRUE;
@@ -1144,11 +1160,10 @@
 				       uint32_t seq)
 {
 	struct mail_index_transaction_keyword_update *kw;
-	bool ret, have_kw_changes = FALSE;
+	bool ret = FALSE, have_kw_changes = FALSE;
 
-	ret = mail_index_cancel_array(&t->keyword_resets, seq);
 	if (!array_is_created(&t->keyword_updates))
-		return ret;
+		return FALSE;
 
 	array_foreach_modifiable(&t->keyword_updates, kw) {
 		if (mail_index_cancel_array(&kw->add_seq, seq))
--- a/src/lib-index/mail-index-transaction-view.c	Tue May 22 16:54:55 2012 +0300
+++ b/src/lib-index/mail-index-transaction-view.c	Tue May 22 17:03:20 2012 +0300
@@ -297,12 +297,6 @@
 		return;
 	}
 
-	/* apply any keyword updates in this transaction */
-	if (array_is_created(&t->keyword_resets)) {
-		if (seq_range_exists(&t->keyword_resets, seq))
-			array_clear(keyword_idx);
-	}
-
 	if (array_is_created(&t->keyword_updates))
 		updates = array_get(&t->keyword_updates, &count);
 	else {
--- a/src/lib-index/mail-index.h	Tue May 22 16:54:55 2012 +0300
+++ b/src/lib-index/mail-index.h	Tue May 22 17:03:20 2012 +0300
@@ -128,8 +128,7 @@
 	MAIL_INDEX_SYNC_TYPE_EXPUNGE		= 0x02,
 	MAIL_INDEX_SYNC_TYPE_FLAGS		= 0x04,
 	MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD	= 0x08,
-	MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE	= 0x10,
-	MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET	= 0x20
+	MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE	= 0x10
 };
 
 enum mail_index_sync_flags {
--- a/src/lib-index/test-mail-index-transaction-update.c	Tue May 22 16:54:55 2012 +0300
+++ b/src/lib-index/test-mail-index-transaction-update.c	Tue May 22 17:03:20 2012 +0300
@@ -49,6 +49,14 @@
 {
 }
 
+struct mail_keywords *
+mail_index_keywords_create_from_indexes(struct mail_index *index ATTR_UNUSED,
+					const ARRAY_TYPE(keyword_indexes)
+						*keyword_indexes ATTR_UNUSED)
+{
+	return NULL;
+}
+
 static struct mail_index_transaction *
 mail_index_transaction_new(void)
 {
--- a/src/lib-storage/index/cydir/cydir-sync.c	Tue May 22 16:54:55 2012 +0300
+++ b/src/lib-storage/index/cydir/cydir-sync.c	Tue May 22 17:03:20 2012 +0300
@@ -96,7 +96,6 @@
 		case MAIL_INDEX_SYNC_TYPE_FLAGS:
 		case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
 		case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
-		case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
 			/* FIXME: should be bother calling sync_notify()? */
 			break;
 		}
--- a/src/lib-storage/index/imapc/imapc-sync.c	Tue May 22 16:54:55 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-sync.c	Tue May 22 17:03:20 2012 +0300
@@ -128,26 +128,6 @@
 	imapc_sync_cmd(ctx, str_c(str));
 }
 
-static void
-imapc_sync_index_keyword_reset(struct imapc_sync_context *ctx,
-			       uint32_t seq1, uint32_t seq2)
-{
-	const struct mail_index_record *rec;
-	string_t *str = t_str_new(128);
-	uint32_t seq;
-
-	for (seq = seq1; seq <= seq2; seq++) {
-		rec = mail_index_lookup(ctx->sync_view, seq);
-		i_assert((rec->flags & MAIL_RECENT) == 0);
-
-		str_truncate(str, 0);
-		str_printfa(str, "UID STORE %u FLAGS (", rec->uid);
-		imap_write_flags(str, rec->flags, NULL);
-		str_append_c(str, ')');
-		imapc_sync_cmd(ctx, str_c(str));
-	}
-}
-
 static void imapc_sync_expunge_finish(struct imapc_sync_context *ctx)
 {
 	string_t *str;
@@ -323,9 +303,6 @@
 		case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
 			imapc_sync_index_keyword(ctx, &sync_rec);
 			break;
-		case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
-			imapc_sync_index_keyword_reset(ctx, seq1, seq2);
-			break;
 		}
 	} T_END;
 
--- a/src/lib-storage/index/index-sync-changes.c	Tue May 22 16:54:55 2012 +0300
+++ b/src/lib-storage/index/index-sync-changes.c	Tue May 22 17:03:20 2012 +0300
@@ -127,7 +127,6 @@
 		case MAIL_INDEX_SYNC_TYPE_FLAGS:
 		case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
 		case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
-		case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
 			if (!ctx->dirty_flag_updates)
 				break;
 
@@ -184,7 +183,6 @@
 			break;
 		case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
 		case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
-		case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
 			if (!array_is_created(keywords)) {
 				/* no existing keywords */
 				if (syncs[i].type !=
--- a/src/lib-storage/index/index-sync.c	Tue May 22 16:54:55 2012 +0300
+++ b/src/lib-storage/index/index-sync.c	Tue May 22 17:03:20 2012 +0300
@@ -437,8 +437,7 @@
 		ret |= MAILBOX_SYNC_TYPE_EXPUNGE;
 	if ((type & (MAIL_INDEX_SYNC_TYPE_FLAGS |
 		     MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD |
-		     MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE |
-		     MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET)) != 0)
+		     MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE)) != 0)
 		ret |= MAILBOX_SYNC_TYPE_FLAGS;
 	return ret;
 }
--- a/src/plugins/virtual/virtual-sync.c	Tue May 22 16:54:55 2012 +0300
+++ b/src/plugins/virtual/virtual-sync.c	Tue May 22 17:03:20 2012 +0300
@@ -353,7 +353,6 @@
 	case MAIL_INDEX_SYNC_TYPE_FLAGS:
 	case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
 	case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
-	case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
 		break;
 	}
 	if (!mail_index_lookup_seq_range(ctx->sync_view,
@@ -408,14 +407,6 @@
 					     modify_type, keywords);
 			mailbox_keywords_unref(&keywords);
 			break;
-		case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
-			kw_names[0] = NULL;
-			keywords = mailbox_keywords_create_valid(bbox->box,
-								 kw_names);
-			mail_update_keywords(bbox->sync_mail, MODIFY_REPLACE,
-					     keywords);
-			mailbox_keywords_unref(&keywords);
-			break;
 		case MAIL_INDEX_SYNC_TYPE_APPEND:
 			i_unreached();
 		}