dovecot-1.1: mbox: Added a new index header where dirtyness stat...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Dec 13 09:39:53 EET 2008
details: http://hg.dovecot.org/dovecot-1.1/rev/a28520d26b5a
changeset: 8035:a28520d26b5a
user: Timo Sirainen <tss at iki.fi>
date: Sat Dec 13 09:39:49 2008 +0200
description:
mbox: Added a new index header where dirtyness state is stored.
This also fixes a bug where sync_size wasn't updated in header when mbox was
marked dirty, causing other parts of code to assume wrong file size and
return wrong size for the last message and/or cause "Next message
unexpectedly lost" errors.
diffstat:
8 files changed, 142 insertions(+), 97 deletions(-)
src/lib-storage/index/mbox/mbox-file.c | 16 +-
src/lib-storage/index/mbox/mbox-mail.c | 11 +
src/lib-storage/index/mbox/mbox-save.c | 45 +++----
src/lib-storage/index/mbox/mbox-storage.c | 3
src/lib-storage/index/mbox/mbox-storage.h | 11 +
src/lib-storage/index/mbox/mbox-sync-private.h | 1
src/lib-storage/index/mbox/mbox-sync.c | 138 ++++++++++++++----------
src/util/idxview.c | 14 ++
diffs (truncated from 503 to 300 lines):
diff -r 74c47fcfb420 -r a28520d26b5a src/lib-storage/index/mbox/mbox-file.c
--- a/src/lib-storage/index/mbox/mbox-file.c Sat Dec 13 08:36:59 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-file.c Sat Dec 13 09:39:49 2008 +0200
@@ -147,7 +147,8 @@ int mbox_file_lookup_offset(struct mbox_
mail_storage_set_critical(&mbox->storage->storage,
"Cached message offset lost for seq %u in mbox file %s",
seq, mbox->path);
- mbox->mbox_sync_dirty = TRUE;
+ mbox->mbox_hdr.dirty_flag = TRUE;
+ mbox->mbox_broken_offsets = TRUE;
return 0;
}
@@ -176,17 +177,18 @@ int mbox_file_seek(struct mbox_mailbox *
return -1;
}
- if (mbox->mbox_sync_dirty)
+ if (mbox->mbox_hdr.dirty_flag)
return 0;
mail_storage_set_critical(&mbox->storage->storage,
"Cached message offset %s is invalid for mbox file %s",
dec2str(offset), mbox->path);
- mbox->mbox_sync_dirty = TRUE;
- return 0;
- }
-
- if (mbox->mbox_sync_dirty) {
+ mbox->mbox_hdr.dirty_flag = TRUE;
+ mbox->mbox_broken_offsets = TRUE;
+ return 0;
+ }
+
+ if (mbox->mbox_hdr.dirty_flag) {
/* we're dirty - make sure this is the correct mail */
if (!mbox_sync_parse_match_mail(mbox, view, seq))
return 0;
diff -r 74c47fcfb420 -r a28520d26b5a src/lib-storage/index/mbox/mbox-mail.c
--- a/src/lib-storage/index/mbox/mbox-mail.c Sat Dec 13 08:36:59 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-mail.c Sat Dec 13 09:39:49 2008 +0200
@@ -189,10 +189,11 @@ mbox_mail_get_next_offset(struct index_m
}
/* We can't really trust trans_view. The next message may already be
- expugned from it. hdr.sync_size may also be updated, but
- hdr.messages_count not. So refresh the index to get the latest
- changes and get the next message's offset using a new view. */
- (void)mail_index_refresh(mail->ibox->index);
+ expunged from it. Also there hdr.messages_count may be incorrect.
+ So refresh the index to get the latest changes and get the next
+ message's offset using a new view. */
+ if (mbox_sync_header_refresh(mbox) < 0)
+ return -1;
view = mail_index_view_open(mail->ibox->index);
hdr = mail_index_get_header(view);
@@ -203,7 +204,7 @@ mbox_mail_get_next_offset(struct index_m
/* last message, use the synced mbox size */
trailer_size = (mbox->storage->storage.flags &
MAIL_STORAGE_FLAG_SAVE_CRLF) != 0 ? 2 : 1;
- *next_offset_r = hdr->sync_size - trailer_size;
+ *next_offset_r = mbox->mbox_hdr.sync_size - trailer_size;
} else {
if (mbox_file_lookup_offset(mbox, view, seq + 1,
next_offset_r) <= 0)
diff -r 74c47fcfb420 -r a28520d26b5a src/lib-storage/index/mbox/mbox-save.c
--- a/src/lib-storage/index/mbox/mbox-save.c Sat Dec 13 08:36:59 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-save.c Sat Dec 13 09:39:49 2008 +0200
@@ -710,41 +710,34 @@ int mbox_transaction_save_commit(struct
{
struct mbox_transaction_context *t =
(struct mbox_transaction_context *)ctx->ctx.transaction;
+ struct mbox_mailbox *mbox = ctx->mbox;
struct stat st;
int ret = 0;
i_assert(ctx->finished);
- if (fstat(ctx->mbox->mbox_fd, &st) < 0) {
- mbox_set_syscall_error(ctx->mbox, "fstat()");
+ if (fstat(mbox->mbox_fd, &st) < 0) {
+ mbox_set_syscall_error(mbox, "fstat()");
ret = -1;
}
if (ctx->synced) {
*t->ictx.saved_uid_validity = ctx->uid_validity;
*t->ictx.first_saved_uid = ctx->first_saved_uid;
+ *t->ictx.last_saved_uid = ctx->next_uid - 1;
mail_index_update_header(ctx->trans,
offsetof(struct mail_index_header, next_uid),
&ctx->next_uid, sizeof(ctx->next_uid), FALSE);
- if (!ctx->mbox->mbox_sync_dirty && ret == 0) {
- uint32_t sync_stamp = st.st_mtime;
-
- mail_index_update_header(ctx->trans,
- offsetof(struct mail_index_header, sync_stamp),
- &sync_stamp, sizeof(sync_stamp), TRUE);
- }
if (ret == 0) {
- /* sync_size is used in calculating the last message's
- size. it must be up-to-date. */
- uint64_t sync_size = st.st_size;
-
- mail_index_update_header(ctx->trans,
- offsetof(struct mail_index_header, sync_size),
- &sync_size, sizeof(sync_size), TRUE);
- }
- *t->ictx.last_saved_uid = ctx->next_uid - 1;
+ mbox->mbox_hdr.sync_mtime = st.st_mtime;
+ mbox->mbox_hdr.sync_size = st.st_size;
+ mail_index_update_header_ext(ctx->trans,
+ mbox->mbox_ext_idx,
+ 0, &mbox->mbox_hdr,
+ sizeof(mbox->mbox_hdr));
+ }
}
if (ret == 0 && ctx->orig_atime != st.st_atime) {
@@ -753,14 +746,14 @@ int mbox_transaction_save_commit(struct
buf.modtime = st.st_mtime;
buf.actime = ctx->orig_atime;
- if (utime(ctx->mbox->path, &buf) < 0)
- mbox_set_syscall_error(ctx->mbox, "utime()");
- }
-
- if (!ctx->synced && ctx->mbox->mbox_fd != -1 &&
- !ctx->mbox->mbox_writeonly && !ctx->mbox->ibox.fsync_disable) {
- if (fdatasync(ctx->mbox->mbox_fd) < 0) {
- mbox_set_syscall_error(ctx->mbox, "fdatasync()");
+ if (utime(mbox->path, &buf) < 0)
+ mbox_set_syscall_error(mbox, "utime()");
+ }
+
+ if (!ctx->synced && mbox->mbox_fd != -1 &&
+ !mbox->mbox_writeonly && !mbox->ibox.fsync_disable) {
+ if (fdatasync(mbox->mbox_fd) < 0) {
+ mbox_set_syscall_error(mbox, "fdatasync()");
ret = -1;
}
}
diff -r 74c47fcfb420 -r a28520d26b5a src/lib-storage/index/mbox/mbox-storage.c
--- a/src/lib-storage/index/mbox/mbox-storage.c Sat Dec 13 08:36:59 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-storage.c Sat Dec 13 09:39:49 2008 +0200
@@ -558,7 +558,8 @@ mbox_alloc_mailbox(struct mbox_storage *
mbox->mbox_fd = -1;
mbox->mbox_lock_type = F_UNLCK;
mbox->mbox_ext_idx =
- mail_index_ext_register(index, "mbox", 0,
+ mail_index_ext_register(index, "mbox",
+ sizeof(mbox->mbox_hdr),
sizeof(uint64_t), sizeof(uint64_t));
mbox->mbox_very_dirty_syncs = getenv("MBOX_VERY_DIRTY_SYNCS") != NULL;
diff -r 74c47fcfb420 -r a28520d26b5a src/lib-storage/index/mbox/mbox-storage.h
--- a/src/lib-storage/index/mbox/mbox-storage.h Sat Dec 13 08:36:59 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-storage.h Sat Dec 13 09:39:49 2008 +0200
@@ -14,6 +14,12 @@
#include "index-storage.h"
#include "mailbox-list-private.h"
+struct mbox_index_header {
+ uint64_t sync_size;
+ uint32_t sync_mtime;
+ uint8_t dirty_flag;
+ uint8_t unused[3];
+};
struct mbox_storage {
struct mail_storage storage;
@@ -36,13 +42,12 @@ struct mbox_mailbox {
unsigned int mbox_lock_id, mbox_global_lock_id;
struct timeout *keep_lock_to;
bool mbox_readonly, mbox_writeonly;
- time_t mbox_dirty_stamp;
- off_t mbox_dirty_size;
uint32_t mbox_ext_idx;
+ struct mbox_index_header mbox_hdr;
unsigned int no_mbox_file:1;
- unsigned int mbox_sync_dirty:1;
+ unsigned int mbox_broken_offsets:1;
unsigned int mbox_do_dirty_syncs:1;
unsigned int mbox_very_dirty_syncs:1;
unsigned int mbox_save_md5:1;
diff -r 74c47fcfb420 -r a28520d26b5a src/lib-storage/index/mbox/mbox-sync-private.h
--- a/src/lib-storage/index/mbox/mbox-sync-private.h Sat Dec 13 08:36:59 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-sync-private.h Sat Dec 13 09:39:49 2008 +0200
@@ -146,6 +146,7 @@ struct mbox_sync_context {
unsigned int errors:1;
};
+int mbox_sync_header_refresh(struct mbox_mailbox *mbox);
int mbox_sync(struct mbox_mailbox *mbox, enum mbox_sync_flags flags);
int mbox_sync_has_changed(struct mbox_mailbox *mbox, bool leave_dirty);
int mbox_sync_has_changed_full(struct mbox_mailbox *mbox, bool leave_dirty,
diff -r 74c47fcfb420 -r a28520d26b5a src/lib-storage/index/mbox/mbox-sync.c
--- a/src/lib-storage/index/mbox/mbox-sync.c Sat Dec 13 08:36:59 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-sync.c Sat Dec 13 09:39:49 2008 +0200
@@ -934,7 +934,7 @@ static int mbox_sync_partial_seek_next(s
} else {
/* if there's no sync records left, we can stop. except if
this is a dirty sync, check if there are new messages. */
- if (!sync_ctx->mbox->mbox_sync_dirty)
+ if (!sync_ctx->mbox->mbox_hdr.dirty_flag)
return 0;
messages_count =
@@ -1005,7 +1005,7 @@ static int mbox_sync_loop(struct mbox_sy
if (mail_ctx->seq == 1) {
if (mbox_sync_uidvalidity_changed(sync_ctx)) {
- sync_ctx->mbox->mbox_sync_dirty = TRUE;
+ sync_ctx->mbox->mbox_hdr.dirty_flag = TRUE;
return 0;
}
}
@@ -1013,14 +1013,14 @@ static int mbox_sync_loop(struct mbox_sy
if (mail_ctx->mail.uid_broken && partial) {
/* UID ordering problems, resync everything to make
sure we get everything right */
- if (sync_ctx->mbox->mbox_sync_dirty)
+ if (sync_ctx->mbox->mbox_hdr.dirty_flag)
return 0;
mbox_sync_set_critical(sync_ctx,
"UIDs broken with partial sync in mbox file %s",
sync_ctx->mbox->path);
- sync_ctx->mbox->mbox_sync_dirty = TRUE;
+ sync_ctx->mbox->mbox_hdr.dirty_flag = TRUE;
return 0;
}
if (mail_ctx->mail.uid_broken)
@@ -1158,13 +1158,14 @@ static int mbox_sync_loop(struct mbox_sy
}
if (!skipped_mails)
- sync_ctx->mbox->mbox_sync_dirty = FALSE;
+ sync_ctx->mbox->mbox_hdr.dirty_flag = FALSE;
+ sync_ctx->mbox->mbox_broken_offsets = FALSE;
if (uids_broken && sync_ctx->delay_writes) {
/* once we get around to writing the changes, we'll need to do
a full sync to avoid the "UIDs broken in partial sync"
error */
- sync_ctx->mbox->mbox_sync_dirty = TRUE;
+ sync_ctx->mbox->mbox_hdr.dirty_flag = TRUE;
}
return 1;
}
@@ -1327,6 +1328,23 @@ static int mbox_sync_handle_eof_updates(
return 0;
}
+static void
+mbox_sync_index_update_ext_header(struct mbox_sync_context *sync_ctx)
+{
+ struct mbox_mailbox *mbox = sync_ctx->mbox;
+ const void *data;
+ size_t data_size;
+
+ mail_index_get_header_ext(mbox->ibox.view, mbox->mbox_ext_idx,
+ &data, &data_size);
+ if (data_size != sizeof(mbox->mbox_hdr) ||
+ memcmp(data, &mbox->mbox_hdr, data_size) != 0) {
+ mail_index_update_header_ext(sync_ctx->t, mbox->mbox_ext_idx,
+ 0, &mbox->mbox_hdr,
+ sizeof(mbox->mbox_hdr));
+ }
+}
+
static int mbox_sync_update_index_header(struct mbox_sync_context *sync_ctx)
{
struct mail_index_view *view;
@@ -1340,7 +1358,7 @@ static int mbox_sync_update_index_header
}
if (sync_ctx->moved_offsets &&
- ((uint64_t)st->st_size == sync_ctx->hdr->sync_size ||
+ ((uint64_t)st->st_size == sync_ctx->mbox->mbox_hdr.sync_size ||
(uint64_t)st->st_size == sync_ctx->orig_size)) {
/* We moved messages inside the mbox file without changing
the file's size. If mtime doesn't change, another process
@@ -1371,6 +1389,10 @@ static int mbox_sync_update_index_header
}
}
+ sync_ctx->mbox->mbox_hdr.sync_mtime = st->st_mtime;
+ sync_ctx->mbox->mbox_hdr.sync_size = st->st_size;
+ mbox_sync_index_update_ext_header(sync_ctx);
+
/* only reason not to have UID validity at this point is if the file
is entirely empty. In that case just make up a new one if needed. */
i_assert(sync_ctx->base_uid_validity != 0 || st->st_size <= 0);
More information about the dovecot-cvs
mailing list