dovecot: Store syncing information to maildir extension header i...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Jul 9 05:44:45 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/b9865213da42
changeset: 5927:b9865213da42
user: Timo Sirainen <tss at iki.fi>
date: Mon Jul 09 01:33:30 2007 +0300
description:
Store syncing information to maildir extension header instead of kludging
them into base header. Also we're now using nanoseconds to check for changes
if they're available.
diffstat:
4 files changed, 188 insertions(+), 136 deletions(-)
src/lib-storage/index/maildir/maildir-storage.c | 4
src/lib-storage/index/maildir/maildir-storage.h | 16 -
src/lib-storage/index/maildir/maildir-sync-index.c | 48 +--
src/lib-storage/index/maildir/maildir-sync.c | 256 +++++++++++---------
diffs (truncated from 472 to 300 lines):
diff -r 095b3adc537b -r b9865213da42 src/lib-storage/index/maildir/maildir-storage.c
--- a/src/lib-storage/index/maildir/maildir-storage.c Mon Jul 09 00:52:04 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.c Mon Jul 09 01:33:30 2007 +0300
@@ -464,6 +464,10 @@ maildir_open(struct maildir_storage *sto
mbox->uidlist = maildir_uidlist_init(mbox);
mbox->keywords = maildir_keywords_init(mbox);
+
+ mbox->maildir_ext_id =
+ mail_index_ext_register(index, "maildir",
+ sizeof(mbox->maildir_hdr), 0, 0);
if (!shared) {
mbox->mail_create_mode = 0600;
diff -r 095b3adc537b -r b9865213da42 src/lib-storage/index/maildir/maildir-storage.h
--- a/src/lib-storage/index/maildir/maildir-storage.h Mon Jul 09 00:52:04 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.h Mon Jul 09 01:33:30 2007 +0300
@@ -49,6 +49,11 @@ struct maildir_save_context;
struct maildir_save_context;
struct maildir_copy_context;
+struct maildir_index_header {
+ uint32_t new_check_time, new_mtime, new_mtime_nsecs;
+ uint32_t cur_check_time, cur_mtime, cur_mtime_nsecs;
+};
+
struct maildir_storage {
struct mail_storage storage;
@@ -61,11 +66,6 @@ struct maildir_storage {
unsigned int stat_dirs:1;
};
-enum maildir_dirty_flags {
- MAILDIR_DIRTY_NEW = 0x01,
- MAILDIR_DIRTY_CUR = 0x02
-};
-
struct maildir_mailbox {
struct index_mailbox ibox;
struct maildir_storage *storage;
@@ -76,9 +76,9 @@ struct maildir_mailbox {
/* maildir sync: */
struct maildir_uidlist *uidlist;
struct maildir_keywords *keywords;
- time_t last_new_mtime, last_cur_mtime;
- time_t dirty_cur_time;
- enum maildir_dirty_flags last_dirty_flags;
+
+ struct maildir_index_header maildir_hdr;
+ uint32_t maildir_ext_id;
mode_t mail_create_mode;
gid_t mail_create_gid;
diff -r 095b3adc537b -r b9865213da42 src/lib-storage/index/maildir/maildir-sync-index.c
--- a/src/lib-storage/index/maildir/maildir-sync-index.c Mon Jul 09 00:52:04 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c Mon Jul 09 01:33:30 2007 +0300
@@ -120,7 +120,7 @@ static void maildir_handle_uid_insertion
shouldn't actually exist. */
if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RACING) == 0) {
/* mark it racy and check in next sync */
- ctx->mbox->dirty_cur_time = ioloop_time;
+ ctx->mbox->maildir_hdr.cur_check_time = 0;
maildir_uidlist_add_flags(ctx->mbox->uidlist, filename,
MAILDIR_UIDLIST_REC_FLAG_RACING);
return;
@@ -212,6 +212,27 @@ int maildir_sync_index_finish(struct mai
index_sync_changes_deinit(&ctx->sync_changes);
i_free(ctx);
return ret;
+}
+
+static void
+maildir_index_update_ext_header(struct maildir_mailbox *mbox,
+ struct mail_index_transaction *trans)
+{
+ const void *data;
+ size_t data_size;
+
+ if (mail_index_get_header_ext(mbox->ibox.view, mbox->maildir_ext_id,
+ &data, &data_size) < 0)
+ data_size = 0;
+
+ if (data_size == sizeof(mbox->maildir_hdr) &&
+ memcmp(data, &mbox->maildir_hdr, data_size) == 0) {
+ /* nothing changed */
+ } else {
+ mail_index_update_header_ext(trans, mbox->maildir_ext_id, 0,
+ &mbox->maildir_hdr,
+ sizeof(mbox->maildir_hdr));
+ }
}
int maildir_sync_index(struct maildir_index_sync_context *ctx,
@@ -229,7 +250,6 @@ int maildir_sync_index(struct maildir_in
const char *filename;
ARRAY_TYPE(keyword_indexes) idx_keywords;
uint32_t uid_validity, next_uid;
- uint64_t value;
unsigned int changes = 0;
int ret = 0;
bool expunged, full_rescan = FALSE;
@@ -439,31 +459,11 @@ int maildir_sync_index(struct maildir_in
}
if (ctx->changed)
- mbox->dirty_cur_time = ioloop_time;
- if (mbox->dirty_cur_time != 0)
- mbox->last_dirty_flags |= MAILDIR_DIRTY_CUR;
-
- if (mbox->last_cur_mtime != (time_t)hdr->sync_stamp) {
- uint32_t sync_stamp = mbox->last_cur_mtime;
-
- mail_index_update_header(trans,
- offsetof(struct mail_index_header, sync_stamp),
- &sync_stamp, sizeof(sync_stamp), TRUE);
- }
-
- /* FIXME: use a header extension instead of sync_size.. */
- value = mbox->last_new_mtime |
- ((uint64_t)mbox->last_dirty_flags << 32);
- if (value != hdr->sync_size) {
- mail_index_update_header(trans,
- offsetof(struct mail_index_header, sync_size),
- &value, sizeof(value), TRUE);
- }
+ ctx->mbox->maildir_hdr.cur_mtime = time(NULL);
+ maildir_index_update_ext_header(ctx->mbox, trans);
if (hdr->uid_validity == 0) {
/* get the initial uidvalidity */
- if (maildir_uidlist_refresh(mbox->uidlist) < 0)
- ret = -1;
uid_validity = maildir_uidlist_get_uid_validity(mbox->uidlist);
if (uid_validity == 0) {
uid_validity = ioloop_time;
diff -r 095b3adc537b -r b9865213da42 src/lib-storage/index/maildir/maildir-sync.c
--- a/src/lib-storage/index/maildir/maildir-sync.c Mon Jul 09 00:52:04 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync.c Mon Jul 09 01:33:30 2007 +0300
@@ -354,25 +354,60 @@ static int maildir_scan_dir(struct maild
static int maildir_scan_dir(struct maildir_sync_context *ctx, bool new_dir)
{
struct mail_storage *storage = &ctx->mbox->storage->storage;
- const char *dir;
+ const char *path;
DIR *dirp;
string_t *src, *dest;
struct dirent *dp;
+ struct stat st;
enum maildir_uidlist_rec_flag flags;
unsigned int i = 0, move_count = 0;
+ time_t now;
int ret = 1;
- bool move_new, check_touch;
-
- dir = new_dir ? ctx->new_dir : ctx->cur_dir;
- dirp = opendir(dir);
+ bool move_new, check_touch, dir_changed = FALSE;
+
+ path = new_dir ? ctx->new_dir : ctx->cur_dir;
+ dirp = opendir(path);
if (dirp == NULL) {
if (errno == ENOENT) {
ctx->mbox->ibox.mailbox_deleted = TRUE;
return -1;
}
mail_storage_set_critical(storage,
- "opendir(%s) failed: %m", dir);
+ "opendir(%s) failed: %m", path);
return -1;
+ }
+
+#ifdef HAVE_DIRFD
+ if (fstat(dirfd(dirp), &st) < 0) {
+ mail_storage_set_critical(storage,
+ "fstat(%s) failed: %m", path);
+ (void)closedir(dirp);
+ return -1;
+ }
+#else
+ if (maildir_stat(ctx->mbox, path, &st) < 0) {
+ (void)closedir(dirp);
+ return -1;
+ }
+#endif
+
+ now = time(NULL);
+ if (new_dir) {
+ ctx->mbox->maildir_hdr.new_check_time = now;
+ ctx->mbox->maildir_hdr.new_mtime = st.st_mtime;
+#ifdef HAVE_STAT_TV_NSEC
+ ctx->mbox->maildir_hdr.new_mtime_nsecs = st.st_mtim.tv_nsec;
+#else
+ ctx->mbox->maildir_hdr.new_mtime_nsecs = 0;
+#endif
+ } else {
+ ctx->mbox->maildir_hdr.cur_check_time = now;
+ ctx->mbox->maildir_hdr.cur_mtime = st.st_mtime;
+#ifdef HAVE_STAT_TV_NSEC
+ ctx->mbox->maildir_hdr.cur_mtime_nsecs = st.st_mtim.tv_nsec;
+#else
+ ctx->mbox->maildir_hdr.cur_mtime_nsecs = 0;
+#endif
}
t_push();
@@ -392,10 +427,7 @@ static int maildir_scan_dir(struct maild
if (ret == 0) {
/* new file and we couldn't lock uidlist, check this
later in next sync. */
- if (new_dir)
- ctx->mbox->last_new_mtime = 0;
- else
- ctx->mbox->dirty_cur_time = ioloop_time;
+ dir_changed = TRUE;
continue;
}
if (ret < 0)
@@ -413,12 +445,13 @@ static int maildir_scan_dir(struct maild
}
if (rename(str_c(src), str_c(dest)) == 0) {
/* we moved it - it's \Recent for us */
+ dir_changed = TRUE;
move_count++;
- ctx->mbox->dirty_cur_time = ioloop_time;
flags |= MAILDIR_UIDLIST_REC_FLAG_MOVED |
MAILDIR_UIDLIST_REC_FLAG_RECENT;
} else if (ENOTFOUND(errno)) {
/* someone else moved it already */
+ dir_changed = TRUE;
move_count++;
flags |= MAILDIR_UIDLIST_REC_FLAG_MOVED;
} else if (ENOSPACE(errno) || errno == EACCES) {
@@ -452,7 +485,7 @@ static int maildir_scan_dir(struct maild
break;
/* possibly duplicate - try fixing it */
- if (maildir_fix_duplicate(ctx, dir, dp->d_name) < 0) {
+ if (maildir_fix_duplicate(ctx, path, dp->d_name) < 0) {
ret = -1;
break;
}
@@ -461,14 +494,21 @@ static int maildir_scan_dir(struct maild
if (errno != 0) {
mail_storage_set_critical(storage,
- "readdir(%s) failed: %m", dir);
+ "readdir(%s) failed: %m", path);
ret = -1;
}
if (closedir(dirp) < 0) {
mail_storage_set_critical(storage,
- "closedir(%s) failed: %m", dir);
+ "closedir(%s) failed: %m", path);
ret = -1;
+ }
+
+ if (dir_changed) {
+ if (new_dir)
+ ctx->mbox->maildir_hdr.new_mtime = now;
+ else
+ ctx->mbox->maildir_hdr.cur_mtime = now;
}
t_pop();
@@ -476,98 +516,107 @@ static int maildir_scan_dir(struct maild
(move_count <= MAILDIR_RENAME_RESCAN_COUNT ? 0 : 1);
}
-static void
-maildir_sync_update_from_header(struct maildir_mailbox *mbox,
- struct mail_index_header *hdr_r)
-{
- struct mail_index_view *view;
- const struct mail_index_header *hdr;
-
- /* open a new view so we get the latest header */
- view = mail_index_view_open(mbox->ibox.index);
- hdr = mail_index_get_header(view);
-
- /* FIXME: ugly, replace with extension header */
- mbox->last_new_mtime = hdr->sync_size & 0xffffffff;
- mbox->last_dirty_flags = (hdr->sync_size >> 32) &
- (MAILDIR_DIRTY_NEW | MAILDIR_DIRTY_CUR);
-
- mbox->last_cur_mtime = hdr->sync_stamp;
-
- if ((mbox->last_dirty_flags & MAILDIR_DIRTY_CUR) != 0 &&
- mbox->dirty_cur_time < mbox->last_cur_mtime)
- mbox->dirty_cur_time = mbox->last_cur_mtime;
-
- *hdr_r = *hdr;
- mail_index_view_close(&view);
-}
-
-static int
-maildir_sync_quick_check(struct maildir_mailbox *mbox,
- const char *new_dir, const char *cur_dir,
- bool *new_changed_r, bool *cur_changed_r)
More information about the dovecot-cvs
mailing list