mail-index-sync.c revision 768b7f5783c8de119d7386321e5d0c72d5c2d9f6
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* Copyright (c) 2003-2007 Dovecot authors, see the included COPYING file */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "lib.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "array.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "mail-index-view-private.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "mail-index-sync-private.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "mail-index-transaction-private.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "mail-transaction-log-private.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "mail-cache.h"
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include <stdio.h>
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include <stdlib.h>
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstruct mail_index_sync_ctx {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index *index;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_view *view;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_transaction *sync_trans, *ext_trans;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher enum mail_index_sync_flags flags;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_header *hdr;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const void *data;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ARRAY_DEFINE(sync_list, struct mail_index_sync_list);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t next_uid;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t last_tail_seq, last_tail_offset;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t append_uid_first, append_uid_last;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher unsigned int sync_appends:1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher};
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_add_expunge(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_expunge *e = ctx->data;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher size_t i, size = ctx->hdr->size / sizeof(*e);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t uid;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < size; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (uid = e[i].uid1; uid <= e[i].uid2; uid++)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_expunge(ctx->sync_trans, uid);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_add_flag_update(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_flag_update *u = ctx->data;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher size_t i, size = ctx->hdr->size / sizeof(*u);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 u[i].uid1, u[i].uid2,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher MODIFY_ADD,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher u[i].add_flags);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (u[i].remove_flags != 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_update_flags_range(ctx->sync_trans,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher u[i].uid1, u[i].uid2,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher MODIFY_REMOVE,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher u[i].remove_flags);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_add_keyword_update(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_keyword_update *u = ctx->data;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const char *keyword_names[2];
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_keywords *keywords;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const uint32_t *uids;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t uid;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher size_t uidset_offset, i, size;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uidset_offset = sizeof(*u) + u->name_size;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((uidset_offset % 4) != 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uidset_offset += 4 - (uidset_offset % 4);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uids = CONST_PTR_OFFSET(u, uidset_offset);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher t_push();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher keyword_names[0] = t_strndup(u + 1, u->name_size);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher keyword_names[1] = NULL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher keywords = mail_index_keywords_create(ctx->index, keyword_names);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher size = (ctx->hdr->size - uidset_offset) / sizeof(uint32_t);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < size; i += 2) {
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 Gallagher u->modify_type, keywords);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_keywords_free(&keywords);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher t_pop();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_add_keyword_reset(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_keyword_reset *u = ctx->data;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher size_t i, size = ctx->hdr->size / sizeof(*u);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_keywords *keywords;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t uid;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 Gallagher MODIFY_REPLACE, keywords);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_keywords_free(&keywords);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_add_append(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_index_record *rec = ctx->data;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ctx->append_uid_first == 0 || rec->uid < ctx->append_uid_first)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->append_uid_first = rec->uid;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec = CONST_PTR_OFFSET(ctx->data, ctx->hdr->size - sizeof(*rec));
056302a92862fda16351d7192600746746f38e5dStephen Gallagher if (rec->uid > ctx->append_uid_last)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->append_uid_last = rec->uid;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher ctx->sync_appends = TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic bool mail_index_sync_add_transaction(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher switch (ctx->hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case MAIL_TRANSACTION_EXPUNGE:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_add_expunge(ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case MAIL_TRANSACTION_FLAG_UPDATE:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_add_flag_update(ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case MAIL_TRANSACTION_KEYWORD_UPDATE:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_add_keyword_update(ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case MAIL_TRANSACTION_KEYWORD_RESET:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_add_keyword_reset(ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case MAIL_TRANSACTION_APPEND:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_add_append(ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher default:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_add_dirty_updates(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_transaction_flag_update update;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_index_record *rec;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t seq, messages_count;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher memset(&update, 0, sizeof(update));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher messages_count = mail_index_view_get_messages_count(ctx->view);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (seq = 1; seq <= messages_count; seq++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec = mail_index_lookup(ctx->view, seq);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) == 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher continue;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_update_flags(ctx->sync_trans, rec->uid,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher MODIFY_REPLACE, rec->flags);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghermail_index_sync_update_mailbox_pos(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t seq;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uoff_t offset;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher &seq, &offset);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->last_tail_seq = seq;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->last_tail_offset = offset + ctx->hdr->size + sizeof(*ctx->hdr);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghermail_index_sync_read_and_sort(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_transaction *sync_trans = ctx->sync_trans;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_sync_list *synclist;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_index_transaction_keyword_update *keyword_updates;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher unsigned int i, keyword_count;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 mail_index_sync_add_dirty_updates(ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 &ctx->hdr,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher &ctx->data)) > 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((ctx->hdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher continue;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (mail_index_sync_add_transaction(ctx))
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_update_mailbox_pos(ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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
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 }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 synclist->keyword_idx = i;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (array_is_created(&keyword_updates[i].remove_seq)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher synclist = array_append_space(&ctx->sync_list);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher synclist->array =
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (void *)&keyword_updates[i].remove_seq;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher synclist->keyword_idx = i;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher synclist->keyword_remove = TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
056302a92862fda16351d7192600746746f38e5dStephen Gallagherstatic bool
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghermail_index_need_sync(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_index_header *hdr,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher enum mail_index_sync_flags flags,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t log_file_seq, uoff_t log_file_offset)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (hdr->first_recent_uid < hdr->next_uid &&
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (flags & MAIL_INDEX_SYNC_FLAG_DROP_RECENT) != 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (hdr->log_file_seq < log_file_seq ||
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (hdr->log_file_seq == log_file_seq &&
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher hdr->log_file_tail_offset < log_file_offset))
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* already synced */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return mail_cache_need_compress(index->cache);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int
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{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t log_seq;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uoff_t log_offset;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher bool reset;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_get_head(view->index->log, &log_seq, &log_offset);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = mail_transaction_log_view_set(view->log_view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher start_file_seq, start_file_offset,
056302a92862fda16351d7192600746746f38e5dStephen Gallagher log_seq, log_offset, &reset);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher if (ret <= 0) {
056302a92862fda16351d7192600746746f38e5dStephen Gallagher /* either corrupted or the file was deleted for
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher some reason. either way, we can't go forward */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_set_error(view->index,
056302a92862fda16351d7192600746746f38e5dStephen Gallagher "Unexpected transaction log desync with index %s",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher view->index->filepath);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint mail_index_sync_begin(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_sync_ctx **ctx_r,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_view **view_r,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_transaction **trans_r,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher enum mail_index_sync_flags flags)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int ret;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = mail_index_sync_begin_to(index, ctx_r, view_r, trans_r,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (uint32_t)-1, (uoff_t)-1, flags);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(ret != 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return ret <= 0 ? -1 : 0;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint mail_index_sync_begin_to(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_sync_ctx **ctx_r,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_view **view_r,
056302a92862fda16351d7192600746746f38e5dStephen Gallagher struct mail_index_transaction **trans_r,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t log_file_seq, uoff_t log_file_offset,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher enum mail_index_sync_flags flags)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_index_header *hdr;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_sync_ctx *ctx;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_view *sync_view;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher enum mail_index_transaction_flags trans_flags;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t seq;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uoff_t offset;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (mail_transaction_log_sync_lock(index->log, &seq, &offset) < 0)
056302a92862fda16351d7192600746746f38e5dStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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.
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
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 if (ret == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_sync_unlock(index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
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 return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher hdr = &index->map->hdr;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (!mail_index_need_sync(index, hdr, flags,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher log_file_seq, log_file_offset)) {
056302a92862fda16351d7192600746746f38e5dStephen Gallagher mail_transaction_log_sync_unlock(index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (hdr->log_file_tail_offset > hdr->log_file_head_offset ||
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher hdr->log_file_seq > seq ||
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (hdr->log_file_seq == seq && hdr->log_file_tail_offset > offset)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* broken sync positions. fix them. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_set_error(index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "broken sync positions in index file %s",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->filepath);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_fsck_locked(index);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx = i_new(struct mail_index_sync_ctx, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->index = index;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->last_tail_seq = hdr->log_file_seq;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->last_tail_offset = hdr->log_file_tail_offset;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->flags = flags;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->view = mail_index_view_open(index);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sync_view = mail_index_dummy_view_open(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->sync_trans = mail_index_transaction_begin(sync_view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_view_close(&sync_view);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
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 hdr->log_file_tail_offset) < 0) {
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 mail_index_fsck_locked(index);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher mail_index_sync_rollback(&ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return mail_index_sync_begin_to(index, ctx_r, view_r, trans_r,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher log_file_seq, log_file_offset,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher flags);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
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 mail_index_sync_rollback(&ctx);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->view->index_sync_view = TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *ctx_r = ctx;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *view_r = ctx->view;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *trans_r = ctx->ext_trans;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic bool mail_index_sync_view_have_any(struct mail_index_view *view,
056302a92862fda16351d7192600746746f38e5dStephen Gallagher enum mail_index_sync_flags flags)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_header *hdr;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const void *data;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t log_seq;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uoff_t log_offset;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher bool reset;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 view->map->hdr.log_file_seq,
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher view->map->hdr.log_file_tail_offset,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher log_seq, log_offset, &reset) <= 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* let the actual syncing handle the error */
056302a92862fda16351d7192600746746f38e5dStephen Gallagher return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher while ((ret = mail_transaction_log_view_next(view->log_view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher &hdr, &data)) > 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher continue;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case MAIL_TRANSACTION_EXPUNGE:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case MAIL_TRANSACTION_FLAG_UPDATE:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case MAIL_TRANSACTION_KEYWORD_UPDATE:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case MAIL_TRANSACTION_KEYWORD_RESET:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return TRUE;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher default:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return ret < 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherbool mail_index_sync_have_any(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher enum mail_index_sync_flags flags)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_view *view;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher bool ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher view = mail_index_view_open(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = mail_index_sync_view_have_any(view, flags);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_view_close(&view);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghermail_index_sync_get_expunge(struct mail_index_sync_rec *rec,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_expunge *exp)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->type = MAIL_INDEX_SYNC_TYPE_EXPUNGE;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher rec->uid1 = exp->uid1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->uid2 = exp->uid2;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void
056302a92862fda16351d7192600746746f38e5dStephen Gallaghermail_index_sync_get_update(struct mail_index_sync_rec *rec,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_flag_update *update)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->type = MAIL_INDEX_SYNC_TYPE_FLAGS;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->uid1 = update->uid1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->uid2 = update->uid2;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->add_flags = update->add_flags;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->remove_flags = update->remove_flags;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghermail_index_sync_get_keyword_update(struct mail_index_sync_rec *rec,
056302a92862fda16351d7192600746746f38e5dStephen Gallagher const struct uid_range *range,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_sync_list *sync_list)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->type = !sync_list->keyword_remove ?
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD :
056302a92862fda16351d7192600746746f38e5dStephen Gallagher MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->uid1 = range->uid1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->uid2 = range->uid2;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->keyword_idx = sync_list->keyword_idx;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_get_keyword_reset(struct mail_index_sync_rec *rec,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct uid_range *range)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher rec->uid1 = range->uid1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rec->uid2 = range->uid2;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherbool mail_index_sync_next(struct mail_index_sync_ctx *ctx,
056302a92862fda16351d7192600746746f38e5dStephen Gallagher struct mail_index_sync_rec *sync_rec)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_transaction *sync_trans = ctx->sync_trans;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_sync_list *sync_list;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct uid_range *uid_range = NULL;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher unsigned int i, count, next_i;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher uint32_t next_found_uid;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher next_i = (unsigned int)-1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher next_found_uid = (uint32_t)-1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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))
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher continue;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uid_range = array_idx(sync_list[i].array, sync_list[i].idx);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher if (uid_range->uid1 == ctx->next_uid) {
056302a92862fda16351d7192600746746f38e5dStephen Gallagher /* use this one. */
056302a92862fda16351d7192600746746f38e5dStephen Gallagher break;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (uid_range->uid1 < next_found_uid) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher next_i = i;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher next_found_uid = uid_range->uid1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
056302a92862fda16351d7192600746746f38e5dStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (i == count) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (next_i == (unsigned int)-1) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* nothing left in sync_list */
056302a92862fda16351d7192600746746f38e5dStephen Gallagher if (ctx->sync_appends) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->sync_appends = FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sync_rec->type = MAIL_INDEX_SYNC_TYPE_APPEND;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sync_rec->uid1 = ctx->append_uid_first;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sync_rec->uid2 = ctx->append_uid_last;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->next_uid = next_found_uid;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i = next_i;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uid_range = array_idx(sync_list[i].array, sync_list[i].idx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (sync_list[i].array == (void *)&sync_trans->expunges) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_get_expunge(sync_rec,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (const struct mail_transaction_expunge *)uid_range);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else if (sync_list[i].array == (void *)&sync_trans->updates) {
056302a92862fda16351d7192600746746f38e5dStephen Gallagher mail_index_sync_get_update(sync_rec,
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);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else {
056302a92862fda16351d7192600746746f38e5dStephen Gallagher mail_index_sync_get_keyword_update(sync_rec, uid_range,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher &sync_list[i]);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sync_list[i].idx++;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherbool mail_index_sync_have_more(struct mail_index_sync_ctx *ctx)
056302a92862fda16351d7192600746746f38e5dStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_index_sync_list *sync_list;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher unsigned int i, count;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ctx->sync_appends)
056302a92862fda16351d7192600746746f38e5dStephen Gallagher return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 Gallagher return TRUE;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_sync_reset(struct mail_index_sync_ctx *ctx)
056302a92862fda16351d7192600746746f38e5dStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_sync_list *sync_list;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher unsigned int i, count;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->next_uid = 0;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sync_list = array_get_modifiable(&ctx->sync_list, &count);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < count; i++)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sync_list[i].idx = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mail_index_sync_end(struct mail_index_sync_ctx **_ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_sync_ctx *ctx = *_ctx;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *_ctx = NULL;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_sync_unlock(ctx->index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_view_close(&ctx->view);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_transaction_rollback(&ctx->sync_trans);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (array_is_created(&ctx->sync_list))
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_free(&ctx->sync_list);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_free(ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghermail_index_sync_update_mailbox_offset(struct mail_index_sync_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_index_header *hdr = &ctx->index->map->hdr;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t seq;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher uoff_t offset;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher &seq, &offset);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_set_mailbox_sync_pos(ctx->index->log, seq, offset);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 Gallagher ctx->ext_trans->log_updates = TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint mail_index_sync_commit(struct mail_index_sync_ctx **_ctx)
056302a92862fda16351d7192600746746f38e5dStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_sync_ctx *ctx = *_ctx;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher struct mail_index *index = ctx->index;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t seq, diff, next_uid;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uoff_t offset;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher bool want_rotate;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int ret = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 mail_index_update_header(ctx->ext_trans,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher offsetof(struct mail_index_header,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher first_recent_uid),
056302a92862fda16351d7192600746746f38e5dStephen Gallagher &next_uid, sizeof(next_uid), FALSE);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (mail_index_transaction_commit(&ctx->ext_trans, &seq, &offset) < 0) {
056302a92862fda16351d7192600746746f38e5dStephen Gallagher mail_index_sync_end(&ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 ret = -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 index->last_read_log_file_tail_offset;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ret == 0 && (diff > 1024 || want_rotate || index->need_recreate)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->need_recreate = FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_write(index, want_rotate);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_end(_ctx);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher return ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_sync_rollback(struct mail_index_sync_ctx **ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
056302a92862fda16351d7192600746746f38e5dStephen Gallagher if ((*ctx)->ext_trans != NULL)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_transaction_rollback(&(*ctx)->ext_trans);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_end(ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
056302a92862fda16351d7192600746746f38e5dStephen Gallaghervoid mail_index_sync_flags_apply(const struct mail_index_sync_rec *sync_rec,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint8_t *flags)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(sync_rec->type == MAIL_INDEX_SYNC_TYPE_FLAGS);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *flags = (*flags & ~sync_rec->remove_flags) | sync_rec->add_flags;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
056302a92862fda16351d7192600746746f38e5dStephen Gallagherbool mail_index_sync_keywords_apply(const struct mail_index_sync_rec *sync_rec,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ARRAY_TYPE(keyword_indexes) *keywords)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const unsigned int *keyword_indexes;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher unsigned int idx = sync_rec->keyword_idx;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher unsigned int i, count;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher keyword_indexes = array_get(keywords, &count);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher switch (sync_rec->type) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
056302a92862fda16351d7192600746746f38e5dStephen Gallagher for (i = 0; i < count; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (keyword_indexes[i] == idx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
056302a92862fda16351d7192600746746f38e5dStephen Gallagher array_append(keywords, &idx, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < count; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (keyword_indexes[i] == idx) {
056302a92862fda16351d7192600746746f38e5dStephen Gallagher array_delete(keywords, i, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return FALSE;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (array_count(keywords) == 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_clear(keywords);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher default:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_unreached();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
056302a92862fda16351d7192600746746f38e5dStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_sync_set_corrupted(struct mail_index_sync_map_ctx *ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const char *fmt, ...)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
056302a92862fda16351d7192600746746f38e5dStephen Gallagher va_list va;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t seq;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uoff_t offset;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->errors = TRUE;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher &seq, &offset);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 return;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher va_start(va, fmt);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher t_push();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_set_error(ctx->view->index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Log synchronization error at "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "seq=%u,offset=%"PRIuUOFF_T" for %s: %s",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher seq, offset, ctx->view->index->filepath,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher t_strdup_vprintf(fmt, va));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher t_pop();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher va_end(va);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
056302a92862fda16351d7192600746746f38e5dStephen Gallagher