Mercurial > dovecot > original-hg > dovecot-1.2
changeset 5898:54ef7dccdfc7 HEAD
Moved index sync record grouping from mbox to generic code.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 08 Jul 2007 19:57:09 +0300 |
parents | 3ec9ce7cd5e7 |
children | f29b93c0519c |
files | src/lib-storage/index/index-sync-changes.c src/lib-storage/index/index-sync-changes.h src/lib-storage/index/mbox/mbox-sync-private.h src/lib-storage/index/mbox/mbox-sync-update.c src/lib-storage/index/mbox/mbox-sync.c |
diffstat | 5 files changed, 282 insertions(+), 174 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-storage/index/index-sync-changes.c Sun Jul 08 19:57:09 2007 +0300 @@ -0,0 +1,213 @@ +/* Copyright (C) 2007 Timo Sirainen */ + +#include "lib.h" +#include "array.h" +#include "index-storage.h" +#include "index-sync-changes.h" + +struct index_sync_changes_context { + struct index_mailbox *ibox; + struct mail_index_sync_ctx *index_sync_ctx; + struct mail_index_view *sync_view; + struct mail_index_transaction *sync_trans; + + ARRAY_DEFINE(syncs, struct mail_index_sync_rec); + struct mail_index_sync_rec sync_rec; + bool dirty_flag_updates; +}; + +struct index_sync_changes_context * +index_sync_changes_init(struct index_mailbox *ibox, + struct mail_index_sync_ctx *index_sync_ctx, + struct mail_index_view *sync_view, + struct mail_index_transaction *sync_trans, + bool dirty_flag_updates) +{ + struct index_sync_changes_context *ctx; + + ctx = i_new(struct index_sync_changes_context, 1); + ctx->ibox = ibox; + ctx->index_sync_ctx = index_sync_ctx; + ctx->sync_view = sync_view; + ctx->sync_trans = sync_trans; + ctx->dirty_flag_updates = dirty_flag_updates; + i_array_init(&ctx->syncs, 16); + return ctx; +} + +void index_sync_changes_deinit(struct index_sync_changes_context **_ctx) +{ + struct index_sync_changes_context *ctx = *_ctx; + + *_ctx = NULL; + array_free(&ctx->syncs); + i_free(ctx); +} + +void index_sync_changes_reset(struct index_sync_changes_context *ctx) +{ + array_clear(&ctx->syncs); + memset(&ctx->sync_rec, 0, sizeof(ctx->sync_rec)); +} + +void index_sync_changes_delete_to(struct index_sync_changes_context *ctx, + uint32_t last_uid) +{ + struct mail_index_sync_rec *syncs; + unsigned int src, dest, count; + + syncs = array_get_modifiable(&ctx->syncs, &count); + + for (src = dest = 0; src < count; src++) { + i_assert(last_uid >= syncs[src].uid1); + if (last_uid <= syncs[src].uid2) { + /* keep it */ + if (src != dest) + syncs[dest] = syncs[src]; + dest++; + } + } + + array_delete(&ctx->syncs, dest, count - dest); +} + +static bool +index_sync_changes_have_expunges(struct index_sync_changes_context *ctx, + unsigned int count) +{ + const struct mail_index_sync_rec *syncs; + unsigned int i; + + syncs = array_idx(&ctx->syncs, 0); + for (i = 0; i < count; i++) { + if (syncs[i].type == MAIL_INDEX_SYNC_TYPE_EXPUNGE) + return TRUE; + } + return FALSE; +} + +int index_sync_changes_read(struct index_sync_changes_context *ctx, + uint32_t uid, bool *sync_expunge_r) +{ + struct mail_index_sync_rec *sync_rec = &ctx->sync_rec; + uint32_t seq1, seq2; + unsigned int orig_count; + int ret; + + *sync_expunge_r = FALSE; + + index_sync_changes_delete_to(ctx, uid); + orig_count = array_count(&ctx->syncs); + + while (uid >= sync_rec->uid1) { + if (uid <= sync_rec->uid2 && + sync_rec->type != MAIL_INDEX_SYNC_TYPE_APPEND) { + array_append(&ctx->syncs, sync_rec, 1); + + if (sync_rec->type == MAIL_INDEX_SYNC_TYPE_EXPUNGE) + *sync_expunge_r = TRUE; + } + + ret = mail_index_sync_next(ctx->index_sync_ctx, sync_rec); + if (ret < 0) { + mail_storage_set_index_error(ctx->ibox); + return -1; + } + + if (ret == 0) { + memset(sync_rec, 0, sizeof(*sync_rec)); + break; + } + + switch (sync_rec->type) { + case MAIL_INDEX_SYNC_TYPE_APPEND: + /* ignore */ + memset(sync_rec, 0, sizeof(*sync_rec)); + break; + case MAIL_INDEX_SYNC_TYPE_EXPUNGE: + 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: + if (!ctx->dirty_flag_updates) + break; + + /* mark the changes as dirty */ + if (mail_index_lookup_uid_range(ctx->sync_view, + sync_rec->uid1, + sync_rec->uid2, + &seq1, &seq2) < 0) { + mail_storage_set_index_error(ctx->ibox); + return -1; + } + memset(sync_rec, 0, sizeof(*sync_rec)); + + if (seq1 == 0) + break; + + mail_index_update_flags_range(ctx->sync_trans, + seq1, seq2, MODIFY_ADD, + (enum mail_flags)MAIL_INDEX_MAIL_FLAG_DIRTY); + break; + } + } + + if (!*sync_expunge_r && orig_count > 0) { + *sync_expunge_r = + index_sync_changes_have_expunges(ctx, orig_count); + } + + return 0; +} + +bool index_sync_changes_have(struct index_sync_changes_context *ctx) +{ + return array_count(&ctx->syncs) > 0; +} + +uint32_t +index_sync_changes_get_next_uid(struct index_sync_changes_context *ctx) +{ + return ctx->sync_rec.uid1; +} + +void index_sync_changes_apply(struct index_sync_changes_context *ctx, + pool_t pool, uint8_t *flags, + ARRAY_TYPE(keyword_indexes) *keywords, + enum mailbox_sync_type *sync_type_r) +{ + const struct mail_index_sync_rec *syncs; + unsigned int i, count; + enum mailbox_sync_type sync_type = 0; + + syncs = array_get(&ctx->syncs, &count); + for (i = 0; i < count; i++) { + switch (syncs[i].type) { + case MAIL_INDEX_SYNC_TYPE_FLAGS: + mail_index_sync_flags_apply(&syncs[i], flags); + 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: + if (!array_is_created(keywords)) { + /* no existing keywords */ + if (syncs[i].type != + MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD) + break; + + /* adding, create the array */ + p_array_init(keywords, pool, + I_MIN(10, count - i)); + } + if (mail_index_sync_keywords_apply(&syncs[i], keywords)) + sync_type |= MAILBOX_SYNC_TYPE_KEYWORDS; + break; + default: + break; + } + } + + *sync_type_r = sync_type; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-storage/index/index-sync-changes.h Sun Jul 08 19:57:09 2007 +0300 @@ -0,0 +1,27 @@ +#ifndef __INDEX_SYNC_CHANGES_H +#define __INDEX_SYNC_CHANGES_H + +struct index_sync_changes_context * +index_sync_changes_init(struct index_mailbox *ibox, + struct mail_index_sync_ctx *index_sync_ctx, + struct mail_index_view *sync_view, + struct mail_index_transaction *sync_trans, + bool dirty_flag_updates); +void index_sync_changes_deinit(struct index_sync_changes_context **_ctx); + +void index_sync_changes_reset(struct index_sync_changes_context *ctx); +void index_sync_changes_delete_to(struct index_sync_changes_context *ctx, + uint32_t last_uid); + +int index_sync_changes_read(struct index_sync_changes_context *ctx, + uint32_t uid, bool *sync_expunge_r); +bool index_sync_changes_have(struct index_sync_changes_context *ctx); +uint32_t +index_sync_changes_get_next_uid(struct index_sync_changes_context *ctx); + +void index_sync_changes_apply(struct index_sync_changes_context *ctx, + pool_t pool, uint8_t *flags, + ARRAY_TYPE(keyword_indexes) *keywords, + enum mailbox_sync_type *sync_type_r); + +#endif
--- a/src/lib-storage/index/mbox/mbox-sync-private.h Sun Jul 08 19:46:31 2007 +0300 +++ b/src/lib-storage/index/mbox/mbox-sync-private.h Sun Jul 08 19:57:09 2007 +0300 @@ -4,8 +4,6 @@ #include "md5.h" #include "mail-index.h" -ARRAY_DEFINE_TYPE(sync_recs, struct mail_index_sync_rec); - #include <sys/stat.h> enum mbox_sync_flags { @@ -124,8 +122,7 @@ /* mail state: */ ARRAY_DEFINE(mails, struct mbox_sync_mail); - ARRAY_TYPE(sync_recs) syncs; - struct mail_index_sync_rec sync_rec; + struct index_sync_changes_context *sync_changes; /* per-mail pool */ pool_t mail_keyword_pool; @@ -166,9 +163,6 @@ uoff_t end_offset, off_t move_diff, uoff_t extra_space, uint32_t first_seq, uint32_t last_seq); -void mbox_sync_apply_index_syncs(struct mbox_sync_context *sync_ctx, - struct mbox_sync_mail *mail, - enum mailbox_sync_type *sync_type_r); int mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset); void mbox_sync_file_update_ext_modified(struct mbox_sync_context *sync_ctx); void mbox_sync_file_updated(struct mbox_sync_context *sync_ctx, bool dirty);
--- a/src/lib-storage/index/mbox/mbox-sync-update.c Sun Jul 08 19:46:31 2007 +0300 +++ b/src/lib-storage/index/mbox/mbox-sync-update.c Sun Jul 08 19:57:09 2007 +0300 @@ -6,6 +6,7 @@ #include "str.h" #include "message-parser.h" #include "index-storage.h" +#include "index-sync-changes.h" #include "mbox-storage.h" #include "mbox-sync-private.h" @@ -388,16 +389,16 @@ old_flags = ctx->mail.flags; - if (array_count(&ctx->sync_ctx->syncs) > 0) { - mbox_sync_apply_index_syncs(ctx->sync_ctx, &ctx->mail, - &sync_type); + index_sync_changes_apply(ctx->sync_ctx->sync_changes, + ctx->sync_ctx->mail_keyword_pool, + &ctx->mail.flags, &ctx->mail.keywords, + &sync_type); - if ((old_flags & XSTATUS_FLAGS_MASK) != - (ctx->mail.flags & XSTATUS_FLAGS_MASK)) - mbox_sync_update_xstatus(ctx); - if ((sync_type & MAILBOX_SYNC_TYPE_KEYWORDS) != 0) - mbox_sync_update_xkeywords(ctx); - } + if ((old_flags & XSTATUS_FLAGS_MASK) != + (ctx->mail.flags & XSTATUS_FLAGS_MASK)) + mbox_sync_update_xstatus(ctx); + if ((sync_type & MAILBOX_SYNC_TYPE_KEYWORDS) != 0) + mbox_sync_update_xkeywords(ctx); if (!ctx->sync_ctx->mbox->ibox.keep_recent) ctx->mail.flags &= ~MAIL_RECENT;
--- a/src/lib-storage/index/mbox/mbox-sync.c Sun Jul 08 19:46:31 2007 +0300 +++ b/src/lib-storage/index/mbox/mbox-sync.c Sun Jul 08 19:57:09 2007 +0300 @@ -44,6 +44,7 @@ #include "message-date.h" #include "istream-raw-mbox.h" #include "mbox-storage.h" +#include "index-sync-changes.h" #include "mbox-from.h" #include "mbox-file.h" #include "mbox-lock.h" @@ -122,27 +123,6 @@ i_stream_sync(sync_ctx->input); } -static void mbox_sync_array_delete_to(ARRAY_TYPE(sync_recs) *syncs_arr, - uint32_t last_uid) -{ - struct mail_index_sync_rec *syncs; - unsigned int src, dest, count; - - syncs = array_get_modifiable(syncs_arr, &count); - - for (src = dest = 0; src < count; src++) { - i_assert(last_uid >= syncs[src].uid1); - if (last_uid <= syncs[src].uid2) { - /* keep it */ - if (src != dest) - syncs[dest] = syncs[src]; - dest++; - } - } - - array_delete(syncs_arr, dest, count - dest); -} - static int mbox_sync_read_next_mail(struct mbox_sync_context *sync_ctx, struct mbox_sync_mail_context *mail_ctx) @@ -183,140 +163,25 @@ return 1; } -static bool mbox_sync_buf_have_expunges(ARRAY_TYPE(sync_recs) *syncs_arr) -{ - const struct mail_index_sync_rec *syncs; - unsigned int i, count; - - syncs = array_get(syncs_arr, &count); - for (i = 0; i < count; i++) { - if (syncs[i].type == MAIL_INDEX_SYNC_TYPE_EXPUNGE) - return TRUE; - } - return FALSE; -} - static int mbox_sync_read_index_syncs(struct mbox_sync_context *sync_ctx, uint32_t uid, bool *sync_expunge_r) { - struct mail_index_sync_rec *sync_rec = &sync_ctx->sync_rec; - int ret; - - *sync_expunge_r = FALSE; - - if (sync_ctx->index_sync_ctx == NULL) - return 0; - if (uid == 0 || sync_ctx->index_reset) { /* nothing for this or the future ones */ uid = (uint32_t)-1; } - mbox_sync_array_delete_to(&sync_ctx->syncs, uid); - while (uid >= sync_rec->uid1) { - if (uid <= sync_rec->uid2 && - sync_rec->type != MAIL_INDEX_SYNC_TYPE_APPEND && - (sync_rec->type != MAIL_INDEX_SYNC_TYPE_EXPUNGE || - !sync_ctx->mbox->mbox_readonly)) { - array_append(&sync_ctx->syncs, sync_rec, 1); - - if (sync_rec->type == MAIL_INDEX_SYNC_TYPE_EXPUNGE) - *sync_expunge_r = TRUE; - } - - ret = mail_index_sync_next(sync_ctx->index_sync_ctx, sync_rec); - if (ret < 0) { - mail_storage_set_index_error(&sync_ctx->mbox->ibox); - return -1; - } - - if (ret == 0) { - memset(sync_rec, 0, sizeof(*sync_rec)); - break; - } - - switch (sync_rec->type) { - case MAIL_INDEX_SYNC_TYPE_APPEND: - if (sync_rec->uid2 >= sync_ctx->next_uid) - sync_ctx->next_uid = sync_rec->uid2 + 1; - memset(sync_rec, 0, sizeof(*sync_rec)); - break; - case MAIL_INDEX_SYNC_TYPE_EXPUNGE: - 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: - if (sync_ctx->delay_writes) { - /* we're not going to write these yet */ - uint32_t seq1, seq2; - - if (mail_index_lookup_uid_range( - sync_ctx->sync_view, - sync_rec->uid1, sync_rec->uid2, - &seq1, &seq2) < 0) - return -1; - memset(sync_rec, 0, sizeof(*sync_rec)); - - if (seq1 == 0) - break; + if (index_sync_changes_read(sync_ctx->sync_changes, uid, + sync_expunge_r) < 0) + return -1; - mail_index_update_flags_range(sync_ctx->t, - seq1, seq2, MODIFY_ADD, - (enum mail_flags) - MAIL_INDEX_MAIL_FLAG_DIRTY); - } - break; - } + if (sync_ctx->mbox->mbox_readonly) { + /* we can't expunge anything from read-only mboxes */ + *sync_expunge_r = FALSE; } - - if (!*sync_expunge_r) - *sync_expunge_r = mbox_sync_buf_have_expunges(&sync_ctx->syncs); - return 0; } -void mbox_sync_apply_index_syncs(struct mbox_sync_context *sync_ctx, - struct mbox_sync_mail *mail, - enum mailbox_sync_type *sync_type_r) -{ - const struct mail_index_sync_rec *syncs; - unsigned int i, count; - enum mailbox_sync_type sync_type = 0; - - syncs = array_get(&sync_ctx->syncs, &count); - for (i = 0; i < count; i++) { - switch (syncs[i].type) { - case MAIL_INDEX_SYNC_TYPE_FLAGS: - mail_index_sync_flags_apply(&syncs[i], &mail->flags); - 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: - if (!array_is_created(&mail->keywords)) { - /* no existing keywords */ - if (syncs[i].type != - MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD) - break; - - /* adding, create the array */ - p_array_init(&mail->keywords, - sync_ctx->mail_keyword_pool, - I_MIN(10, count - i)); - } - if (mail_index_sync_keywords_apply(&syncs[i], - &mail->keywords)) - sync_type |= MAILBOX_SYNC_TYPE_KEYWORDS; - break; - default: - break; - } - } - - *sync_type_r = sync_type; -} - static int mbox_sync_read_index_rec(struct mbox_sync_context *sync_ctx, uint32_t uid, const struct mail_index_record **rec_r) @@ -531,8 +396,11 @@ t_pop(); return -1; } - mbox_sync_apply_index_syncs(sync_ctx, &idx_mail, - &sync_type); + + index_sync_changes_apply(sync_ctx->sync_changes, + sync_ctx->mail_keyword_pool, + &idx_mail.flags, &idx_mail.keywords, + &sync_type); if (sync_type != 0 && box->v.sync_notify != NULL) box->v.sync_notify(box, rec->uid, sync_type); @@ -809,7 +677,7 @@ } } } else if (mail_ctx->need_rewrite || - array_count(&sync_ctx->syncs) != 0) { + index_sync_changes_have(sync_ctx->sync_changes)) { mbox_sync_update_header(mail_ctx); if (sync_ctx->delay_writes) { /* mark it dirty and do it later */ @@ -1047,22 +915,23 @@ uint32_t next_uid, bool *partial, bool *skipped_mails) { - uint32_t messages_count; + uint32_t messages_count, uid; int ret; i_assert(!sync_ctx->index_reset); /* delete sync records up to next message. so if there's still something left in array, it means the next message needs modifying */ - mbox_sync_array_delete_to(&sync_ctx->syncs, next_uid); - if (array_count(&sync_ctx->syncs) > 0) + index_sync_changes_delete_to(sync_ctx->sync_changes, next_uid); + if (index_sync_changes_have(sync_ctx->sync_changes)) return 1; - if (sync_ctx->sync_rec.uid1 != 0) { + uid = index_sync_changes_get_next_uid(sync_ctx->sync_changes); + if (uid != 0) { /* we can skip forward to next record which needs updating. */ - if (sync_ctx->sync_rec.uid1 != next_uid) { + if (uid != next_uid) { *skipped_mails = TRUE; - next_uid = sync_ctx->sync_rec.uid1; + next_uid = uid; } ret = mbox_sync_seek_to_uid(sync_ctx, next_uid); } else { @@ -1559,10 +1428,9 @@ sync_ctx->base_uid_last_offset = 0; array_clear(&sync_ctx->mails); - array_clear(&sync_ctx->syncs); p_clear(sync_ctx->saved_keywords_pool); - memset(&sync_ctx->sync_rec, 0, sizeof(sync_ctx->sync_rec)); + index_sync_changes_reset(sync_ctx->sync_changes); mail_index_sync_reset(sync_ctx->index_sync_ctx); mail_index_transaction_reset(sync_ctx->t); @@ -1649,8 +1517,7 @@ /* only syncs left should be just appends (and their updates) which weren't synced yet for some reason (crash). we'll just ignore them, as we've overwritten them above. */ - array_clear(&sync_ctx->syncs); - memset(&sync_ctx->sync_rec, 0, sizeof(sync_ctx->sync_rec)); + index_sync_changes_reset(sync_ctx->sync_changes); if (mbox_sync_update_index_header(sync_ctx) < 0) return -1; @@ -1699,6 +1566,7 @@ static void mbox_sync_context_free(struct mbox_sync_context *sync_ctx) { + index_sync_changes_deinit(&sync_ctx->sync_changes); if (sync_ctx->index_sync_ctx != NULL) mail_index_sync_rollback(&sync_ctx->index_sync_ctx); pool_unref(sync_ctx->mail_keyword_pool); @@ -1706,7 +1574,6 @@ str_free(&sync_ctx->header); str_free(&sync_ctx->from_line); array_free(&sync_ctx->mails); - array_free(&sync_ctx->syncs); } static int mbox_sync_int(struct mbox_mailbox *mbox, enum mbox_sync_flags flags) @@ -1831,19 +1698,25 @@ (void)mail_index_get_keywords(mbox->ibox.index); i_array_init(&sync_ctx.mails, 64); - i_array_init(&sync_ctx.syncs, 32); sync_ctx.flags = flags; sync_ctx.delay_writes = delay_writes || sync_ctx.mbox->mbox_readonly; + sync_ctx.sync_changes = + index_sync_changes_init(&mbox->ibox, index_sync_ctx, + sync_view, trans, + sync_ctx.delay_writes); + if (!changed && delay_writes) { /* if we have only flag changes, we don't need to open the mbox file */ bool expunged; + uint32_t uid; if (mbox_sync_read_index_syncs(&sync_ctx, 1, &expunged) < 0) return -1; - if (sync_ctx.sync_rec.uid1 == 0) { + uid = index_sync_changes_get_next_uid(sync_ctx.sync_changes); + if (uid == 0) { sync_ctx.index_sync_ctx = NULL; mbox_sync_context_free(&sync_ctx); goto __nothing_to_do;