dovecot-2.0: Moved transaction commiting code to mail-index-tran...

dovecot at dovecot.org dovecot at dovecot.org
Sat May 9 22:05:31 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/937dca181d77
changeset: 9252:937dca181d77
user:      Timo Sirainen <tss at iki.fi>
date:      Sat May 09 14:53:06 2009 -0400
description:
Moved transaction commiting code to mail-index-transaction-*.c

diffstat:

8 files changed, 1132 insertions(+), 1074 deletions(-)
src/lib-index/Makefile.am                           |    3 
src/lib-index/mail-index-transaction-export.c       |  429 ++++++++++++
src/lib-index/mail-index-transaction-finish.c       |  294 ++++++++
src/lib-index/mail-index-transaction-private.h      |   14 
src/lib-index/mail-index-transaction-sort-appends.c |  182 +++++
src/lib-index/mail-index-transaction.c              |  588 +++-------------
src/lib-index/mail-transaction-log-append.c         |  676 +------------------
src/lib-index/mail-transaction-log.h                |   20 

diffs (truncated from 2452 to 300 lines):

diff -r 08cf5c1814ef -r 937dca181d77 src/lib-index/Makefile.am
--- a/src/lib-index/Makefile.am	Sat May 09 12:32:04 2009 -0400
+++ b/src/lib-index/Makefile.am	Sat May 09 14:53:06 2009 -0400
@@ -19,6 +19,9 @@ libindex_la_SOURCES = \
         mail-index-map.c \
         mail-index-modseq.c \
         mail-index-transaction.c \
+        mail-index-transaction-export.c \
+        mail-index-transaction-finish.c \
+        mail-index-transaction-sort-appends.c \
         mail-index-transaction-view.c \
         mail-index-strmap.c \
         mail-index-sync.c \
diff -r 08cf5c1814ef -r 937dca181d77 src/lib-index/mail-index-transaction-export.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-index/mail-index-transaction-export.c	Sat May 09 14:53:06 2009 -0400
@@ -0,0 +1,429 @@
+/* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "mail-index-private.h"
+#include "mail-index-modseq.h"
+#include "mail-transaction-log-private.h"
+#include "mail-index-transaction-private.h"
+
+struct mail_index_export_context {
+	struct mail_index_transaction *trans;
+	struct mail_transaction_log_append_ctx *append_ctx;
+};
+
+static void log_append_buffer(struct mail_index_export_context *ctx,
+			      const buffer_t *buf, const buffer_t *hdr_buf,
+			      enum mail_transaction_type type)
+{
+	buffer_t *output = ctx->append_ctx->output;
+	struct mail_transaction_header hdr;
+
+	i_assert((type & MAIL_TRANSACTION_TYPE_MASK) != 0);
+	i_assert((buf->used % 4) == 0);
+	i_assert(hdr_buf == NULL || (hdr_buf->used % 4) == 0);
+
+	if (buf->used == 0)
+		return;
+
+	memset(&hdr, 0, sizeof(hdr));
+	hdr.type = type;
+	if (type == MAIL_TRANSACTION_EXPUNGE)
+		hdr.type |= MAIL_TRANSACTION_EXPUNGE_PROT;
+	if ((ctx->trans->flags & MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL) != 0)
+		hdr.type |= MAIL_TRANSACTION_EXTERNAL;
+	hdr.size = sizeof(hdr) + buf->used +
+		(hdr_buf == NULL ? 0 : hdr_buf->used);
+	hdr.size = mail_index_uint32_to_offset(hdr.size);
+
+	buffer_append(output, &hdr, sizeof(hdr));
+	if (hdr_buf != NULL)
+		buffer_append(output, hdr_buf->data, hdr_buf->used);
+	buffer_append(output, buf->data, buf->used);
+
+	if (mail_transaction_header_has_modseq(buf->data,
+				CONST_PTR_OFFSET(buf->data, sizeof(hdr)),
+				ctx->append_ctx->new_highest_modseq))
+		ctx->append_ctx->new_highest_modseq++;
+}
+
+static const buffer_t *
+log_get_hdr_update_buffer(struct mail_index_transaction *t, bool prepend)
+{
+	buffer_t *buf;
+	const unsigned char *data, *mask;
+	struct mail_transaction_header_update u;
+	uint16_t offset;
+	int state = 0;
+
+	memset(&u, 0, sizeof(u));
+
+	data = prepend ? t->pre_hdr_change : t->post_hdr_change;
+	mask = prepend ? t->pre_hdr_mask : t->post_hdr_mask;
+
+	buf = buffer_create_dynamic(pool_datastack_create(), 256);
+	for (offset = 0; offset <= sizeof(t->pre_hdr_change); offset++) {
+		if (offset < sizeof(t->pre_hdr_change) && mask[offset]) {
+			if (state == 0) {
+				u.offset = offset;
+				state++;
+			}
+		} else {
+			if (state > 0) {
+				u.size = offset - u.offset;
+				buffer_append(buf, &u, sizeof(u));
+				buffer_append(buf, data + u.offset, u.size);
+				state = 0;
+			}
+		}
+	}
+	return buf;
+}
+
+static void log_append_ext_intro(struct mail_index_export_context *ctx,
+				 uint32_t ext_id, uint32_t reset_id)
+{
+	struct mail_index_transaction *t = ctx->trans;
+	const struct mail_index_registered_ext *rext;
+        struct mail_transaction_ext_intro *intro, *resizes;
+	buffer_t *buf;
+	uint32_t idx;
+	unsigned int count;
+
+	i_assert(ext_id != (uint32_t)-1);
+
+	if (t->reset ||
+	    !mail_index_map_get_ext_idx(t->view->index->map, ext_id, &idx)) {
+		/* new extension */
+		idx = (uint32_t)-1;
+	}
+
+	rext = array_idx(&t->view->index->extensions, ext_id);
+	if (!array_is_created(&t->ext_resizes)) {
+		resizes = NULL;
+		count = 0;
+	} else {
+		resizes = array_get_modifiable(&t->ext_resizes, &count);
+	}
+
+	buf = buffer_create_dynamic(pool_datastack_create(), 128);
+	if (ext_id < count && resizes[ext_id].name_size != 0) {
+		/* we're resizing the extension. use the resize struct. */
+		intro = &resizes[ext_id];
+
+		i_assert(intro->ext_id == idx);
+		intro->name_size = idx != (uint32_t)-1 ? 0 :
+			strlen(rext->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 = rext->hdr_size;
+		intro->record_size = rext->record_size;
+		intro->record_align = rext->record_align;
+		intro->flags = MAIL_TRANSACTION_EXT_INTRO_FLAG_NO_SHRINK;
+		intro->name_size = idx != (uint32_t)-1 ? 0 :
+			strlen(rext->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 =
+			array_idx(&t->view->index->map->extensions, idx);
+		intro->reset_id = map_ext->reset_id;
+	} else {
+		/* new extension, reset_id defaults to 0 */
+	}
+	buffer_append(buf, rext->name, intro->name_size);
+	if ((buf->used % 4) != 0)
+		buffer_append_zero(buf, 4 - (buf->used % 4));
+
+	if (ctx->append_ctx->new_highest_modseq == 0 &&
+	    strcmp(rext->name, MAIL_INDEX_MODSEQ_EXT_NAME) == 0) {
+		/* modseq tracking started */
+		ctx->append_ctx->new_highest_modseq = 1;
+	}
+
+	log_append_buffer(ctx, buf, NULL, MAIL_TRANSACTION_EXT_INTRO);
+}
+
+static void
+log_append_ext_hdr_update(struct mail_index_export_context *ctx,
+			const struct mail_index_transaction_ext_hdr_update *hdr)
+{
+	buffer_t *buf;
+	const unsigned char *data, *mask;
+	struct mail_transaction_ext_hdr_update u;
+	uint16_t offset;
+	bool started = FALSE;
+
+	memset(&u, 0, sizeof(u));
+
+	data = hdr->data;
+	mask = hdr->mask;
+
+	buf = buffer_create_dynamic(pool_datastack_create(), 256);
+	for (offset = 0; offset <= hdr->alloc_size; offset++) {
+		if (offset < hdr->alloc_size && mask[offset] != 0) {
+			if (!started) {
+				u.offset = offset;
+				started = TRUE;
+			}
+		} else {
+			if (started) {
+				u.size = offset - u.offset;
+				buffer_append(buf, &u, sizeof(u));
+				buffer_append(buf, data + u.offset, u.size);
+				started = FALSE;
+			}
+		}
+	}
+	if (buf->used % 4 != 0)
+		buffer_append_zero(buf, 4 - buf->used % 4);
+	log_append_buffer(ctx, buf, NULL, MAIL_TRANSACTION_EXT_HDR_UPDATE);
+}
+
+static void
+mail_transaction_log_append_ext_intros(struct mail_index_export_context *ctx)
+{
+	struct mail_index_transaction *t = ctx->trans;
+        const struct mail_transaction_ext_intro *resize;
+	const struct mail_index_transaction_ext_hdr_update *hdrs;
+	struct mail_transaction_ext_reset ext_reset;
+	unsigned int resize_count, ext_count = 0;
+	unsigned int hdrs_count, reset_id_count, reset_count;
+	uint32_t ext_id, reset_id;
+	const struct mail_transaction_ext_reset *reset;
+	const uint32_t *reset_ids;
+	buffer_t *reset_buf;
+
+	if (!array_is_created(&t->ext_resizes)) {
+		resize = NULL;
+		resize_count = 0;
+	} else {
+		resize = array_get(&t->ext_resizes, &resize_count);
+		if (ext_count < resize_count)
+			ext_count = resize_count;
+	}
+
+	if (!array_is_created(&t->ext_reset_ids)) {
+		reset_ids = NULL;
+		reset_id_count = 0;
+	} else {
+		reset_ids = array_get(&t->ext_reset_ids, &reset_id_count);
+	}
+
+	if (!array_is_created(&t->ext_resets)) {
+		reset = NULL;
+		reset_count = 0;
+	} else {
+		reset = array_get(&t->ext_resets, &reset_count);
+		if (ext_count < reset_count)
+			ext_count = reset_count;
+	}
+
+	if (!array_is_created(&t->ext_hdr_updates)) {
+		hdrs = NULL;
+		hdrs_count = 0;
+	} else {
+		hdrs = array_get(&t->ext_hdr_updates, &hdrs_count);
+		if (ext_count < hdrs_count)
+			ext_count = hdrs_count;
+	}
+
+	memset(&ext_reset, 0, sizeof(ext_reset));
+	reset_buf = buffer_create_data(pool_datastack_create(),
+				       &ext_reset, sizeof(ext_reset));
+	buffer_set_used_size(reset_buf, sizeof(ext_reset));
+
+	for (ext_id = 0; ext_id < ext_count; ext_id++) {
+		if (ext_id < reset_count)
+			ext_reset = reset[ext_id];
+		else
+			ext_reset.new_reset_id = 0;
+		if ((ext_id < resize_count && resize[ext_id].name_size) ||
+		    ext_reset.new_reset_id != 0 ||
+		    (ext_id < hdrs_count && hdrs[ext_id].alloc_size > 0)) {
+			if (ext_reset.new_reset_id != 0) {
+				/* we're going to reset this extension
+				   immediately after the intro */
+				reset_id = 0;
+			} else {
+				reset_id = ext_id < reset_id_count ?
+					reset_ids[ext_id] : 0;
+			}
+			log_append_ext_intro(ctx, ext_id, reset_id);
+		}
+		if (ext_reset.new_reset_id != 0) {
+			i_assert(ext_id < reset_id_count &&
+				 ext_reset.new_reset_id == reset_ids[ext_id]);
+			log_append_buffer(ctx, reset_buf, NULL,
+					  MAIL_TRANSACTION_EXT_RESET);
+		}
+		if (ext_id < hdrs_count && hdrs[ext_id].alloc_size > 0) {
+			T_BEGIN {
+				log_append_ext_hdr_update(ctx, &hdrs[ext_id]);
+			} T_END;
+		}
+	}
+}
+
+static void log_append_ext_recs(struct mail_index_export_context *ctx,
+				const ARRAY_TYPE(seq_array_array) *arr,
+				enum mail_transaction_type type)
+{
+	struct mail_index_transaction *t = ctx->trans;
+	const ARRAY_TYPE(seq_array) *updates;
+	const uint32_t *reset_ids;
+	unsigned int ext_id, count, reset_id_count;
+	uint32_t reset_id;
+


More information about the dovecot-cvs mailing list