index-sync.c revision ff78c4ba4e897026eb99788e0a6ac15e9205fcd7
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2002-2007 Dovecot authors, see the included COPYING file */
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen#include "lib.h"
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen#include "seq-range-array.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "array.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "buffer.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "index-storage.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainenstruct index_mailbox_sync_context {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct mailbox_sync_context ctx;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen struct index_mailbox *ibox;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen struct mail_index_view_sync_ctx *sync_ctx;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen uint32_t messages_count;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen const ARRAY_TYPE(seq_range) *expunges;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen unsigned int expunge_pos;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen uint32_t last_seq1, last_seq2;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen bool failed;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen};
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainenvoid index_mailbox_set_recent_uid(struct index_mailbox *ibox, uint32_t uid)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen{
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen if (uid <= ibox->recent_flags_prev_uid) {
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen i_assert(seq_range_exists(&ibox->recent_flags, uid));
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen return;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ibox->recent_flags_prev_uid = uid;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen seq_range_array_add(&ibox->recent_flags, 64, uid);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen ibox->recent_flags_count++;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen}
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
4c892b0d94c5b1d6853dbe8e0b38059ea5b08ecaTimo Sirainenvoid index_mailbox_set_recent_seq(struct index_mailbox *ibox,
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen struct mail_index_view *view,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen uint32_t seq1, uint32_t seq2)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen{
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen uint32_t uid;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
4c892b0d94c5b1d6853dbe8e0b38059ea5b08ecaTimo Sirainen for (; seq1 <= seq2; seq1++) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_index_lookup_uid(view, seq1, &uid);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen index_mailbox_set_recent_uid(ibox, uid);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen }
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenbool index_mailbox_is_recent(struct index_mailbox *ibox, uint32_t uid)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return array_is_created(&ibox->recent_flags) &&
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen seq_range_exists(&ibox->recent_flags, uid);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenunsigned int index_mailbox_get_recent_count(struct index_mailbox *ibox)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const struct mail_index_header *hdr;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const struct seq_range *range;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen unsigned int i, count, recent_count;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (!array_is_created(&ibox->recent_flags))
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen hdr = mail_index_get_header(ibox->view);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen recent_count = ibox->recent_flags_count;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen range = array_get(&ibox->recent_flags, &count);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen for (i = count; i > 0; ) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i--;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen if (range[i].seq2 < hdr->next_uid)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen break;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen if (range[i].seq1 >= hdr->next_uid) {
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen /* completely invisible to this view */
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen recent_count -= range[i].seq2 - range[i].seq1 + 1;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen } else {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen /* partially invisible */
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen recent_count -= range[i].seq2 - hdr->next_uid + 1;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen break;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return recent_count;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen}
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainenstatic void index_mailbox_expunge_recent(struct index_mailbox *ibox,
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen uint32_t seq1, uint32_t seq2)
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen{
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen uint32_t uid;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (!array_is_created(&ibox->recent_flags))
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen for (; seq1 <= seq2; seq1++) {
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen mail_index_lookup_uid(ibox->view, seq1, &uid);
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen if (seq_range_array_remove(&ibox->recent_flags, uid))
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen ibox->recent_flags_count--;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen }
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen}
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainenstruct mailbox_sync_context *
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainenindex_mailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags,
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen bool failed)
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct index_mailbox *ibox = (struct index_mailbox *)box;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct index_mailbox_sync_context *ctx;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen enum mail_index_view_sync_flags sync_flags = 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx = i_new(struct index_mailbox_sync_context, 1);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->ctx.box = box;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->ibox = ibox;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (failed) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->failed = TRUE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return &ctx->ctx;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if ((flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) != 0)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen sync_flags |= MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FIX_INCONSISTENT) != 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen sync_flags |= MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->messages_count = 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen } else {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->messages_count =
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_index_view_get_messages_count(ibox->view);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (mail_index_view_sync_begin(ibox->view, sync_flags,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen &ctx->sync_ctx) < 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_storage_set_index_error(ibox);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->failed = TRUE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return &ctx->ctx;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if ((flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) == 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_index_view_sync_get_expunges(ctx->sync_ctx,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen &ctx->expunges);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->expunge_pos = array_count(ctx->expunges);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return &ctx->ctx;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic bool sync_rec_check_skips(struct index_mailbox_sync_context *ctx,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct mailbox_sync_rec *sync_rec)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen uint32_t seq, new_seq1, new_seq2;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (sync_rec->seq1 >= ctx->last_seq1 &&
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen sync_rec->seq1 <= ctx->last_seq2)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen new_seq1 = ctx->last_seq2 + 1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen else
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen new_seq1 = sync_rec->seq1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (sync_rec->seq2 >= ctx->last_seq1 &&
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen sync_rec->seq2 <= ctx->last_seq2)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen new_seq2 = ctx->last_seq1 - 1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen else
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen new_seq2 = sync_rec->seq2;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (new_seq1 > new_seq2)
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return FALSE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen ctx->last_seq1 = sync_rec->seq1;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen ctx->last_seq2 = sync_rec->seq2;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen sync_rec->seq1 = new_seq1;
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen sync_rec->seq2 = new_seq2;
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* FIXME: we're only skipping messages from the beginning and from
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen the end. we should skip also the middle ones. This takes care of
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen the most common repeats though. */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (ctx->expunges != NULL) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* skip expunged messages from the beginning and the end */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen for (seq = sync_rec->seq1; seq <= sync_rec->seq2; seq++) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (!seq_range_exists(ctx->expunges, seq))
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen break;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (seq > sync_rec->seq2) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* everything skipped */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return FALSE;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen sync_rec->seq1 = seq;
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen for (seq = sync_rec->seq2; seq >= sync_rec->seq1; seq--) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (!seq_range_exists(ctx->expunges, seq))
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen break;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen }
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen sync_rec->seq2 = seq;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen }
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen return TRUE;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen}
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainenstatic int
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainenindex_mailbox_sync_next_expunge(struct index_mailbox_sync_context *ctx,
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen struct mailbox_sync_rec *sync_rec_r)
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen{
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen const struct seq_range *range;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen if (ctx->expunge_pos == 0)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen return 0;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen /* expunges is a sorted array of sequences. it's easiest for
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen us to print them from end to beginning. */
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen ctx->expunge_pos--;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen range = array_idx(ctx->expunges, ctx->expunge_pos);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen i_assert(range->seq2 <= ctx->messages_count);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen index_mailbox_expunge_recent(ctx->ibox, range->seq1, range->seq2);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen ctx->messages_count -= range->seq2 - range->seq1 + 1;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
d2c853636ec2d99c9f96da877ff520a3b86a18baTimo Sirainen sync_rec_r->seq1 = range->seq1;
d2c853636ec2d99c9f96da877ff520a3b86a18baTimo Sirainen sync_rec_r->seq2 = range->seq2;
d2c853636ec2d99c9f96da877ff520a3b86a18baTimo Sirainen sync_rec_r->type = MAILBOX_SYNC_TYPE_EXPUNGE;
d2c853636ec2d99c9f96da877ff520a3b86a18baTimo Sirainen return 1;
d2c853636ec2d99c9f96da877ff520a3b86a18baTimo Sirainen}
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainenbool index_mailbox_sync_next(struct mailbox_sync_context *_ctx,
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen struct mailbox_sync_rec *sync_rec_r)
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen{
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen struct index_mailbox_sync_context *ctx =
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen (struct index_mailbox_sync_context *)_ctx;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen struct mail_index_view_sync_rec sync;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (ctx->failed)
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return FALSE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen while (mail_index_view_sync_next(ctx->sync_ctx, &sync)) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen switch (sync.type) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen case MAIL_INDEX_SYNC_TYPE_APPEND:
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen /* not interested */
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen break;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen /* later */
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen break;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen case MAIL_INDEX_SYNC_TYPE_FLAGS:
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
d2c853636ec2d99c9f96da877ff520a3b86a18baTimo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
d2c853636ec2d99c9f96da877ff520a3b86a18baTimo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen /* FIXME: hide the flag updates for expunged messages */
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen mail_index_lookup_seq_range(ctx->ibox->view,
d2c853636ec2d99c9f96da877ff520a3b86a18baTimo Sirainen sync.uid1, sync.uid2,
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen &sync_rec_r->seq1,
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen &sync_rec_r->seq2);
d2c853636ec2d99c9f96da877ff520a3b86a18baTimo Sirainen if (sync_rec_r->seq1 == 0)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen break;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen if (!sync_rec_check_skips(ctx, sync_rec_r))
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen break;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen sync_rec_r->type =
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen sync.type == MAIL_INDEX_SYNC_TYPE_FLAGS ?
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen MAILBOX_SYNC_TYPE_FLAGS :
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen MAILBOX_SYNC_TYPE_KEYWORDS;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return 1;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return index_mailbox_sync_next_expunge(ctx, sync_rec_r);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen}
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainenstatic void
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainenindex_mailbox_expunge_unseen_recent(struct index_mailbox_sync_context *ctx)
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen{
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen struct index_mailbox *ibox = ctx->ibox;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen const struct mail_index_header *hdr;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen uint32_t seq, start_uid, uid;
if (!array_is_created(&ibox->recent_flags))
return;
/* expunges array contained expunges for the messages that were already
visible in this view, but append+expunge would be invisible.
recent_flags may however contain the append UID, so we'll have to
remove it separately */
hdr = mail_index_get_header(ibox->view);
if (ctx->messages_count == 0)
uid = 0;
else if (ctx->messages_count <= hdr->messages_count)
mail_index_lookup_uid(ibox->view, ctx->messages_count, &uid);
else {
i_assert(mail_index_view_is_inconsistent(ibox->view));
return;
}
for (seq = ctx->messages_count + 1; seq <= hdr->messages_count; seq++) {
start_uid = uid;
mail_index_lookup_uid(ibox->view, seq, &uid);
if (start_uid + 1 > uid - 1)
continue;
ibox->recent_flags_count -=
seq_range_array_remove_range(&ibox->recent_flags,
start_uid + 1, uid - 1);
}
if (uid + 1 < hdr->next_uid) {
ibox->recent_flags_count -=
seq_range_array_remove_range(&ibox->recent_flags,
uid + 1,
hdr->next_uid - 1);
}
#ifdef DEBUG
{
const struct seq_range *range;
unsigned int i, count;
range = array_get(&ibox->recent_flags, &count);
for (i = 0; i < count; i++) {
for (uid = range[i].seq1; uid <= range[i].seq2; uid++) {
if (uid >= hdr->next_uid)
break;
mail_index_lookup_seq(ibox->view, uid, &seq);
i_assert(seq != 0);
}
}
}
#endif
}
int index_mailbox_sync_deinit(struct mailbox_sync_context *_ctx,
enum mailbox_status_items status_items,
struct mailbox_status *status_r)
{
struct index_mailbox_sync_context *ctx =
(struct index_mailbox_sync_context *)_ctx;
struct index_mailbox *ibox = ctx->ibox;
struct mailbox_sync_rec sync_rec;
const struct mail_index_header *hdr;
uint32_t seq1, seq2;
int ret = ctx->failed ? -1 : 0;
/* finish handling expunges, so we don't break when updating
recent flags */
while (ctx->expunge_pos > 0)
index_mailbox_sync_next_expunge(ctx, &sync_rec);
if (ctx->sync_ctx != NULL) {
if (mail_index_view_sync_commit(&ctx->sync_ctx) < 0) {
mail_storage_set_index_error(ibox);
ret = -1;
}
}
index_mailbox_expunge_unseen_recent(ctx);
if (ibox->keep_recent) {
/* mailbox syncing didn't necessarily update our recent state */
hdr = mail_index_get_header(ibox->view);
if (hdr->first_recent_uid > ibox->recent_flags_prev_uid) {
mail_index_lookup_seq_range(ibox->view,
hdr->first_recent_uid,
hdr->next_uid,
&seq1, &seq2);
if (seq1 != 0) {
index_mailbox_set_recent_seq(ibox, ibox->view,
seq1, seq2);
}
}
}
if (ret == 0 && status_items != 0)
mailbox_get_status(_ctx->box, status_items, status_r);
i_free(ctx);
return ret;
}
bool index_keyword_array_cmp(const ARRAY_TYPE(keyword_indexes) *k1,
const ARRAY_TYPE(keyword_indexes) *k2)
{
const unsigned int *idx1, *idx2;
unsigned int i, j, count1, count2;
if (!array_is_created(k1))
return !array_is_created(k2) || array_count(k2) == 0;
if (!array_is_created(k2))
return array_count(k1) == 0;
/* The arrays may not be sorted, but they usually are. Optimize for
the assumption that they are */
idx1 = array_get(k1, &count1);
idx2 = array_get(k2, &count2);
if (count1 != count2)
return FALSE;
for (i = 0; i < count1; i++) {
if (idx1[i] != idx2[i]) {
/* not found / unsorted array. check. */
for (j = 0; j < count1; j++) {
if (idx1[i] == idx2[j])
break;
}
if (j == count1)
return FALSE;
}
}
return TRUE;
}