changeset 1356:026ae7f33d61 HEAD

More optimized mbox rewriting. It now tries to shrink/extend the filler in x-keywords header.
author Timo Sirainen <tss@iki.fi>
date Sun, 13 Apr 2003 21:02:14 +0300
parents 96e28b964269
children 5986d8920b86
files src/lib-index/mbox/mbox-index.h src/lib-index/mbox/mbox-rewrite.c src/lib-storage/index/mbox/mbox-save.c
diffstat 3 files changed, 51 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mbox/mbox-index.h	Sun Apr 13 21:01:25 2003 +0300
+++ b/src/lib-index/mbox/mbox-index.h	Sun Apr 13 21:02:14 2003 +0300
@@ -4,6 +4,9 @@
 #include "md5.h"
 #include "mail-index.h"
 
+/* Extra space to leave in X-Keywords header when rewriting mbox */
+#define MBOX_HEADER_EXTRA_SPACE 100
+
 struct mbox_header_context {
 	struct mail_index *index;
 	enum mail_flags flags;
--- a/src/lib-index/mbox/mbox-rewrite.c	Sun Apr 13 21:01:25 2003 +0300
+++ b/src/lib-index/mbox/mbox-rewrite.c	Sun Apr 13 21:02:14 2003 +0300
@@ -24,13 +24,13 @@
 	uoff_t content_length;
 	unsigned int seq, uid;
 	unsigned int msg_flags;
-        const char **custom_flags;
+	const char **custom_flags;
 
 	unsigned int uid_validity;
 	unsigned int uid_last;
+	char *x_keywords;
 
 	unsigned int ximapbase_found:1;
-	unsigned int xkeywords_found:1;
 	unsigned int xuid_found:1;
 	unsigned int status_found:1;
 	unsigned int xstatus_found:1;
@@ -120,14 +120,19 @@
 }
 
 static int mbox_write_xkeywords(struct mbox_rewrite_context *ctx,
-				const char *x_keywords)
+				const char *x_keywords, uoff_t wanted_offset,
+				int force_filler)
 {
 	unsigned int field;
 	int i;
 
 	if ((ctx->msg_flags & MAIL_CUSTOM_FLAGS_MASK) == 0 &&
-	    x_keywords == NULL)
+	    x_keywords == NULL && !force_filler &&
+	    ctx->output->offset + sizeof("X-Keywords:")+1 >= wanted_offset) {
+		/* nothing to do, and not enough extra space to write the
+		   filler. Do it only if there's space for "X-Keywords: \n" */
 		return TRUE;
+	}
 
 	if (o_stream_send_str(ctx->output, "X-Keywords:") < 0)
 		return FALSE;
@@ -153,6 +158,23 @@
 			return FALSE;
 	}
 
+	/* fill the rest with spaces. -1 for \n */
+	if (ctx->output->offset < wanted_offset-1 || force_filler) {
+		char buf[1024];
+		uoff_t fill_left;
+
+		fill_left = force_filler ? MBOX_HEADER_EXTRA_SPACE :
+			wanted_offset-1 - ctx->output->offset;
+		memset(buf, ' ', sizeof(buf));
+		while (fill_left > sizeof(buf)) {
+			if (o_stream_send(ctx->output, buf, sizeof(buf)) < 0)
+				return FALSE;
+			fill_left -= sizeof(buf);
+		}
+		if (o_stream_send(ctx->output, buf, fill_left) < 0)
+			return FALSE;
+	}
+
 	if (o_stream_send(ctx->output, "\n", 1) < 0)
 		return FALSE;
 
@@ -304,17 +326,17 @@
 		break;
 	case 10:
 		if (strcasecmp(hdr->name, "X-Keywords") == 0) {
-			if (ctx->xkeywords_found)
+			if (ctx->x_keywords != NULL)
 				return TRUE;
 			if (hdr->continues) {
 				hdr->use_full_value = TRUE;
 				return TRUE;
 			}
 
-			ctx->xkeywords_found = TRUE;
 			str = strip_custom_flags(hdr->full_value,
 						 hdr->full_value_len, ctx);
-			return mbox_write_xkeywords(ctx, str);
+			ctx->x_keywords = i_strdup(str);
+			return TRUE;
 		} else if (strcasecmp(hdr->name, "X-IMAPbase") == 0) {
 			if (ctx->seq != 1 || ctx->ximapbase_found)
 				return TRUE;
@@ -352,7 +374,7 @@
 static int mbox_write_header(struct mail_index *index,
 			     struct mail_index_record *rec, unsigned int seq,
 			     struct istream *input, struct ostream *output,
-			     uoff_t end_offset,
+			     uoff_t end_offset, uoff_t wanted_offset,
 			     uoff_t hdr_size, uoff_t body_size)
 {
 	/* We need to update fields that define message flags. Standard fields
@@ -370,6 +392,7 @@
 	struct message_header_parser_ctx *hdr_ctx;
 	struct message_header_line *hdr;
 	struct message_size hdr_parsed_size;
+	int force_filler;
 
 	if (input->v_offset >= end_offset) {
 		/* fsck should have noticed it.. */
@@ -394,8 +417,11 @@
 	i_stream_set_read_limit(input, input->v_offset + hdr_size);
 
 	hdr_ctx = message_parse_header_init(input, &hdr_parsed_size);
-	while ((hdr = message_parse_header_next(hdr_ctx)) != NULL)
+	while ((hdr = message_parse_header_next(hdr_ctx)) != NULL) {
+		t_push();
 		write_header(&ctx, hdr);
+		t_pop();
+	}
 	message_parse_header_deinit(hdr_ctx);
 
 	i_stream_set_read_limit(input, 0);
@@ -408,17 +434,22 @@
 		(void)mbox_write_ximapbase(&ctx);
 	}
 
+	force_filler = !ctx.xuid_found;
 	if (!ctx.status_found)
 		(void)mbox_write_status(&ctx, NULL);
 	if (!ctx.xstatus_found)
 		(void)mbox_write_xstatus(&ctx, NULL);
-	if (!ctx.xkeywords_found)
-		(void)mbox_write_xkeywords(&ctx, NULL);
 	if (!ctx.xuid_found)
 		(void)mbox_write_xuid(&ctx);
 	if (!ctx.content_length_found)
 		(void)mbox_write_content_length(&ctx);
 
+	/* write the x-keywords header last so it can fill the extra space
+	   with spaces. -1 is for ending \n. */
+	(void)mbox_write_xkeywords(&ctx, ctx.x_keywords,
+				   wanted_offset - 1, force_filler);
+	i_free(ctx.x_keywords);
+
 	t_pop();
 
 	/* empty line ends headers */
@@ -533,7 +564,7 @@
 	struct mail_index_record *rec;
 	struct istream *input;
 	struct ostream *output;
-	uoff_t offset, hdr_size, body_size, dirty_offset;
+	uoff_t offset, hdr_size, body_size, dirty_offset, wanted_offset;
 	const char *path;
 	unsigned int seq;
 	int tmp_fd, failed, dirty_found, rewrite, no_locking;
@@ -659,14 +690,15 @@
 
 			/* write header, updating flag fields */
 			offset += hdr_size;
+			wanted_offset = offset - dirty_offset;
 			if (!mbox_write_header(index, rec, seq, input, output,
-					       offset, hdr_size, body_size)) {
+					       offset, wanted_offset,
+					       hdr_size, body_size)) {
 				failed = TRUE;
 				break;
 			}
 
-			if (dirty_found &&
-			    offset - dirty_offset == output->offset) {
+			if (dirty_found && wanted_offset == output->offset) {
 				/* no need to write more, flush */
 				if (!dirty_flush(index, dirty_offset,
 						 output, tmp_fd)) {
--- a/src/lib-storage/index/mbox/mbox-save.c	Sun Apr 13 21:01:25 2003 +0300
+++ b/src/lib-storage/index/mbox/mbox-save.c	Sun Apr 13 21:02:14 2003 +0300
@@ -15,8 +15,6 @@
 #include <sys/stat.h>
 #include <netdb.h>
 
-#define HEADER_EXTRA_SPACE 100
-
 struct mail_save_context {
 	struct index_mailbox *ibox;
 	int transaction;
@@ -196,7 +194,7 @@
 		   value needs, then write that amount of spaces. */
 		space = strlen(get_custom_flags(ctx->flags));
 		space += sizeof("X-Keywords: ");
-		space += HEADER_EXTRA_SPACE + MAX_INT_STRLEN + 1;
+		space += MBOX_HEADER_EXTRA_SPACE + MAX_INT_STRLEN + 1;
 
 		/* @UNSAFE */
 		buf = t_malloc(space);