mail-index-sync.c revision 768b7f5783c8de119d7386321e5d0c72d5c2d9f6
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* Copyright (c) 2003-2007 Dovecot authors, see the included COPYING file */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "mail-index-transaction-private.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_transaction *sync_trans, *ext_trans;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_header *hdr;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ARRAY_DEFINE(sync_list, struct mail_index_sync_list);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t append_uid_first, append_uid_last;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_add_expunge(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_expunge *e = ctx->data;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher size_t i, size = ctx->hdr->size / sizeof(*e);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < size; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (uid = e[i].uid1; uid <= e[i].uid2; uid++)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_add_flag_update(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_flag_update *u = ctx->data;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher size_t i, size = ctx->hdr->size / sizeof(*u);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < size; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (u[i].add_flags != 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_update_flags_range(ctx->sync_trans,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (u[i].remove_flags != 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_update_flags_range(ctx->sync_trans,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_add_keyword_update(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_keyword_update *u = ctx->data;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uidset_offset = sizeof(*u) + u->name_size;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uids = CONST_PTR_OFFSET(u, uidset_offset);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher keyword_names[0] = t_strndup(u + 1, u->name_size);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher keywords = mail_index_keywords_create(ctx->index, keyword_names);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher size = (ctx->hdr->size - uidset_offset) / sizeof(uint32_t);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* FIXME: mail_index_update_keywords_range() */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (uid = uids[i]; uid <= uids[i+1]; uid++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_update_keywords(ctx->sync_trans, uid,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_add_keyword_reset(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_keyword_reset *u = ctx->data;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher size_t i, size = ctx->hdr->size / sizeof(*u);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher keywords = mail_index_keywords_create(ctx->index, NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < size; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (uid = u[i].uid1; uid <= u[i].uid2; uid++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_update_keywords(ctx->sync_trans, uid,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_add_append(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_index_record *rec = ctx->data;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ctx->append_uid_first == 0 || rec->uid < ctx->append_uid_first)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec = CONST_PTR_OFFSET(ctx->data, ctx->hdr->size - sizeof(*rec));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic bool mail_index_sync_add_transaction(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher switch (ctx->hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_add_dirty_updates(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_transaction_flag_update update;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher messages_count = mail_index_view_get_messages_count(ctx->view);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (seq = 1; seq <= messages_count; seq++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) == 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_update_flags(ctx->sync_trans, rec->uid,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghermail_index_sync_update_mailbox_pos(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->last_tail_offset = offset + ctx->hdr->size + sizeof(*ctx->hdr);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghermail_index_sync_read_and_sort(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_transaction *sync_trans = ctx->sync_trans;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_index_transaction_keyword_update *keyword_updates;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher unsigned int i, keyword_count;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((ctx->view->map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) &&
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (ctx->flags & MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY) != 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* show dirty flags as flag updates */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* read all transactions from log into a transaction in memory.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher skip the external ones, they're already synced to mailbox and
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher included in our view */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher while ((ret = mail_transaction_log_view_next(ctx->view->log_view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((ctx->hdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* create an array containing all expunge, flag and keyword update
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher arrays so we can easily go through all of the changes. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher keyword_count = !array_is_created(&sync_trans->keyword_updates) ? 0 :
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_count(&sync_trans->keyword_updates);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_array_init(&ctx->sync_list, keyword_count + 2);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (array_is_created(&sync_trans->expunges)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher synclist = array_append_space(&ctx->sync_list);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher synclist->array = (void *)&sync_trans->expunges;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (array_is_created(&sync_trans->updates)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher synclist = array_append_space(&ctx->sync_list);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher synclist->array = (void *)&sync_trans->updates;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* we must return resets before keyword additions or they get lost */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (array_is_created(&sync_trans->keyword_resets)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher synclist = array_append_space(&ctx->sync_list);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher synclist->array = (void *)&sync_trans->keyword_resets;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher keyword_updates = keyword_count == 0 ? NULL :
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_idx(&sync_trans->keyword_updates, 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < keyword_count; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (array_is_created(&keyword_updates[i].add_seq)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher synclist = array_append_space(&ctx->sync_list);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher synclist->array = (void *)&keyword_updates[i].add_seq;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (array_is_created(&keyword_updates[i].remove_seq)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher synclist = array_append_space(&ctx->sync_list);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghermail_index_need_sync(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t log_file_seq, uoff_t log_file_offset)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (hdr->first_recent_uid < hdr->next_uid &&
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (flags & MAIL_INDEX_SYNC_FLAG_DROP_RECENT) != 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher hdr->log_file_tail_offset < log_file_offset))
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* already synced */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return mail_cache_need_compress(index->cache);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghermail_index_sync_set_log_view(struct mail_index_view *view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t start_file_seq, uoff_t start_file_offset)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_get_head(view->index->log, &log_seq, &log_offset);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = mail_transaction_log_view_set(view->log_view,
056302a92862fda16351d7192600746746f38e5dStephen Gallagher /* either corrupted or the file was deleted for
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher some reason. either way, we can't go forward */
056302a92862fda16351d7192600746746f38e5dStephen Gallagher "Unexpected transaction log desync with index %s",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint mail_index_sync_begin(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = mail_index_sync_begin_to(index, ctx_r, view_r, trans_r,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint mail_index_sync_begin_to(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t log_file_seq, uoff_t log_file_offset,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher enum mail_index_transaction_flags trans_flags;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (mail_transaction_log_sync_lock(index->log, &seq, &offset) < 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* The view must contain what we expect the mailbox to look like
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher currently. That allows the backend to update external flag
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher changes (etc.) if the view doesn't match the mailbox.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher We'll update the view to contain everything that exist in the
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher transaction log except for expunges. They're synced in
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_commit(). */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((ret = mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD)) <= 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_sync_unlock(index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* let's try again */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD) <= 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_sync_unlock(index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (!mail_index_need_sync(index, hdr, flags,
056302a92862fda16351d7192600746746f38e5dStephen Gallagher mail_transaction_log_sync_unlock(index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (hdr->log_file_tail_offset > hdr->log_file_head_offset ||
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (hdr->log_file_seq == seq && hdr->log_file_tail_offset > offset)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* broken sync positions. fix them. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "broken sync positions in index file %s",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx = i_new(struct mail_index_sync_ctx, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->last_tail_offset = hdr->log_file_tail_offset;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sync_view = mail_index_dummy_view_open(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->sync_trans = mail_index_transaction_begin(sync_view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* we wish to see all the changes from last mailbox sync position to
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher the end of the transaction log */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (mail_index_sync_set_log_view(ctx->view, hdr->log_file_seq,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* if a log file is missing, there's nothing we can do except
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher to skip over it. fix the problem with fsck and try again. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return mail_index_sync_begin_to(index, ctx_r, view_r, trans_r,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* we need to have all the transactions sorted to optimize
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher caller's mailbox access patterns */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (mail_index_sync_read_and_sort(ctx) < 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* create the transaction after the view has been updated with
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher external transactions and marked as sync view */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher trans_flags = MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((ctx->flags & MAIL_INDEX_SYNC_FLAG_AVOID_FLAG_UPDATES) != 0)
056302a92862fda16351d7192600746746f38e5dStephen Gallagher trans_flags |= MAIL_INDEX_TRANSACTION_FLAG_AVOID_FLAG_UPDATES;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->ext_trans = mail_index_transaction_begin(ctx->view, trans_flags);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic bool mail_index_sync_view_have_any(struct mail_index_view *view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_header *hdr;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher if (view->map->hdr.first_recent_uid < view->map->hdr.next_uid &&
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (flags & MAIL_INDEX_SYNC_FLAG_DROP_RECENT) != 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((view->map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) &&
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (flags & MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY) != 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_get_head(view->index->log, &log_seq, &log_offset);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher if (mail_transaction_log_view_set(view->log_view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* let the actual syncing handle the error */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher while ((ret = mail_transaction_log_view_next(view->log_view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherbool mail_index_sync_have_any(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = mail_index_sync_view_have_any(view, flags);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghermail_index_sync_get_expunge(struct mail_index_sync_rec *rec,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_expunge *exp)
056302a92862fda16351d7192600746746f38e5dStephen Gallaghermail_index_sync_get_update(struct mail_index_sync_rec *rec,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_flag_update *update)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghermail_index_sync_get_keyword_update(struct mail_index_sync_rec *rec,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->keyword_idx = sync_list->keyword_idx;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_get_keyword_reset(struct mail_index_sync_rec *rec,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherbool mail_index_sync_next(struct mail_index_sync_ctx *ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_transaction *sync_trans = ctx->sync_trans;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher /* FIXME: replace with a priority queue so we don't have to go
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher through the whole list constantly. and remember to make sure that
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher keyword resets are sent before adds! */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sync_list = array_get_modifiable(&ctx->sync_list, &count);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < count; i++) {
056302a92862fda16351d7192600746746f38e5dStephen Gallagher if (!array_is_created(sync_list[i].array) ||
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sync_list[i].idx == array_count(sync_list[i].array))
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uid_range = array_idx(sync_list[i].array, sync_list[i].idx);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher /* use this one. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* nothing left in sync_list */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sync_rec->type = MAIL_INDEX_SYNC_TYPE_APPEND;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uid_range = array_idx(sync_list[i].array, sync_list[i].idx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (sync_list[i].array == (void *)&sync_trans->expunges) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (const struct mail_transaction_expunge *)uid_range);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else if (sync_list[i].array == (void *)&sync_trans->updates) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (const struct mail_transaction_flag_update *)uid_range);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else if (sync_list[i].array == (void *)&sync_trans->keyword_resets) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_get_keyword_reset(sync_rec, uid_range);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher mail_index_sync_get_keyword_update(sync_rec, uid_range,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherbool mail_index_sync_have_more(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_index_sync_list *sync_list;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher unsigned int i, count;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sync_list = array_get(&ctx->sync_list, &count);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < count; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (array_is_created(sync_list[i].array) &&
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sync_list[i].idx != array_count(sync_list[i].array))
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_sync_reset(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher unsigned int i, count;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sync_list = array_get_modifiable(&ctx->sync_list, &count);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < count; i++)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_end(struct mail_index_sync_ctx **_ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_sync_unlock(ctx->index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_transaction_rollback(&ctx->sync_trans);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghermail_index_sync_update_mailbox_offset(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_index_header *hdr = &ctx->index->map->hdr;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_set_mailbox_sync_pos(ctx->index->log, seq, offset);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* If tail offset has changed, make sure it gets written to
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher transaction log. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (hdr->log_file_tail_offset != ctx->last_tail_offset)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint mail_index_sync_commit(struct mail_index_sync_ctx **_ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_update_mailbox_offset(ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (mail_cache_need_compress(index->cache)) {
056302a92862fda16351d7192600746746f38e5dStephen Gallagher /* if cache compression fails, we don't really care.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher the cache offsets are updated only if the compression was
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher successful. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (void)mail_cache_compress(index->cache, ctx->ext_trans);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((ctx->flags & MAIL_INDEX_SYNC_FLAG_DROP_RECENT) != 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher next_uid = mail_index_transaction_get_next_uid(ctx->ext_trans);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->map->hdr.first_recent_uid < next_uid) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (mail_index_transaction_commit(&ctx->ext_trans, &seq, &offset) < 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* refresh the mapping with newly committed external transactions
056302a92862fda16351d7192600746746f38e5dStephen Gallagher and the synced expunges. sync using file handler here so that the
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher expunge handlers get called. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (mail_index_map(ctx->index, MAIL_INDEX_SYNC_HANDLER_FILE) <= 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* FIXME: create a better rule? */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher want_rotate = mail_transaction_log_want_rotate(index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher diff = index->map->hdr.log_file_tail_offset -
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ret == 0 && (diff > 1024 || want_rotate || index->need_recreate)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_sync_rollback(struct mail_index_sync_ctx **ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_transaction_rollback(&(*ctx)->ext_trans);
056302a92862fda16351d7192600746746f38e5dStephen Gallaghervoid mail_index_sync_flags_apply(const struct mail_index_sync_rec *sync_rec,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(sync_rec->type == MAIL_INDEX_SYNC_TYPE_FLAGS);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *flags = (*flags & ~sync_rec->remove_flags) | sync_rec->add_flags;
056302a92862fda16351d7192600746746f38e5dStephen Gallagherbool mail_index_sync_keywords_apply(const struct mail_index_sync_rec *sync_rec,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const unsigned int *keyword_indexes;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher unsigned int i, count;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher keyword_indexes = array_get(keywords, &count);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher for (i = 0; i < count; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < count; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_sync_set_corrupted(struct mail_index_sync_map_ctx *ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const char *fmt, ...)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (seq < ctx->view->index->fsck_log_head_file_seq ||
056302a92862fda16351d7192600746746f38e5dStephen Gallagher (seq == ctx->view->index->fsck_log_head_file_seq &&
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher offset < ctx->view->index->fsck_log_head_file_offset)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* be silent */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Log synchronization error at "