[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