index-sync.c revision 5a86309a6c58bdeb9921bf2989aaabaaa04a29ab
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen#include "seq-range-array.h"
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen#include "ioloop.h"
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen#include "array.h"
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen#include "index-sync-private.h"
105addcb709523868418cc3e3baad7ad3453a91eTimo Sirainen
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainenbool index_mailbox_want_full_sync(struct index_mailbox *ibox,
105addcb709523868418cc3e3baad7ad3453a91eTimo Sirainen enum mailbox_sync_flags flags)
105addcb709523868418cc3e3baad7ad3453a91eTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FAST) != 0 &&
105addcb709523868418cc3e3baad7ad3453a91eTimo Sirainen ioloop_time < ibox->sync_last_check + MAILBOX_FULL_SYNC_INTERVAL)
105addcb709523868418cc3e3baad7ad3453a91eTimo Sirainen return FALSE;
105addcb709523868418cc3e3baad7ad3453a91eTimo Sirainen
105addcb709523868418cc3e3baad7ad3453a91eTimo Sirainen if (ibox->notify_to != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen timeout_reset(ibox->notify_to);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ibox->sync_last_check = ioloop_time;
0add8c99ca65e56dbf613595fc37c41aafff3f7fTimo Sirainen return TRUE;
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen}
105addcb709523868418cc3e3baad7ad3453a91eTimo Sirainen
49d4afbb76f47c8904537d087bc81e43f1c0aa25Timo Sirainenvoid index_mailbox_set_recent_uid(struct index_mailbox *ibox, uint32_t uid)
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen{
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen if (uid <= ibox->recent_flags_prev_uid) {
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen i_assert(seq_range_exists(&ibox->recent_flags, uid));
b44faf865da16ac4d18eecd85a55b3fab6b9e63aTimo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ibox->recent_flags_prev_uid = uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen seq_range_array_add(&ibox->recent_flags, 64, uid);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen ibox->recent_flags_count++;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen}
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenvoid index_mailbox_set_recent_seq(struct index_mailbox *ibox,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen struct mail_index_view *view,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen uint32_t seq1, uint32_t seq2)
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen{
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen uint32_t uid;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen for (; seq1 <= seq2; seq1++) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_index_lookup_uid(view, seq1, &uid);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen index_mailbox_set_recent_uid(ibox, uid);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen }
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen}
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen
e188bab0b830136d04a1dd8b55e9afefae20d930Timo Sirainenbool index_mailbox_is_recent(struct index_mailbox *ibox, uint32_t uid)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
5a3f143585110536a7f72628e66a42b998bfc5fcTimo Sirainen return array_is_created(&ibox->recent_flags) &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen seq_range_exists(&ibox->recent_flags, uid);
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen}
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen
041d312b44f8d41f0c9a5762c23e4d146ef7302bTimo Sirainenvoid index_mailbox_reset_uidvalidity(struct index_mailbox *ibox)
041d312b44f8d41f0c9a5762c23e4d146ef7302bTimo Sirainen{
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen /* can't trust the currently cached recent flags anymore */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (array_is_created(&ibox->recent_flags))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_clear(&ibox->recent_flags);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen ibox->recent_flags_count = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ibox->recent_flags_prev_uid = 0;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenunsigned int index_mailbox_get_recent_count(struct index_mailbox *ibox)
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_index_header *hdr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct seq_range *range;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i, count, recent_count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!array_is_created(&ibox->recent_flags))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen hdr = mail_index_get_header(ibox->view);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen recent_count = ibox->recent_flags_count;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen range = array_get(&ibox->recent_flags, &count);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen for (i = count; i > 0; ) {
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen i--;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (range[i].seq2 < hdr->next_uid)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen break;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (range[i].seq1 >= hdr->next_uid) {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen /* completely invisible to this view */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen recent_count -= range[i].seq2 - range[i].seq1 + 1;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen } else {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* partially invisible */
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen recent_count -= range[i].seq2 - hdr->next_uid + 1;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen return recent_count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
232d5bef3c709e90e24f0874a36854b92187bb6cTimo Sirainenstatic void index_mailbox_expunge_recent(struct index_mailbox *ibox,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen uint32_t seq1, uint32_t seq2)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen uint32_t uid;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (!array_is_created(&ibox->recent_flags))
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen return;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen for (; seq1 <= seq2; seq1++) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen mail_index_lookup_uid(ibox->view, seq1, &uid);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (seq_range_array_remove(&ibox->recent_flags, uid))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ibox->recent_flags_count--;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen }
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen}
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainenstatic void index_view_sync_recs_get(struct index_mailbox_sync_context *ctx)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen{
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct mail_index_view_sync_rec sync_rec;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen uint32_t seq1, seq2;
a928e7efabb1672b1476e597106d4b4b81ac6f3cTimo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen i_array_init(&ctx->flag_updates, 128);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if ((ctx->ibox->box.enabled_features & MAILBOX_FEATURE_CONDSTORE) != 0)
838f56174b963779a88083a0d0e85b30d2d846e7Timo Sirainen i_array_init(&ctx->modseq_updates, 32);
894987bf45718f8849cc3898afdfb1ac3cfa2445Timo Sirainen while (mail_index_view_sync_next(ctx->sync_ctx, &sync_rec)) {
894987bf45718f8849cc3898afdfb1ac3cfa2445Timo Sirainen switch (sync_rec.type) {
894987bf45718f8849cc3898afdfb1ac3cfa2445Timo Sirainen case MAIL_INDEX_SYNC_TYPE_APPEND:
838f56174b963779a88083a0d0e85b30d2d846e7Timo Sirainen /* not interested */
838f56174b963779a88083a0d0e85b30d2d846e7Timo Sirainen break;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen /* later */
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case MAIL_INDEX_SYNC_TYPE_FLAGS:
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (!mail_index_lookup_seq_range(ctx->ibox->view,
838f56174b963779a88083a0d0e85b30d2d846e7Timo Sirainen sync_rec.uid1, sync_rec.uid2,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen &seq1, &seq2))
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen break;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (!sync_rec.hidden) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen seq_range_array_add_range(&ctx->flag_updates,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen seq1, seq2);
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen } else if (array_is_created(&ctx->modseq_updates)) {
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen seq_range_array_add_range(&ctx->modseq_updates,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen seq1, seq2);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* remove expunged messages from flag/modseq updates */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (ctx->expunges != NULL) {
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen seq_range_array_remove_seq_range(&ctx->flag_updates,
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen ctx->expunges);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen if (array_is_created(&ctx->modseq_updates)) {
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen seq_range_array_remove_seq_range(&ctx->modseq_updates,
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen ctx->expunges);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen }
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen }
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen /* remove flag updates from modseq updates */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (array_is_created(&ctx->modseq_updates)) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen seq_range_array_remove_seq_range(&ctx->modseq_updates,
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen &ctx->flag_updates);
a928e7efabb1672b1476e597106d4b4b81ac6f3cTimo Sirainen }
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen}
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainenstruct mailbox_sync_context *
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainenindex_mailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags,
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen bool failed)
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen{
e188bab0b830136d04a1dd8b55e9afefae20d930Timo Sirainen struct index_mailbox *ibox = (struct index_mailbox *)box;
e188bab0b830136d04a1dd8b55e9afefae20d930Timo Sirainen struct index_mailbox_sync_context *ctx;
e188bab0b830136d04a1dd8b55e9afefae20d930Timo Sirainen enum mail_index_view_sync_flags sync_flags = 0;
e188bab0b830136d04a1dd8b55e9afefae20d930Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ctx = i_new(struct index_mailbox_sync_context, 1);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ctx->ctx.box = box;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ctx->ibox = ibox;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (failed) {
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen ctx->failed = TRUE;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return &ctx->ctx;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if ((flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) != 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen sync_flags |= MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FIX_INCONSISTENT) != 0) {
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen sync_flags |= MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->messages_count = 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen } else {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ctx->messages_count =
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_index_view_get_messages_count(ibox->view);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ctx->sync_ctx = mail_index_view_sync_begin(ibox->view, sync_flags);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if ((flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) == 0) {
94aa90d2d17a7aebcda5a4193a62e80ddbb169b7Timo Sirainen mail_index_view_sync_get_expunges(ctx->sync_ctx,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen &ctx->expunges);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ctx->expunge_pos = array_count(ctx->expunges);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen index_view_sync_recs_get(ctx);
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen index_sync_search_results_expunge(ctx);
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen return &ctx->ctx;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic bool
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenindex_mailbox_sync_next_expunge(struct index_mailbox_sync_context *ctx,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct mailbox_sync_rec *sync_rec_r)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const struct seq_range *range;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (ctx->expunge_pos == 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return FALSE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* expunges is a sorted array of sequences. it's easiest for
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen us to print them from end to beginning. */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ctx->expunge_pos--;
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen range = array_idx(ctx->expunges, ctx->expunge_pos);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(range->seq2 <= ctx->messages_count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen index_mailbox_expunge_recent(ctx->ibox, range->seq1, range->seq2);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->messages_count -= range->seq2 - range->seq1 + 1;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen sync_rec_r->seq1 = range->seq1;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen sync_rec_r->seq2 = range->seq2;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen sync_rec_r->type = MAILBOX_SYNC_TYPE_EXPUNGE;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return TRUE;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen}
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
096953143c4032bad154637f687551856f7946cbTimo Sirainenbool index_mailbox_sync_next(struct mailbox_sync_context *_ctx,
096953143c4032bad154637f687551856f7946cbTimo Sirainen struct mailbox_sync_rec *sync_rec_r)
c680a6b35b459045e92814778908da5a93922107Timo Sirainen{
c680a6b35b459045e92814778908da5a93922107Timo Sirainen struct index_mailbox_sync_context *ctx =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (struct index_mailbox_sync_context *)_ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct seq_range *range;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx->failed)
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen return FALSE;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen range = array_get(&ctx->flag_updates, &count);
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen if (ctx->flag_update_idx < count) {
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen sync_rec_r->type = MAILBOX_SYNC_TYPE_FLAGS;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen sync_rec_r->seq1 = range[ctx->flag_update_idx].seq1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sync_rec_r->seq2 = range[ctx->flag_update_idx].seq2;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->flag_update_idx++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (array_is_created(&ctx->modseq_updates)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen range = array_get(&ctx->modseq_updates, &count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx->modseq_update_idx < count) {
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen sync_rec_r->type = MAILBOX_SYNC_TYPE_MODSEQ;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen sync_rec_r->seq1 = range[ctx->modseq_update_idx].seq1;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen sync_rec_r->seq2 = range[ctx->modseq_update_idx].seq2;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen ctx->modseq_update_idx++;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return index_mailbox_sync_next_expunge(ctx, sync_rec_r);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic void
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenindex_mailbox_expunge_unseen_recent(struct index_mailbox_sync_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
40a5aeebf6b4858b93f0ddff0bf12fba769cf903Timo Sirainen struct index_mailbox *ibox = ctx->ibox;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_header *hdr;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen uint32_t seq, start_uid, uid;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen
40a5aeebf6b4858b93f0ddff0bf12fba769cf903Timo Sirainen if (!array_is_created(&ibox->recent_flags))
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* expunges array contained expunges for the messages that were already
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen visible in this view, but append+expunge would be invisible.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen recent_flags may however contain the append UID, so we'll have to
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen remove it separately */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen hdr = mail_index_get_header(ibox->view);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx->messages_count == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uid = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (ctx->messages_count <= hdr->messages_count)
3ee5f5427b36ea30a01561b35f4002232db7b061Timo Sirainen mail_index_lookup_uid(ibox->view, ctx->messages_count, &uid);
3ee5f5427b36ea30a01561b35f4002232db7b061Timo Sirainen else {
3ee5f5427b36ea30a01561b35f4002232db7b061Timo Sirainen i_assert(mail_index_view_is_inconsistent(ibox->view));
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen return;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (seq = ctx->messages_count + 1; seq <= hdr->messages_count; seq++) {
902222fb0928d1701f20a384b73f327b1d9a15ddTimo Sirainen start_uid = uid;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_index_lookup_uid(ibox->view, seq, &uid);
902222fb0928d1701f20a384b73f327b1d9a15ddTimo Sirainen if (start_uid + 1 > uid - 1)
6c2ddb9f586e6392552ddfb82ab55e57fcfc4110Timo Sirainen continue;
6c2ddb9f586e6392552ddfb82ab55e57fcfc4110Timo Sirainen
6c2ddb9f586e6392552ddfb82ab55e57fcfc4110Timo Sirainen ibox->recent_flags_count -=
6c2ddb9f586e6392552ddfb82ab55e57fcfc4110Timo Sirainen seq_range_array_remove_range(&ibox->recent_flags,
1be964ec6d835f95b4fdebf02add9265d58ad290Timo Sirainen start_uid + 1, uid - 1);
1be964ec6d835f95b4fdebf02add9265d58ad290Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen 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;
bool delayed_expunges = FALSE;
int ret = ctx->failed ? -1 : 0;
/* finish handling expunges, so we don't break when updating
recent flags */
while (index_mailbox_sync_next_expunge(ctx, &sync_rec) > 0) ;
if (ctx->sync_ctx != NULL) {
if (mail_index_view_sync_commit(&ctx->sync_ctx,
&delayed_expunges) < 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);
status_r->sync_delayed_expunges = delayed_expunges;
}
index_sync_search_results_update(ctx);
if (array_is_created(&ctx->flag_updates))
array_free(&ctx->flag_updates);
if (array_is_created(&ctx->modseq_updates))
array_free(&ctx->modseq_updates);
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;
}
enum mailbox_sync_type index_sync_type_convert(enum mail_index_sync_type type)
{
enum mailbox_sync_type ret = 0;
if ((type & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0)
ret |= MAILBOX_SYNC_TYPE_EXPUNGE;
if ((type & (MAIL_INDEX_SYNC_TYPE_FLAGS |
MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD |
MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE |
MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET)) != 0)
ret |= MAILBOX_SYNC_TYPE_FLAGS;
return ret;
}