[dovecot-cvs] dovecot/src/lib-storage/index/mbox mbox-sync-private.h, 1.54, 1.55 mbox-sync-rewrite.c, 1.54, 1.55 mbox-sync.c, 1.173, 1.174

cras at dovecot.org cras at dovecot.org
Thu Oct 27 15:12:59 EEST 2005


Update of /var/lib/cvs/dovecot/src/lib-storage/index/mbox
In directory talvi:/tmp/cvs-serv11957

Modified Files:
	mbox-sync-private.h mbox-sync-rewrite.c mbox-sync.c 
Log Message:
When rewriting mbox, don't parse the last message again. We already have its
contents in mail_ctx, so pass it over to rewriter so it can reuse it. This
fixes also a crash when last message's header ended unexpectedly and mbox
file was grown (the added NULs were treated as the last message's headers).



Index: mbox-sync-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync-private.h,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -d -r1.54 -r1.55
--- mbox-sync-private.h	7 Aug 2005 11:28:13 -0000	1.54
+++ mbox-sync-private.h	27 Oct 2005 12:12:57 -0000	1.55
@@ -140,6 +140,7 @@
 				  const struct mbox_sync_mail *mail);
 int mbox_sync_try_rewrite(struct mbox_sync_mail_context *ctx, off_t move_diff);
 int mbox_sync_rewrite(struct mbox_sync_context *sync_ctx,
+                      struct mbox_sync_mail_context *mail_ctx,
 		      uoff_t end_offset, off_t move_diff, uoff_t extra_space,
 		      uint32_t first_seq, uint32_t last_seq);
 

Index: mbox-sync-rewrite.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync-rewrite.c,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -d -r1.54 -r1.55
--- mbox-sync-rewrite.c	19 Aug 2005 16:01:16 -0000	1.54
+++ mbox-sync-rewrite.c	27 Oct 2005 12:12:57 -0000	1.55
@@ -309,28 +309,22 @@
 	return 1;
 }
 
-static int mbox_sync_read_and_move(struct mbox_sync_context *sync_ctx,
-				   struct mbox_sync_mail *mails,
-				   uint32_t seq, uint32_t idx, uint32_t padding,
-				   off_t move_diff, uoff_t expunged_space,
-				   uoff_t end_offset, int first_nonexpunged)
+static void mbox_sync_read_next(struct mbox_sync_context *sync_ctx,
+				struct mbox_sync_mail_context *mail_ctx,
+				struct mbox_sync_mail *mails,
+				uint32_t seq, uint32_t idx,
+				uoff_t expunged_space)
 {
-	struct mbox_sync_mail_context mail_ctx;
 	uint32_t old_prev_msg_uid;
-	uoff_t hdr_offset, offset, dest_offset;
-	size_t need_space;
 
-	if (mbox_sync_seek(sync_ctx, mails[idx].from_offset) < 0)
-		return -1;
-
-	memset(&mail_ctx, 0, sizeof(mail_ctx));
-	mail_ctx.sync_ctx = sync_ctx;
-	mail_ctx.seq = seq;
-	mail_ctx.header = sync_ctx->header;
+	memset(mail_ctx, 0, sizeof(*mail_ctx));
+	mail_ctx->sync_ctx = sync_ctx;
+	mail_ctx->seq = seq;
+	mail_ctx->header = sync_ctx->header;
 
-	hdr_offset = istream_raw_mbox_get_header_offset(sync_ctx->input);
-	mail_ctx.mail.offset = hdr_offset;
-	mail_ctx.mail.body_size = mails[idx].body_size;
+	mail_ctx->mail.offset =
+		istream_raw_mbox_get_header_offset(sync_ctx->input);
+	mail_ctx->mail.body_size = mails[idx].body_size;
 
 	/* mbox_sync_parse_next_mail() checks that UIDs are growing,
 	   so we have to fool it. */
@@ -345,18 +339,44 @@
 		mails[idx].from_offset++;
 	}
 
-	mbox_sync_parse_next_mail(sync_ctx->input, &mail_ctx);
+	mbox_sync_parse_next_mail(sync_ctx->input, mail_ctx);
 	if (mails[idx].space != 0) {
 		if (mails[idx].space < 0) {
 			/* remove all possible spacing before updating */
-			mbox_sync_headers_remove_space(&mail_ctx, (size_t)-1);
+			mbox_sync_headers_remove_space(mail_ctx, (size_t)-1);
 		}
-		mbox_sync_update_header_from(&mail_ctx, &mails[idx]);
+		mbox_sync_update_header_from(mail_ctx, &mails[idx]);
 	} else {
 		/* updating might just try to add headers and mess up our
 		   calculations completely. so only add the EOH here. */
-		if (mail_ctx.have_eoh)
-			str_append_c(mail_ctx.header, '\n');
+		if (mail_ctx->have_eoh)
+			str_append_c(mail_ctx->header, '\n');
+	}
+
+	sync_ctx->prev_msg_uid = old_prev_msg_uid;
+}
+
+static int mbox_sync_read_and_move(struct mbox_sync_context *sync_ctx,
+                                   struct mbox_sync_mail_context *mail_ctx,
+				   struct mbox_sync_mail *mails,
+				   uint32_t seq, uint32_t idx, uint32_t padding,
+				   off_t move_diff, uoff_t expunged_space,
+				   uoff_t end_offset, int first_nonexpunged)
+{
+	struct mbox_sync_mail_context new_mail_ctx;
+	uoff_t offset, dest_offset;
+	size_t need_space;
+
+	if (mail_ctx == NULL) {
+		if (mbox_sync_seek(sync_ctx, mails[idx].from_offset) < 0)
+			return -1;
+
+		mbox_sync_read_next(sync_ctx, &new_mail_ctx, mails, seq, idx,
+				    expunged_space);
+		mail_ctx = &new_mail_ctx;
+	} else {
+		if (mail_ctx->mail.space < 0)
+			mail_ctx->mail.space = 0;
 	}
 
 	if (first_nonexpunged && expunged_space > 0) {
@@ -368,20 +388,18 @@
 			return -1;
 	}
 
-	sync_ctx->prev_msg_uid = old_prev_msg_uid;
-
-	need_space = str_len(mail_ctx.header) - mail_ctx.mail.space -
-		(mail_ctx.body_offset - mail_ctx.hdr_offset);
+	need_space = str_len(mail_ctx->header) - mail_ctx->mail.space -
+		(mail_ctx->body_offset - mail_ctx->hdr_offset);
 	i_assert(need_space == (uoff_t)-mails[idx].space);
 
 	if (mails[idx].space == 0) {
 		/* don't touch spacing */
-	} else if (padding < (uoff_t)mail_ctx.mail.space) {
-		mbox_sync_headers_remove_space(&mail_ctx, mail_ctx.mail.space -
+	} else if (padding < (uoff_t)mail_ctx->mail.space) {
+		mbox_sync_headers_remove_space(mail_ctx, mail_ctx->mail.space -
 					       padding);
 	} else {
-		mbox_sync_headers_add_space(&mail_ctx, padding -
-					    mail_ctx.mail.space);
+		mbox_sync_headers_add_space(mail_ctx, padding -
+					    mail_ctx->mail.space);
 	}
 
 	/* move the body of this message and headers of next message forward,
@@ -394,26 +412,28 @@
 
 	/* the header may actually be moved backwards if there was expunged
 	   space which we wanted to remove */
-	i_assert(dest_offset >= str_len(mail_ctx.header));
-	dest_offset -= str_len(mail_ctx.header);
-	if (pwrite_full(sync_ctx->write_fd, str_data(mail_ctx.header),
-			str_len(mail_ctx.header), dest_offset) < 0) {
+	i_assert(dest_offset >= str_len(mail_ctx->header));
+	dest_offset -= str_len(mail_ctx->header);
+	i_assert(dest_offset >= mails[idx].from_offset - expunged_space);
+	if (pwrite_full(sync_ctx->write_fd, str_data(mail_ctx->header),
+			str_len(mail_ctx->header), dest_offset) < 0) {
 		mbox_set_syscall_error(sync_ctx->mbox, "pwrite_full()");
 		return -1;
 	}
 
 	if (sync_ctx->dest_first_mail) {
-		mbox_sync_first_mail_written(&mail_ctx, dest_offset);
+		mbox_sync_first_mail_written(mail_ctx, dest_offset);
 		sync_ctx->dest_first_mail = FALSE;
 	}
 
 	mails[idx].offset = dest_offset +
-		(mail_ctx.mail.offset - mail_ctx.hdr_offset);
-	mails[idx].space = mail_ctx.mail.space;
+		(mail_ctx->mail.offset - mail_ctx->hdr_offset);
+	mails[idx].space = mail_ctx->mail.space;
 	return 0;
 }
 
 int mbox_sync_rewrite(struct mbox_sync_context *sync_ctx,
+		      struct mbox_sync_mail_context *mail_ctx,
 		      uoff_t end_offset, off_t move_diff, uoff_t extra_space,
 		      uint32_t first_seq, uint32_t last_seq)
 {
@@ -471,7 +491,7 @@
 			int first_nonexpunged = idx == first_nonexpunged_idx;
 
 			next_move_diff = -mails[idx].space;
-			if (mbox_sync_read_and_move(sync_ctx, mails,
+			if (mbox_sync_read_and_move(sync_ctx, mail_ctx, mails,
 						    first_seq + idx, idx,
 						    padding_per_mail,
 						    move_diff, expunged_space,
@@ -480,6 +500,7 @@
 				ret = -1;
 				break;
 			}
+			mail_ctx = NULL;
 			move_diff -= next_move_diff + mails[idx].space;
 		} else {
 			/* this mail provides more space. just move it forward

Index: mbox-sync.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync.c,v
retrieving revision 1.173
retrieving revision 1.174
diff -u -d -r1.173 -r1.174
--- mbox-sync.c	27 Oct 2005 10:30:27 -0000	1.173
+++ mbox-sync.c	27 Oct 2005 12:12:57 -0000	1.174
@@ -824,8 +824,9 @@
 		extra_space = sync_ctx->space_diff;
 	}
 
-	if (mbox_sync_rewrite(sync_ctx, end_offset, move_diff, extra_space,
-			      sync_ctx->need_space_seq, last_seq) < 0)
+	if (mbox_sync_rewrite(sync_ctx, mail_ctx, end_offset, move_diff,
+			      extra_space, sync_ctx->need_space_seq,
+			      last_seq) < 0)
 		return -1;
 
 	update_from_offsets(sync_ctx);
@@ -1263,7 +1264,7 @@
 		}
 		i_stream_sync(sync_ctx->input);
 
-		if (mbox_sync_rewrite(sync_ctx, file_size,
+		if (mbox_sync_rewrite(sync_ctx, mail_ctx, file_size,
 				      -sync_ctx->space_diff, padding,
 				      sync_ctx->need_space_seq,
 				      sync_ctx->seq) < 0)



More information about the dovecot-cvs mailing list