mail-index-sync.c revision 5238fe9419d071cfbee6f3ff8f2411541e95537d
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (C) 2003-2004 Timo Sirainen */
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen#include "lib.h"
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen#include "array.h"
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen#include "buffer.h"
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen#include "mail-index-view-private.h"
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen#include "mail-index-sync-private.h"
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen#include "mail-index-transaction-private.h"
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen#include "mail-transaction-log-private.h"
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen#include "mail-transaction-util.h"
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen#include "mail-cache.h"
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen#include <stdlib.h>
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainenstruct uid_range {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen uint32_t uid1, uid2;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen};
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainenstatic void mail_index_sync_add_expunge(struct mail_index_sync_ctx *ctx)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen{
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen const struct mail_transaction_expunge *e = ctx->data;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen size_t i, size = ctx->hdr->size / sizeof(*e);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen uint32_t uid;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen for (i = 0; i < size; i++) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen for (uid = e[i].uid1; uid <= e[i].uid2; uid++)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_index_expunge(ctx->trans, uid);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen}
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainenstatic void mail_index_sync_add_flag_update(struct mail_index_sync_ctx *ctx)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen{
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen const struct mail_transaction_flag_update *u = ctx->data;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen size_t i, size = ctx->hdr->size / sizeof(*u);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen for (i = 0; i < size; i++) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (u[i].add_flags != 0) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_index_update_flags_range(ctx->trans,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen u[i].uid1, u[i].uid2,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen MODIFY_ADD,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen u[i].add_flags);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (u[i].remove_flags != 0) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_index_update_flags_range(ctx->trans,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen u[i].uid1, u[i].uid2,
d28179fd78550a58be44dcb1e3e830ab7d33172dTimo Sirainen MODIFY_REMOVE,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen u[i].remove_flags);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen}
62c05ba0290a0bf9c2b0ab4ce117f9a736907c21Timo Sirainen
62c05ba0290a0bf9c2b0ab4ce117f9a736907c21Timo Sirainenstatic void mail_index_sync_add_keyword_update(struct mail_index_sync_ctx *ctx)
62c05ba0290a0bf9c2b0ab4ce117f9a736907c21Timo Sirainen{
62c05ba0290a0bf9c2b0ab4ce117f9a736907c21Timo Sirainen const struct mail_transaction_keyword_update *u = ctx->data;
62c05ba0290a0bf9c2b0ab4ce117f9a736907c21Timo Sirainen const char *keyword_names[2];
62c05ba0290a0bf9c2b0ab4ce117f9a736907c21Timo Sirainen struct mail_keywords *keywords;
62c05ba0290a0bf9c2b0ab4ce117f9a736907c21Timo Sirainen const uint32_t *uids;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen uint32_t uid;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen size_t uidset_offset, i, size;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen uidset_offset = sizeof(*u) + u->name_size;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if ((uidset_offset % 4) != 0)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen uidset_offset += 4 - (uidset_offset % 4);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen uids = CONST_PTR_OFFSET(u, uidset_offset);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen t_push();
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen keyword_names[0] = t_strndup(u + 1, u->name_size);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen keyword_names[1] = NULL;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen keywords = mail_index_keywords_create(ctx->trans, keyword_names);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen size = (ctx->hdr->size - uidset_offset) / sizeof(uint32_t);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen for (i = 0; i < size; i += 2) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen /* FIXME: mail_index_update_keywords_range() */
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen for (uid = uids[i]; uid <= uids[i+1]; uid++) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_index_update_keywords(ctx->trans, uid,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen u->modify_type, keywords);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_index_keywords_free(keywords);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen t_pop();
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen}
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainenstatic void mail_index_sync_add_keyword_reset(struct mail_index_sync_ctx *ctx)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen{
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen const struct mail_transaction_keyword_reset *u = ctx->data;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen size_t i, size = ctx->hdr->size / sizeof(*u);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen struct mail_keywords *keywords;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen uint32_t uid;
ef4661aec4031e24944175ab914dc60942a2b68aTimo Sirainen
ef4661aec4031e24944175ab914dc60942a2b68aTimo Sirainen keywords = mail_index_keywords_create(ctx->trans, NULL);
ef4661aec4031e24944175ab914dc60942a2b68aTimo Sirainen for (i = 0; i < size; i++) {
ef4661aec4031e24944175ab914dc60942a2b68aTimo Sirainen for (uid = u[i].uid1; uid <= u[i].uid2; uid++) {
ef4661aec4031e24944175ab914dc60942a2b68aTimo Sirainen mail_index_update_keywords(ctx->trans, uid,
ef4661aec4031e24944175ab914dc60942a2b68aTimo Sirainen MODIFY_REPLACE, keywords);
ef4661aec4031e24944175ab914dc60942a2b68aTimo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_index_keywords_free(keywords);
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody}
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainenstatic void mail_index_sync_add_append(struct mail_index_sync_ctx *ctx)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen{
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen const struct mail_index_record *rec = ctx->data;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
62c05ba0290a0bf9c2b0ab4ce117f9a736907c21Timo Sirainen if (ctx->append_uid_first == 0 || rec->uid < ctx->append_uid_first)
62c05ba0290a0bf9c2b0ab4ce117f9a736907c21Timo Sirainen ctx->append_uid_first = rec->uid;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen rec = CONST_PTR_OFFSET(ctx->data, ctx->hdr->size - sizeof(*rec));
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (rec->uid > ctx->append_uid_last)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen ctx->append_uid_last = rec->uid;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen ctx->sync_appends = TRUE;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen}
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainenstatic void mail_index_sync_add_transaction(struct mail_index_sync_ctx *ctx)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen{
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen switch (ctx->hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen case MAIL_TRANSACTION_EXPUNGE:
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_index_sync_add_expunge(ctx);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen break;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen case MAIL_TRANSACTION_FLAG_UPDATE:
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_index_sync_add_flag_update(ctx);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen break;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen case MAIL_TRANSACTION_KEYWORD_UPDATE:
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_index_sync_add_keyword_update(ctx);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen break;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen case MAIL_TRANSACTION_KEYWORD_RESET:
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_index_sync_add_keyword_reset(ctx);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen break;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen case MAIL_TRANSACTION_APPEND:
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_index_sync_add_append(ctx);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen break;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen}
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainenstatic int mail_index_sync_add_dirty_updates(struct mail_index_sync_ctx *ctx)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen{
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen struct mail_transaction_flag_update update;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen const struct mail_index_record *rec;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen uint32_t seq, messages_count;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
ad31916e2ad230d0e553203a5461bf7a8dc0d816Timo Sirainen memset(&update, 0, sizeof(update));
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen messages_count = mail_index_view_get_messages_count(ctx->view);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen for (seq = 1; seq <= messages_count; seq++) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (mail_index_lookup(ctx->view, seq, &rec) < 0)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return -1;
62c05ba0290a0bf9c2b0ab4ce117f9a736907c21Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) == 0)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen continue;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_index_update_flags(ctx->trans, rec->uid,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen MODIFY_REPLACE, rec->flags);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return 0;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen}
ad31916e2ad230d0e553203a5461bf7a8dc0d816Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainenstatic int mail_index_sync_add_recent_updates(struct mail_index_sync_ctx *ctx)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen{
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen const struct mail_index_record *rec;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen uint32_t seq, messages_count;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen int seen_recent = FALSE;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen messages_count = mail_index_view_get_messages_count(ctx->view);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen for (seq = 1; seq <= messages_count; seq++) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (mail_index_lookup(ctx->view, seq, &rec) < 0)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return -1;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if ((rec->flags & MAIL_RECENT) != 0) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen seen_recent = TRUE;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_index_update_flags(ctx->trans, rec->uid,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen MODIFY_REMOVE, MAIL_RECENT);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (!seen_recent) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen /* no recent messages, drop the sync_recent flag so we
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen don't scan through the message again */
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen ctx->sync_recent = FALSE;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return 0;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen}
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainenstatic int
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainenmail_index_sync_read_and_sort(struct mail_index_sync_ctx *ctx,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen int *seen_external_r)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen{
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen struct mail_index_sync_list *synclist;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen const struct mail_index_transaction_keyword_update *keyword_updates;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen unsigned int i, keyword_count;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen int ret;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen *seen_external_r = FALSE;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if ((ctx->view->map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) &&
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen ctx->sync_dirty) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen /* show dirty flags as flag updates */
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (mail_index_sync_add_dirty_updates(ctx) < 0)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return -1;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (ctx->sync_recent) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (mail_index_sync_add_recent_updates(ctx) < 0)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return -1;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen /* read all transactions from log into a transaction in memory */
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen while ((ret = mail_transaction_log_view_next(ctx->view->log_view,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen &ctx->hdr,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen &ctx->data, NULL)) > 0) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if ((ctx->hdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen *seen_external_r = TRUE;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen else
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_index_sync_add_transaction(ctx);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen /* create an array containing all expunge, flag and keyword update
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen arrays so we can easily go through all of the changes. */
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen keyword_count = !array_is_created(&ctx->trans->keyword_updates) ? 0 :
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen array_count(&ctx->trans->keyword_updates);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen ARRAY_CREATE(&ctx->sync_list, default_pool,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen struct mail_index_sync_list, keyword_count + 2);
9dadffcd2545eab4b251e83b60cee78ceb1e8362Anton Yuzhaninov
7f74811b78f8915e73dffc88bb49009e98b6846dTimo Sirainen if (array_is_created(&ctx->trans->expunges)) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen synclist = array_append_space(&ctx->sync_list);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen synclist->array = &ctx->trans->expunges;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (array_is_created(&ctx->trans->updates)) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen synclist = array_append_space(&ctx->sync_list);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen synclist->array = &ctx->trans->updates;
9dadffcd2545eab4b251e83b60cee78ceb1e8362Anton Yuzhaninov }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen /* we must return resets before keyword additions or they get lost */
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (array_is_created(&ctx->trans->keyword_resets)) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen synclist = array_append_space(&ctx->sync_list);
7f74811b78f8915e73dffc88bb49009e98b6846dTimo Sirainen synclist->array = &ctx->trans->keyword_resets;
7f74811b78f8915e73dffc88bb49009e98b6846dTimo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen keyword_updates = keyword_count == 0 ? NULL :
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen array_get(&ctx->trans->keyword_updates, NULL);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen for (i = 0; i < keyword_count; i++) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (array_is_created(&keyword_updates[i].add_seq)) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen synclist = array_append_space(&ctx->sync_list);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen synclist->array = &keyword_updates[i].add_seq;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen synclist->keyword_idx = i;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (array_is_created(&keyword_updates[i].remove_seq)) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen synclist = array_append_space(&ctx->sync_list);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen synclist->array = &keyword_updates[i].remove_seq;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen synclist->keyword_idx = i;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen synclist->keyword_remove = TRUE;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return ret;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen}
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainenstatic int mail_index_need_lock(struct mail_index *index, int sync_recent,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen uint32_t log_file_seq, uoff_t log_file_offset)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen{
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (sync_recent && index->hdr->recent_messages_count > 0)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return 1;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (index->hdr->log_file_seq > log_file_seq ||
2c0f1cb7a0564d48ec43c7315ea46ea38d2abd19Timo Sirainen (index->hdr->log_file_seq == log_file_seq &&
2c0f1cb7a0564d48ec43c7315ea46ea38d2abd19Timo Sirainen index->hdr->log_file_int_offset >= log_file_offset &&
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen index->hdr->log_file_ext_offset >= log_file_offset)) {
2c0f1cb7a0564d48ec43c7315ea46ea38d2abd19Timo Sirainen /* already synced */
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return mail_cache_need_compress(index->cache);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return 1;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen}
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainenstatic int mail_index_sync_commit_external(struct mail_index_sync_ctx *ctx,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen uint32_t seq, uoff_t offset)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen{
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen int ret;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
7f74811b78f8915e73dffc88bb49009e98b6846dTimo Sirainen while ((ret = mail_transaction_log_view_next(ctx->view->log_view,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen &ctx->hdr, &ctx->data,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen NULL)) > 0) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if ((ctx->hdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen break;
7f74811b78f8915e73dffc88bb49009e98b6846dTimo Sirainen }
7f74811b78f8915e73dffc88bb49009e98b6846dTimo Sirainen if (ret < 0)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return -1;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (ret > 0) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (mail_transaction_log_view_set(ctx->view->log_view,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen ctx->index->hdr->log_file_seq,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen ctx->index->hdr->log_file_ext_offset,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen seq, offset, MAIL_TRANSACTION_TYPE_MASK) < 0)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return -1;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (mail_index_sync_update_index(ctx, TRUE) < 0)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return -1;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return 0;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen}
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen#define MAIL_INDEX_IS_SYNCS_SAME(index) \
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen ((index)->hdr != NULL && \
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen (index)->sync_log_file_seq == (index)->hdr->log_file_seq && \
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen (index)->sync_log_file_offset == (index)->hdr->log_file_ext_offset)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainenint mail_index_sync_begin(struct mail_index *index,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen struct mail_index_sync_ctx **ctx_r,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen struct mail_index_view **view_r,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen uint32_t log_file_seq, uoff_t log_file_offset,
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen int sync_recent, int sync_dirty)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen{
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen struct mail_index_sync_ctx *ctx;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen struct mail_index_view *dummy_view;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen uint32_t seq;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen uoff_t offset;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen unsigned int lock_id = 0;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen int seen_external;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (mail_transaction_log_sync_lock(index->log, &seq, &offset) < 0)
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return -1;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (!index->mmap_disable || !MAIL_INDEX_IS_SYNCS_SAME(index) ||
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen index->sync_log_file_seq != seq ||
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen index->sync_log_file_offset != offset) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen /* make sure we have the latest file mapped */
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (mail_index_lock_shared(index, TRUE, &lock_id) < 0) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_transaction_log_sync_unlock(index->log);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return -1;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen /* with mmap_disable the force parameter has somewhat special
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen meaning, it syncs exactly to the log seq/offset in index
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen file's header. */
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen if (mail_index_map(index, index->mmap_disable) <= 0) {
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen mail_transaction_log_sync_unlock(index->log);
2974dca6be5120e49279f06c8aa952e5fac56048Timo Sirainen mail_index_unlock(index, lock_id);
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen return -1;
12983e9d3b4ebdfb1e14f197c153304b3af44b59Timo Sirainen }
}
if ((index->hdr->flags & MAIL_INDEX_HDR_FLAG_FSCK) != 0) {
if (mail_index_fsck(index) <= 0) {
mail_index_unlock(index, lock_id);
mail_transaction_log_sync_unlock(index->log);
return -1;
}
}
if (!mail_index_need_lock(index, sync_recent,
log_file_seq, log_file_offset)) {
mail_index_unlock(index, lock_id);
mail_transaction_log_sync_unlock(index->log);
return 0;
}
ctx = i_new(struct mail_index_sync_ctx, 1);
ctx->index = index;
ctx->lock_id = lock_id;
ctx->sync_recent = sync_recent;
ctx->sync_dirty = sync_dirty;
ctx->view = mail_index_view_open(index);
dummy_view = mail_index_dummy_view_open(index);
ctx->trans = mail_index_transaction_begin(dummy_view, FALSE, TRUE);
mail_index_view_close(dummy_view);
if (index->hdr->log_file_seq == seq &&
index->hdr->log_file_ext_offset > offset) {
/* synced offset is greater than what we have available.
the log sequences have gotten messed up. */
mail_transaction_log_file_set_corrupted(index->log->head,
"log_file_ext_offset (%u) > log size (%"PRIuUOFF_T")",
index->hdr->log_file_ext_offset, offset);
mail_index_sync_rollback(ctx);
return -1;
}
if (mail_transaction_log_view_set(ctx->view->log_view,
index->hdr->log_file_seq,
index->hdr->log_file_int_offset,
seq, offset,
MAIL_TRANSACTION_TYPE_MASK) < 0) {
mail_index_sync_rollback(ctx);
return -1;
}
/* See if there are some external transactions which were
written to transaction log, but weren't yet committed to
index. commit them first to avoid conflicts with another
external sync.
This is mostly needed to make sure there won't be multiple
appends with same UIDs, because those would cause
transaction log to be marked corrupted.
Note that any internal transactions must not be committed
yet. They need to be synced with the real mailbox first. */
if (seq != index->hdr->log_file_seq ||
offset != index->hdr->log_file_ext_offset) {
if (mail_index_sync_commit_external(ctx, seq, offset) < 0) {
mail_index_sync_rollback(ctx);
return -1;
}
mail_index_view_close(ctx->view);
ctx->view = mail_index_view_open(index);
if (mail_transaction_log_view_set(ctx->view->log_view,
index->hdr->log_file_seq,
index->hdr->log_file_int_offset,
seq, offset,
MAIL_TRANSACTION_TYPE_MASK) < 0) {
mail_index_sync_rollback(ctx);
return -1;
}
}
/* we need to have all the transactions sorted to optimize
caller's mailbox access patterns */
if (mail_index_sync_read_and_sort(ctx, &seen_external) < 0) {
mail_index_sync_rollback(ctx);
return -1;
}
*ctx_r = ctx;
*view_r = ctx->view;
return 1;
}
void
mail_index_sync_get_expunge(struct mail_index_sync_rec *rec,
const struct mail_transaction_expunge *exp)
{
rec->type = MAIL_INDEX_SYNC_TYPE_EXPUNGE;
rec->uid1 = exp->uid1;
rec->uid2 = exp->uid2;
}
void
mail_index_sync_get_update(struct mail_index_sync_rec *rec,
const struct mail_transaction_flag_update *update)
{
rec->type = MAIL_INDEX_SYNC_TYPE_FLAGS;
rec->uid1 = update->uid1;
rec->uid2 = update->uid2;
rec->add_flags = update->add_flags;
rec->remove_flags = update->remove_flags;
}
static void
mail_index_sync_get_keyword_update(struct mail_index_sync_rec *rec,
const struct uid_range *range,
struct mail_index_sync_list *sync_list)
{
rec->type = !sync_list->keyword_remove ?
MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD :
MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE;
rec->uid1 = range->uid1;
rec->uid2 = range->uid2;
rec->keyword_idx = sync_list->keyword_idx;
}
static void mail_index_sync_get_keyword_reset(struct mail_index_sync_rec *rec,
const struct uid_range *range)
{
rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET;
rec->uid1 = range->uid1;
rec->uid2 = range->uid2;
}
static int mail_index_sync_rec_check(struct mail_index_view *view,
struct mail_index_sync_rec *rec)
{
switch (rec->type) {
case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
case MAIL_INDEX_SYNC_TYPE_FLAGS:
case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
if (rec->uid1 > rec->uid2 || rec->uid1 == 0) {
mail_transaction_log_view_set_corrupted(view->log_view,
"Broken UID range: %u..%u (type 0x%x)",
rec->uid1, rec->uid2, rec->type);
return FALSE;
}
break;
case MAIL_INDEX_SYNC_TYPE_APPEND:
break;
}
return TRUE;
}
int mail_index_sync_next(struct mail_index_sync_ctx *ctx,
struct mail_index_sync_rec *sync_rec)
{
struct mail_index_sync_list *sync_list;
const struct uid_range *uid_range = NULL;
unsigned int i, count, next_i;
uint32_t next_found_uid;
next_i = (unsigned int)-1;
next_found_uid = (uint32_t)-1;
/* FIXME: replace with a priority queue so we don't have to go
through the whole list constantly. and remember to make sure that
keyword resets are sent before adds! */
sync_list = array_get_modifyable(&ctx->sync_list, &count);
for (i = 0; i < count; i++) {
if (!array_is_created(sync_list[i].array) ||
sync_list[i].idx == array_count(sync_list[i].array))
continue;
uid_range = array_idx(sync_list[i].array, sync_list[i].idx);
if (uid_range->uid1 == ctx->next_uid) {
/* use this one. */
break;
}
if (uid_range->uid1 < next_found_uid) {
next_i = i;
next_found_uid = uid_range->uid1;
}
}
if (i == count) {
if (next_i == (unsigned int)-1) {
/* nothing left in sync_list */
if (ctx->sync_appends) {
ctx->sync_appends = FALSE;
sync_rec->type = MAIL_INDEX_SYNC_TYPE_APPEND;
sync_rec->uid1 = ctx->append_uid_first;
sync_rec->uid2 = ctx->append_uid_last;
return 1;
}
return 0;
}
ctx->next_uid = next_found_uid;
i = next_i;
uid_range = array_idx(sync_list[i].array, sync_list[i].idx);
}
if (sync_list[i].array == &ctx->trans->expunges) {
mail_index_sync_get_expunge(sync_rec,
(const struct mail_transaction_expunge *)uid_range);
} else if (sync_list[i].array == &ctx->trans->updates) {
mail_index_sync_get_update(sync_rec,
(const struct mail_transaction_flag_update *)uid_range);
} else if (sync_list[i].array == &ctx->trans->keyword_resets) {
mail_index_sync_get_keyword_reset(sync_rec, uid_range);
} else {
mail_index_sync_get_keyword_update(sync_rec, uid_range,
&sync_list[i]);
}
sync_list[i].idx++;
if (mail_index_sync_rec_check(ctx->view, sync_rec) < 0)
return -1;
return 1;
}
int mail_index_sync_have_more(struct mail_index_sync_ctx *ctx)
{
const struct mail_index_sync_list *sync_list;
unsigned int i, count;
if (ctx->sync_appends)
return TRUE;
sync_list = array_get(&ctx->sync_list, &count);
for (i = 0; i < count; i++) {
if (array_is_created(sync_list[i].array) &&
sync_list[i].idx != array_count(sync_list[i].array))
return TRUE;
}
return FALSE;
}
void mail_index_sync_reset(struct mail_index_sync_ctx *ctx)
{
struct mail_index_sync_list *sync_list;
unsigned int i, count;
ctx->next_uid = 0;
sync_list = array_get_modifyable(&ctx->sync_list, &count);
for (i = 0; i < count; i++)
sync_list[i].idx = 0;
}
static void mail_index_sync_end(struct mail_index_sync_ctx *ctx)
{
mail_index_unlock(ctx->index, ctx->lock_id);
i_assert(!ctx->index->map->write_to_disk);
mail_transaction_log_sync_unlock(ctx->index->log);
mail_index_view_close(ctx->view);
mail_index_transaction_rollback(ctx->trans);
i_free(ctx);
}
int mail_index_sync_commit(struct mail_index_sync_ctx *ctx)
{
struct mail_index *index = ctx->index;
const struct mail_index_header *hdr;
uint32_t seq, seq2;
uoff_t offset, offset2;
int ret = 0;
if (mail_transaction_log_view_is_corrupted(ctx->view->log_view))
ret = -1;
/* we have had the transaction log locked since the beginning of sync,
so only external changes could have been committed. write them to
the index here as well. */
mail_transaction_log_get_head(index->log, &seq, &offset);
hdr = index->hdr;
if (ret == 0 && (hdr->log_file_seq != seq ||
hdr->log_file_int_offset != offset ||
hdr->log_file_ext_offset != offset)) {
if (mail_transaction_log_view_set(ctx->view->log_view,
hdr->log_file_seq, hdr->log_file_int_offset,
seq, offset, MAIL_TRANSACTION_TYPE_MASK) < 0)
ret = -1;
else if (mail_index_sync_update_index(ctx, FALSE) < 0)
ret = -1;
}
if (ret == 0 && mail_cache_need_compress(index->cache)) {
if (mail_cache_compress(index->cache, ctx->view) < 0)
ret = -1;
else {
/* cache_offsets have changed, sync them */
mail_transaction_log_get_head(index->log,
&seq2, &offset2);
if (mail_transaction_log_view_set(ctx->view->log_view,
seq, offset, seq2, offset2,
MAIL_TRANSACTION_TYPE_MASK) < 0)
ret = -1;
else if (mail_index_sync_update_index(ctx, FALSE) < 0)
ret = -1;
}
}
index->sync_log_file_seq = index->map->hdr.log_file_seq;
index->sync_log_file_offset = index->map->hdr.log_file_int_offset;
mail_index_sync_end(ctx);
return ret;
}
void mail_index_sync_rollback(struct mail_index_sync_ctx *ctx)
{
mail_index_sync_end(ctx);
}
void mail_index_sync_flags_apply(const struct mail_index_sync_rec *sync_rec,
uint8_t *flags)
{
i_assert(sync_rec->type == MAIL_INDEX_SYNC_TYPE_FLAGS);
*flags = (*flags & ~sync_rec->remove_flags) | sync_rec->add_flags;
}
int mail_index_sync_keywords_apply(const struct mail_index_sync_rec *sync_rec,
array_t *keywords)
{
ARRAY_SET_TYPE(keywords, unsigned int);
const unsigned int *keyword_indexes;
unsigned int idx = sync_rec->keyword_idx;
unsigned int i, count;
keyword_indexes = array_get(keywords, &count);
switch (sync_rec->type) {
case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
for (i = 0; i < count; i++) {
if (keyword_indexes[i] == idx)
return FALSE;
}
array_append(keywords, &idx, 1);
return TRUE;
case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
for (i = 0; i < count; i++) {
if (keyword_indexes[i] == idx) {
array_delete(keywords, i, 1);
return TRUE;
}
}
return FALSE;
case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
if (array_count(keywords) == 0)
return FALSE;
array_clear(keywords);
return TRUE;
default:
i_unreached();
return FALSE;
}
}