[dovecot-cvs] dovecot/src/lib-index mail-index-sync-private.h, 1.12, 1.13 mail-index-sync-update.c, 1.50, 1.51 mail-index-transaction-private.h, 1.14, 1.15 mail-index-transaction.c, 1.31, 1.32 mail-index-view-sync.c, 1.23, 1.24 mail-transaction-log.c, 1.66, 1.67 mail-transaction-log.h, 1.19, 1.20 mail-transaction-util.c, 1.19, 1.20 mail-transaction-util.h, 1.10, 1.11

cras at dovecot.org cras at dovecot.org
Sun Oct 17 21:24:23 EEST 2004


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

Modified Files:
	mail-index-sync-private.h mail-index-sync-update.c 
	mail-index-transaction-private.h mail-index-transaction.c 
	mail-index-view-sync.c mail-transaction-log.c 
	mail-transaction-log.h mail-transaction-util.c 
	mail-transaction-util.h 
Log Message:
New way of handling extension introductions in transaction log.



Index: mail-index-sync-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-sync-private.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- mail-index-sync-private.h	4 Oct 2004 16:31:51 -0000	1.12
+++ mail-index-sync-private.h	17 Oct 2004 18:24:21 -0000	1.13
@@ -27,6 +27,7 @@
 
 struct mail_index_sync_map_ctx {
 	struct mail_index_view *view;
+	uint32_t last_ext_id;
 
 	unsigned int update_cache:1;
 	unsigned int cache_locked:1;
@@ -36,6 +37,10 @@
 
 int mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx);
 
+int mail_index_sync_record(struct mail_index_sync_map_ctx *ctx,
+			   const struct mail_transaction_header *hdr,
+			   const void *data);
+
 void
 mail_index_sync_get_expunge(struct mail_index_sync_rec *rec,
 			    const struct mail_transaction_expunge *exp);

Index: mail-index-sync-update.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-sync-update.c,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- mail-index-sync-update.c	17 Oct 2004 16:39:58 -0000	1.50
+++ mail-index-sync-update.c	17 Oct 2004 18:24:21 -0000	1.51
@@ -423,7 +423,7 @@
 	return new_map;
 }
 
-static int
+static void
 sync_ext_resize(const struct mail_transaction_ext_intro *u, uint32_t ext_id,
 		struct mail_index_sync_map_ctx *ctx)
 {
@@ -434,13 +434,6 @@
 	uint32_t offset, old_size, new_size, old_record_size;
 	int modified = FALSE;
 
-	if (ext_id != u->ext_id) {
-		mail_transaction_log_view_set_corrupted(ctx->view->log_view,
-			"Introduced existing extension with wrong id: %u != %u",
-			u->ext_id, ext_id);
-		return -1;
-	}
-
 	ext = buffer_get_modifyable_data(map->extensions, NULL);
 	ext += ext_id;
 
@@ -492,8 +485,6 @@
 		mail_index_sync_replace_map(ctx->view, map);
 		modified = TRUE;
 	}
-
-	return 1;
 }
 
 static int sync_ext_intro(const struct mail_transaction_ext_intro *u,
@@ -507,17 +498,37 @@
 	const char *name;
 	buffer_t *hdr_buf;
 	uint32_t ext_id, hdr_offset;
-	int ret;
+
+	if (u->ext_id != (uint32_t)-1 &&
+	    (map->extensions == NULL ||
+	     u->ext_id >= map->extensions->used / sizeof(*ext))) {
+		mail_transaction_log_view_set_corrupted(ctx->view->log_view,
+			"Extension introduction for unknown id %u", u->ext_id);
+		return -1;
+	}
+
+	if (u->ext_id == (uint32_t)-1 && u->name_size == 0) {
+		mail_transaction_log_view_set_corrupted(ctx->view->log_view,
+			"Extension introduction without id or name");
+		return -1;
+	}
 
 	t_push();
-	name = t_strndup(u + 1, u->name_size);
+	if (u->ext_id != (uint32_t)-1) {
+		name = NULL;
+		ext_id = u->ext_id;
+	} else {
+		name = t_strndup(u + 1, u->name_size);
+		ext_id = mail_index_map_lookup_ext(map, name);
+	}
 
-	ext_id = mail_index_map_lookup_ext(map, name);
 	if (ext_id != (uint32_t)-1) {
 		/* exists already - are we resizing? */
-		ret = sync_ext_resize(u, ext_id, ctx);
+		sync_ext_resize(u, ext_id, ctx);
 		t_pop();
-		return ret;
+
+		ctx->last_ext_id = ext_id;
+		return 1;
 	}
 
 	hdr_buf = map->hdr_copy_buf;
@@ -562,20 +573,14 @@
 
 	t_pop();
 
-	if (ext_id != u->ext_id) {
-		mail_transaction_log_view_set_corrupted(ctx->view->log_view,
-			"Introduced extension with invalid id: %u != %u",
-			u->ext_id, ext_id);
-		return -1;
-	}
-
 	map = sync_ext_reorder(map, ext_id, 0);
 	mail_index_sync_replace_map(ctx->view, map);
+
+	ctx->last_ext_id = ext_id;
 	return 1;
 }
 
-static int sync_ext_reset(const struct mail_transaction_ext_rec_header *u,
-			  void *context)
+static int sync_ext_reset(void *context)
 {
         struct mail_index_sync_map_ctx *ctx = context;
 	struct mail_index_view *view = ctx->view;
@@ -584,15 +589,14 @@
 	struct mail_index_record *rec;
 	uint32_t i;
 
-	if (map->extensions == NULL ||
-	    u->ext_id >= map->extensions->used / sizeof(*ext)) {
+	if (ctx->last_ext_id == (uint32_t)-1) {
 		mail_transaction_log_view_set_corrupted(view->log_view,
-			"Extension reset for unknown id %u", u->ext_id);
+			"Extension reset without intro prefix");
 		return -1;
 	}
 
 	ext = map->extensions->data;
-	ext += u->ext_id;
+	ext += ctx->last_ext_id;
 
 	memset(buffer_get_space_unsafe(map->hdr_copy_buf, ext->hdr_offset,
 				       ext->hdr_size), 0, ext->hdr_size);
@@ -613,15 +617,14 @@
 	struct mail_index_map *map = ctx->view->map;
         const struct mail_index_ext *ext;
 
-	if (map->extensions == NULL ||
-	    u->ext_id >= map->extensions->used / sizeof(*ext)) {
+	if (ctx->last_ext_id == (uint32_t)-1) {
 		mail_transaction_log_view_set_corrupted(ctx->view->log_view,
-			"Extension header update for unknown id %u", u->ext_id);
+			"Extension header update without intro prefix");
 		return -1;
 	}
 
 	ext = map->extensions->data;
-	ext += u->ext_id;
+	ext += ctx->last_ext_id;
 
 	buffer_write(map->hdr_copy_buf, ext->hdr_offset + u->offset,
 		     u + 1, u->size);
@@ -630,8 +633,7 @@
 }
 
 static int
-sync_ext_rec_update(const struct mail_transaction_ext_rec_header *hdr,
-		    const struct mail_transaction_ext_rec_update *u,
+sync_ext_rec_update(const struct mail_transaction_ext_rec_update *u,
 		    void *context)
 {
         struct mail_index_sync_map_ctx *ctx = context;
@@ -640,10 +642,9 @@
         const struct mail_index_ext *ext;
 	uint32_t seq;
 
-	if (view->map->extensions == NULL ||
-	    hdr->ext_id >= view->map->extensions->used / sizeof(*ext)) {
-		mail_transaction_log_view_set_corrupted(view->log_view,
-			"Extension update for unknown id %u", hdr->ext_id);
+	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;
 	}
 
@@ -652,7 +653,7 @@
 
 	if (seq != 0) {
 		ext = view->map->extensions->data;
-		ext += hdr->ext_id;
+		ext += ctx->last_ext_id;
 
 		rec = MAIL_INDEX_MAP_IDX(view->map, seq-1);
 		memcpy(PTR_OFFSET(rec, ext->record_offset),
@@ -750,6 +751,152 @@
 	hdr->day_first_uid[0] = uid;
 }
 
+int mail_index_sync_record(struct mail_index_sync_map_ctx *ctx,
+			   const struct mail_transaction_header *hdr,
+			   const void *data)
+{
+	int ret = 0;
+
+	switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
+	case MAIL_TRANSACTION_APPEND: {
+		const struct mail_index_record *rec, *end;
+
+		end = CONST_PTR_OFFSET(data, hdr->size);
+		for (rec = data; rec < end; rec++) {
+			ret = sync_append(rec, ctx);
+			if (ret <= 0)
+				break;
+		}
+		break;
+	}
+	case MAIL_TRANSACTION_EXPUNGE:
+	case MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT: {
+		const struct mail_transaction_expunge *rec, *end;
+
+		end = CONST_PTR_OFFSET(data, hdr->size);
+		for (rec = data; rec < end; rec++) {
+			ret = sync_expunge(rec, ctx);
+			if (ret <= 0)
+				break;
+		}
+		break;
+	}
+	case MAIL_TRANSACTION_FLAG_UPDATE: {
+		const struct mail_transaction_flag_update *rec, *end;
+
+		end = CONST_PTR_OFFSET(data, hdr->size);
+		for (rec = data; rec < end; rec++) {
+			ret = sync_flag_update(rec, ctx);
+			if (ret <= 0)
+				break;
+		}
+		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;
+
+		for (i = 0; i < hdr->size; ) {
+			rec = CONST_PTR_OFFSET(data, i);
+			ret = sync_header_update(rec, ctx);
+			if (ret <= 0)
+				break;
+
+			i += sizeof(*rec) + rec->size;
+			if ((i % 4) != 0)
+				i += 4 - (i % 4);
+		}
+		break;
+	}
+	case MAIL_TRANSACTION_EXT_INTRO: {
+		const struct mail_transaction_ext_intro *rec = data;
+		unsigned int i;
+
+		for (i = 0; i < hdr->size; ) {
+			if (i + sizeof(*rec) > hdr->size) {
+				/* should be just extra padding */
+				break;
+			}
+
+			rec = CONST_PTR_OFFSET(data, i);
+			ret = sync_ext_intro(rec, ctx);
+			if (ret <= 0)
+				break;
+
+			i += sizeof(*rec) + rec->name_size;
+			if ((i % 4) != 0)
+				i += 4 - (i % 4);
+		}
+		break;
+	}
+	case MAIL_TRANSACTION_EXT_RESET:
+		ret = sync_ext_reset(ctx);
+		break;
+	case MAIL_TRANSACTION_EXT_HDR_UPDATE: {
+		const struct mail_transaction_ext_hdr_update *rec = data;
+		unsigned int i;
+
+		for (i = 0; i < hdr->size; ) {
+			rec = CONST_PTR_OFFSET(data, i);
+			ret = sync_ext_hdr_update(rec, ctx);
+			if (ret <= 0)
+				break;
+
+			i += sizeof(*rec) + rec->size;
+			if ((i % 4) != 0)
+				i += 4 - (i % 4);
+		}
+		break;
+	}
+	case MAIL_TRANSACTION_EXT_REC_UPDATE: {
+		const struct mail_transaction_ext_rec_update *rec, *end;
+		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)
+			break;
+
+		ext = ctx->view->map->extensions->data;
+		record_size = sizeof(*rec) + ext[ctx->last_ext_id].record_size;
+
+		rec = CONST_PTR_OFFSET(rec, record_size);
+		end = CONST_PTR_OFFSET(data, hdr->size);
+		while (rec < end) {
+			ret = sync_ext_rec_update(rec, ctx);
+			if (ret <= 0)
+				break;
+
+			rec = CONST_PTR_OFFSET(rec, record_size);
+		}
+		break;
+	}
+	default:
+		i_unreached();
+	}
+
+	return ret;
+}
+
 int mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx)
 {
 	struct mail_index *index = sync_ctx->index;
@@ -767,6 +914,7 @@
 	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;
 
 	/* we'll have to update view->lock_id to avoid mail_index_view_lock()
 	   trying to update the file later. */
@@ -821,9 +969,7 @@
 			}
 		}
 
-		if (mail_transaction_map(view->map, thdr, data,
-					 &mail_index_map_sync_funcs,
-					 &sync_map_ctx) < 0) {
+		if (mail_index_sync_record(&sync_map_ctx, thdr, data) < 0) {
 			ret = -1;
 			break;
 		}
@@ -884,10 +1030,3 @@
         mail_index_view_unlock(view);
 	return ret;
 }
-
-struct mail_transaction_map_functions mail_index_map_sync_funcs = {
-	sync_expunge, sync_append, sync_flag_update,
-	sync_cache_reset, sync_cache_update, sync_header_update,
-	sync_ext_intro, sync_ext_reset,
-	sync_ext_hdr_update, sync_ext_rec_update
-};

Index: mail-index-transaction-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-transaction-private.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- mail-index-transaction-private.h	3 Oct 2004 16:32:59 -0000	1.14
+++ mail-index-transaction-private.h	17 Oct 2004 18:24:21 -0000	1.15
@@ -21,8 +21,6 @@
 
 	buffer_t *ext_rec_updates; /* buffer[] */
 	buffer_t *ext_resizes; /* struct mail_transaction_ext_intro[] */
-	buffer_t *ext_intros;
-	uint32_t ext_intros_max_id;
 
 	uint32_t new_cache_file_seq, last_cache_file_seq;
 	buffer_t *cache_updates;

Index: mail-index-transaction.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-transaction.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -d -r1.31 -r1.32
--- mail-index-transaction.c	8 Oct 2004 17:51:48 -0000	1.31
+++ mail-index-transaction.c	17 Oct 2004 18:24:21 -0000	1.32
@@ -57,8 +57,6 @@
 		buffer_free(t->updates);
 	if (t->cache_updates != NULL)
 		buffer_free(t->cache_updates);
-	if (t->ext_intros != NULL)
-		buffer_free(t->ext_intros);
 	i_free(t);
 }
 

Index: mail-index-view-sync.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-view-sync.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- mail-index-view-sync.c	17 Oct 2004 16:42:20 -0000	1.23
+++ mail-index-view-sync.c	17 Oct 2004 18:24:21 -0000	1.24
@@ -206,10 +206,10 @@
 
 		memset(&sync_map_ctx, 0, sizeof(sync_map_ctx));
 		sync_map_ctx.view = view;
+		sync_map_ctx.last_ext_id = (uint32_t)-1;
 
-		if (mail_transaction_map(view->map, ctx->hdr, ctx->data,
-					 &mail_index_map_sync_funcs,
-					 &sync_map_ctx) < 0)
+		if (mail_index_sync_record(&sync_map_ctx, ctx->hdr,
+					   ctx->data) < 0)
 			return -1;
 	}
 

Index: mail-transaction-log.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log.c,v
retrieving revision 1.66
retrieving revision 1.67
diff -u -d -r1.66 -r1.67
--- mail-transaction-log.c	17 Oct 2004 16:39:58 -0000	1.66
+++ mail-transaction-log.c	17 Oct 2004 18:24:21 -0000	1.67
@@ -921,38 +921,6 @@
 	return ret;
 }
 
-static void
-transaction_save_ext_intro(struct mail_index_transaction *t,
-			   const struct mail_transaction_ext_intro *intro)
-{
-	const char *name;
-	void *p;
-	uint32_t ext_id;
-	size_t pos;
-
-	if (t->ext_intros == NULL)
-		t->ext_intros = buffer_create_dynamic(default_pool, 128);
-
-	t_push();
-	name = t_strndup((const char *)(intro+1), intro->name_size);
-	ext_id = mail_index_ext_register(t->view->index, name,
-					 intro->hdr_size, intro->record_size,
-					 intro->record_align);
-	pos = ext_id * sizeof(intro->ext_id);
-	if (pos > t->ext_intros->used) {
-		/* unused records are -1 */
-		p = buffer_append_space_unsafe(t->ext_intros,
-					       pos - t->ext_intros->used);
-		memset(p, 0xff, pos - t->ext_intros->used);
-	}
-
-	buffer_write(t->ext_intros, pos,
-		     &intro->ext_id, sizeof(intro->ext_id));
-	if (intro->ext_id > t->ext_intros_max_id)
-		t->ext_intros_max_id = intro->ext_id;
-	t_pop();
-}
-
 static int mail_transaction_log_scan_pending(struct mail_transaction_log *log,
 					     struct mail_index_transaction *t)
 {
@@ -976,23 +944,6 @@
 			max_cache_file_seq = reset->new_file_seq;
 			break;
 		}
-		case MAIL_TRANSACTION_EXT_INTRO: {
-			const struct mail_transaction_ext_intro *intro;
-			uint32_t i;
-
-			for (i = 0; i < hdr->size; ) {
-				if (i + sizeof(*intro) > hdr->size) {
-					/* should be just extra padding */
-					break;
-				}
-
-				intro = CONST_PTR_OFFSET(data, i);
-				transaction_save_ext_intro(t, intro);
-
-				i += sizeof(*intro) + intro->name_size;
-			}
-			break;
-		}
 		}
 	}
 
@@ -1120,121 +1071,111 @@
 	return buf;
 }
 
-static uint32_t
-mail_transaction_log_lookup_ext(struct mail_index_transaction *t,
-				uint32_t ext_id)
-{
-	const uint32_t *id_map;
-	uint32_t idx;
-	size_t size;
-
-	/* already in nonsynced part of transaction log? */
-	if (t->ext_intros != NULL) {
-		id_map = buffer_get_data(t->ext_intros, &size);
-		size /= sizeof(*id_map);
-
-		if (ext_id < size && id_map[ext_id] != (uint32_t)-1)
-			return id_map[ext_id];
-	}
-
-	if (mail_index_map_get_ext_idx(t->view->map, ext_id, &idx))
-		return idx;
-
-	return (uint32_t)-1;
-}
-
 static int
-mail_transaction_log_append_ext_intros(struct mail_transaction_log_file *file,
-				       struct mail_index_transaction *t)
+mail_transaction_log_append_ext_intro(struct mail_transaction_log_file *file,
+				      struct mail_index_transaction *t,
+				      uint32_t ext_id)
 {
 	const struct mail_index_ext *ext;
         struct mail_transaction_ext_intro *intro;
-	buffer_t **updates, *buf;
+	buffer_t *buf;
 	uint32_t idx;
-	size_t i, size;
-
-	ext = t->view->index->extensions->data;
-
-	if (t->ext_rec_updates != NULL) {
-		updates = buffer_get_modifyable_data(t->ext_rec_updates, &size);
-		size /= sizeof(*updates);
-
-		/* add new extension introductions into resize buffer */
-		for (i = 0; i < size; i++) {
-			if (updates[i] == NULL)
-				continue;
+	size_t size;
 
-			idx = mail_transaction_log_lookup_ext(t, i);
-			if (idx == (uint32_t)-1) {
-				mail_index_ext_resize(t, i, ext[i].hdr_size,
-						      ext[i].record_size,
-						      ext[i].record_align);
-			}
-		}
+	if (!mail_index_map_get_ext_idx(t->view->map, ext_id, &idx)) {
+		/* new extension */
+		idx = (uint32_t)-1;
 	}
 
-	if (t->ext_resizes == NULL)
-		return 0;
+	ext = t->view->index->extensions->data;
+	ext += ext_id;
 
-	/* give IDs to new extensions */
-	intro = buffer_get_modifyable_data(t->ext_resizes, &size);
-	size /= sizeof(*intro);
-	for (i = 0; i < size; i++) {
-		if (intro[i].name_size != 0 && intro[i].ext_id == (uint32_t)-1)
-			intro[i].ext_id = t->ext_intros_max_id++;
+	if (t->ext_resizes == NULL) {
+		intro = NULL;
+		size = 0;
+	} else {
+		intro = buffer_get_modifyable_data(t->ext_resizes, &size);
+		size /= sizeof(*intro);
 	}
 
-	/* and register them */
 	buf = buffer_create_dynamic(pool_datastack_create(), 128);
-	for (i = 0; i < size; i++) {
-		if (intro[i].name_size != 0) {
-			intro[i].name_size = strlen(ext[i].name);
-			buffer_append(buf, &intro[i], sizeof(*intro));
-			buffer_append(buf, ext[i].name, intro[i].name_size);
-		}
+	if (ext_id < size && intro[ext_id].name_size != 0) {
+		/* we're resizing it */
+		intro += ext_id;
+
+		i_assert(intro->ext_id == idx);
+		intro->name_size = idx != (uint32_t)-1 ? 0 :
+			strlen(ext->name);
+		buffer_append(buf, intro, sizeof(*intro));
+	} else {
+		/* generate a new intro structure */
+		intro = buffer_append_space_unsafe(buf, sizeof(*intro));
+		intro->ext_id = idx;
+		intro->hdr_size = ext->hdr_size;
+		intro->record_size = ext->record_size;
+		intro->record_align = ext->record_align;
+		intro->name_size = idx != (uint32_t)-1 ? 0 :
+			strlen(ext->name);
 	}
+	buffer_append(buf, ext->name, intro->name_size);
 
 	if ((buf->used % 4) != 0)
 		buffer_append_zero(buf, 4 - (buf->used % 4));
 
-	if (buf->used == 0)
-		return 0;
-
 	return log_append_buffer(file, buf, NULL, MAIL_TRANSACTION_EXT_INTRO,
 				 t->view->external);
 }
 
-static uint32_t
-mail_transaction_log_get_ext_idx(struct mail_index_transaction *t,
-				 uint32_t ext_id)
+static int
+mail_transaction_log_append_ext_intros(struct mail_transaction_log_file *file,
+				       struct mail_index_transaction *t)
 {
-        const struct mail_transaction_ext_intro *intro;
-	uint32_t idx;
+        const struct mail_transaction_ext_intro *resize;
+	uint32_t ext_id, ext_count, update_count, resize_count;
+	buffer_t **update;
+	size_t size;
 
-	idx = mail_transaction_log_lookup_ext(t, ext_id);
-	if (idx != (uint32_t)-1)
-		return idx;
+	if (t->ext_rec_updates == NULL) {
+		update = NULL;
+		update_count = 0;
+	} else {
+		update = buffer_get_modifyable_data(t->ext_rec_updates, &size);
+		update_count = size / sizeof(*update);
+	}
 
-	i_assert(ext_id < t->ext_resizes->used / sizeof(*intro));
-	intro = t->ext_resizes->data;
-	intro += ext_id;
+	if (t->ext_resizes == NULL) {
+		resize = NULL;
+		resize_count = 0;
+	} else {
+		resize = buffer_get_modifyable_data(t->ext_resizes, &size);
+		resize_count = size / sizeof(*resize);
+	}
 
-	i_assert(intro->name_size > 0 && intro->ext_id != (uint32_t)-1);
-	return intro->ext_id;
+	ext_count = I_MAX(update_count, resize_count);
+
+	for (ext_id = 0; ext_id < ext_count; ext_id++) {
+		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)
+				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)
 {
-	struct mail_transaction_ext_rec_header ext_rec_hdr;
 	struct mail_index_view *view = t->view;
 	struct mail_index *index;
 	struct mail_transaction_log *log;
 	struct mail_transaction_log_file *file;
 	struct mail_index_header idx_hdr;
 	uoff_t append_offset;
-	buffer_t *hdr_buf, **updates;
+	buffer_t **updates;
 	unsigned int i, lock_id;
 	size_t size;
 	int ret;
@@ -1297,10 +1238,6 @@
 		t->cache_updates = NULL;
 	}
 
-	t->ext_intros_max_id = t->view->index->map->extensions == NULL ? 0 :
-		(t->view->index->map->extensions->used /
-		 sizeof(struct mail_index_ext));
-
 	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)) {
@@ -1313,10 +1250,9 @@
 
 	ret = 0;
 
-	/* introduce extensions before appends to avoid having to resize
-	   records unneededly */
-	if (mail_transaction_log_append_ext_intros(file, t) < 0)
-		ret = -1;
+	/* send all extension introductions and resizes before appends
+	   to avoid resize overhead as much as possible */
+        ret = mail_transaction_log_append_ext_intros(file, t);
 
 	if (t->appends != NULL && ret == 0) {
 		ret = log_append_buffer(file, t->appends, NULL,
@@ -1347,15 +1283,15 @@
 		size /= sizeof(*updates);
 	}
 
-	hdr_buf = buffer_create_data(pool_datastack_create(),
-				     &ext_rec_hdr, sizeof(ext_rec_hdr));
-	buffer_set_used_size(hdr_buf, sizeof(ext_rec_hdr));
 	for (i = 0; i < size && ret == 0; i++) {
 		if (updates[i] == NULL)
 			continue;
 
-		ext_rec_hdr.ext_id = mail_transaction_log_get_ext_idx(t, i);
-		ret = log_append_buffer(file, updates[i], hdr_buf,
+		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);
 	}

Index: mail-transaction-log.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- mail-transaction-log.h	3 Oct 2004 16:32:59 -0000	1.19
+++ mail-transaction-log.h	17 Oct 2004 18:24:21 -0000	1.20
@@ -69,7 +69,9 @@
 };
 
 struct mail_transaction_ext_intro {
-	uint32_t ext_id; /* must be first */
+	/* old extension: set ext_id. don't set name.
+	   new extension: ext_id = (uint32_t)-1. give name. */
+	uint32_t ext_id;
 	uint32_t hdr_size;
 	uint16_t record_size;
 	uint16_t record_align;
@@ -78,17 +80,13 @@
 	/* unsigned char name[]; */
 };
 
+/* these are set for the last ext_intro */
 struct mail_transaction_ext_hdr_update {
-	uint32_t ext_id; /* must be first */
 	uint16_t offset;
 	uint16_t size;
 	/* unsigned char data[]; */
 };
 
-struct mail_transaction_ext_rec_header {
-	uint32_t ext_id; /* must be first */
-};
-
 struct mail_transaction_ext_rec_update {
 	uint32_t uid;
 	/* unsigned char data[]; */

Index: mail-transaction-util.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-util.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- mail-transaction-util.c	26 Sep 2004 14:15:55 -0000	1.19
+++ mail-transaction-util.c	17 Oct 2004 18:24:21 -0000	1.20
@@ -6,13 +6,6 @@
 #include "mail-transaction-log.h"
 #include "mail-transaction-util.h"
 
-struct mail_transaction_expunge_iter_ctx {
-	const struct mail_transaction_expunge *expunges;
-	size_t expunges_count;
-	uint32_t cur_seq, cur_idx, expunges_before;
-	uint32_t iter_seq, iter_count, iter_idx;
-};
-
 const struct mail_transaction_type_map mail_transaction_type_map[] = {
 	{ MAIL_TRANSACTION_APPEND, MAIL_INDEX_SYNC_TYPE_APPEND,
 	  1 }, /* index-specific size, use 1 */
@@ -26,8 +19,7 @@
 	  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,
-	  sizeof(struct mail_transaction_ext_rec_header) },
+	{ MAIL_TRANSACTION_EXT_RESET, 0, 0 },
 	{ MAIL_TRANSACTION_EXT_HDR_UPDATE, 0, 1 },
 	{ MAIL_TRANSACTION_EXT_REC_UPDATE, 0, 1 },
 	{ 0, 0, 0 }
@@ -58,192 +50,6 @@
 	return type;
 }
 
-int mail_transaction_map(struct mail_index_map *map,
-			 const struct mail_transaction_header *hdr,
-			 const void *data,
-			 struct mail_transaction_map_functions *func_map,
-			 void *context)
-{
-	int ret = 0;
-
-	switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
-	case MAIL_TRANSACTION_APPEND: {
-		const struct mail_index_record *rec, *end;
-
-		if (func_map->append == NULL)
-			break;
-
-		end = CONST_PTR_OFFSET(data, hdr->size);
-		for (rec = data; rec != end; rec++) {
-			ret = func_map->append(rec, context);
-			if (ret <= 0)
-				break;
-		}
-		break;
-	}
-	case MAIL_TRANSACTION_EXPUNGE:
-	case MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT: {
-		const struct mail_transaction_expunge *rec, *end;
-
-		if (func_map->expunge == NULL)
-			break;
-
-		end = CONST_PTR_OFFSET(data, hdr->size);
-		for (rec = data; rec != end; rec++) {
-			ret = func_map->expunge(rec, context);
-			if (ret <= 0)
-				break;
-		}
-		break;
-	}
-	case MAIL_TRANSACTION_FLAG_UPDATE: {
-		const struct mail_transaction_flag_update *rec, *end;
-
-		if (func_map->flag_update == NULL)
-			break;
-
-		end = CONST_PTR_OFFSET(data, hdr->size);
-		for (rec = data; rec != end; rec++) {
-			ret = func_map->flag_update(rec, context);
-			if (ret <= 0)
-				break;
-		}
-		break;
-	}
-	case MAIL_TRANSACTION_CACHE_RESET: {
-		const struct mail_transaction_cache_reset *rec = data;
-
-		if (func_map->cache_reset != NULL)
-			ret = func_map->cache_reset(rec, context);
-		break;
-	}
-	case MAIL_TRANSACTION_CACHE_UPDATE: {
-		const struct mail_transaction_cache_update *rec, *end;
-
-		if (func_map->cache_update == NULL)
-			break;
-
-		end = CONST_PTR_OFFSET(data, hdr->size);
-		for (rec = data; rec != end; rec++) {
-			ret = func_map->cache_update(rec, context);
-			if (ret <= 0)
-				break;
-		}
-		break;
-	}
-	case MAIL_TRANSACTION_HEADER_UPDATE: {
-		const struct mail_transaction_header_update *rec;
-		unsigned int i;
-
-		if (func_map->header_update == NULL)
-			break;
-
-		for (i = 0; i < hdr->size; ) {
-			rec = CONST_PTR_OFFSET(data, i);
-			ret = func_map->header_update(rec, context);
-			if (ret <= 0)
-				break;
-
-			i += sizeof(*rec) + rec->size;
-		}
-		break;
-	}
-	case MAIL_TRANSACTION_EXT_INTRO: {
-		const struct mail_transaction_ext_intro *rec = data;
-		unsigned int i;
-
-		if (func_map->ext_intro == NULL)
-			break;
-
-		for (i = 0; i < hdr->size; ) {
-			if (i + sizeof(*rec) > hdr->size) {
-				/* should be just extra padding */
-				break;
-			}
-
-			rec = CONST_PTR_OFFSET(data, i);
-			ret = func_map->ext_intro(rec, context);
-			if (ret <= 0)
-				break;
-
-			i += sizeof(*rec) + rec->name_size;
-		}
-		break;
-	}
-	case MAIL_TRANSACTION_EXT_RESET: {
-		const struct mail_transaction_ext_rec_header *rec = data;
-		unsigned int i, size;
-
-		if (func_map->ext_reset == NULL)
-			break;
-
-		size = hdr->size / sizeof(*rec);
-		for (i = 0; i < size; i++) {
-			ret = func_map->ext_reset(&rec[i], context);
-			if (ret <= 0)
-				break;
-		}
-		break;
-	}
-	case MAIL_TRANSACTION_EXT_HDR_UPDATE: {
-		const struct mail_transaction_ext_hdr_update *rec = data;
-		unsigned int i;
-
-		if (func_map->ext_hdr_update == NULL)
-			break;
-
-		for (i = 0; i < hdr->size; ) {
-			rec = CONST_PTR_OFFSET(data, i);
-			ret = func_map->ext_hdr_update(rec, context);
-			if (ret <= 0)
-				break;
-
-			i += sizeof(*rec) + rec->size;
-		}
-		break;
-	}
-	case MAIL_TRANSACTION_EXT_REC_UPDATE: {
-		const struct mail_transaction_ext_rec_header *ehdr = data;
-		const struct mail_transaction_ext_rec_update *rec, *end;
-		const struct mail_index_ext *ext;
-		unsigned int record_size;
-
-		if (func_map->ext_rec_update == NULL)
-			break;
-
-		rec = CONST_PTR_OFFSET(data, sizeof(*ehdr));
-
-		if (map->extensions == NULL ||
-		    ehdr->ext_id >= map->extensions->used / sizeof(*ext)) {
-			/* broken. let the ext_rec_update handler do the
-			   error handling. */
-			ret = func_map->ext_rec_update(ehdr, rec, context);
-			if (ret >= 0)
-				i_unreached();
-			break;
-		}
-
-		ext = map->extensions->data;
-		ext += ehdr->ext_id;
-		record_size = sizeof(*ehdr) + ext->record_size;
-
-		end = CONST_PTR_OFFSET(data, hdr->size);
-		while (rec != end) {
-			ret = func_map->ext_rec_update(ehdr, rec, context);
-			if (ret <= 0)
-				break;
-
-			rec = CONST_PTR_OFFSET(rec, record_size);
-		}
-		break;
-	}
-	default:
-		i_unreached();
-	}
-
-	return ret;
-}
-
 void
 mail_transaction_log_sort_expunges(buffer_t *expunges_buf,
 				   const struct mail_transaction_expunge *src,

Index: mail-transaction-util.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-util.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- mail-transaction-util.h	26 Sep 2004 14:15:55 -0000	1.10
+++ mail-transaction-util.h	17 Oct 2004 18:24:21 -0000	1.11
@@ -8,39 +8,11 @@
 };
 extern const struct mail_transaction_type_map mail_transaction_type_map[];
 
-struct mail_transaction_map_functions {
-	int (*expunge)(const struct mail_transaction_expunge *e, void *context);
-	int (*append)(const struct mail_index_record *rec, void *context);
-	int (*flag_update)(const struct mail_transaction_flag_update *u,
-			   void *context);
-	int (*cache_reset)(const struct mail_transaction_cache_reset *u,
-			    void *context);
-	int (*cache_update)(const struct mail_transaction_cache_update *u,
-			    void *context);
-	int (*header_update)(const struct mail_transaction_header_update *u,
-			     void *context);
-	int (*ext_intro)(const struct mail_transaction_ext_intro *u,
-			 void *context);
-	int (*ext_reset)(const struct mail_transaction_ext_rec_header *u,
-			 void *context);
-	int (*ext_hdr_update)(const struct mail_transaction_ext_hdr_update *u,
-			      void *context);
-	int (*ext_rec_update)(const struct mail_transaction_ext_rec_header *hdr,
-			      const struct mail_transaction_ext_rec_update *u,
-			      void *context);
-};
-
 const struct mail_transaction_type_map *
 mail_transaction_type_lookup(enum mail_transaction_type type);
 enum mail_transaction_type
 mail_transaction_type_mask_get(enum mail_index_sync_type sync_type);
 
-int mail_transaction_map(struct mail_index_map *map,
-			 const struct mail_transaction_header *hdr,
-			 const void *data,
-			 struct mail_transaction_map_functions *func_map,
-			 void *context);
-
 void
 mail_transaction_log_sort_expunges(buffer_t *expunges_buf,
 				   const struct mail_transaction_expunge *src,



More information about the dovecot-cvs mailing list