dovecot: Sync index changes while iterating through uidlist entr...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Jul 9 05:44:41 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/ae731dbf3a6f
changeset: 5914:ae731dbf3a6f
user: Timo Sirainen <tss at iki.fi>
date: Sun Jul 08 22:54:55 2007 +0300
description:
Sync index changes while iterating through uidlist entries. This avoids
unnecessary (and broken) flag updates.
diffstat:
1 file changed, 107 insertions(+), 260 deletions(-)
src/lib-storage/index/maildir/maildir-sync.c | 367 +++++++-------------------
diffs (truncated from 624 to 300 lines):
diff -r 699356ffe549 -r ae731dbf3a6f src/lib-storage/index/maildir/maildir-sync.c
--- a/src/lib-storage/index/maildir/maildir-sync.c Sun Jul 08 22:53:31 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync.c Sun Jul 08 22:54:55 2007 +0300
@@ -177,6 +177,7 @@
#include "hash.h"
#include "str.h"
#include "maildir-storage.h"
+#include "index-sync-changes.h"
#include "maildir-uidlist.h"
#include "maildir-keywords.h"
#include "maildir-filename.h"
@@ -217,7 +218,6 @@ struct maildir_sync_context {
const char *new_dir, *cur_dir;
bool partial;
- unsigned int move_count, check_count;
time_t last_touch, last_notify;
struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
@@ -233,9 +233,13 @@ struct maildir_index_sync_context {
struct maildir_keywords_sync_ctx *keywords_sync_ctx;
struct mail_index_transaction *trans;
- ARRAY_DEFINE(sync_recs, struct mail_index_sync_rec);
+ struct index_sync_changes_context *sync_changes;
+ enum mail_flags flags;
+ ARRAY_TYPE(keyword_indexes) keywords;
+
uint32_t seq, uid;
- int dirty_state;
+
+ bool changed;
};
struct maildir_keywords_sync_ctx *
@@ -255,7 +259,7 @@ static int maildir_expunge(struct maildi
MAILBOX_SYNC_TYPE_EXPUNGE);
}
mail_index_expunge(ctx->trans, ctx->seq);
- mbox->dirty_cur_time = ioloop_time;
+ ctx->changed = TRUE;
return 1;
}
if (errno == ENOENT)
@@ -270,79 +274,47 @@ static int maildir_sync_flags(struct mai
struct maildir_index_sync_context *ctx)
{
struct mailbox *box = &mbox->ibox.box;
- const struct mail_index_sync_rec *recs;
const char *dir, *fname, *newfname, *newpath;
- enum mail_flags flags;
enum mailbox_sync_type sync_type = 0;
- ARRAY_TYPE(keyword_indexes) keywords;
- unsigned int i, count;
uint8_t flags8;
-
- ctx->dirty_state = 0;
fname = strrchr(path, '/');
i_assert(fname != NULL);
fname++;
dir = t_strdup_until(path, fname);
- t_array_init(&keywords, 16);
+ /* get the current flags and keywords */
maildir_filename_get_flags(ctx->keywords_sync_ctx,
- fname, &flags, &keywords);
- flags8 = flags;
-
- recs = array_get_modifiable(&ctx->sync_recs, &count);
- for (i = 0; i < count; i++) {
- if (recs[i].uid1 != ctx->seq)
- break;
-
- switch (recs[i].type) {
- case MAIL_INDEX_SYNC_TYPE_FLAGS:
- mail_index_sync_flags_apply(&recs[i], &flags8);
- sync_type |= MAILBOX_SYNC_TYPE_FLAGS;
- break;
- case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
- case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
- case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
- mail_index_sync_keywords_apply(&recs[i], &keywords);
- sync_type |= MAILBOX_SYNC_TYPE_KEYWORDS;
- break;
- case MAIL_INDEX_SYNC_TYPE_APPEND:
- case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
- i_unreached();
- break;
- }
- }
- i_assert(sync_type != 0);
-
- newfname = maildir_filename_set_flags(ctx->keywords_sync_ctx,
- fname, flags8, &keywords);
+ fname, &ctx->flags, &ctx->keywords);
+
+ /* apply changes */
+ flags8 = ctx->flags;
+ index_sync_changes_apply(ctx->sync_changes, NULL,
+ &flags8, &ctx->keywords, &sync_type);
+ ctx->flags = flags8;
+
+ /* and try renaming with the new name */
+ newfname = maildir_filename_set_flags(ctx->keywords_sync_ctx, fname,
+ ctx->flags, &ctx->keywords);
newpath = t_strconcat(dir, newfname, NULL);
if (rename(path, newpath) == 0) {
if (box->v.sync_notify != NULL)
box->v.sync_notify(box, ctx->uid, sync_type);
- if ((flags8 & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
- ctx->dirty_state = -1;
- mbox->dirty_cur_time = ioloop_time;
+ ctx->changed = TRUE;
return 1;
}
if (errno == ENOENT)
return 0;
- if (ENOSPACE(errno) || errno == EACCES) {
- mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_ADD,
- (enum mail_flags)MAIL_INDEX_MAIL_FLAG_DIRTY);
- ctx->dirty_state = 1;
- return 1;
- }
-
- mail_storage_set_critical(&mbox->storage->storage,
- "rename(%s, %s) failed: %m", path, newpath);
+ if (!ENOSPACE(errno) && errno != EACCES) {
+ mail_storage_set_critical(&mbox->storage->storage,
+ "rename(%s, %s) failed: %m", path, newpath);
+ }
return -1;
}
-static void
-maildir_sync_check_timeouts(struct maildir_sync_context *ctx, bool move)
+static void maildir_sync_notify(struct maildir_sync_context *ctx)
{
time_t now;
@@ -352,16 +324,6 @@ maildir_sync_check_timeouts(struct maild
return;
}
- if (move) {
- ctx->move_count++;
- if ((ctx->move_count % MAILDIR_SLOW_MOVE_COUNT) != 0)
- return;
- } else {
- ctx->check_count++;
- if ((ctx->check_count % MAILDIR_SLOW_CHECK_COUNT) != 0)
- return;
- }
-
now = time(NULL);
if (now - ctx->last_touch > MAILDIR_LOCK_TOUCH_SECS) {
(void)maildir_uidlist_lock_touch(ctx->mbox->uidlist);
@@ -377,152 +339,6 @@ maildir_sync_check_timeouts(struct maild
}
ctx->last_notify = now;
}
-}
-
-static int
-maildir_sync_record_commit_until(struct maildir_index_sync_context *ctx,
- uint32_t last_seq)
-{
- struct mail_index_sync_rec *recs;
- unsigned int i, count;
- uint32_t seq, uid;
- bool expunged, flag_changed;
-
- recs = array_get_modifiable(&ctx->sync_recs, &count);
- for (seq = recs[0].uid1; seq <= last_seq; seq++) {
- expunged = flag_changed = FALSE;
- for (i = 0; i < count; i++) {
- if (recs[i].uid1 > seq)
- break;
-
- i_assert(recs[i].uid1 == seq);
- switch (recs[i].type) {
- case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
- expunged = TRUE;
- break;
- case MAIL_INDEX_SYNC_TYPE_FLAGS:
- case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
- case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
- case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
- flag_changed = TRUE;
- break;
- case MAIL_INDEX_SYNC_TYPE_APPEND:
- i_unreached();
- break;
- }
- }
-
- if (mail_index_lookup_uid(ctx->view, seq, &uid) < 0) {
- mail_storage_set_index_error(&ctx->mbox->ibox);
- return -1;
- }
-
- ctx->seq = seq;
- ctx->uid = uid;
- if (expunged) {
- maildir_sync_check_timeouts(ctx->maildir_sync_ctx,
- TRUE);
- (void)maildir_file_do(ctx->mbox, uid,
- maildir_expunge, ctx);
- } else if (flag_changed) {
- maildir_sync_check_timeouts(ctx->maildir_sync_ctx,
- TRUE);
- (void)maildir_file_do(ctx->mbox, uid,
- maildir_sync_flags, ctx);
- }
-
- for (i = count; i > 0; i--) {
- if (++recs[i-1].uid1 > recs[i-1].uid2) {
- array_delete(&ctx->sync_recs, i-1, 1);
- recs = array_get_modifiable(&ctx->sync_recs,
- &count);
- if (count == 0) {
- /* all sync_recs committed */
- return 0;
- }
- }
- }
- }
- return 0;
-}
-
-static int maildir_sync_record(struct maildir_index_sync_context *ctx,
- const struct mail_index_sync_rec *sync_rec)
-{
- struct mail_index_view *view = ctx->view;
- struct mail_index_sync_rec sync_copy;
-
- if (sync_rec == NULL) {
- /* deinit */
- while (array_count(&ctx->sync_recs) > 0) {
- if (maildir_sync_record_commit_until(ctx,
- (uint32_t)-1) < 0)
- return -1;
- }
- return 0;
- }
-
- if (sync_rec->type == MAIL_INDEX_SYNC_TYPE_APPEND)
- return 0; /* ignore */
-
- /* convert to sequences to avoid looping through huge holes in
- UID range */
- sync_copy = *sync_rec;
- if (mail_index_lookup_uid_range(view, sync_rec->uid1,
- sync_rec->uid2,
- &sync_copy.uid1,
- &sync_copy.uid2) < 0) {
- mail_storage_set_index_error(&ctx->mbox->ibox);
- return -1;
- }
-
- if (sync_copy.uid1 == 0) {
- /* UIDs were expunged */
- return 0;
- }
-
- while (array_count(&ctx->sync_recs) > 0) {
- const struct mail_index_sync_rec *rec =
- array_idx(&ctx->sync_recs, 0);
-
- i_assert(rec->uid1 <= sync_copy.uid1);
- if (rec->uid1 == sync_copy.uid1)
- break;
-
- if (maildir_sync_record_commit_until(ctx, sync_copy.uid1-1) < 0)
- return -1;
- }
-
- array_append(&ctx->sync_recs, &sync_copy, 1);
- return 0;
-}
-
-static int maildir_sync_index_records(struct maildir_index_sync_context *ctx)
-{
- struct mail_index_sync_rec sync_rec;
- int ret;
-
- ret = mail_index_sync_next(ctx->sync_ctx, &sync_rec);
- if (ret <= 0) {
- if (ret < 0)
- mail_storage_set_index_error(&ctx->mbox->ibox);
- return ret;
- }
-
- t_array_init(&ctx->sync_recs, 32);
- do {
- if (maildir_sync_record(ctx, &sync_rec) < 0)
- return -1;
-
More information about the dovecot-cvs
mailing list