[dovecot-cvs]
dovecot/src/lib-storage/index/mbox istream-raw-mbox.c, 1.6,
1.7 istream-raw-mbox.h, 1.3, 1.4 mbox-lock.c, 1.3,
1.4 mbox-sync-parse.c, 1.10, 1.11 mbox-sync-private.h, 1.10,
1.11 mbox-sync-update.c, 1.9, 1.10 mbox-sync.c, 1.19, 1.20
cras at procontrol.fi
cras at procontrol.fi
Tue Jun 15 01:44:58 EEST 2004
- Previous message: [dovecot-cvs] dovecot/src/lib-storage/index/mbox
mbox-sync-private.h, 1.9, 1.10 mbox-sync-rewrite.c, 1.11,
1.12 mbox-sync-update.c, 1.8, 1.9 mbox-sync.c, 1.18, 1.19
- Next message: [dovecot-cvs]
dovecot/src/lib-storage/index/mbox istream-raw-mbox.c, 1.7,
1.8 mbox-mail.c, 1.3, 1.4 mbox-sync-rewrite.c, 1.12,
1.13 mbox-sync.c, 1.20, 1.21
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /home/cvs/dovecot/src/lib-storage/index/mbox
In directory talvi:/tmp/cvs-serv9963/lib-storage/index/mbox
Modified Files:
istream-raw-mbox.c istream-raw-mbox.h mbox-lock.c
mbox-sync-parse.c mbox-sync-private.h mbox-sync-update.c
mbox-sync.c
Log Message:
several fixes and optimizations.
Index: istream-raw-mbox.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/istream-raw-mbox.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- istream-raw-mbox.c 11 Jun 2004 03:20:10 -0000 1.6
+++ istream-raw-mbox.c 14 Jun 2004 22:44:56 -0000 1.7
@@ -295,6 +295,30 @@
return rstream->hdr_offset;
}
+uoff_t istream_raw_mbox_get_body_offset(struct istream *stream)
+{
+ struct raw_mbox_istream *rstream =
+ (struct raw_mbox_istream *)stream->real_stream;
+ uoff_t offset;
+ size_t pos;
+
+ if (rstream->body_offset != (uoff_t)-1)
+ return rstream->body_offset;
+
+ offset = stream->v_offset;
+ i_stream_seek(stream, rstream->hdr_offset);
+ while (rstream->body_offset == (uoff_t)-1) {
+ i_stream_get_data(rstream->input, &pos);
+ i_stream_skip(stream, pos);
+
+ if (_read(&rstream->istream) < 0)
+ break;
+ }
+
+ i_stream_seek(stream, offset);
+ return rstream->body_offset;
+}
+
uoff_t istream_raw_mbox_get_body_size(struct istream *stream, uoff_t body_size)
{
struct raw_mbox_istream *rstream =
@@ -302,13 +326,15 @@
const unsigned char *data;
size_t size;
+ i_assert(rstream->hdr_offset != (uoff_t)-1);
+ i_assert(rstream->body_offset != (uoff_t)-1);
+
if (rstream->mail_size != (uoff_t)-1) {
return rstream->mail_size -
(rstream->body_offset - rstream->hdr_offset);
}
if (body_size != (uoff_t)-1) {
- i_assert(rstream->body_offset != (uoff_t)-1);
i_stream_seek(rstream->input, rstream->body_offset + body_size);
if (istream_raw_mbox_is_valid_from(rstream) > 0) {
rstream->mail_size = body_size +
Index: istream-raw-mbox.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/istream-raw-mbox.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- istream-raw-mbox.h 9 May 2004 17:06:06 -0000 1.3
+++ istream-raw-mbox.h 14 Jun 2004 22:44:56 -0000 1.4
@@ -9,6 +9,8 @@
uoff_t istream_raw_mbox_get_start_offset(struct istream *stream);
/* Return offset to beginning of the headers. */
uoff_t istream_raw_mbox_get_header_offset(struct istream *stream);
+/* Return offset to beginning of the body. */
+uoff_t istream_raw_mbox_get_body_offset(struct istream *stream);
/* Return the number of bytes in the body of this message. If body_size isn't
(uoff_t)-1, we'll use it as potentially valid body size to avoid actually
Index: mbox-lock.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-lock.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- mbox-lock.c 3 Jun 2004 15:01:27 -0000 1.3
+++ mbox-lock.c 14 Jun 2004 22:44:56 -0000 1.4
@@ -258,7 +258,8 @@
return -1;
}
- if (st.st_dev != ibox->mbox_dev || st.st_ino != ibox->mbox_ino)
+ if (st.st_ino != ibox->mbox_ino ||
+ !CMP_DEV_T(st.st_dev, ibox->mbox_dev))
mbox_file_close(ibox);
if (ibox->mbox_fd == -1) {
Index: mbox-sync-parse.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync-parse.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- mbox-sync-parse.c 14 Jun 2004 04:30:32 -0000 1.10
+++ mbox-sync-parse.c 14 Jun 2004 22:44:56 -0000 1.11
@@ -260,6 +260,7 @@
struct mbox_sync_mail_context *ctx,
int rewriting)
{
+ struct mbox_sync_context *sync_ctx = ctx->sync_ctx;
struct message_header_parser_ctx *hdr_ctx;
struct message_header_line *hdr;
struct header_func *func;
@@ -316,16 +317,21 @@
}
message_parse_header_deinit(hdr_ctx);
- if ((ctx->seq == 1 && ctx->sync_ctx->base_uid_validity == 0) ||
- (ctx->seq > 1 && ctx->sync_ctx->first_uid == 0)) {
+ if ((ctx->seq == 1 && sync_ctx->base_uid_validity == 0) ||
+ (ctx->seq > 1 && sync_ctx->first_uid == 0)) {
/* missing X-IMAPbase */
ctx->need_rewrite = TRUE;
}
+ if (ctx->seq == 1 && sync_ctx->update_base_uid_last != 0 &&
+ sync_ctx->update_base_uid_last > sync_ctx->base_uid_last) {
+ /* update uid-last field in X-IMAPbase */
+ ctx->need_rewrite = TRUE;
+ }
if (ctx->mail.uid == 0 && !rewriting) {
/* missing X-UID */
ctx->need_rewrite = TRUE;
- ctx->mail.uid = ctx->sync_ctx->next_uid++;
- ctx->sync_ctx->prev_msg_uid = ctx->mail.uid;
+ ctx->mail.uid = sync_ctx->next_uid++;
+ sync_ctx->prev_msg_uid = ctx->mail.uid;
}
ctx->body_offset = input->v_offset;
Index: mbox-sync-private.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync-private.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- mbox-sync-private.h 14 Jun 2004 19:23:25 -0000 1.10
+++ mbox-sync-private.h 14 Jun 2004 22:44:56 -0000 1.11
@@ -69,9 +69,12 @@
const struct mail_index_header *hdr;
string_t *header, *from_line;
+
+ /* header state: */
uint32_t base_uid_validity, base_uid_last;
+ uint32_t update_base_uid_last;
- /* state: */
+ /* mail state: */
buffer_t *mails, *syncs;
struct mail_index_sync_rec sync_rec;
Index: mbox-sync-update.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync-update.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- mbox-sync-update.c 14 Jun 2004 19:23:25 -0000 1.9
+++ mbox-sync-update.c 14 Jun 2004 22:44:56 -0000 1.10
@@ -16,8 +16,37 @@
}
}
+static void mbox_sync_move_buffer(struct mbox_sync_mail_context *ctx,
+ size_t pos, size_t need, size_t have)
+{
+ int i;
+
+ if (need == have) {
+ if (ctx->header_last_change < pos + have ||
+ ctx->header_last_change == (size_t)-1)
+ ctx->header_last_change = pos + have;
+ } else {
+ ctx->header_last_change = (size_t)-1;
+ for (i = 0; i < MBOX_HDR_COUNT; i++) {
+ if (ctx->hdr_pos[i] > pos &&
+ ctx->hdr_pos[i] != (size_t)-1)
+ ctx->hdr_pos[i] += need - have;
+ }
+
+ if (need < have) {
+ str_delete(ctx->header, pos, have-need);
+ ctx->mail.space += have - need;
+ } else {
+ ctx->header_last_change = (size_t)-1;
+ buffer_copy(ctx->header, pos + (need-have),
+ ctx->header, pos, (size_t)-1);
+ ctx->mail.space -= need - have;
+ }
+ }
+}
+
static void status_flags_replace(struct mbox_sync_mail_context *ctx, size_t pos,
- const struct mbox_flag_type *flags_list)
+ const struct mbox_flag_type *flags_list)
{
unsigned char *data;
size_t size;
@@ -52,19 +81,7 @@
}
}
pos -= have;
-
- if (need < have)
- str_delete(ctx->header, pos, have-need);
- else if (need > have) {
- buffer_copy(ctx->header, pos + (need-have),
- ctx->header, pos, (size_t)-1);
- }
-
- for (i = 0; i < MBOX_HDR_COUNT; i++) {
- if (ctx->hdr_pos[i] > pos &&
- ctx->hdr_pos[i] != (size_t)-1)
- ctx->hdr_pos[i] += need - have;
- }
+ mbox_sync_move_buffer(ctx, pos, need, have);
/* @UNSAFE */
data = buffer_get_space_unsafe(ctx->header, pos, need);
@@ -104,7 +121,6 @@
//FIXME:keywords_append(ctx, all_keywords);
str_append_c(ctx->header, '\n');
}
- i_assert(ctx->sync_ctx->base_uid_validity != 0);
if (ctx->hdr_pos[MBOX_HDR_X_UID] == (size_t)-1) {
ctx->hdr_pos[MBOX_HDR_X_UID] = str_len(ctx->header);
@@ -186,7 +202,47 @@
static void mbox_sync_update_xkeywords(struct mbox_sync_mail_context *ctx)
{
- // FIXME
+}
+
+static void mbox_sync_update_x_imap_base(struct mbox_sync_mail_context *ctx)
+{
+ string_t *str;
+ const char *p, *hdr;
+ size_t pos;
+
+ if (ctx->mail.uid != ctx->sync_ctx->first_uid ||
+ ctx->hdr_pos[MBOX_HDR_X_IMAPBASE] == (size_t)-1 ||
+ ctx->sync_ctx->update_base_uid_last == 0 ||
+ ctx->sync_ctx->update_base_uid_last < ctx->sync_ctx->base_uid_last)
+ return;
+
+ pos = ctx->hdr_pos[MBOX_HDR_X_IMAPBASE];
+ if (ctx->header_first_change > pos)
+ ctx->header_first_change = pos;
+
+ /* update uid-last field in X-IMAPbase */
+ t_push();
+ str = t_str_new(200);
+ str_printfa(str, "%u %010u", ctx->sync_ctx->base_uid_validity,
+ ctx->sync_ctx->update_base_uid_last);
+ //FIXME:keywords_append(ctx, all_keywords);
+ str_append_c(str, '\n');
+
+ hdr = str_c(ctx->header);
+ p = strchr(hdr, '\n');
+
+ if (p == NULL) {
+ /* shouldn't really happen, but allow anyway.. */
+ ctx->header_last_change = (size_t)-1;
+ str_truncate(ctx->header, pos);
+ str_append_str(ctx->header, str);
+ } else {
+ mbox_sync_move_buffer(ctx, pos, str_len(str),
+ (p - hdr + 1) - pos);
+ buffer_copy(ctx->header, pos, str, 0, (size_t)-1);
+ }
+
+ t_pop();
}
void mbox_sync_update_header(struct mbox_sync_mail_context *ctx,
@@ -228,6 +284,7 @@
}
}
+ mbox_sync_update_x_imap_base(ctx);
mbox_sync_add_missing_headers(ctx);
ctx->updated = TRUE;
}
@@ -257,5 +314,7 @@
i_assert(ctx->mail.uid == 0 || ctx->mail.uid == mail->uid);
ctx->mail.uid = mail->uid;
+
+ mbox_sync_update_x_imap_base(ctx);
mbox_sync_add_missing_headers(ctx);
}
Index: mbox-sync.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- mbox-sync.c 14 Jun 2004 19:23:25 -0000 1.19
+++ mbox-sync.c 14 Jun 2004 22:44:56 -0000 1.20
@@ -60,6 +60,64 @@
#include <stddef.h>
#include <sys/stat.h>
+#define MBOX_SYNC_SECS 1
+
+/* returns -1 = error, 0 = mbox changed since previous lock, 1 = didn't */
+static int mbox_sync_lock(struct mbox_sync_context *sync_ctx, int lock_type)
+{
+ struct index_mailbox *ibox = sync_ctx->ibox;
+ struct stat old_st, st;
+ uoff_t old_from_offset, old_offset = 0;
+
+ if (sync_ctx->lock_id != 0) {
+ if (fstat(sync_ctx->fd, &old_st) < 0) {
+ mbox_set_syscall_error(ibox, "stat()");
+ return -1;
+ }
+ old_from_offset =
+ istream_raw_mbox_get_start_offset(sync_ctx->input);
+ old_offset = sync_ctx->input->v_offset;
+
+ (void)mbox_unlock(ibox, sync_ctx->lock_id);
+ sync_ctx->lock_id = 0;
+ } else {
+ memset(&old_st, 0, sizeof(old_st));
+ }
+
+ if (mbox_lock(ibox, lock_type, &sync_ctx->lock_id) <= 0)
+ return -1;
+ if (mbox_file_open_stream(ibox) < 0)
+ return -1;
+
+ sync_ctx->file_input = sync_ctx->ibox->mbox_file_stream;
+ sync_ctx->input = sync_ctx->ibox->mbox_stream;
+ sync_ctx->fd = sync_ctx->ibox->mbox_fd;
+
+ if (old_st.st_mtime == 0) {
+ /* we didn't have the file open before -> it changed */
+ return 0;
+ }
+
+ if (fstat(sync_ctx->fd, &st) < 0) {
+ mbox_set_syscall_error(ibox, "fstat()");
+ return -1;
+ }
+
+ if (st.st_mtime != old_st.st_mtime || st.st_size != old_st.st_size ||
+ st.st_ino != old_st.st_ino ||
+ !CMP_DEV_T(st.st_dev, old_st.st_dev) ||
+ time(NULL) - st.st_mtime <= MBOX_SYNC_SECS)
+ return 0;
+
+ /* same as before. we'll have to fix mbox stream to contain
+ correct from_offset, hdr_offset and body_offset. so, seek
+ to from_offset and read through the header. */
+ istream_raw_mbox_seek(sync_ctx->input, old_from_offset);
+ (void)istream_raw_mbox_get_body_offset(sync_ctx->input);
+ i_stream_seek(sync_ctx->input, old_offset);
+ return 1;
+}
+
static int mbox_sync_grow_file(struct mbox_sync_context *sync_ctx,
struct mbox_sync_mail_context *mail_ctx,
uoff_t grow_size)
@@ -230,25 +288,35 @@
return 0;
}
+static int mbox_sync_get_from_offset(struct mbox_sync_context *sync_ctx,
+ uint32_t seq, uint64_t *offset_r)
+{
+ const void *data;
+
+ /* see if from_offset needs updating */
+ if (mail_index_lookup_extra(sync_ctx->sync_view, seq,
+ sync_ctx->ibox->mbox_extra_idx,
+ &data) < 0) {
+ mail_storage_set_index_error(sync_ctx->ibox);
+ return -1;
+ }
+
+ *offset_r = *((const uint64_t *)data);
+ return 0;
+}
+
static int
mbox_sync_update_from_offset(struct mbox_sync_context *sync_ctx,
struct mbox_sync_mail *mail,
int nocheck)
{
- const void *data;
uint64_t offset;
if (!nocheck) {
- /* see if from_offset needs updating */
- if (mail_index_lookup_extra(sync_ctx->sync_view,
- sync_ctx->idx_seq,
- sync_ctx->ibox->mbox_extra_idx,
- &data) < 0) {
- mail_storage_set_index_error(sync_ctx->ibox);
+ if (mbox_sync_get_from_offset(sync_ctx, sync_ctx->idx_seq,
+ &offset) < 0)
return -1;
- }
- offset = *((const uint64_t *)data);
if (offset == mail->from_offset)
return 0;
} else {
@@ -367,10 +435,25 @@
}
}
+static int mbox_sync_check_excl_lock(struct mbox_sync_context *sync_ctx)
+{
+ int ret;
+
+ if (sync_ctx->ibox->mbox_lock_type == F_RDLCK) {
+ if ((ret = mbox_sync_lock(sync_ctx, F_WRLCK)) < 0)
+ return -1;
+ if (ret == 0)
+ return -2;
+ }
+ return 0;
+}
+
static int mbox_sync_handle_expunge(struct mbox_sync_mail_context *mail_ctx)
{
- if (mail_ctx->sync_ctx->ibox->mbox_lock_type == F_RDLCK)
- return -2;
+ int ret;
+
+ if ((ret = mbox_sync_check_excl_lock(mail_ctx->sync_ctx)) < 0)
+ return ret;
mail_ctx->mail.offset = mail_ctx->from_offset;
mail_ctx->mail.space =
@@ -402,8 +485,8 @@
if (sync_ctx->expunged_space > 0 && sync_ctx->need_space_seq == 0) {
/* move the header backwards to fill expunged space */
- if (sync_ctx->ibox->mbox_lock_type == F_RDLCK)
- return -2;
+ if ((ret = mbox_sync_check_excl_lock(sync_ctx)) < 0)
+ return ret;
move_diff = -sync_ctx->expunged_space;
@@ -425,11 +508,11 @@
}
} else if (mail_ctx->need_rewrite ||
buffer_get_used_size(sync_ctx->syncs) != 0) {
- if (sync_ctx->ibox->mbox_lock_type == F_RDLCK)
- return -2;
+ if ((ret = mbox_sync_check_excl_lock(sync_ctx)) < 0)
+ return ret;
mbox_sync_update_header(mail_ctx, sync_ctx->syncs);
- if ((ret = mbox_sync_try_rewrite(mail_ctx, move_diff)) < 0)
+ if ((ret = mbox_sync_try_rewrite(mail_ctx, 0)) < 0)
return -1;
} else {
/* nothing to do */
@@ -498,19 +581,63 @@
return 0;
}
-static int mbox_sync_parse_all(struct mbox_sync_context *sync_ctx,
- struct mbox_sync_mail_context *mail_ctx)
+static int
+mbox_sync_seek_to_uid(struct mbox_sync_context *sync_ctx, uint32_t uid)
+{
+ uint32_t seq;
+ uint64_t offset;
+
+ if (mail_index_lookup_uid_range(sync_ctx->sync_view, uid, uid,
+ &seq, &seq) < 0)
+ return -1;
+
+ if (seq == 0)
+ return 0;
+
+ if (mbox_sync_get_from_offset(sync_ctx, seq, &offset) < 0)
+ return -1;
+
+ /* set to -1, since they're always increased later */
+ sync_ctx->seq = sync_ctx->idx_seq = seq-1;
+ istream_raw_mbox_seek(sync_ctx->input, offset);
+ return 0;
+}
+
+static int mbox_sync_loop(struct mbox_sync_context *sync_ctx,
+ struct mbox_sync_mail_context *mail_ctx,
+ uint32_t min_message_count)
{
const struct mail_index_record *rec;
uint32_t uid, messages_count;
uoff_t offset;
int ret, expunged;
- sync_ctx->file_input = sync_ctx->ibox->mbox_file_stream;
- sync_ctx->input = sync_ctx->ibox->mbox_stream;
- sync_ctx->fd = sync_ctx->ibox->mbox_fd;
+ if (min_message_count != 0)
+ istream_raw_mbox_seek(sync_ctx->input, 0);
+ else {
+ /* we sync only what we need to. jump to first record that
+ needs updating */
+ if (sync_ctx->sync_rec.uid1 == 0) {
+ if (mbox_sync_read_index_syncs(sync_ctx, 1,
+ &expunged) < 0)
+ return -1;
+ }
- istream_raw_mbox_seek(sync_ctx->input, 0);
+ if (sync_ctx->sync_rec.uid1 == 0) {
+ /* nothing to do */
+ return 0;
+ }
+
+ uid = sync_ctx->sync_rec.uid1;
+ if (mbox_sync_seek_to_uid(sync_ctx, uid) < 0)
+ return -1;
+
+ if (sync_ctx->seq > 0) {
+ if (mail_index_lookup_uid(sync_ctx->sync_view, 1,
+ &sync_ctx->first_uid) < 0)
+ return -1;
+ }
+ }
while ((ret = mbox_sync_read_next_mail(sync_ctx, mail_ctx)) > 0) {
uid = mail_ctx->mail.uid;
@@ -526,7 +653,7 @@
ret = mbox_sync_handle_expunge(mail_ctx);
}
if (ret < 0) {
- /* -1 = error, -2 = need exclusive lock */
+ /* -1 = error, -2 = need to restart */
return ret;
}
@@ -547,22 +674,47 @@
if (mbox_sync_handle_missing_space(mail_ctx) < 0)
return -1;
i_stream_seek(sync_ctx->input, offset);
- } else if (sync_ctx->expunged_space > 0 && !expunged) {
- /* move the body */
- if (mbox_move(sync_ctx,
- mail_ctx->body_offset -
- sync_ctx->expunged_space,
- mail_ctx->body_offset,
- mail_ctx->mail.body_size) < 0)
- return -1;
- i_stream_seek(sync_ctx->input, offset);
+ } else if (sync_ctx->expunged_space > 0) {
+ if (!expunged) {
+ /* move the body */
+ if (mbox_move(sync_ctx,
+ mail_ctx->body_offset -
+ sync_ctx->expunged_space,
+ mail_ctx->body_offset,
+ mail_ctx->mail.body_size) < 0)
+ return -1;
+ i_stream_seek(sync_ctx->input, offset);
+ }
+ } else if (sync_ctx->seq >= min_message_count) {
+ mbox_sync_buffer_delete_old(sync_ctx->syncs, uid+1);
+ if (buffer_get_used_size(sync_ctx->syncs) == 0) {
+ /* if there's no sync records left,
+ we can stop */
+ if (sync_ctx->sync_rec.uid1 == 0)
+ break;
+
+ /* we can skip forward to next record which
+ needs updating. */
+ uid = sync_ctx->sync_rec.uid1;
+ if (mbox_sync_seek_to_uid(sync_ctx, uid) < 0)
+ return -1;
+ }
}
}
- /* rest of the messages in index don't exist -> expunge them */
- messages_count = mail_index_view_get_message_count(sync_ctx->sync_view);
- while (sync_ctx->idx_seq < messages_count)
- mail_index_expunge(sync_ctx->t, ++sync_ctx->idx_seq);
+ if (sync_ctx->input->eof) {
+ /* rest of the messages in index don't exist -> expunge them */
+ messages_count =
+ mail_index_view_get_message_count(sync_ctx->sync_view);
+ while (sync_ctx->idx_seq < messages_count)
+ mail_index_expunge(sync_ctx->t, ++sync_ctx->idx_seq);
+ } else {
+ /* we didn't go through everything. fake the headers and all */
+ i_assert(sync_ctx->next_uid <= sync_ctx->hdr->next_uid);
+ sync_ctx->next_uid = sync_ctx->hdr->next_uid;
+ sync_ctx->base_uid_last = sync_ctx->hdr->next_uid-1;
+ sync_ctx->base_uid_validity = sync_ctx->hdr->uid_validity;
+ }
return 0;
}
@@ -572,6 +724,12 @@
{
uoff_t offset, extra_space, trailer_size;
+ if (!sync_ctx->input->eof) {
+ i_assert(sync_ctx->need_space_seq == 0);
+ i_assert(sync_ctx->expunged_space == 0);
+ return 0;
+ }
+
trailer_size = i_stream_get_size(sync_ctx->file_input) -
sync_ctx->file_input->v_offset;
@@ -613,6 +771,9 @@
sync_ctx->need_space_seq,
sync_ctx->seq);
}
+
+ sync_ctx->need_space_seq = 0;
+ buffer_set_used_size(sync_ctx->mails, 0);
}
if (sync_ctx->expunged_space > 0) {
@@ -624,8 +785,7 @@
offset + sync_ctx->expunged_space,
trailer_size) < 0)
return -1;
- if (ftruncate(sync_ctx->ibox->mbox_fd,
- offset + trailer_size) < 0) {
+ if (ftruncate(sync_ctx->fd, offset + trailer_size) < 0) {
mbox_set_syscall_error(sync_ctx->ibox, "ftruncate()");
return -1;
}
@@ -639,7 +799,7 @@
{
struct stat st;
- if (fstat(sync_ctx->ibox->mbox_fd, &st) < 0) {
+ if (fstat(sync_ctx->fd, &st) < 0) {
mbox_set_syscall_error(sync_ctx->ibox, "fstat()");
return -1;
}
@@ -687,48 +847,59 @@
sync_ctx->t = mail_index_transaction_begin(sync_ctx->sync_view, FALSE);
}
-static int mbox_sync_do(struct mbox_sync_context *sync_ctx, int index_synced)
+static int mbox_sync_do(struct mbox_sync_context *sync_ctx)
{
- struct index_mailbox *ibox = sync_ctx->ibox;
struct mbox_sync_mail_context mail_ctx;
+ struct stat st;
+ uint32_t min_msg_count;
int ret, lock_type;
lock_type = mail_index_sync_have_more(sync_ctx->index_sync_ctx) ?
F_WRLCK : F_RDLCK;
- if ((ret = mbox_lock(ibox, lock_type, &sync_ctx->lock_id)) <= 0)
- return ret;
+ if (mbox_sync_lock(sync_ctx, lock_type) < 0)
+ return -1;
- if (mbox_file_open_stream(ibox) < 0)
+ if (fstat(sync_ctx->fd, &st) < 0) {
+ mbox_set_syscall_error(sync_ctx->ibox, "stat()");
return -1;
+ }
- if ((ret = mbox_sync_parse_all(sync_ctx, &mail_ctx)) == -1)
+ min_msg_count =
+ (uint32_t)st.st_mtime == sync_ctx->hdr->sync_stamp &&
+ (uint64_t)st.st_size == sync_ctx->hdr->sync_size ?
+ 0 : (uint32_t)-1;
+
+ mbox_sync_restart(sync_ctx);
+ if ((ret = mbox_sync_loop(sync_ctx, &mail_ctx, min_msg_count)) == -1)
return -1;
if (ret == -2) {
- /* we want to modify mbox, get exclusive lock. this requires
- dropping the read lock first, so we have to parse the whole
- mbox again */
- (void)mbox_unlock(ibox, sync_ctx->lock_id);
- sync_ctx->lock_id = 0;
-
- if ((ret = mbox_lock(ibox, F_WRLCK, &sync_ctx->lock_id)) <= 0)
- return ret;
- if (mbox_file_open_stream(ibox) < 0)
- return -1;
+ /* initially we had mbox read-locked, but later we needed a
+ write-lock. doing it required dropping the read lock.
+ we're here because mbox was modified before we got the
+ write-lock. so, restart the whole syncing. */
+ i_assert(sync_ctx->ibox->mbox_lock_type == F_WRLCK);
- /* FIXME: if mbox timestamp hasn't changed and it's older than
- 2 secs, we could continue from where we left */
mbox_sync_restart(sync_ctx);
-
- if (mbox_sync_parse_all(sync_ctx, &mail_ctx) < 0)
+ if (mbox_sync_loop(sync_ctx, &mail_ctx, (uint32_t)-1) < 0)
return -1;
}
if (mbox_sync_handle_eof_updates(sync_ctx, &mail_ctx) < 0)
return -1;
- if (sync_ctx->base_uid_last+1 != sync_ctx->next_uid) {
- // FIXME: rewrite X-IMAPbase header
+ if (sync_ctx->base_uid_last != sync_ctx->next_uid-1) {
+ /* rewrite X-IMAPbase header */
+ if (mbox_sync_check_excl_lock(sync_ctx) == -1)
+ return -1;
+
+ sync_ctx->update_base_uid_last = sync_ctx->next_uid-1;
+ mbox_sync_restart(sync_ctx);
+ if (mbox_sync_loop(sync_ctx, &mail_ctx, 1) < 0)
+ return -1;
+
+ if (mbox_sync_handle_eof_updates(sync_ctx, &mail_ctx) < 0)
+ return -1;
}
/* only syncs left should be just appends (and their updates)
@@ -770,13 +941,12 @@
struct mbox_sync_context sync_ctx;
uint32_t seq;
uoff_t offset;
- int ret, index_synced;
+ int ret;
if ((ret = mbox_sync_has_changed(ibox)) < 0)
return -1;
if (ret == 0 && !last_commit)
return 0;
- index_synced = ret > 0;
if (last_commit) {
seq = ibox->commit_log_file_seq;
@@ -805,12 +975,11 @@
sync_ctx.mails = buffer_create_dynamic(default_pool, 4096, (size_t)-1);
sync_ctx.syncs = buffer_create_dynamic(default_pool, 256, (size_t)-1);
- sync_ctx.next_uid = 1;
ret = mail_index_get_header(sync_view, &sync_ctx.hdr);
i_assert(ret == 0);
- if (mbox_sync_do(&sync_ctx, index_synced) < 0)
+ if (mbox_sync_do(&sync_ctx) < 0)
ret = -1;
if (ret < 0)
@@ -826,6 +995,8 @@
ret = -1;
if (sync_ctx.lock_id != 0) {
+ /* FIXME: drop to read locking and keep it MBOX_SYNC_SECS+1
+ to make sure we notice changes made by others */
if (mbox_unlock(ibox, sync_ctx.lock_id) < 0)
ret = -1;
}
- Previous message: [dovecot-cvs] dovecot/src/lib-storage/index/mbox
mbox-sync-private.h, 1.9, 1.10 mbox-sync-rewrite.c, 1.11,
1.12 mbox-sync-update.c, 1.8, 1.9 mbox-sync.c, 1.18, 1.19
- Next message: [dovecot-cvs]
dovecot/src/lib-storage/index/mbox istream-raw-mbox.c, 1.7,
1.8 mbox-mail.c, 1.3, 1.4 mbox-sync-rewrite.c, 1.12,
1.13 mbox-sync.c, 1.20, 1.21
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the dovecot-cvs
mailing list