dovecot-1.2: mail_get_flags/keywords() now returns updated value...

dovecot at dovecot.org dovecot at dovecot.org
Sun Dec 14 07:21:17 EET 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/7b16388a3bb0
changeset: 8549:7b16388a3bb0
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Dec 14 07:19:48 2008 +0200
description:
mail_get_flags/keywords() now returns updated values if they've been changed within transaction.

diffstat:

9 files changed, 277 insertions(+), 141 deletions(-)
src/lib-index/mail-index-dummy-view.c          |    1 
src/lib-index/mail-index-transaction-private.h |    6 
src/lib-index/mail-index-transaction-view.c    |  113 +++++++++++
src/lib-index/mail-index-transaction.c         |   15 -
src/lib-index/mail-index-view-private.h        |    2 
src/lib-index/mail-index-view.c                |  239 ++++++++++++------------
src/lib-storage/index/index-mail.c             |   35 ++-
src/lib-storage/index/index-mail.h             |    1 
src/plugins/virtual/virtual-mail.c             |    6 

diffs (truncated from 622 to 300 lines):

diff -r 6a6a3bfea547 -r 7b16388a3bb0 src/lib-index/mail-index-dummy-view.c
--- a/src/lib-index/mail-index-dummy-view.c	Sun Dec 14 06:51:04 2008 +0200
+++ b/src/lib-index/mail-index-dummy-view.c	Sun Dec 14 07:19:48 2008 +0200
@@ -29,6 +29,7 @@ static struct mail_index_view_vfuncs dum
 	NULL,
 	NULL,
 	NULL,
+	NULL,
 	NULL
 };
 
diff -r 6a6a3bfea547 -r 7b16388a3bb0 src/lib-index/mail-index-transaction-private.h
--- a/src/lib-index/mail-index-transaction-private.h	Sun Dec 14 06:51:04 2008 +0200
+++ b/src/lib-index/mail-index-transaction-private.h	Sun Dec 14 07:19:48 2008 +0200
@@ -100,6 +100,12 @@ void mail_index_transaction_convert_to_u
 void mail_index_transaction_convert_to_uids(struct mail_index_transaction *t);
 void mail_index_transaction_check_conflicts(struct mail_index_transaction *t);
 
+unsigned int
+mail_index_transaction_get_flag_update_pos(struct mail_index_transaction *t,
+					   unsigned int left_idx,
+					   unsigned int right_idx,
+					   uint32_t seq);
+
 bool mail_index_seq_array_lookup(const ARRAY_TYPE(seq_array) *array,
 				 uint32_t seq, unsigned int *idx_r);
 
diff -r 6a6a3bfea547 -r 7b16388a3bb0 src/lib-index/mail-index-transaction-view.c
--- a/src/lib-index/mail-index-transaction-view.c	Sun Dec 14 06:51:04 2008 +0200
+++ b/src/lib-index/mail-index-transaction-view.c	Sun Dec 14 07:19:48 2008 +0200
@@ -15,8 +15,12 @@ struct mail_index_view_transaction {
 
 	struct mail_index_map *lookup_map;
 	struct mail_index_header hdr;
+
 	buffer_t *lookup_return_data;
 	uint32_t lookup_prev_seq;
+
+	unsigned int recs_count;
+	struct mail_index_record *recs;
 };
 
 static void tview_close(struct mail_index_view *view)
@@ -29,6 +33,7 @@ static void tview_close(struct mail_inde
 		mail_index_unmap(&tview->lookup_map);
 	if (tview->lookup_return_data != NULL)
 		buffer_free(&tview->lookup_return_data);
+	i_free(tview->recs);
 
 	tview->super->close(view);
 	mail_index_transaction_unref(&t);
@@ -62,6 +67,42 @@ tview_get_header(struct mail_index_view 
 		hdr = &tview->hdr;
 	}
 	return hdr;
+}
+
+static const struct mail_index_record *
+tview_apply_flag_updates(struct mail_index_view_transaction *tview,
+			 const struct mail_index_record *rec, uint32_t seq)
+{
+	struct mail_index_transaction *t = tview->t;
+	const struct mail_transaction_flag_update *updates;
+	unsigned int idx, count;
+
+	/* see if there are any flag updates */
+	if (seq < t->min_flagupdate_seq || seq > t->max_flagupdate_seq ||
+	    !array_is_created(&t->updates))
+		return rec;
+
+	updates = array_get(&t->updates, &count);
+	idx = mail_index_transaction_get_flag_update_pos(t, 0, count, seq);
+	if (seq < updates[idx].uid1 || seq > updates[idx].uid2)
+		return rec;
+
+	/* yes, we have flag updates. since we can't modify rec directly and
+	   we want to be able to handle multiple mail_index_lookup() calls
+	   without the second one overriding the first one's data, we'll
+	   create a records array and return data from there */
+	if (tview->recs == NULL) {
+		tview->recs_count = t->first_new_seq;
+		tview->recs = i_new(struct mail_index_record,
+				    tview->recs_count);
+	}
+	i_assert(tview->recs_count == t->first_new_seq);
+	i_assert(seq > 0 && seq <= tview->recs_count);
+
+	tview->recs[seq-1] = *rec;
+	tview->recs[seq-1].flags |= updates[idx].add_flags;
+	tview->recs[seq-1].flags &= ~updates[idx].remove_flags;
+	return &tview->recs[seq-1];
 }
 
 static const struct mail_index_record *
@@ -81,8 +122,8 @@ tview_lookup_full(struct mail_index_view
 	}
 
 	rec = tview->super->lookup_full(view, seq, map_r, expunged_r);
-
-	/* if we're expunged within this transaction, return 0 */
+	rec = tview_apply_flag_updates(tview, rec, seq);
+
 	if (array_is_created(&tview->t->expunges) &&
 	    seq_range_exists(&tview->t->expunges, seq))
 		*expunged_r = TRUE;
@@ -187,6 +228,73 @@ static void tview_lookup_first(struct ma
 			*seq_r = seq;
 			break;
 		}
+	}
+}
+
+static void keyword_index_add(ARRAY_TYPE(keyword_indexes) *keywords,
+			      unsigned int idx)
+{
+	const unsigned int *indexes;
+	unsigned int i, count;
+
+	indexes = array_get(keywords, &count);
+	for (i = 0; i < count; i++) {
+		if (indexes[i] == idx)
+			return;
+	}
+	array_append(keywords, &idx, 1);
+}
+
+static void keyword_index_remove(ARRAY_TYPE(keyword_indexes) *keywords,
+				 unsigned int idx)
+{
+	const unsigned int *indexes;
+	unsigned int i, count;
+
+	indexes = array_get(keywords, &count);
+	for (i = 0; i < count; i++) {
+		if (indexes[i] == idx) {
+			array_delete(keywords, i, 1);
+			break;
+		}
+	}
+}
+
+static void tview_lookup_keywords(struct mail_index_view *view, uint32_t seq,
+				  ARRAY_TYPE(keyword_indexes) *keyword_idx)
+{
+	struct mail_index_view_transaction *tview =
+		(struct mail_index_view_transaction *)view;
+	struct mail_index_transaction *t = tview->t;
+	const struct mail_index_transaction_keyword_update *updates;
+	unsigned int i, count;
+
+	tview->super->lookup_keywords(view, seq, keyword_idx);
+
+	if (seq < t->min_flagupdate_seq || seq > t->max_flagupdate_seq) {
+		/* no keyword updates for this sequence */
+		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 {
+		updates = NULL;
+		count = 0;
+	}
+	for (i = 0; i < count; i++) {
+		if (array_is_created(&updates[i].add_seq) &&
+		    seq_range_exists(&updates[i].add_seq, seq))
+			keyword_index_add(keyword_idx, i);
+		else if (array_is_created(&updates[i].remove_seq) &&
+			 seq_range_exists(&updates[i].remove_seq, seq))
+			keyword_index_remove(keyword_idx, i);
 	}
 }
 
@@ -336,6 +444,7 @@ static struct mail_index_view_vfuncs tra
 	tview_lookup_uid,
 	tview_lookup_seq_range,
 	tview_lookup_first,
+	tview_lookup_keywords,
 	tview_lookup_ext_full,
 	tview_get_header_ext,
 	tview_ext_get_reset_id
diff -r 6a6a3bfea547 -r 7b16388a3bb0 src/lib-index/mail-index-transaction.c
--- a/src/lib-index/mail-index-transaction.c	Sun Dec 14 06:51:04 2008 +0200
+++ b/src/lib-index/mail-index-transaction.c	Sun Dec 14 07:19:48 2008 +0200
@@ -805,10 +805,11 @@ mail_transaction_update_want_add(struct 
 	return FALSE;
 }
 
-static uint32_t
-mail_index_find_update_insert_pos(struct mail_index_transaction *t,
-				  unsigned int left_idx, unsigned int right_idx,
-				  uint32_t seq)
+unsigned int
+mail_index_transaction_get_flag_update_pos(struct mail_index_transaction *t,
+					   unsigned int left_idx,
+					   unsigned int right_idx,
+					   uint32_t seq)
 {
 	const struct mail_transaction_flag_update *updates;
 	unsigned int idx, count;
@@ -1038,8 +1039,8 @@ void mail_index_update_flags_range(struc
 			first_idx = 0;
 			count = t->last_update_idx + 1;
 		}
-		idx = mail_index_find_update_insert_pos(t, first_idx, count,
-							u.uid1);
+		idx = mail_index_transaction_get_flag_update_pos(t, first_idx,
+								 count, u.uid1);
 		mail_index_insert_flag_update(t, u, idx);
 	}
 }
@@ -1567,7 +1568,7 @@ mail_index_update_cancel(struct mail_ind
 		return ret;
 
 	updates = array_get_modifiable(&t->updates, &count);
-	i = mail_index_find_update_insert_pos(t, 0, count, seq);
+	i = mail_index_transaction_get_flag_update_pos(t, 0, count, seq);
 	if (i < count && updates[i].uid1 <= seq && updates[i].uid2 >= seq) {
 		/* exists */
 		ret = TRUE;
diff -r 6a6a3bfea547 -r 7b16388a3bb0 src/lib-index/mail-index-view-private.h
--- a/src/lib-index/mail-index-view-private.h	Sun Dec 14 06:51:04 2008 +0200
+++ b/src/lib-index/mail-index-view-private.h	Sun Dec 14 07:19:48 2008 +0200
@@ -26,6 +26,8 @@ struct mail_index_view_vfuncs {
 	void (*lookup_first)(struct mail_index_view *view,
 			     enum mail_flags flags, uint8_t flags_mask,
 			     uint32_t *seq_r);
+	void (*lookup_keywords)(struct mail_index_view *view, uint32_t seq,
+				ARRAY_TYPE(keyword_indexes) *keyword_idx);
 	void (*lookup_ext_full)(struct mail_index_view *view, uint32_t seq,
 				uint32_t ext_id, struct mail_index_map **map_r,
 				const void **data_r, bool *expunged_r);
diff -r 6a6a3bfea547 -r 7b16388a3bb0 src/lib-index/mail-index-view.c
--- a/src/lib-index/mail-index-view.c	Sun Dec 14 06:51:04 2008 +0200
+++ b/src/lib-index/mail-index-view.c	Sun Dec 14 07:19:48 2008 +0200
@@ -333,116 +333,6 @@ static void view_lookup_first(struct mai
 }
 
 static void
-view_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
-		     uint32_t ext_id, struct mail_index_map **map_r,
-		     const void **data_r, bool *expunged_r)
-{
-	const struct mail_index_ext *ext;
-	const struct mail_index_record *rec;
-	uint32_t idx, offset;
-
-	rec = view->v.lookup_full(view, seq, map_r, expunged_r);
-	if (!mail_index_map_get_ext_idx(*map_r, ext_id, &idx)) {
-		*data_r = NULL;
-		return;
-	}
-
-	ext = array_idx(&(*map_r)->extensions, idx);
-	offset = ext->record_offset;
-
-	*data_r = offset == 0 ? NULL : CONST_PTR_OFFSET(rec, offset);
-}
-
-static void view_get_header_ext(struct mail_index_view *view,
-				struct mail_index_map *map, uint32_t ext_id,
-				const void **data_r, size_t *data_size_r)
-{
-	const struct mail_index_ext *ext;
-	uint32_t idx;
-
-	if (map == NULL) {
-		/* no mapping given, use head mapping */
-		map = view->index->map;
-	}
-
-	if (!mail_index_map_get_ext_idx(map, ext_id, &idx)) {
-		/* extension doesn't exist in this index file */
-		*data_r = NULL;
-		*data_size_r = 0;
-		return;
-	}
-
-	ext = array_idx(&map->extensions, idx);
-	*data_r = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
-	*data_size_r = ext->hdr_size;
-}
-
-static bool view_ext_get_reset_id(struct mail_index_view *view ATTR_UNUSED,
-				  struct mail_index_map *map,
-				  uint32_t ext_id, uint32_t *reset_id_r)
-{
-	const struct mail_index_ext *ext;
-	uint32_t idx;
-
-	if (!mail_index_map_get_ext_idx(map, ext_id, &idx))
-		return FALSE;
-
-	ext = array_idx(&map->extensions, idx);


More information about the dovecot-cvs mailing list