[dovecot-cvs] dovecot/src/lib-storage/index/mbox mbox-sync-private.h, 1.15, 1.16 mbox-sync-rewrite.c, 1.17, 1.18 mbox-sync-update.c, 1.14, 1.15 mbox-sync.c, 1.33, 1.34

cras at procontrol.fi cras at procontrol.fi
Sat Jun 19 03:19:50 EEST 2004


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

Modified Files:
	mbox-sync-private.h mbox-sync-rewrite.c mbox-sync-update.c 
	mbox-sync.c 
Log Message:
fixes



Index: mbox-sync-private.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync-private.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- mbox-sync-private.h	18 Jun 2004 00:33:08 -0000	1.15
+++ mbox-sync-private.h	19 Jun 2004 00:19:48 -0000	1.16
@@ -106,8 +106,8 @@
 void mbox_sync_update_header_from(struct mbox_sync_mail_context *ctx,
 				  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,
-		      uint32_t first_seq, uint32_t last_seq, off_t extra_space);
+int mbox_sync_rewrite(struct mbox_sync_context *sync_ctx, uoff_t extra_space,
+		      uint32_t first_seq, uint32_t last_seq);
 
 int mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset);
 int mbox_move(struct mbox_sync_context *sync_ctx,

Index: mbox-sync-rewrite.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync-rewrite.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- mbox-sync-rewrite.c	17 Jun 2004 23:08:48 -0000	1.17
+++ mbox-sync-rewrite.c	19 Jun 2004 00:19:48 -0000	1.18
@@ -49,6 +49,28 @@
 	return (int)ret;
 }
 
+static int mbox_fill_space(struct mbox_sync_context *sync_ctx,
+			   uoff_t offset, uoff_t size)
+{
+	unsigned char space[1024];
+
+	memset(space, ' ', sizeof(space));
+	while (size > sizeof(space)) {
+		if (pwrite_full(sync_ctx->fd, space,
+				sizeof(space), offset) < 0) {
+			mbox_set_syscall_error(sync_ctx->ibox, "pwrite_full()");
+			return -1;
+		}
+		size -= sizeof(space);
+	}
+
+	if (pwrite_full(sync_ctx->fd, space, size, offset) < 0) {
+		mbox_set_syscall_error(sync_ctx->ibox, "pwrite_full()");
+		return -1;
+	}
+	return 0;
+}
+
 static void mbox_sync_headers_add_space(struct mbox_sync_mail_context *ctx,
 					size_t size)
 {
@@ -58,23 +80,11 @@
 
 	i_assert(size < SSIZE_T_MAX);
 
-	if (ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] == (size_t)-1 &&
-	    size >= sizeof("X-Keywords: \n")-1) {
-		/* Add X-Keywords */
-		start_pos = str_len(ctx->header);
-		if (ctx->have_eoh)
-			start_pos--;
-		ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] = start_pos;
-
-		str_insert(ctx->header, start_pos, "X-Keywords: \n");
-		size -= sizeof("X-Keywords: \n")-1;
-	} else {
-		/* Append at the end of X-Keywords header,
-		   or X-UID if it doesn't exist */
-		start_pos = ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] != (size_t)-1 ?
-			ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] :
-			ctx->hdr_pos[MBOX_HDR_X_UID];
-	}
+	/* Append at the end of X-Keywords header,
+	   or X-UID if it doesn't exist */
+	start_pos = ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] != (size_t)-1 ?
+		ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] :
+		ctx->hdr_pos[MBOX_HDR_X_UID];
 
 	data = str_data(ctx->header);
 	data_size = str_len(ctx->header);
@@ -90,8 +100,8 @@
 		}
 	}
 
-	/* pos points to end of headers now, and start_pos to beginning of
-	   whitespace. */
+	/* pos points to end of headers now, and start_pos to beginning
+	   of whitespace. */
 	buffer_copy(ctx->header, pos + size,
 		    ctx->header, pos, (size_t)-1);
 	p = buffer_get_space_unsafe(ctx->header, pos, size);
@@ -193,8 +203,9 @@
 	old_hdr_size = ctx->body_offset - ctx->hdr_offset;
 	new_hdr_size = str_len(ctx->header);
 
-	/* do we have enough space? */
-	if (new_hdr_size < old_hdr_size) {
+	if (new_hdr_size <= old_hdr_size) {
+		/* add space. note that we must call add_space() even if we're
+		   not adding anything so mail.offset gets fixed. */
 		mbox_sync_headers_add_space(ctx, old_hdr_size - new_hdr_size);
 	} else if (new_hdr_size > old_hdr_size) {
 		/* try removing the space where we can */
@@ -205,6 +216,8 @@
 		if (new_hdr_size <= old_hdr_size) {
 			/* good, we removed enough. */
 			i_assert(new_hdr_size == old_hdr_size);
+			ctx->mail.space =
+				-(ssize_t)(new_hdr_size - old_hdr_size);
 		} else if (move_diff < 0 &&
 			   new_hdr_size - old_hdr_size <= -move_diff) {
 			/* moving backwards - we can use the extra space from
@@ -256,12 +269,12 @@
 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 extra_per_mail,
-				   uoff_t *end_offset)
+				   uoff_t space_diff, uoff_t end_offset)
 {
 	struct mbox_sync_mail_context mail_ctx;
 	uint32_t old_prev_msg_uid;
-	uoff_t offset;
+	uoff_t hdr_offset, offset, dest_offset;
+	size_t old_hdr_size, need_space;
 
 	if (mbox_sync_seek(sync_ctx, mails[idx].from_offset) < 0)
 		return -1;
@@ -271,6 +284,7 @@
 	mail_ctx.seq = seq;
 	mail_ctx.header = sync_ctx->header;
 
+	hdr_offset = mails[idx].offset;
 	mail_ctx.mail.offset = mails[idx].offset;
 	mail_ctx.mail.body_size = mails[idx].body_size;
 
@@ -293,96 +307,48 @@
 	sync_ctx->prev_msg_uid = old_prev_msg_uid;
 	sync_ctx->dest_first_mail = FALSE;
 
-	mail_ctx.mail.space =
-		-(ssize_t)(str_len(mail_ctx.header) -
-			   (mail_ctx.body_offset - mail_ctx.hdr_offset));
-	i_assert(mail_ctx.mail.space == mails[idx].space);
+	old_hdr_size = mail_ctx.body_offset - mail_ctx.hdr_offset;
+	need_space = str_len(mail_ctx.header) - mail_ctx.mail.space -
+		old_hdr_size;
+	i_assert(need_space == -mails[idx].space);
+	i_assert(space_diff >= need_space);
 
-	if (mail_ctx.mail.space <= 0)
-		mbox_sync_headers_add_space(&mail_ctx, extra_per_mail);
-	else if (mail_ctx.mail.space <= extra_per_mail) {
-		mbox_sync_headers_add_space(&mail_ctx, extra_per_mail -
-					    mail_ctx.mail.space);
-	} else {
+	if (space_diff - need_space < (uoff_t)mail_ctx.mail.space) {
 		mbox_sync_headers_remove_space(&mail_ctx, mail_ctx.mail.space -
-					       extra_per_mail);
+					       (space_diff - need_space));
+	} else {
+		mbox_sync_headers_add_space(&mail_ctx, space_diff - need_space -
+					    mail_ctx.mail.space);
 	}
+	mails[idx].offset = mail_ctx.mail.offset;
+	mails[idx].space = mail_ctx.mail.space;
 
-	/* now we have to move it. first move the body of the message,
-	   then write the header and leave the extra space to beginning of
-	   headers. */
+	/* move the body of this message and headers of next message forward,
+	   then write the headers */
 	offset = sync_ctx->input->v_offset;
-	if (mbox_move(sync_ctx, offset + mails[idx+1].space, offset,
-		      *end_offset - offset - mails[idx+1].space) < 0)
-		return -1;
-	mails[idx+1].from_offset += mails[idx+1].space;
-
-	*end_offset = offset + mails[idx+1].space - str_len(mail_ctx.header);
-
-	if (pwrite_full(sync_ctx->fd, str_data(mail_ctx.header),
-			str_len(mail_ctx.header), *end_offset) < 0) {
-		mbox_set_syscall_error(sync_ctx->ibox, "pwrite_full()");
+	dest_offset = offset + space_diff;
+	if (mbox_move(sync_ctx, dest_offset, offset,
+		      end_offset - dest_offset) < 0)
 		return -1;
-	}
-
-	mails[idx].offset = *end_offset;
-	mails[idx].space += mails[idx+1].space - extra_per_mail;
-	return 0;
-}
-
-static int mbox_sync_fill_leftover(struct mbox_sync_context *sync_ctx,
-				   struct mbox_sync_mail *mails,
-				   uint32_t seq, uint32_t idx,
-				   uoff_t start_offset, uoff_t end_offset)
-{
-	struct mbox_sync_mail_context mail_ctx;
-	uint32_t old_prev_msg_uid;
-
-	i_assert(start_offset < end_offset);
-
-	i_stream_seek(sync_ctx->input, mails[idx].offset);
-
-	memset(&mail_ctx, 0, sizeof(mail_ctx));
-	mail_ctx.sync_ctx = sync_ctx;
-	mail_ctx.seq = seq;
-	mail_ctx.header = sync_ctx->header;
-
-	mail_ctx.mail.offset = mails[idx].offset;
-	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. */
-        old_prev_msg_uid = sync_ctx->prev_msg_uid;
-        sync_ctx->prev_msg_uid = mails[idx].uid-1;
-	sync_ctx->dest_first_mail = seq == 1;
-
-	mbox_sync_parse_next_mail(sync_ctx->input, &mail_ctx, TRUE);
-	mbox_sync_update_header_from(&mail_ctx, &mails[idx]);
-
-        sync_ctx->prev_msg_uid = old_prev_msg_uid;
-	sync_ctx->dest_first_mail = FALSE;
-
-	mbox_sync_headers_add_space(&mail_ctx,end_offset - start_offset);
 
 	if (pwrite_full(sync_ctx->fd, str_data(mail_ctx.header),
-			str_len(mail_ctx.header), start_offset) < 0) {
+			str_len(mail_ctx.header), hdr_offset) < 0) {
 		mbox_set_syscall_error(sync_ctx->ibox, "pwrite_full()");
 		return -1;
 	}
 
-	/* just a cleanup - shouldn't be needed anymore */
-	mails[idx].offset = start_offset;
-	mails[idx].space = 0;
 	return 0;
 }
 
-int mbox_sync_rewrite(struct mbox_sync_context *sync_ctx,
-		      uint32_t first_seq, uint32_t last_seq, off_t extra_space)
+/* extra_space specifies how many bytes from last_seq's space will be left
+   over after all the rewrites. */
+int mbox_sync_rewrite(struct mbox_sync_context *sync_ctx, uoff_t extra_space,
+		      uint32_t first_seq, uint32_t last_seq)
 {
 	struct mbox_sync_mail *mails;
-	size_t size;
-	uoff_t offset, start_offset, end_offset, dest_offset;
+	uoff_t offset, end_offset, dest_offset, space_diff;
 	uint32_t idx, extra_per_mail;
+	size_t size;
 	int ret = 0;
 
 	i_assert(first_seq != last_seq);
@@ -396,83 +362,71 @@
 	   data which hasn't yet been copied backwards. to avoid too much
 	   complexity, we just leave all the rest of the extra space to first
 	   mail */
-	extra_per_mail = extra_space / (last_seq - first_seq + 1);
 	idx = last_seq - first_seq;
-
-	if (mails[idx].uid != 0)
-		mails[idx].space -= extra_per_mail;
-	i_assert(mails[idx].space >= 0);
-	end_offset = mails[idx].offset + mails[idx].space;
+	extra_per_mail = extra_space / (idx + 1);
 
 	/* after expunge the next mail must have been missing space, or we
 	   would have moved it backwards already */
 	i_assert(mails[0].space < 0 || mails[0].uid == 0);
-	start_offset = mails[0].offset;
 
-	/* start moving backwards */
+	/* start moving backwards. */
 	do {
+		/* this message's body is always moved space_diff bytes
+		   forward along with next message's headers, so current
+		   message gets temporarily space_diff amount of extra
+		   whitespace.
+
+		   the moving stops at next message's beginning of extra
+		   space. each message gets left extra_per_mail bytes of
+		   space. what gets left over is given to first message */
+		i_assert(mails[idx].space > 0);
+		space_diff = mails[idx].space;
+		end_offset = mails[idx].offset + mails[idx].space;
+
+		if (mails[idx].uid != 0) {
+			space_diff -= extra_per_mail;
+			end_offset -= extra_per_mail;
+			mails[idx].space = extra_per_mail;
+		}
+
 		idx--;
 		if (mails[idx].space <= 0 && mails[idx].uid != 0) {
 			/* offset points to beginning of headers. read the
 			   header again, update it and give enough space to
-			   it */
+			   fill space_diff */
 			if (mbox_sync_read_and_move(sync_ctx, mails,
 						    first_seq + idx, idx,
-						    extra_per_mail,
-						    &end_offset) < 0) {
+						    space_diff,
+						    end_offset) < 0) {
 				ret = -1;
 				break;
 			}
 		} else {
-			/* X-Keywords: xx [offset]     \n
+			/* X-Keywords: xx    [offset]\n
 			   ...
-			   X-Keywords: xx    [end_offset] \n
+			   X-Keywords: xx    [end_offset]   \n
 
 			   move data forward so mails before us gets the extra
 			   space (ie. we temporarily get more space to us) */
 			offset = mails[idx].offset + mails[idx].space;
-			dest_offset = offset + mails[idx+1].space;
+			dest_offset = offset + space_diff;
 			if (mbox_move(sync_ctx, dest_offset, offset,
 				      end_offset - dest_offset) < 0) {
 				ret = -1;
 				break;
 			}
 
-			mails[idx+1].from_offset += mails[idx+1].space;
-
-			mails[idx].space += mails[idx+1].space;
-			if (mails[idx].uid != 0)
-				mails[idx].space -= extra_per_mail;
-			i_assert(mails[idx].space > 0);
-			end_offset = mails[idx].offset + mails[idx].space;
-		}
-	} while (idx > 0);
-
-	if (end_offset != start_offset) {
-		/* some space was left over - give it to first message. */
-		if (mails[0].uid == 0) {
-			/* "body" start_offset .. end_offset "\nFrom .."
-			   we need to move From-line to start_offset */
-			offset = mails[1].offset;
-			if (mbox_move(sync_ctx, start_offset, end_offset,
-				      offset - end_offset) < 0)
+			if (mbox_fill_space(sync_ctx, offset,
+					    dest_offset - offset) < 0) {
 				ret = -1;
-			mails[1].from_offset -= end_offset - start_offset;
-			idx++;
+				break;
+			}
 
-			start_offset += offset - end_offset;
-			end_offset = offset;
-		} else {
-			/* "\nFrom ..\n" start_offset .. end_offset "hdr.." */
-		}
+			mails[idx].space += space_diff;
+ 		}
 
-		/* now parse it again and give it more space */
-		mails[idx+1].space = 0; /* from_offset doesn't move.. */
-		if (mbox_sync_fill_leftover(sync_ctx, mails,
-					    first_seq + idx, idx,
-					    start_offset, end_offset) < 0)
-			ret = -1;
-	}
+		mails[idx+1].from_offset += space_diff;
+	} while (idx > 0);
 
 	istream_raw_mbox_flush(sync_ctx->input);
 	return ret;

Index: mbox-sync-update.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync-update.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- mbox-sync-update.c	17 Jun 2004 23:52:50 -0000	1.14
+++ mbox-sync-update.c	19 Jun 2004 00:19:48 -0000	1.15
@@ -31,7 +31,8 @@
 	} else {
 		/* FIXME: if (diff < ctx->space && pos < ctx->offset) then
 		   move the data only up to space offset and give/take the
-		   space from there. update header_last_change accordingly. */
+		   space from there. update header_last_change accordingly.
+		   (except pos and offset can't be compared directly) */
 		ctx->header_last_change = (size_t)-1;
 		for (i = 0; i < MBOX_HDR_COUNT; i++) {
 			if (ctx->hdr_pos[i] > pos &&

Index: mbox-sync.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- mbox-sync.c	18 Jun 2004 00:33:08 -0000	1.33
+++ mbox-sync.c	19 Jun 2004 00:19:48 -0000	1.34
@@ -605,8 +605,8 @@
 		sync_ctx->expunged_space = 0;
 	}
 
-	if (mbox_sync_rewrite(sync_ctx, sync_ctx->need_space_seq, sync_ctx->seq,
-			      sync_ctx->space_diff) < 0)
+	if (mbox_sync_rewrite(sync_ctx, sync_ctx->space_diff,
+			      sync_ctx->need_space_seq, sync_ctx->seq) < 0)
 		return -1;
 
 	update_from_offsets(sync_ctx->ibox, sync_ctx->t, sync_ctx->mails,
@@ -816,9 +816,9 @@
 			buffer_append(sync_ctx->mails, &mail_ctx->mail,
 				      sizeof(mail_ctx->mail));
 
-			if (mbox_sync_rewrite(sync_ctx,
+			if (mbox_sync_rewrite(sync_ctx, extra_space,
 					      sync_ctx->need_space_seq,
-					      sync_ctx->seq, extra_space) < 0)
+					      sync_ctx->seq) < 0)
 				return -1;
 
 			update_from_offsets(sync_ctx->ibox, sync_ctx->t,



More information about the dovecot-cvs mailing list