[dovecot-cvs] dovecot/src/lib-index Makefile.am, 1.21, 1.22 mail-cache-compress.c, 1.23, 1.24 mail-cache-lookup.c, 1.24, 1.25 mail-cache-private.h, 1.16, 1.17 mail-cache-sync-update.c, NONE, 1.1 mail-cache-transaction.c, 1.30, 1.31 mail-cache.c, 1.50, 1.51 mail-index-private.h, 1.33, 1.34 mail-index-sync-private.h, 1.14, 1.15 mail-index-sync-update.c, 1.52, 1.53 mail-index-transaction-private.h, 1.15, 1.16 mail-index-transaction-view.c, 1.6, 1.7 mail-index-transaction.c, 1.32, 1.33 mail-index-view-private.h, 1.11, 1.12 mail-index-view-sync.c, 1.26, 1.27 mail-index-view.c, 1.26, 1.27 mail-index.c, 1.160, 1.161 mail-index.h, 1.133, 1.134 mail-transaction-log.c, 1.69, 1.70 mail-transaction-log.h, 1.20, 1.21 mail-transaction-util.c, 1.20, 1.21

cras at dovecot.org cras at dovecot.org
Sat Nov 6 19:20:22 EET 2004


Update of /var/lib/cvs/dovecot/src/lib-index
In directory talvi:/tmp/cvs-serv6738/src/lib-index

Modified Files:
	Makefile.am mail-cache-compress.c mail-cache-lookup.c 
	mail-cache-private.h mail-cache-transaction.c mail-cache.c 
	mail-index-private.h mail-index-sync-private.h 
	mail-index-sync-update.c mail-index-transaction-private.h 
	mail-index-transaction-view.c mail-index-transaction.c 
	mail-index-view-private.h mail-index-view-sync.c 
	mail-index-view.c mail-index.c mail-index.h 
	mail-transaction-log.c mail-transaction-log.h 
	mail-transaction-util.c 
Added Files:
	mail-cache-sync-update.c 
Log Message:
Removed cache_offset from mail_index_record and changed it to use extension
instead. Added possibility to register sync and expunge handlers for
extensions. Changed the way extension resets work: all extension updates
which were committed without having seen the reset are ignored.



Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/Makefile.am,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- Makefile.am	20 Oct 2004 23:05:55 -0000	1.21
+++ Makefile.am	6 Nov 2004 17:20:18 -0000	1.22
@@ -11,6 +11,7 @@
 	mail-cache-fields.c \
 	mail-cache-lookup.c \
 	mail-cache-transaction.c \
+	mail-cache-sync-update.c \
         mail-index.c \
         mail-index-fsck.c \
         mail-index-lock.c \

Index: mail-cache-compress.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-cache-compress.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- mail-cache-compress.c	8 Oct 2004 17:51:48 -0000	1.23
+++ mail-cache-compress.c	6 Nov 2004 17:20:18 -0000	1.24
@@ -94,6 +94,17 @@
 	return 1;
 }
 
+static uint32_t
+get_next_file_seq(struct mail_cache *cache, struct mail_index_view *view)
+{
+	const struct mail_index_ext *ext;
+	uint32_t file_seq;
+
+	ext = mail_index_view_get_ext(view, cache->ext_id);
+	file_seq = ext != NULL ? ext->reset_id + 1 : (uint32_t)ioloop_time;
+	return file_seq != 0 ? file_seq : 1;
+}
+
 static int
 mail_cache_copy(struct mail_cache *cache, struct mail_index_view *view, int fd)
 {
@@ -131,7 +142,7 @@
 	memset(&hdr, 0, sizeof(hdr));
 	hdr.version = MAIL_CACHE_VERSION;
 	hdr.indexid = idx_hdr->indexid;
-	hdr.file_seq = idx_hdr->cache_file_seq + 1;
+	hdr.file_seq = get_next_file_seq(cache, view);
 	o_stream_send(output, &hdr, sizeof(hdr));
 
 	memset(&ctx, 0, sizeof(ctx));
@@ -139,7 +150,7 @@
 	ctx.field_seen = buffer_create_dynamic(default_pool, 64);
 	ctx.field_seen_value = 0;
 
-	mail_index_reset_cache(t, hdr.file_seq);
+	mail_index_ext_reset(t, cache->ext_id, hdr.file_seq);
 
 	for (seq = 1; seq <= message_count; seq++) {
 		ctx.new_msg = seq >= first_new_seq;
@@ -161,12 +172,11 @@
 		if (cache_rec.size == sizeof(cache_rec))
 			continue;
 
-		mail_index_update_cache(t, seq, hdr.file_seq,
-					output->offset, &old_offset);
+		mail_index_update_ext(t, seq, cache->ext_id, &output->offset,
+				      &old_offset);
 
 		buffer_write(ctx.buffer, 0, &cache_rec, sizeof(cache_rec));
-		o_stream_send(output, buffer_get_data(ctx.buffer, NULL),
-			      cache_rec.size);
+		o_stream_send(output, ctx.buffer->data, cache_rec.size);
 	}
 
 	if (cache->fields_count != 0) {

Index: mail-cache-lookup.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-cache-lookup.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- mail-cache-lookup.c	8 Oct 2004 17:51:48 -0000	1.24
+++ mail-cache-lookup.c	6 Nov 2004 17:20:18 -0000	1.25
@@ -45,23 +45,37 @@
 	return cache_rec;
 }
 
-static int mail_cache_lookup_offset(struct mail_cache_view *view, uint32_t seq,
-				    uint32_t *offset_r)
+static int
+mail_cache_lookup_offset(struct mail_cache *cache, struct mail_index_view *view,
+			 uint32_t seq, uint32_t *offset_r)
 {
-	const struct mail_index_record *rec;
 	struct mail_index_map *map;
+	const struct mail_index_ext *ext;
+	const void *data;
+	uint32_t idx;
 	int i, ret;
 
-	for (i = 0; i < 2; i++) {
-		if (mail_index_lookup_full(view->view, seq, &map, &rec) < 0)
-			return -1;
+	if (mail_index_lookup_ext_full(view, seq, cache->ext_id,
+				       &map, &data) < 0)
+		return -1;
+	if (data == NULL)
+		return 0;
 
-		if (map->hdr->cache_file_seq == view->cache->hdr->file_seq) {
-			*offset_r = rec->cache_offset;
+	if (!mail_index_map_get_ext_idx(map, cache->ext_id, &idx)) {
+		/* no cache */
+		return 0;
+	}
+
+	ext = map->extensions->data;
+	ext += idx;
+
+	for (i = 0; i < 2; i++) {
+		if (cache->hdr->file_seq == ext->reset_id) {
+			*offset_r = *((const uint32_t *)data);
 			return 1;
 		}
 
-		if ((ret = mail_cache_reopen(view->cache)) <= 0)
+		if ((ret = mail_cache_reopen(cache)) <= 0)
 			return ret;
 	}
 
@@ -170,7 +184,8 @@
 	if (view->cached_offset_seq == seq)
 		offset = view->cached_offset;
 	else {
-		if ((ret = mail_cache_lookup_offset(view, seq, &offset)) <= 0)
+		if ((ret = mail_cache_lookup_offset(view->cache, view->view,
+						    seq, &offset)) <= 0)
 			return ret;
 
 		view->cached_offset_seq = seq;
@@ -191,7 +206,8 @@
 	}
 
 	if (ret > 0 && view->trans_seq1 <= seq && view->trans_seq2 >= seq &&
-	    mail_cache_transaction_lookup(view->transaction, seq, &offset)) {
+	    mail_cache_lookup_offset(view->cache, view->trans_view,
+				     seq, &offset)) {
 		buffer_set_used_size(view->offsets_buf, 0);
 		while (offset != 0 && ret > 0) {
 			if (buffer_find_offset(view->offsets_buf, offset)) {

Index: mail-cache-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-cache-private.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- mail-cache-private.h	16 Sep 2004 14:33:16 -0000	1.16
+++ mail-cache-private.h	6 Nov 2004 17:20:18 -0000	1.17
@@ -115,6 +115,7 @@
 
 struct mail_cache {
 	struct mail_index *index;
+	uint32_t ext_id;
 
 	char *filepath;
 	int fd;
@@ -142,7 +143,7 @@
 
 struct mail_cache_view {
 	struct mail_cache *cache;
-	struct mail_index_view *view;
+	struct mail_index_view *view, *trans_view;
 
 	struct mail_cache_transaction_ctx *transaction;
 	uint32_t trans_seq1, trans_seq2;
@@ -183,9 +184,6 @@
 int mail_cache_transaction_commit(struct mail_cache_transaction_ctx *ctx);
 void mail_cache_transaction_rollback(struct mail_cache_transaction_ctx *ctx);
 
-int mail_cache_transaction_lookup(struct mail_cache_transaction_ctx *ctx,
-				  uint32_t seq, uint32_t *offset_r);
-
 int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size);
 void mail_cache_file_close(struct mail_cache *cache);
 int mail_cache_reopen(struct mail_cache *cache);
@@ -201,6 +199,12 @@
 void mail_cache_decision_add(struct mail_cache_view *view, uint32_t seq,
 			     uint32_t field);
 
+int mail_cache_expunge_handler(struct mail_index_sync_map_ctx *sync_ctx,
+			       uint32_t seq, const void *data, void **context);
+int mail_cache_sync_handler(struct mail_index_sync_map_ctx *sync_ctx,
+			    uint32_t seq, void *old_data, const void *new_data,
+			    void **context);
+
 void mail_cache_set_syscall_error(struct mail_cache *cache,
 				  const char *function);
 

--- NEW FILE: mail-cache-sync-update.c ---
/* Copyright (C) 2004 Timo Sirainen */

#include "lib.h"
#include "mail-cache-private.h"
#include "mail-index-view-private.h"
#include "mail-index-sync-private.h"

struct mail_cache_sync_context {
	unsigned int locked:1;
	unsigned int lock_failed:1;
};

static void mail_cache_handler_deinit(struct mail_index_sync_map_ctx *sync_ctx,
				      struct mail_cache_sync_context *ctx)
{
	if (ctx == NULL)
		return;

	if (ctx->locked)
		mail_cache_unlock(sync_ctx->view->index->cache);
	i_free(ctx);
}

static int mail_cache_handler_init(struct mail_cache_sync_context **ctx_r,
				   struct mail_cache *cache)
{
	struct mail_cache_sync_context *ctx = *ctx_r;
	int ret;

	if (ctx == NULL)
		ctx = *ctx_r = i_new(struct mail_cache_sync_context, 1);

	if (ctx->locked || ctx->lock_failed)
		return 1;

	if (!ctx->locked) {
		if ((ret = mail_cache_lock(cache)) <= 0) {
                        ctx->lock_failed = TRUE;
			return ret;
		}
		ctx->locked = TRUE;
	}
	return 1;
}

static int get_cache_file_seq(struct mail_index_view *view,
			      uint32_t *cache_file_seq_r)
{
	const struct mail_index_ext *ext;

	ext = mail_index_view_get_ext(view, view->index->cache->ext_id);
	if (ext == NULL)
		return 0;

	*cache_file_seq_r = ext->reset_id;
	return 1;
}

int mail_cache_expunge_handler(struct mail_index_sync_map_ctx *sync_ctx,
			       uint32_t seq __attr_unused__,
			       const void *data, void **context)
{
	struct mail_index_view *view = sync_ctx->view;
	struct mail_cache_sync_context *ctx = *context;
	struct mail_cache *cache = view->index->cache;
	const uint32_t *cache_offset = data;
	uint32_t cache_file_seq;
	int ret;

	if (data == NULL) {
		mail_cache_handler_deinit(sync_ctx, ctx);
		*context = NULL;
		return 1;
	}

	if (*cache_offset == 0)
		return 1;

	ret = mail_cache_handler_init(&ctx, cache);
	*context = ctx;
	if (ret <= 0)
		return ret < 0 ? -1 : 1;

	if (!get_cache_file_seq(view, &cache_file_seq))
		return 1;

	if (!MAIL_CACHE_IS_UNUSABLE(cache) &&
	    cache_file_seq != cache->hdr->file_seq)
		(void)mail_cache_delete(cache, *cache_offset);
	return 1;
}

int mail_cache_sync_handler(struct mail_index_sync_map_ctx *sync_ctx,
			    uint32_t seq __attr_unused__,
			    void *old_data, const void *new_data,
			    void **context)
{
	struct mail_index_view *view = sync_ctx->view;
	struct mail_cache_sync_context *ctx = *context;
	const uint32_t *old_cache_offset = old_data;
	const uint32_t *new_cache_offset = new_data;
	uint32_t cache_file_seq;
	int ret;

	if (new_cache_offset == NULL) {
		mail_cache_handler_deinit(sync_ctx, ctx);
		*context = NULL;
		return 1;
	}

	if (*old_cache_offset == 0)
		return 1;

	/* we'll need to link the old and new cache records */
	ret = mail_cache_handler_init(&ctx, view->index->cache);
	*context = ctx;
	if (ret <= 0)
		return ret < 0 ? -1 : 1;

	if (!get_cache_file_seq(view, &cache_file_seq))
		return 1;

	if (cache_file_seq != view->index->cache->hdr->file_seq) {
		/* cache has been compressed, don't modify it */
		return 1;
	}

	if (mail_cache_link(view->index->cache,
			    *old_cache_offset, *new_cache_offset) < 0)
		return -1;

	return 1;
}

Index: mail-cache-transaction.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-cache-transaction.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- mail-cache-transaction.c	14 Oct 2004 23:06:49 -0000	1.30
+++ mail-cache-transaction.c	6 Nov 2004 17:20:18 -0000	1.31
@@ -52,6 +52,7 @@
 
 	i_assert(view->transaction == NULL);
 	view->transaction = ctx;
+	view->trans_view = mail_index_transaction_open_updated_view(t);
 
 	t->cache_trans_ctx = ctx;
 	return ctx;
@@ -436,9 +437,9 @@
 		   is updated to point to old cache record when index is being
 		   synced. */
 		for (; seq_idx < seq_limit; seq_idx++) {
-			mail_index_update_cache(ctx->trans, seq[seq_idx],
-						cache->hdr->file_seq,
-						write_offset, &old_offset);
+			mail_index_update_ext(ctx->trans, seq[seq_idx],
+					      cache->ext_id, &write_offset,
+					      &old_offset);
 			if (old_offset != 0) {
 				/* we added records for this message multiple
 				   times in this same uncommitted transaction.
@@ -689,12 +690,6 @@
                 buffer_append(ctx->cache_data, null4, 4 - (data_size & 3));
 }
 
-int mail_cache_transaction_lookup(struct mail_cache_transaction_ctx *ctx,
-				  uint32_t seq, uint32_t *offset_r)
-{
-	return mail_index_update_cache_lookup(ctx->trans, seq, offset_r);
-}
-
 static int mail_cache_link_unlocked(struct mail_cache *cache,
 				    uint32_t old_offset, uint32_t new_offset)
 {

Index: mail-cache.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-cache.c,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- mail-cache.c	25 Oct 2004 21:23:33 -0000	1.50
+++ mail-cache.c	6 Nov 2004 17:20:18 -0000	1.51
@@ -59,6 +59,9 @@
 
 int mail_cache_reopen(struct mail_cache *cache)
 {
+	struct mail_index_view *view;
+	const struct mail_index_ext *ext;
+
 	if (MAIL_CACHE_IS_UNUSABLE(cache) && cache->need_compress) {
 		/* unusable, we're just waiting for compression */
 		return 0;
@@ -81,15 +84,19 @@
 	if (mail_cache_header_fields_read(cache) < 0)
 		return -1;
 
-	if (cache->hdr->file_seq != cache->index->hdr->cache_file_seq) {
+	view = mail_index_view_open(cache->index);
+	ext = mail_index_view_get_ext(view, cache->ext_id);
+	if (ext == NULL || cache->hdr->file_seq != ext->reset_id) {
 		/* still different - maybe a race condition or maybe the
 		   file_seq really is corrupted. either way, this shouldn't
 		   happen often so we'll just mark cache to be compressed
 		   later which fixes this. */
 		cache->need_compress = TRUE;
+		mail_index_view_close(view);
 		return 0;
 	}
 
+	mail_index_view_close(view);
 	return 1;
 }
 
@@ -218,6 +225,13 @@
 		}
 	}
 
+	cache->ext_id =
+		mail_index_ext_register(index, "cache", 0,
+					sizeof(uint32_t), sizeof(uint32_t));
+	mail_index_register_expunge_handler(index, cache->ext_id,
+					    mail_cache_expunge_handler);
+	mail_index_register_sync_handler(index, cache->ext_id,
+					 mail_cache_sync_handler);
 	return cache;
 }
 
@@ -236,7 +250,8 @@
 
 int mail_cache_lock(struct mail_cache *cache)
 {
-	unsigned int lock_id;
+	struct mail_index_view *view;
+	const struct mail_index_ext *ext;
 	int i, ret;
 
 	i_assert(!cache->locked);
@@ -244,13 +259,20 @@
 	if (MAIL_CACHE_IS_UNUSABLE(cache))
 		return 0;
 
-	if (mail_index_lock_shared(cache->index, TRUE, &lock_id) < 0)
+	if (mail_index_view_open_locked(cache->index, &view) < 0)
 		return -1;
 
-	if (cache->hdr->file_seq != cache->index->hdr->cache_file_seq) {
+	ext = mail_index_view_get_ext(view, cache->ext_id);
+	if (ext == NULL) {
+		/* cache not used */
+		mail_index_view_close(view);
+		return 0;
+	}
+
+	if (cache->hdr->file_seq != ext->reset_id) {
 		/* we want the latest cache file */
 		if ((ret = mail_cache_reopen(cache)) <= 0) {
-			mail_index_unlock(cache->index, lock_id);
+			mail_index_view_close(view);
 			return ret;
 		}
 	}
@@ -265,7 +287,7 @@
 		}
 		cache->locked = TRUE;
 
-		if (cache->hdr->file_seq == cache->index->hdr->cache_file_seq) {
+		if (cache->hdr->file_seq == ext->reset_id) {
 			/* got it */
 			break;
 		}
@@ -280,7 +302,7 @@
 	if (ret > 0)
 		cache->hdr_copy = *cache->hdr;
 
-	mail_index_unlock(cache->index, lock_id);
+	mail_index_view_close(view);
 	return ret;
 }
 
@@ -349,6 +371,9 @@
 	if (view->cache->field_header_write_pending)
                 (void)mail_cache_header_fields_update(view->cache);
 
+	if (view->trans_view != NULL)
+		mail_index_view_close(view->trans_view);
+
 	buffer_free(view->offsets_buf);
 	buffer_free(view->cached_exists_buf);
 	i_free(view);

Index: mail-index-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-private.h,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- mail-index-private.h	25 Oct 2004 17:42:51 -0000	1.33
+++ mail-index-private.h	6 Nov 2004 17:20:18 -0000	1.34
@@ -9,6 +9,7 @@
 #include "mail-index.h"
 
 struct mail_transaction_header;
+struct mail_index_sync_map_ctx;
 
 /* How many seconds to wait a lock for index file. */
 #define MAIL_INDEX_LOCK_SECS 120
@@ -27,11 +28,19 @@
 	((struct mail_index_record *) \
 		PTR_OFFSET((map)->records, (idx) * (map)->hdr->record_size))
 
+typedef int mail_index_expunge_handler_t(struct mail_index_sync_map_ctx *ctx,
+					 uint32_t seq, const void *data,
+					 void **context);
+typedef int mail_index_sync_handler_t(struct mail_index_sync_map_ctx *ctx,
+				      uint32_t seq, void *old_data,
+				      const void *new_data, void **context);
+
 #define MAIL_INDEX_HEADER_SIZE_ALIGN(size) \
 	(((size) + 7) & ~7)
 
 struct mail_index_ext {
 	const char *name;
+	uint32_t reset_id;
 	uint32_t hdr_offset;
 	uint32_t hdr_size;
 	uint16_t record_offset;
@@ -41,6 +50,7 @@
 
 struct mail_index_ext_header {
 	uint32_t hdr_size;
+	uint32_t reset_id;
 	uint16_t record_offset;
 	uint16_t record_size;
 	uint16_t record_align;
@@ -87,6 +97,9 @@
 	pool_t extension_pool;
 	buffer_t *extensions; /* struct mail_index_ext[] */
 
+	buffer_t *expunge_handlers; /* mail_index_expunge_handler_t*[] */
+	buffer_t *sync_handlers; /* mail_index_sync_handler_t*[] */
+
 	char *filepath;
 	int fd;
 
@@ -114,6 +127,13 @@
 	unsigned int fsck:1;
 };
 
+/* Add/replace sync handler for specified extra record. */
+void mail_index_register_expunge_handler(struct mail_index *index,
+					 uint32_t ext_id,
+					 mail_index_expunge_handler_t *cb);
+void mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
+				      mail_index_sync_handler_t *cb);
+
 int mail_index_write_base_header(struct mail_index *index,
 				 const struct mail_index_header *hdr);
 
@@ -151,21 +171,11 @@
 			    struct mail_index_map *map, const char *name,
 			    uint32_t hdr_offset, uint32_t hdr_size,
 			    uint32_t record_offset, uint32_t record_size,
-			    uint32_t record_align);
+			    uint32_t record_align, uint32_t reset_id);
 int mail_index_map_get_ext_idx(struct mail_index_map *map,
 			       uint32_t ext_id, uint32_t *idx_r);
-
-int mail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
-			   struct mail_index_map **map_r,
-			   const struct mail_index_record **rec_r);
-
-void mail_index_reset_cache(struct mail_index_transaction *t,
-			    uint32_t new_file_seq);
-void mail_index_update_cache(struct mail_index_transaction *t, uint32_t seq,
-			     uint32_t file_seq, uint32_t offset,
-			     uint32_t *old_offset_r);
-int mail_index_update_cache_lookup(struct mail_index_transaction *t,
-				   uint32_t seq, uint32_t *offset_r);
+const struct mail_index_ext *
+mail_index_view_get_ext(struct mail_index_view *view, uint32_t ext_id);
 
 int mail_index_fix_header(struct mail_index *index, struct mail_index_map *map,
 			  struct mail_index_header *hdr, const char **error_r);

Index: mail-index-sync-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-sync-private.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- mail-index-sync-private.h	25 Oct 2004 17:42:51 -0000	1.14
+++ mail-index-sync-private.h	6 Nov 2004 17:20:18 -0000	1.15
@@ -25,16 +25,31 @@
 	unsigned int sync_dirty:1;
 };
 
+struct mail_index_expunge_handler {
+	mail_index_expunge_handler_t *handler;
+	void **context;
+	uint32_t record_offset;
+};
+
 struct mail_index_sync_map_ctx {
 	struct mail_index_view *view;
-	uint32_t last_ext_id;
+	uint32_t cur_ext_id;
 
-	unsigned int update_cache:1;
-	unsigned int cache_locked:1;
+	buffer_t *expunge_handlers; /* struct mail_index_expunge_handler[] */
+
+	buffer_t *extra_context_buf;
+	void **extra_context;
+
+	unsigned int sync_handlers_initialized:1;
+	unsigned int expunge_handlers_set:1;
+	unsigned int expunge_handlers_used:1;
+	unsigned int cur_ext_ignore:1;
 };
 
 extern struct mail_transaction_map_functions mail_index_map_sync_funcs;
 
+void mail_index_sync_map_init(struct mail_index_sync_map_ctx *sync_map_ctx,
+			      struct mail_index_view *view);
 int mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx,
 				 int sync_only_external);
 

Index: mail-index-sync-update.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-sync-update.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -d -r1.52 -r1.53
--- mail-index-sync-update.c	25 Oct 2004 17:42:51 -0000	1.52
+++ mail-index-sync-update.c	6 Nov 2004 17:20:18 -0000	1.53
@@ -9,7 +9,6 @@
 #include "mail-index-sync-private.h"
 #include "mail-transaction-log.h"
 #include "mail-transaction-util.h"
-#include "mail-cache-private.h"
 
 #include <stdlib.h>
 
@@ -26,6 +25,117 @@
 }
 
 static void
+mail_index_sync_init_expunge_handlers(struct mail_index_sync_map_ctx *ctx)
+{
+	const mail_index_expunge_handler_t *const *handlers;
+        const struct mail_index_ext *extensions;
+	const uint32_t *id_map;
+	struct mail_index_expunge_handler eh;
+	size_t handlers_count, id_map_size, size;
+	uint32_t ext_id;
+
+	handlers = buffer_get_data(ctx->view->index->expunge_handlers,
+				   &handlers_count);
+	handlers_count /= sizeof(*handlers);
+
+	if (handlers_count == 0)
+		return;
+
+	/* set expunge handlers */
+	memset(&eh, 0, sizeof(eh));
+	if (ctx->expunge_handlers != NULL)
+		buffer_set_used_size(ctx->expunge_handlers, 0);
+	else {
+		ctx->expunge_handlers =
+			buffer_create_dynamic(default_pool, 256);
+	}
+
+	extensions = ctx->view->map->extensions->data;
+	id_map = buffer_get_data(ctx->view->map->ext_id_map, &id_map_size);
+	id_map_size /= sizeof(*id_map);
+
+	size = I_MIN(handlers_count, id_map_size);
+	for (ext_id = 0; ext_id < size; ext_id++) {
+		if (handlers[ext_id] == NULL || id_map[ext_id] == (uint32_t)-1)
+			continue;
+
+		eh.handler = handlers[ext_id];
+		eh.context = &ctx->extra_context[ext_id];
+		eh.record_offset = extensions[id_map[ext_id]].record_offset;
+		buffer_append(ctx->expunge_handlers, &eh, sizeof(eh));
+	}
+	ctx->expunge_handlers_set = TRUE;
+	ctx->expunge_handlers_used = TRUE;
+}
+
+static void
+mail_index_sync_deinit_expunge_handlers(struct mail_index_sync_map_ctx *ctx)
+{
+	const struct mail_index_expunge_handler *eh;
+	size_t i, size;
+
+	if (ctx->expunge_handlers == NULL)
+		return;
+
+	eh = buffer_get_data(ctx->expunge_handlers, &size);
+	size /= sizeof(*eh);
+
+	for (i = 0; i < size; i++) {
+		if (eh->context != NULL)
+			eh[i].handler(ctx, 0, NULL, eh->context);
+	}
+
+	buffer_free(ctx->expunge_handlers);
+}
+
+static void mail_index_sync_init_handlers(struct mail_index_sync_map_ctx *ctx)
+{
+	size_t size;
+
+	if (ctx->view->map->extensions == NULL)
+		return;
+
+	/* set space for extra contexts */
+	size = sizeof(void *) * (ctx->view->index->extensions->used /
+				 sizeof(struct mail_index_ext));
+	if (ctx->extra_context_buf == NULL) {
+		ctx->extra_context_buf =
+			buffer_create_dynamic(default_pool, size);
+	} else {
+		buffer_set_used_size(ctx->extra_context_buf, 0);
+	}
+	buffer_append_zero(ctx->extra_context_buf, size);
+	ctx->extra_context =
+		buffer_get_modifyable_data(ctx->extra_context_buf, NULL);
+
+	ctx->expunge_handlers_set = FALSE;
+	ctx->sync_handlers_initialized = TRUE;
+}
+
+static void mail_index_sync_deinit_handlers(struct mail_index_sync_map_ctx *ctx)
+{
+	mail_index_sync_handler_t *const *sync_handlers;
+	size_t i, size;
+
+	if (ctx->extra_context == NULL)
+		return;
+
+	sync_handlers = buffer_get_data(ctx->view->index->sync_handlers, &size);
+	size /= sizeof(*sync_handlers);
+
+	i_assert(size <= ctx->extra_context_buf->used / sizeof(void *));
+
+	for (i = 0; i < size; i++) {
+		if (ctx->extra_context[i] != NULL) {
+			sync_handlers[i](ctx, 0, NULL, NULL,
+					 &ctx->extra_context[i]);
+		}
+	}
+
+	buffer_free(ctx->extra_context_buf);
+}
+
+static void
 mail_index_header_update_counts(struct mail_index_header *hdr,
 				uint8_t old_flags, uint8_t new_flags)
 {
@@ -69,24 +179,6 @@
 		hdr->first_deleted_uid_lowwater = rec->uid;
 }
 
-static void mail_index_sync_cache_expunge(struct mail_index_sync_map_ctx *ctx,
-					  uoff_t cache_offset)
-{
-	if (!ctx->update_cache)
-		return;
-
-	if (!ctx->cache_locked) {
-		if (mail_cache_lock(ctx->view->index->cache) <= 0)
-			return;
-		ctx->cache_locked = TRUE;
-	}
-
-	if (!MAIL_CACHE_IS_UNUSABLE(ctx->view->index->cache) &&
-	    ctx->view->map->hdr->cache_file_seq !=
-	    ctx->view->index->cache->hdr->file_seq)
-		(void)mail_cache_delete(ctx->view->index->cache, cache_offset);
-}
-
 static int sync_expunge(const struct mail_transaction_expunge *e, void *context)
 {
         struct mail_index_sync_map_ctx *ctx = context;
@@ -95,6 +187,8 @@
 	struct mail_index_header *hdr;
 	struct mail_index_record *rec;
 	uint32_t count, seq, seq1, seq2;
+        struct mail_index_expunge_handler *expunge_handlers, *eh;
+	size_t i, expunge_handlers_count;
 
 	if (!view->map->write_to_disk) {
 		/* expunges have to be atomic. so we'll have to copy
@@ -115,13 +209,35 @@
 	if (seq1 == 0)
 		return 1;
 
+	if (ctx->sync_handlers_initialized) {
+		if (!ctx->expunge_handlers_set)
+			mail_index_sync_init_expunge_handlers(ctx);
+
+		expunge_handlers =
+			buffer_get_modifyable_data(ctx->expunge_handlers,
+						   &expunge_handlers_count);
+		expunge_handlers_count /= sizeof(*expunge_handlers);
+	} else {
+		/* syncing view - don't call expunge handlers */
+		expunge_handlers = NULL;
+		expunge_handlers_count = 0;
+	}
+
 	hdr = buffer_get_modifyable_data(map->hdr_copy_buf, NULL);
 	for (seq = seq1; seq <= seq2; seq++) {
                 rec = MAIL_INDEX_MAP_IDX(map, seq-1);
 		mail_index_header_update_counts(hdr, rec->flags, 0);
-		
-		if (rec->cache_offset != 0)
-			mail_index_sync_cache_expunge(ctx, rec->cache_offset);
+	}
+
+	for (i = 0; i < expunge_handlers_count; i++) {
+		eh = &expunge_handlers[i];
+
+		for (seq = seq1; seq <= seq2; seq++) {
+			rec = MAIL_INDEX_MAP_IDX(map, seq-1);
+			eh->handler(ctx, seq,
+				    PTR_OFFSET(rec, eh->record_offset),
+				    eh->context);
+		}
 	}
 
 	/* @UNSAFE */
@@ -236,62 +352,6 @@
 	return 1;
 }
 
-static int sync_cache_reset(const struct mail_transaction_cache_reset *u,
-			    void *context)
-{
-        struct mail_index_sync_map_ctx *ctx = context;
-	struct mail_index_view *view = ctx->view;
-	struct mail_index_header *hdr;
-	uint32_t i;
-
-	hdr = buffer_get_modifyable_data(view->map->hdr_copy_buf, NULL);
-	hdr->cache_file_seq = u->new_file_seq;
-
-	for (i = 0; i < view->messages_count; i++)
-		MAIL_INDEX_MAP_IDX(view->map, i)->cache_offset = 0;
-	return 1;
-}
-
-static int sync_cache_update(const struct mail_transaction_cache_update *u,
-			     void *context)
-{
-        struct mail_index_sync_map_ctx *ctx = context;
-	struct mail_index_view *view = ctx->view;
-	struct mail_index_record *rec;
-	uint32_t seq;
-	int ret;
-
-	if (mail_index_lookup_uid_range(view, u->uid, u->uid, &seq, &seq) < 0)
-		return -1;
-
-	if (seq == 0) {
-		/* already expunged */
-		return 1;
-	}
-
-	rec = MAIL_INDEX_MAP_IDX(view->map, seq-1);
-	if (rec->cache_offset != 0 && ctx->update_cache) {
-		/* we'll need to link the old and new cache records */
-		if (!ctx->cache_locked) {
-			if ((ret = mail_cache_lock(view->index->cache)) <= 0)
-				return ret < 0 ? -1 : 1;
-			ctx->cache_locked = TRUE;
-		}
-
-		if (view->map->hdr->cache_file_seq !=
-		    view->index->cache->hdr->file_seq) {
-			/* cache has been compressed, don't modify it */
-			return 1;
-		}
-
-		if (mail_cache_link(view->index->cache,
-				    rec->cache_offset, u->cache_offset) < 0)
-			return -1;
-	}
-	rec->cache_offset = u->cache_offset;
-	return 1;
-}
-
 static int sync_header_update(const struct mail_transaction_header_update *u,
 			      void *context)
 {
@@ -311,6 +371,25 @@
 	return 1;
 }
 
+static struct mail_index_ext_header *
+get_ext_header(struct mail_index_map *map, const struct mail_index_ext *ext)
+{
+	struct mail_index_ext_header *ext_hdr;
+	uint32_t offset;
+	void *hdr;
+
+	/* do some kludgy jumping to get to it. */
+	offset = ext->hdr_offset -
+		MAIL_INDEX_HEADER_SIZE_ALIGN(sizeof(*ext_hdr) +
+					     strlen(ext->name));
+
+	hdr = buffer_get_modifyable_data(map->hdr_copy_buf, NULL);
+	ext_hdr = PTR_OFFSET(hdr, offset);
+	i_assert(memcmp((char *)(ext_hdr + 1),
+			ext->name, strlen(ext->name)) == 0);
+	return ext_hdr;
+}
+
 static int mail_index_ext_align_cmp(const void *p1, const void *p2)
 {
 	const struct mail_index_ext *const *e1 = p1, *const *e2 = p2;
@@ -327,7 +406,6 @@
 	uint16_t *old_offsets, min_align;
 	uint32_t offset, old_records_count, rec_idx;
 	const void *src;
-	void *hdr;
 	size_t i, size;
 
 	t_push();
@@ -407,15 +485,8 @@
 	new_map->records_count = old_records_count;
 
 	/* update record offsets in headers */
-	hdr = buffer_get_modifyable_data(new_map->hdr_copy_buf, NULL);
 	for (i = 0; i < size; i++) {
-		/* kludgy jumping to get to the beginning of header. */
-		offset = ext[i].hdr_offset -
-			MAIL_INDEX_HEADER_SIZE_ALIGN(sizeof(*ext_hdr) +
-						     strlen(ext[i].name));
-		ext_hdr = PTR_OFFSET(hdr, offset);
-		i_assert(memcmp((char *)(ext_hdr + 1),
-				ext[i].name, strlen(ext->name)) == 0);
+                ext_hdr = get_ext_header(new_map, &ext[i]);
 		ext_hdr->record_offset = ext[i].record_offset;
 	}
 
@@ -431,7 +502,7 @@
 	struct mail_index_ext *ext;
 	struct mail_index_ext_header *ext_hdr;
 	struct mail_index_header *hdr;
-	uint32_t offset, old_size, new_size, old_record_size;
+	uint32_t old_size, new_size, old_record_size;
 	int modified = FALSE;
 
 	ext = buffer_get_modifyable_data(map->extensions, NULL);
@@ -466,14 +537,8 @@
 		hdr->header_size = map->hdr_copy_buf->used;
 		map->hdr = hdr;
 
-		/* we need to modify ext header. do some kludgy jumping to
-		   get to it. */
-		offset = ext->hdr_offset -
-			MAIL_INDEX_HEADER_SIZE_ALIGN(sizeof(*ext_hdr) +
-						     strlen(ext->name));
-		ext_hdr = PTR_OFFSET(hdr, offset);
-		i_assert(memcmp((char *)(ext_hdr + 1),
-				ext->name, strlen(ext->name)) == 0);
+		ext_hdr = get_ext_header(map, ext);
+		ext_hdr->reset_id = ext->reset_id;
 		ext_hdr->hdr_size = ext->hdr_size;
 		ext_hdr->record_offset = ext->record_offset;
 		ext_hdr->record_size = ext->record_size;
@@ -483,7 +548,6 @@
 	if (old_record_size != u->record_size) {
 		map = sync_ext_reorder(map, ext_id, old_record_size);
 		mail_index_sync_replace_map(ctx->view, map);
-		modified = TRUE;
 	}
 }
 
@@ -523,11 +587,22 @@
 	}
 
 	if (ext_id != (uint32_t)-1) {
-		/* exists already - are we resizing? */
-		sync_ext_resize(u, ext_id, ctx);
+		/* exists already */
+		ext = map->extensions->data;
+		ext += ext_id;
+
+		if (u->reset_id == ext->reset_id) {
+			/* check if we need to resize anything */
+			sync_ext_resize(u, ext_id, ctx);
+			ctx->cur_ext_ignore = FALSE;
+		} else {
+			/* extension was reset and this transaction hadn't
+			   yet seen it. ignore this update. */
+			ctx->cur_ext_ignore = TRUE;
+		}
 		t_pop();
 
-		ctx->last_ext_id = ext_id;
+		ctx->cur_ext_id = ext_id;
 		return 1;
 	}
 
@@ -539,14 +614,14 @@
 				   hdr_buf->used);
 	}
 
-	/* register record offset initially using record size,
+	/* register record offset initially using zero,
 	   sync_ext_reorder() will fix it. */
 	hdr_offset = map->hdr_copy_buf->used + sizeof(ext_hdr) + strlen(name);
 	hdr_offset = MAIL_INDEX_HEADER_SIZE_ALIGN(hdr_offset);
-	ext_id = mail_index_map_register_ext(ctx->view->index, map,
-					     name, hdr_offset, u->hdr_size,
-					     map->hdr->record_size,
-					     u->record_size, u->record_align);
+	ext_id = mail_index_map_register_ext(ctx->view->index, map, name,
+					     hdr_offset, u->hdr_size, 0,
+					     u->record_size, u->record_align,
+					     u->reset_id);
 
 	ext = map->extensions->data;
 	ext += ext_id;
@@ -554,6 +629,7 @@
 	/* <ext_hdr> <name> [padding] [header data] */
 	memset(&ext_hdr, 0, sizeof(ext_hdr));
 	ext_hdr.name_size = strlen(name);
+	ext_hdr.reset_id = ext->reset_id;
 	ext_hdr.hdr_size = ext->hdr_size;
 	ext_hdr.record_offset = ext->record_offset;
 	ext_hdr.record_size = ext->record_size;
@@ -573,30 +649,38 @@
 
 	t_pop();
 
+        mail_index_sync_init_handlers(ctx);
+
 	map = sync_ext_reorder(map, ext_id, 0);
 	mail_index_sync_replace_map(ctx->view, map);
 
-	ctx->last_ext_id = ext_id;
+	ctx->cur_ext_ignore = FALSE;
+	ctx->cur_ext_id = ext_id;
 	return 1;
 }
 
-static int sync_ext_reset(void *context)
+static int sync_ext_reset(const struct mail_transaction_ext_reset *u,
+			  void *context)
 {
         struct mail_index_sync_map_ctx *ctx = context;
 	struct mail_index_view *view = ctx->view;
 	struct mail_index_map *map = view->map;
-        const struct mail_index_ext *ext;
+	struct mail_index_ext_header *ext_hdr;
+        struct mail_index_ext *ext;
 	struct mail_index_record *rec;
 	uint32_t i;
 
-	if (ctx->last_ext_id == (uint32_t)-1) {
+	if (ctx->cur_ext_id == (uint32_t)-1) {
 		mail_transaction_log_view_set_corrupted(view->log_view,
 			"Extension reset without intro prefix");
 		return -1;
 	}
+	if (ctx->cur_ext_ignore)
+		return 1;
 
-	ext = map->extensions->data;
-	ext += ctx->last_ext_id;
+	ext = buffer_get_modifyable_data(map->extensions, NULL);
+	ext += ctx->cur_ext_id;
+	ext->reset_id = u->new_reset_id;
 
 	memset(buffer_get_space_unsafe(map->hdr_copy_buf, ext->hdr_offset,
 				       ext->hdr_size), 0, ext->hdr_size);
@@ -607,6 +691,10 @@
 		memset(PTR_OFFSET(rec, ext->record_offset), 0,
 		       ext->record_size);
 	}
+
+	ext_hdr = get_ext_header(map, ext);
+	ext_hdr->reset_id = u->new_reset_id;
+
 	return 1;
 }
 
@@ -617,14 +705,16 @@
 	struct mail_index_map *map = ctx->view->map;
         const struct mail_index_ext *ext;
 
-	if (ctx->last_ext_id == (uint32_t)-1) {
+	if (ctx->cur_ext_id == (uint32_t)-1) {
 		mail_transaction_log_view_set_corrupted(ctx->view->log_view,
 			"Extension header update without intro prefix");
 		return -1;
 	}
+	if (ctx->cur_ext_ignore)
+		return 1;
 
 	ext = map->extensions->data;
-	ext += ctx->last_ext_id;
+	ext += ctx->cur_ext_id;
 
 	buffer_write(map->hdr_copy_buf, ext->hdr_offset + u->offset,
 		     u + 1, u->size);
@@ -639,26 +729,40 @@
         struct mail_index_sync_map_ctx *ctx = context;
 	struct mail_index_view *view = ctx->view;
 	struct mail_index_record *rec;
-        const struct mail_index_ext *ext;
+	mail_index_sync_handler_t *const *sync_handlers;
+	const struct mail_index_ext *ext;
+	void *old_data;
 	uint32_t seq;
+	int ret;
 
-	if (ctx->last_ext_id == (uint32_t)-1) {
-		mail_transaction_log_view_set_corrupted(ctx->view->log_view,
-			"Extension record update update without intro prefix");
-		return -1;
-	}
+	i_assert(ctx->cur_ext_id != (uint32_t)-1);
+	i_assert(!ctx->cur_ext_ignore);
 
 	if (mail_index_lookup_uid_range(view, u->uid, u->uid, &seq, &seq) < 0)
 		return -1;
 
-	if (seq != 0) {
-		ext = view->map->extensions->data;
-		ext += ctx->last_ext_id;
+	if (seq == 0)
+		return 1;
 
-		rec = MAIL_INDEX_MAP_IDX(view->map, seq-1);
-		memcpy(PTR_OFFSET(rec, ext->record_offset),
-		       u + 1, ext->record_size);
+	ext = view->map->extensions->data;
+	ext += ctx->cur_ext_id;
+
+	rec = MAIL_INDEX_MAP_IDX(view->map, seq-1);
+	old_data = PTR_OFFSET(rec, ext->record_offset);
+
+	/* @UNSAFE */
+	sync_handlers = view->index->sync_handlers->data;
+	sync_handlers += ctx->cur_ext_id;
+
+	/* call sync handlers only when we're syncing index (not view) */
+	if (*sync_handlers != NULL && ctx->sync_handlers_initialized) {
+		ret = (*sync_handlers)(ctx, seq, old_data, u + 1,
+				       &ctx->extra_context[ctx->cur_ext_id]);
+		if (ret <= 0)
+			return ret;
 	}
+
+	memcpy(old_data, u + 1, ext->record_size);
 	return 1;
 }
 
@@ -792,23 +896,6 @@
 		}
 		break;
 	}
-	case MAIL_TRANSACTION_CACHE_RESET: {
-		const struct mail_transaction_cache_reset *rec = data;
-
-		ret = sync_cache_reset(rec, ctx);
-		break;
-	}
-	case MAIL_TRANSACTION_CACHE_UPDATE: {
-		const struct mail_transaction_cache_update *rec, *end;
-
-		end = CONST_PTR_OFFSET(data, hdr->size);
-		for (rec = data; rec != end; rec++) {
-			ret = sync_cache_update(rec, ctx);
-			if (ret <= 0)
-				break;
-		}
-		break;
-	}
 	case MAIL_TRANSACTION_HEADER_UPDATE: {
 		const struct mail_transaction_header_update *rec;
 		unsigned int i;
@@ -846,9 +933,11 @@
 		}
 		break;
 	}
-	case MAIL_TRANSACTION_EXT_RESET:
-		ret = sync_ext_reset(ctx);
+	case MAIL_TRANSACTION_EXT_RESET: {
+		const struct mail_transaction_ext_reset *rec = data;
+		ret = sync_ext_reset(rec, ctx);
 		break;
+	}
 	case MAIL_TRANSACTION_EXT_HDR_UPDATE: {
 		const struct mail_transaction_ext_hdr_update *rec = data;
 		unsigned int i;
@@ -870,16 +959,24 @@
 		const struct mail_index_ext *ext;
 		unsigned int record_size;
 
-		/* call the first one, it checks if last_ext_id isn't set */
-		rec = data;
-		ret = sync_ext_rec_update(rec, ctx);
-		if (ret <= 0)
+		if (ctx->cur_ext_id == (uint32_t)-1) {
+			mail_transaction_log_view_set_corrupted(
+				ctx->view->log_view,
+				"Extension record update update "
+				"without intro prefix");
+			ret = -1;
+			break;
+		}
+
+		if (ctx->cur_ext_ignore) {
+			ret = 1;
 			break;
+		}
 
 		ext = ctx->view->map->extensions->data;
-		record_size = sizeof(*rec) + ext[ctx->last_ext_id].record_size;
+		record_size = sizeof(*rec) + ext[ctx->cur_ext_id].record_size;
 
-		rec = CONST_PTR_OFFSET(rec, record_size);
+		rec = data;
 		end = CONST_PTR_OFFSET(data, hdr->size);
 		while (rec < end) {
 			ret = sync_ext_rec_update(rec, ctx);
@@ -897,6 +994,14 @@
 	return ret;
 }
 
+void mail_index_sync_map_init(struct mail_index_sync_map_ctx *sync_map_ctx,
+			      struct mail_index_view *view)
+{
+	memset(sync_map_ctx, 0, sizeof(*sync_map_ctx));
+	sync_map_ctx->view = view;
+        sync_map_ctx->cur_ext_id = (uint32_t)-1;
+}
+
 int mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx,
 				 int sync_only_external)
 {
@@ -912,10 +1017,8 @@
 	uoff_t offset;
 	int ret, had_dirty, skipped, check_ext_offsets;
 
-	memset(&sync_map_ctx, 0, sizeof(sync_map_ctx));
-	sync_map_ctx.view = view;
-	sync_map_ctx.update_cache = TRUE;
-        sync_map_ctx.last_ext_id = (uint32_t)-1;
+        mail_index_sync_map_init(&sync_map_ctx, view);
+	mail_index_sync_init_handlers(&sync_map_ctx);
 
 	/* we'll have to update view->lock_id to avoid mail_index_view_lock()
 	   trying to update the file later. */
@@ -997,10 +1100,9 @@
 	}
 	map = view->map;
 
-	if (sync_map_ctx.cache_locked) {
-		mail_cache_unlock(index->cache);
-		sync_map_ctx.cache_locked = FALSE;
-	}
+	if (sync_map_ctx.expunge_handlers_used)
+		mail_index_sync_deinit_expunge_handlers(&sync_map_ctx);
+	mail_index_sync_deinit_handlers(&sync_map_ctx);
 
 	if (ret < 0) {
 		mail_index_view_unlock(view);

Index: mail-index-transaction-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-transaction-private.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- mail-index-transaction-private.h	17 Oct 2004 18:24:21 -0000	1.15
+++ mail-index-transaction-private.h	6 Nov 2004 17:20:18 -0000	1.16
@@ -21,9 +21,8 @@
 
 	buffer_t *ext_rec_updates; /* buffer[] */
 	buffer_t *ext_resizes; /* struct mail_transaction_ext_intro[] */
+	buffer_t *ext_resets; /* uint32_t[] */
 
-	uint32_t new_cache_file_seq, last_cache_file_seq;
-	buffer_t *cache_updates;
         struct mail_cache_transaction_ctx *cache_trans_ctx;
 
 	unsigned int hide_transaction:1;

Index: mail-index-transaction-view.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-transaction-view.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- mail-index-transaction-view.c	26 Sep 2004 14:15:54 -0000	1.6
+++ mail-index-transaction-view.c	6 Nov 2004 17:20:18 -0000	1.7
@@ -134,8 +134,10 @@
 	return 0;
 }
 
-static int _tview_lookup_ext(struct mail_index_view *view, uint32_t seq,
-			     uint32_t ext_id, const void **data_r)
+static int
+_tview_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)
 {
 	struct mail_index_view_transaction *tview =
 		(struct mail_index_view_transaction *)view;
@@ -143,21 +145,29 @@
 	buffer_t *const *ext_bufs;
 	size_t size, pos;
 
-	if (seq < tview->t->first_new_seq)
-		return tview->parent->lookup_ext(view, seq, ext_id, data_r);
-
-	i_assert(seq <= tview->t->last_new_seq);
 	i_assert(ext_id < view->index->extensions->used / sizeof(*ext));
 
 	ext = view->index->extensions->data;
 	ext += ext_id;
 
-	ext_bufs = buffer_get_data(tview->t->ext_rec_updates, &size);
-	size /= sizeof(*ext_bufs);
+	if (tview->t->ext_rec_updates == NULL) {
+		ext_bufs = NULL;
+		size = 0;
+	} else {
+		ext_bufs = buffer_get_data(tview->t->ext_rec_updates, &size);
+		size /= sizeof(*ext_bufs);
+	}
 
+	*map_r = view->index->map;
 	if (size <= ext_id || ext_bufs[ext_id] == NULL ||
 	    !mail_index_seq_buffer_lookup(ext_bufs[ext_id], seq,
 					  ext->record_size, &pos)) {
+		/* not updated, return the existing value */
+		if (seq < tview->t->first_new_seq) {
+			return tview->parent->lookup_ext_full(view, seq, ext_id,
+							      map_r, data_r);
+		}
+
 		*data_r = NULL;
 		return 1;
 	}
@@ -166,6 +176,18 @@
 	return 1;
 }
 
+static int _tview_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)
+{
+	struct mail_index_view_transaction *tview =
+		(struct mail_index_view_transaction *)view;
+
+	/* FIXME: check updates */
+	return tview->parent->get_header_ext(view, map, ext_id,
+					     data_r, data_size_r);
+}
+
 static struct mail_index_view_methods view_methods = {
 	_tview_close,
         _tview_get_message_count,
@@ -174,7 +196,8 @@
 	_tview_lookup_uid,
 	_tview_lookup_uid_range,
 	_tview_lookup_first,
-	_tview_lookup_ext
+	_tview_lookup_ext_full,
+	_tview_get_header_ext
 };
 
 struct mail_index_view *

Index: mail-index-transaction.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-transaction.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- mail-index-transaction.c	17 Oct 2004 18:24:21 -0000	1.32
+++ mail-index-transaction.c	6 Nov 2004 17:20:18 -0000	1.33
@@ -55,8 +55,10 @@
 		buffer_free(t->expunges);
 	if (t->updates != NULL)
 		buffer_free(t->updates);
-	if (t->cache_updates != NULL)
-		buffer_free(t->cache_updates);
+	if (t->ext_resizes != NULL)
+		buffer_free(t->ext_resizes);
+	if (t->ext_resets != NULL)
+		buffer_free(t->ext_resets);
 	i_free(t);
 }
 
@@ -134,8 +136,6 @@
 		sizeof(struct mail_transaction_expunge), TRUE);
 	mail_index_buffer_convert_to_uids(t, t->updates,
 		sizeof(struct mail_transaction_flag_update), TRUE);
-	mail_index_buffer_convert_to_uids(t, t->cache_updates,
-		sizeof(struct mail_transaction_cache_update), FALSE);
 	return 0;
 }
 
@@ -560,96 +560,6 @@
 	}
 }
 
-static void
-mail_index_transaction_reset_cache_updates(struct mail_index_transaction *t)
-{
-	struct mail_index_record *rec;
-	uint32_t seq;
-
-	if (t->last_cache_file_seq == 0)
-		return;
-
-	buffer_set_used_size(t->cache_updates, 0);
-
-	if (t->first_new_seq != 0) {
-		for (seq = t->first_new_seq; seq <= t->last_new_seq; seq++) {
-			rec = mail_index_transaction_lookup(t, seq);
-			rec->cache_offset = 0;
-		}
-	}
-}
-
-void mail_index_reset_cache(struct mail_index_transaction *t,
-			    uint32_t new_file_seq)
-{
-	t->log_updates = TRUE;
-
-	mail_index_transaction_reset_cache_updates(t);
-	t->new_cache_file_seq = new_file_seq;
-        t->last_cache_file_seq = new_file_seq;
-}
-
-void mail_index_update_cache(struct mail_index_transaction *t, uint32_t seq,
-			     uint32_t file_seq, uint32_t offset,
-			     uint32_t *old_offset_r)
-{
-	struct mail_index_record *rec;
-
-	i_assert(seq > 0 &&
-		 (seq <= mail_index_view_get_message_count(t->view) ||
-		  seq <= t->last_new_seq));
-
-	t->log_updates = TRUE;
-
-	if (file_seq != t->last_cache_file_seq) {
-		mail_index_transaction_reset_cache_updates(t);
-                t->last_cache_file_seq = file_seq;
-	}
-
-	if (seq >= t->first_new_seq) {
-		/* just appended message, modify it directly */
-		rec = mail_index_transaction_lookup(t, seq);
-		*old_offset_r = rec->cache_offset;
-		rec->cache_offset = offset;
-	} else {
-		if (!mail_index_update_seq_buffer(&t->cache_updates, seq,
-						  &offset, sizeof(offset),
-						  old_offset_r))
-			*old_offset_r = 0;
-	}
-}
-
-int mail_index_update_cache_lookup(struct mail_index_transaction *t,
-				   uint32_t seq, uint32_t *offset_r)
-{
-	const void *p;
-	size_t pos;
-
-	i_assert(seq > 0 &&
-		 (seq <= mail_index_view_get_message_count(t->view) ||
-		  seq <= t->last_new_seq));
-
-	if (t->cache_updates == NULL)
-		return FALSE;
-
-	if (MAIL_CACHE_IS_UNUSABLE(t->view->index->cache) ||
-	    t->view->index->cache->hdr->file_seq != t->last_cache_file_seq) {
-		/* cache file was recreated, our offsets don't work anymore */
-		mail_index_transaction_reset_cache_updates(t);
-		t->last_cache_file_seq = 0;
-		return FALSE;
-	}
-
-	if (!mail_index_seq_buffer_lookup(t->cache_updates, seq,
-					  sizeof(*offset_r), &pos))
-		return FALSE;
-
-	p = buffer_get_data(t->cache_updates, NULL);
-	memcpy(offset_r, CONST_PTR_OFFSET(p, pos + sizeof(*offset_r)),
-	       sizeof(*offset_r));
-	return TRUE;
-}
-
 void mail_index_update_header(struct mail_index_transaction *t,
 			      size_t offset, const void *data, size_t size)
 {
@@ -687,6 +597,8 @@
 		 (ext->record_size == record_size &&
 		  ext->record_align == record_align));
 
+	t->log_updates = TRUE;
+
 	if (t->ext_resizes == NULL)
 		t->ext_resizes = buffer_create_dynamic(default_pool, 128);
 
@@ -698,6 +610,32 @@
 		     &intro, sizeof(intro));
 }
 
+void mail_index_ext_reset(struct mail_index_transaction *t, uint32_t ext_id,
+			  uint32_t reset_id)
+{
+	size_t pos;
+
+	i_assert(reset_id != 0);
+
+	t->log_updates = TRUE;
+
+	if (t->ext_rec_updates != NULL &&
+	    ext_id < t->ext_rec_updates->used / sizeof(buffer_t *)) {
+		buffer_t *const *buf = t->ext_rec_updates->data;
+		buf += ext_id;
+
+		if (*buf != NULL) 
+			buffer_set_used_size(*buf, 0);
+	}
+
+	pos = ext_id * sizeof(uint32_t);
+	if (t->ext_resets == NULL) {
+		t->ext_resets = buffer_create_dynamic(default_pool,
+						      pos + sizeof(uint32_t));
+	}
+	buffer_write(t->ext_resets, pos, &reset_id, sizeof(reset_id));
+}
+
 void mail_index_update_header_ext(struct mail_index_transaction *t,
 				  uint32_t ext_id, size_t offset,
 				  const void *data, size_t size)
@@ -706,7 +644,7 @@
 }
 
 void mail_index_update_ext(struct mail_index_transaction *t, uint32_t seq,
-			   uint32_t ext_id, const void *data)
+			   uint32_t ext_id, const void *data, void *old_data_r)
 {
 	struct mail_index *index = t->view->index;
         const struct mail_index_ext *ext;
@@ -741,5 +679,11 @@
 	buf = buffer_get_space_unsafe(t->ext_rec_updates,
 				      ext_id * sizeof(buffer_t *),
 				      sizeof(buffer_t *));
-	mail_index_update_seq_buffer(buf, seq, data, record_size, NULL);
+
+	/* @UNSAFE */
+	if (!mail_index_update_seq_buffer(buf, seq, data, record_size,
+					  old_data_r)) {
+		if (old_data_r != NULL)
+			memset(old_data_r, 0, record_size);
+	}
 }

Index: mail-index-view-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-view-private.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- mail-index-view-private.h	17 Oct 2004 16:42:20 -0000	1.11
+++ mail-index-view-private.h	6 Nov 2004 17:20:18 -0000	1.12
@@ -18,8 +18,12 @@
 				uint32_t *first_seq_r, uint32_t *last_seq_r);
 	int (*lookup_first)(struct mail_index_view *view, enum mail_flags flags,
 			    uint8_t flags_mask, uint32_t *seq_r);
-	int (*lookup_ext)(struct mail_index_view *view, uint32_t seq,
-			  uint32_t ext_id, const void **data_r);
+	int (*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);
+	int (*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);
 };
 
 struct mail_index_view {

Index: mail-index-view-sync.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-view-sync.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- mail-index-view-sync.c	25 Oct 2004 17:42:51 -0000	1.26
+++ mail-index-view-sync.c	6 Nov 2004 17:20:18 -0000	1.27
@@ -122,9 +122,7 @@
 	ctx->view = view;
 	ctx->trans_sync_mask = want_mask;
 	ctx->expunges = expunges;
-
-	ctx->sync_map_ctx.view = view;
-	ctx->sync_map_ctx.last_ext_id = (uint32_t)-1;
+	mail_index_sync_map_init(&ctx->sync_map_ctx, view);
 
 	if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0) {
 		view->new_map = view->index->map;

Index: mail-index-view.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-view.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- mail-index-view.c	25 Oct 2004 17:42:51 -0000	1.26
+++ mail-index-view.c	6 Nov 2004 17:20:18 -0000	1.27
@@ -374,25 +374,24 @@
 	return 0;
 }
 
-static int _view_lookup_ext(struct mail_index_view *view, uint32_t seq,
-			    uint32_t ext_id, const void **data_r)
+static int _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)
 {
 	const struct mail_index_ext *ext;
 	const struct mail_index_record *rec;
-	struct mail_index_map *map;
 	uint32_t idx, offset;
 	int ret;
 
-	if ((ret = mail_index_lookup_full(view, seq, &map, &rec)) < 0)
+	if ((ret = mail_index_lookup_full(view, seq, map_r, &rec)) < 0)
 		return -1;
 
-	if (rec == NULL ||
-	    !mail_index_map_get_ext_idx(view->map, ext_id, &idx)) {
+	if (rec == NULL || !mail_index_map_get_ext_idx(*map_r, ext_id, &idx)) {
 		*data_r = NULL;
 		return ret;
 	}
 
-	ext = view->map->extensions->data;
+	ext = (*map_r)->extensions->data;
 	ext += idx;
 
 	offset = ext->record_offset;
@@ -400,6 +399,30 @@
 	return ret;
 }
 
+static int _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;
+
+	if (map != NULL) {
+		if (mail_index_view_lock(view) < 0)
+			return -1;
+	} else {
+		if (mail_index_view_lock_head(view, FALSE) < 0)
+			return -1;
+
+		map = view->index->map;
+	}
+
+	ext = map->extensions->data;
+	ext += ext_id;
+
+	*data_r = CONST_PTR_OFFSET(map->hdr, ext->hdr_offset);
+	*data_size_r = ext->hdr_size;
+	return 0;
+}
+
 void mail_index_view_close(struct mail_index_view *view)
 {
 	view->methods.close(view);
@@ -454,7 +477,31 @@
 int mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
 			  uint32_t ext_id, const void **data_r)
 {
-	return view->methods.lookup_ext(view, seq, ext_id, data_r);
+	struct mail_index_map *map;
+
+	return view->methods.lookup_ext_full(view, seq, ext_id, &map, data_r);
+}
+
+int mail_index_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)
+{
+	return view->methods.lookup_ext_full(view, seq, ext_id, map_r, data_r);
+}
+
+int mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id,
+			      const void **data_r, size_t *data_size_r)
+{
+	return view->methods.get_header_ext(view, NULL, ext_id,
+					    data_r, data_size_r);
+}
+
+int mail_index_map_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)
+{
+	return view->methods.get_header_ext(view, map, ext_id,
+					    data_r, data_size_r);
 }
 
 static struct mail_index_view_methods view_methods = {
@@ -465,7 +512,8 @@
 	_view_lookup_uid,
 	_view_lookup_uid_range,
 	_view_lookup_first,
-	_view_lookup_ext
+	_view_lookup_ext_full,
+	_view_get_header_ext
 };
 
 struct mail_index_view *mail_index_view_open(struct mail_index *index)
@@ -488,3 +536,35 @@
 		      view->map->log_file_ext_offset);
 	return view;
 }
+
+int mail_index_view_open_locked(struct mail_index *index,
+				struct mail_index_view **view_r)
+{
+	unsigned int lock_id;
+
+	if (mail_index_lock_shared(index, TRUE, &lock_id) < 0)
+		return -1;
+
+	*view_r = mail_index_view_open(index);
+	if (mail_index_view_lock_head(*view_r, FALSE) < 0) {
+		mail_index_view_close(*view_r);
+		mail_index_unlock(index, lock_id);
+		return -1;
+	}
+
+	mail_index_unlock(index, lock_id);
+	return 0;
+}
+
+const struct mail_index_ext *
+mail_index_view_get_ext(struct mail_index_view *view, uint32_t ext_id)
+{
+	const struct mail_index_ext *ext;
+	uint32_t idx;
+
+	if (!mail_index_map_get_ext_idx(view->map, ext_id, &idx))
+		return 0;
+
+	ext = view->map->extensions->data;
+	return &ext[idx];
+}

Index: mail-index.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index.c,v
retrieving revision 1.160
retrieving revision 1.161
diff -u -d -r1.160 -r1.161
--- mail-index.c	25 Oct 2004 20:04:43 -0000	1.160
+++ mail-index.c	6 Nov 2004 17:20:19 -0000	1.161
@@ -27,6 +27,8 @@
 
 	index->extension_pool = pool_alloconly_create("extension", 256);
 	index->extensions = buffer_create_dynamic(index->extension_pool, 64);
+        index->sync_handlers = buffer_create_dynamic(default_pool, 32);
+        index->expunge_handlers = buffer_create_dynamic(default_pool, 32);
 
 	index->mode = 0600;
 	index->gid = (gid_t)-1;
@@ -38,6 +40,9 @@
 	mail_index_close(index);
 	pool_unref(index->extension_pool);
 
+	buffer_free(index->sync_handlers);
+	buffer_free(index->expunge_handlers);
+
 	i_free(index->error);
 	i_free(index->dir);
 	i_free(index->prefix);
@@ -64,6 +69,9 @@
 	extensions = buffer_get_data(index->extensions, &ext_count);
 	ext_count /= sizeof(*extensions);
 
+	i_assert(index->sync_handlers->used /
+		 sizeof(mail_index_sync_handler_t *) == ext_count);
+
 	/* see if it's already there */
 	for (i = 0; i < ext_count; i++) {
 		if (strcmp(extensions[i].name, name) == 0)
@@ -77,9 +85,26 @@
 	ext.record_align = default_record_align;
 
 	buffer_append(index->extensions, &ext, sizeof(ext));
+	buffer_append_zero(index->sync_handlers,
+			   sizeof(mail_index_sync_handler_t *));
 	return ext_count;
 }
 
+void mail_index_register_expunge_handler(struct mail_index *index,
+					 uint32_t ext_id,
+					 mail_index_expunge_handler_t *cb)
+{
+	buffer_write(index->expunge_handlers, ext_id * sizeof(cb),
+		     &cb, sizeof(cb));
+}
+
+void mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
+				      mail_index_sync_handler_t *cb)
+{
+	buffer_write(index->sync_handlers, ext_id * sizeof(cb),
+		     &cb, sizeof(cb));
+}
+
 static void mail_index_map_init_extbufs(struct mail_index_map *map,
 					unsigned int initial_count)
 {
@@ -125,7 +150,7 @@
 			    struct mail_index_map *map, const char *name,
 			    uint32_t hdr_offset, uint32_t hdr_size,
 			    uint32_t record_offset, uint32_t record_size,
-			    uint32_t record_align)
+			    uint32_t record_align, uint32_t reset_id)
 {
 	struct mail_index_ext *ext;
 	uint32_t idx, ext_id;
@@ -146,6 +171,7 @@
 	ext->record_offset = record_offset;
 	ext->record_size = record_size;
 	ext->record_align = record_align;
+	ext->reset_id = reset_id;
 
 	ext_id = mail_index_ext_register(index, name, hdr_size,
 					 record_size, record_align);
@@ -216,7 +242,8 @@
 					    offset, ext_hdr->hdr_size,
 					    ext_hdr->record_offset,
 					    ext_hdr->record_size,
-					    ext_hdr->record_align);
+					    ext_hdr->record_align,
+					    ext_hdr->reset_id);
 		t_pop();
 
 		offset += MAIL_INDEX_HEADER_SIZE_ALIGN(ext_hdr->hdr_size);
@@ -577,8 +604,15 @@
 		ret = mail_index_map_try_existing(index->map);
 		if (ret != 0)
 			return ret;
+
+		if (index->lock_type == F_WRLCK) {
+			/* we're syncing, don't break the mapping */
+			return 1;
+		}
 	}
 
+	i_assert(index->lock_type != F_WRLCK);
+
 	if (index->map != NULL && index->map->refcount > 1) {
 		/* this map is already used by some views and they may have
 		   pointers into it. leave them and create a new mapping. */

Index: mail-index.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index.h,v
retrieving revision 1.133
retrieving revision 1.134
diff -u -d -r1.133 -r1.134
--- mail-index.h	25 Oct 2004 17:42:51 -0000	1.133
+++ mail-index.h	6 Nov 2004 17:20:19 -0000	1.134
@@ -6,7 +6,7 @@
 #define MAIL_INDEX_MAJOR_VERSION 6
 #define MAIL_INDEX_MINOR_VERSION 0
 
-#define MAIL_INDEX_HEADER_MIN_SIZE 124
+#define MAIL_INDEX_HEADER_MIN_SIZE 120
 
 /* Number of keywords in mail_index_record. */
 #define INDEX_KEYWORDS_COUNT (3*8)
@@ -103,8 +103,6 @@
 	uint64_t sync_size;
 	uint32_t sync_stamp;
 
-	uint32_t cache_file_seq;
-
 	/* daily first UIDs that have been added to index. */
 	uint32_t day_stamp;
 	uint32_t day_first_uid[8];
@@ -114,7 +112,6 @@
 	uint32_t uid;
 	uint8_t flags; /* mail_flags | mail_index_mail_flags */
 	keywords_mask_t keywords;
-	uint32_t cache_offset;
 };
 
 enum mail_index_sync_type {
@@ -136,6 +133,7 @@
 };
 
 struct mail_index;
+struct mail_index_map;
 struct mail_index_view;
 struct mail_index_transaction;
 struct mail_index_sync_ctx;
@@ -158,9 +156,11 @@
 
 /* View can be used to look into index. Sequence numbers inside view change
    only when you synchronize it. The view acquires required locks
-   automatically, but you'll have to drop them manually. Opening view
-   acquires a lock immediately. */
+   automatically, but you'll have to drop them manually. */
 struct mail_index_view *mail_index_view_open(struct mail_index *index);
+/* Open view to latest index locked. */
+int mail_index_view_open_locked(struct mail_index *index,
+				struct mail_index_view **view_r);
 void mail_index_view_close(struct mail_index_view *view);
 
 /* Returns the index for given view. */
@@ -255,6 +255,9 @@
    expunged but data was returned from some older index.  */
 int mail_index_lookup(struct mail_index_view *view, uint32_t seq,
 		      const struct mail_index_record **rec_r);
+int mail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
+			   struct mail_index_map **map_r,
+			   const struct mail_index_record **rec_r);
 /* Returns the UID for given message. May be slightly faster than
    mail_index_lookup()->uid. */
 int mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
@@ -318,19 +321,33 @@
 			   uint32_t hdr_size, uint16_t record_size,
 			   uint16_t record_align);
 
+/* Reset extension records and header. Any updates for this extension which
+   were issued before the writer had seen this reset are discarded. reset_id is
+   used to figure this out, so it must be different every time. */
+void mail_index_ext_reset(struct mail_index_transaction *t, uint32_t ext_id,
+			  uint32_t reset_id);
+
 /* Returns extension header. */
 int mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id,
 			      const void **data_r, size_t *data_size_r);
+int mail_index_map_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);
 /* Returns the wanted extension record for given message. If it doesn't exist,
    *data_r is set to NULL. Return values are same as for mail_index_lookup(). */
 int mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
 			  uint32_t ext_id, const void **data_r);
+int mail_index_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);
 /* Update extension header field. */
 void mail_index_update_header_ext(struct mail_index_transaction *t,
 				  uint32_t ext_id, size_t offset,
 				  const void *data, size_t size);
-/* Update extension record. */
+/* Update extension record. If old_data_r is non-NULL and the record extension
+   was already updated in this transaction, it's set to contain the data it's
+   now overwriting. */
 void mail_index_update_ext(struct mail_index_transaction *t, uint32_t seq,
-			   uint32_t ext_id, const void *data);
+			   uint32_t ext_id, const void *data, void *old_data);
 
 #endif

Index: mail-transaction-log.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log.c,v
retrieving revision 1.69
retrieving revision 1.70
diff -u -d -r1.69 -r1.70
--- mail-transaction-log.c	25 Oct 2004 17:42:51 -0000	1.69
+++ mail-transaction-log.c	6 Nov 2004 17:20:19 -0000	1.70
@@ -25,14 +25,6 @@
 
 #define LOG_NEW_DOTLOCK_SUFFIX ".newlock"
 
-struct mail_transaction_add_ctx {
-	struct mail_transaction_log *log;
-	struct mail_index_view *view;
-
-	buffer_t *appends, *expunges;
-	buffer_t *flag_updates, *cache_updates;
-};
-
 static struct mail_transaction_log_file *
 mail_transaction_log_file_open_or_create(struct mail_transaction_log *log,
 					 const char *path);
@@ -921,55 +913,6 @@
 	return ret;
 }
 
-static int mail_transaction_log_scan_pending(struct mail_transaction_log *log,
-					     struct mail_index_transaction *t)
-{
-	struct mail_transaction_log_view *sync_view;
-	const struct mail_transaction_header *hdr;
-	const void *data;
-	uint32_t max_cache_file_seq = 0;
-	int ret;
-
-	sync_view = mail_transaction_log_view_open(log);
-	ret = mail_transaction_log_view_set(sync_view, t->view->log_file_seq,
-					    t->view->log_file_offset,
-					    log->head->hdr.file_seq, (uoff_t)-1,
-					    MAIL_TRANSACTION_TYPE_MASK);
-	while ((ret = mail_transaction_log_view_next(sync_view,
-						     &hdr, &data, NULL)) == 1) {
-		switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
-		case MAIL_TRANSACTION_CACHE_RESET: {
-			const struct mail_transaction_cache_reset *reset = data;
-
-			max_cache_file_seq = reset->new_file_seq;
-			break;
-		}
-		}
-	}
-
-	/* make sure we're not writing cache_offsets to old cache file */
-	if (t->new_cache_file_seq == 0 && max_cache_file_seq != 0 &&
-	    max_cache_file_seq != t->last_cache_file_seq &&
-	    t->cache_updates != NULL) {
-		buffer_free(t->cache_updates);
-		t->cache_updates = NULL;
-
-		if (t->appends != NULL) {
-			struct mail_index_record *rec;
-			size_t i, size;
-
-			rec = buffer_get_modifyable_data(t->appends, &size);
-			size /= sizeof(*rec);
-
-			for (i = 0; i < size; i++)
-				rec[i].cache_offset = 0;
-		}
-	}
-
-	mail_transaction_log_view_close(sync_view);
-	return ret;
-}
-
 static int log_append_buffer(struct mail_transaction_log_file *file,
 			     const buffer_t *buf, const buffer_t *hdr_buf,
 			     enum mail_transaction_type type, int external)
@@ -1028,19 +971,6 @@
 	return 0;
 }
 
-static const buffer_t *get_cache_reset_buf(struct mail_index_transaction *t)
-{
-	struct mail_transaction_cache_reset u;
-	buffer_t *buf;
-
-	memset(&u, 0, sizeof(u));
-	u.new_file_seq = t->new_cache_file_seq;
-
-	buf = buffer_create_static_hard(pool_datastack_create(), sizeof(u));
-	buffer_append(buf, &u, sizeof(u));
-	return buf;
-}
-
 static const buffer_t *
 log_get_hdr_update_buffer(struct mail_index_transaction *t)
 {
@@ -1071,10 +1001,9 @@
 	return buf;
 }
 
-static int
-mail_transaction_log_append_ext_intro(struct mail_transaction_log_file *file,
-				      struct mail_index_transaction *t,
-				      uint32_t ext_id)
+static int log_append_ext_intro(struct mail_transaction_log_file *file,
+				struct mail_index_transaction *t,
+				uint32_t ext_id, uint32_t reset_id)
 {
 	const struct mail_index_ext *ext;
         struct mail_transaction_ext_intro *intro;
@@ -1117,6 +1046,19 @@
 		intro->name_size = idx != (uint32_t)-1 ? 0 :
 			strlen(ext->name);
 	}
+	if (reset_id != 0) {
+		/* we're going to reset this extension in this transaction */
+		intro->reset_id = reset_id;
+	} else if (idx != (uint32_t)-1) {
+		/* use the existing reset_id */
+		const struct mail_index_ext *map_ext =
+			t->view->map->extensions->data;
+		map_ext += idx;
+
+		intro->reset_id = map_ext->reset_id;
+	} else {
+		/* new extension, reset_id defaults to 0 */
+	}
 	buffer_append(buf, ext->name, intro->name_size);
 
 	if ((buf->used % 4) != 0)
@@ -1131,15 +1073,18 @@
 				       struct mail_index_transaction *t)
 {
         const struct mail_transaction_ext_intro *resize;
-	uint32_t ext_id, ext_count, update_count, resize_count;
-	buffer_t **update;
+	struct mail_transaction_ext_reset ext_reset;
+	uint32_t ext_id, ext_count, update_count, resize_count, reset_count;
+	const uint32_t *reset;
+	const buffer_t *const *update;
+	buffer_t *buf;
 	size_t size;
 
 	if (t->ext_rec_updates == NULL) {
 		update = NULL;
 		update_count = 0;
 	} else {
-		update = buffer_get_modifyable_data(t->ext_rec_updates, &size);
+		update = buffer_get_data(t->ext_rec_updates, &size);
 		update_count = size / sizeof(*update);
 	}
 
@@ -1147,17 +1092,39 @@
 		resize = NULL;
 		resize_count = 0;
 	} else {
-		resize = buffer_get_modifyable_data(t->ext_resizes, &size);
+		resize = buffer_get_data(t->ext_resizes, &size);
 		resize_count = size / sizeof(*resize);
 	}
 
-	ext_count = I_MAX(update_count, resize_count);
+	if (t->ext_resets == NULL) {
+		reset = NULL;
+		reset_count = 0;
+	} else {
+		reset = buffer_get_data(t->ext_resets, &size);
+		reset_count = size / sizeof(*reset);
+	}
+
+	memset(&ext_reset, 0, sizeof(ext_reset));
+
+	buf = buffer_create_data(pool_datastack_create(),
+				 &ext_reset, sizeof(ext_reset));
+	buffer_set_used_size(buf, sizeof(ext_reset));
+	ext_count = I_MAX(I_MAX(update_count, resize_count), reset_count);
 
 	for (ext_id = 0; ext_id < ext_count; ext_id++) {
+		ext_reset.new_reset_id =
+			ext_id < reset_count && reset[ext_id] != 0 ?
+			reset[ext_id] : 0;
 		if ((ext_id < resize_count && resize[ext_id].name_size) ||
-		    (ext_id < update_count && update[ext_id] != NULL)) {
-			if (mail_transaction_log_append_ext_intro(file, t,
-								  ext_id) < 0)
+		    (ext_id < update_count && update[ext_id] != NULL) ||
+		    ext_reset.new_reset_id != 0) {
+			if (log_append_ext_intro(file, t, ext_id, 0) < 0)
+				return -1;
+		}
+		if (ext_reset.new_reset_id != 0) {
+			if (log_append_buffer(file, buf, NULL,
+					      MAIL_TRANSACTION_EXT_RESET,
+					      t->view->external) < 0)
 				return -1;
 		}
 	}
@@ -1165,6 +1132,48 @@
 	return 0;
 }
 
+static int log_append_ext_rec_updates(struct mail_transaction_log_file *file,
+				      struct mail_index_transaction *t,
+				      int external)
+{
+	buffer_t **updates;
+	const uint32_t *reset;
+	uint32_t ext_id, reset_id, reset_count;
+	size_t size;
+
+	if (t->ext_rec_updates == NULL) {
+		updates = NULL;
+		size = 0;
+	} else {
+		updates = buffer_get_modifyable_data(t->ext_rec_updates, &size);
+		size /= sizeof(*updates);
+	}
+
+	if (t->ext_resets == NULL) {
+		reset = NULL;
+		reset_count = 0;
+	} else {
+		reset = buffer_get_data(t->ext_resets, &size);
+		reset_count = size / sizeof(*reset);
+	}
+
+	for (ext_id = 0; ext_id < size; ext_id++) {
+		if (updates[ext_id] == NULL)
+			continue;
+
+		reset_id = ext_id < reset_count && reset[ext_id] != 0 ?
+			reset[ext_id] : 0;
+		if (log_append_ext_intro(file, t, ext_id, reset_id) < 0)
+			return -1;
+
+		if (log_append_buffer(file, updates[ext_id], NULL,
+				      MAIL_TRANSACTION_EXT_REC_UPDATE,
+				      external) < 0)
+			return -1;
+	}
+	return 0;
+}
+
 int mail_transaction_log_append(struct mail_index_transaction *t,
 				uint32_t *log_file_seq_r,
 				uoff_t *log_file_offset_r)
@@ -1175,9 +1184,7 @@
 	struct mail_transaction_log_file *file;
 	struct mail_index_header idx_hdr;
 	uoff_t append_offset;
-	buffer_t **updates;
-	unsigned int i, lock_id;
-	size_t size;
+	unsigned int lock_id;
 	int ret;
 
 	index = mail_index_view_get_index(view);
@@ -1232,23 +1239,6 @@
 	file->first_append_size = 0;
 	append_offset = file->sync_offset;
 
-	if (t->cache_updates != NULL &&
-	    t->last_cache_file_seq < idx_hdr.cache_file_seq) {
-		/* cache_offsets point to old file, don't allow */
-		buffer_free(t->cache_updates);
-		t->cache_updates = NULL;
-	}
-
-	if (t->appends != NULL ||
-	    (t->cache_updates != NULL && t->new_cache_file_seq == 0) ||
-	    (t->ext_rec_updates != NULL && t->ext_rec_updates->used > 0)) {
-		if (mail_transaction_log_scan_pending(log, t) < 0) {
-			if (!log->index->log_locked)
-				mail_transaction_log_file_unlock(file);
-			return -1;
-		}
-	}
-
 	ret = 0;
 
 	/* send all extension introductions and resizes before appends
@@ -1265,37 +1255,9 @@
 					MAIL_TRANSACTION_FLAG_UPDATE,
 					view->external);
 	}
-	if (t->new_cache_file_seq != 0) {
-		ret = log_append_buffer(file, get_cache_reset_buf(t), NULL,
-					MAIL_TRANSACTION_CACHE_RESET,
-					view->external);
-	}
-	if (t->cache_updates != NULL && ret == 0) {
-		ret = log_append_buffer(file, t->cache_updates, NULL,
-					MAIL_TRANSACTION_CACHE_UPDATE,
-					view->external);
-	}
-
-	if (t->ext_rec_updates == NULL) {
-		updates = NULL;
-		size = 0;
-	} else {
-		updates = buffer_get_modifyable_data(t->ext_rec_updates, &size);
-		size /= sizeof(*updates);
-	}
 
-	for (i = 0; i < size && ret == 0; i++) {
-		if (updates[i] == NULL)
-			continue;
-
-		ret = mail_transaction_log_append_ext_intro(file, t, i);
-		if (ret < 0)
-			break;
-
-		ret = log_append_buffer(file, updates[i], NULL,
-					MAIL_TRANSACTION_EXT_REC_UPDATE,
-					view->external);
-	}
+	if (t->ext_rec_updates != NULL && ret == 0)
+		ret = log_append_ext_rec_updates(file, t, view->external);
 
 	if (t->expunges != NULL && ret == 0) {
 		ret = log_append_buffer(file, t->expunges, NULL,

Index: mail-transaction-log.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- mail-transaction-log.h	17 Oct 2004 18:24:21 -0000	1.20
+++ mail-transaction-log.h	6 Nov 2004 17:20:19 -0000	1.21
@@ -16,8 +16,6 @@
 	MAIL_TRANSACTION_EXPUNGE		= 0x00000001,
 	MAIL_TRANSACTION_APPEND			= 0x00000002,
 	MAIL_TRANSACTION_FLAG_UPDATE		= 0x00000004,
-	MAIL_TRANSACTION_CACHE_RESET		= 0x00000008,
-	MAIL_TRANSACTION_CACHE_UPDATE		= 0x00000010,
 	MAIL_TRANSACTION_HEADER_UPDATE		= 0x00000020,
 	MAIL_TRANSACTION_EXT_INTRO		= 0x00000040,
 	MAIL_TRANSACTION_EXT_RESET		= 0x00000080,
@@ -53,15 +51,6 @@
 	keywords_mask_t remove_keywords;
 };
 
-struct mail_transaction_cache_reset {
-	uint32_t new_file_seq;
-};
-
-struct mail_transaction_cache_update {
-	uint32_t uid;
-	uint32_t cache_offset;
-};
-
 struct mail_transaction_header_update {
 	uint16_t offset;
 	uint16_t size;
@@ -72,6 +61,7 @@
 	/* old extension: set ext_id. don't set name.
 	   new extension: ext_id = (uint32_t)-1. give name. */
 	uint32_t ext_id;
+	uint32_t reset_id;
 	uint32_t hdr_size;
 	uint16_t record_size;
 	uint16_t record_align;
@@ -80,6 +70,10 @@
 	/* unsigned char name[]; */
 };
 
+struct mail_transaction_ext_reset {
+	uint32_t new_reset_id;
+};
+
 /* these are set for the last ext_intro */
 struct mail_transaction_ext_hdr_update {
 	uint16_t offset;

Index: mail-transaction-util.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-util.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- mail-transaction-util.c	17 Oct 2004 18:24:21 -0000	1.20
+++ mail-transaction-util.c	6 Nov 2004 17:20:19 -0000	1.21
@@ -13,13 +13,10 @@
 	  sizeof(struct mail_transaction_expunge) },
 	{ MAIL_TRANSACTION_FLAG_UPDATE, MAIL_INDEX_SYNC_TYPE_FLAGS,
 	  sizeof(struct mail_transaction_flag_update) },
-	{ MAIL_TRANSACTION_CACHE_RESET, 0,
-	  sizeof(struct mail_transaction_cache_reset) },
-	{ MAIL_TRANSACTION_CACHE_UPDATE, 0,
-	  sizeof(struct mail_transaction_cache_update) },
 	{ MAIL_TRANSACTION_HEADER_UPDATE, 0, 1 }, /* variable size, use 1 */
 	{ MAIL_TRANSACTION_EXT_INTRO, 0, 1 },
-	{ MAIL_TRANSACTION_EXT_RESET, 0, 0 },
+	{ MAIL_TRANSACTION_EXT_RESET, 0,
+	  sizeof(struct mail_transaction_ext_reset) },
 	{ MAIL_TRANSACTION_EXT_HDR_UPDATE, 0, 1 },
 	{ MAIL_TRANSACTION_EXT_REC_UPDATE, 0, 1 },
 	{ 0, 0, 0 }



More information about the dovecot-cvs mailing list