bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen#include "lib.h"
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen#include "array.h"
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen#include "index-storage.h"
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen#include "index-sync-changes.h"
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainenstruct index_sync_changes_context {
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen struct mail_index_sync_ctx *index_sync_ctx;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen struct mail_index_view *sync_view;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen struct mail_index_transaction *sync_trans;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen ARRAY(struct mail_index_sync_rec) syncs;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen struct mail_index_sync_rec sync_rec;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen bool dirty_flag_updates;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen};
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainenstruct index_sync_changes_context *
d22301419109ed4a38351715e6760011421dadecTimo Sirainenindex_sync_changes_init(struct mail_index_sync_ctx *index_sync_ctx,
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen struct mail_index_view *sync_view,
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen struct mail_index_transaction *sync_trans,
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen bool dirty_flag_updates)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen{
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen struct index_sync_changes_context *ctx;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen ctx = i_new(struct index_sync_changes_context, 1);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen ctx->index_sync_ctx = index_sync_ctx;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen ctx->sync_view = sync_view;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen ctx->sync_trans = sync_trans;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen ctx->dirty_flag_updates = dirty_flag_updates;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen i_array_init(&ctx->syncs, 16);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen return ctx;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen}
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainenvoid index_sync_changes_deinit(struct index_sync_changes_context **_ctx)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen{
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen struct index_sync_changes_context *ctx = *_ctx;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen *_ctx = NULL;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen array_free(&ctx->syncs);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen i_free(ctx);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen}
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainenvoid index_sync_changes_reset(struct index_sync_changes_context *ctx)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen{
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen array_clear(&ctx->syncs);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&ctx->sync_rec);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen}
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainenvoid index_sync_changes_delete_to(struct index_sync_changes_context *ctx,
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen uint32_t last_uid)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen{
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen struct mail_index_sync_rec *syncs;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen unsigned int src, dest, count;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen syncs = array_get_modifiable(&ctx->syncs, &count);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen for (src = dest = 0; src < count; src++) {
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen i_assert(last_uid >= syncs[src].uid1);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen if (last_uid <= syncs[src].uid2) {
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen /* keep it */
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen if (src != dest)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen syncs[dest] = syncs[src];
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen dest++;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen array_delete(&ctx->syncs, dest, count - dest);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen}
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainenstatic bool
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainenindex_sync_changes_have_expunges(struct index_sync_changes_context *ctx,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen unsigned int count,
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen guid_128_t expunged_guid_128_r)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen{
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen const struct mail_index_sync_rec *syncs;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen unsigned int i;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen syncs = array_idx(&ctx->syncs, 0);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen for (i = 0; i < count; i++) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (syncs[i].type == MAIL_INDEX_SYNC_TYPE_EXPUNGE) {
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen memcpy(expunged_guid_128_r, syncs[i].guid_128,
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen GUID_128_SIZE);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen return TRUE;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen return FALSE;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen}
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainenvoid index_sync_changes_read(struct index_sync_changes_context *ctx,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen uint32_t uid, bool *sync_expunge_r,
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen guid_128_t expunged_guid_128_r)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen{
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen struct mail_index_sync_rec *sync_rec = &ctx->sync_rec;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen uint32_t seq1, seq2;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen unsigned int orig_count;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen *sync_expunge_r = FALSE;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen index_sync_changes_delete_to(ctx, uid);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen orig_count = array_count(&ctx->syncs);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen while (uid >= sync_rec->uid1) {
7c332266561b8e6562a9151e6af1ed3cd6fb79d6Timo Sirainen if (uid <= sync_rec->uid2) {
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen array_append(&ctx->syncs, sync_rec, 1);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (sync_rec->type == MAIL_INDEX_SYNC_TYPE_EXPUNGE) {
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen *sync_expunge_r = TRUE;
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen memcpy(expunged_guid_128_r, sync_rec->guid_128,
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen GUID_128_SIZE);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen if (!mail_index_sync_next(ctx->index_sync_ctx, sync_rec)) {
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(sync_rec);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen break;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen switch (sync_rec->type) {
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen break;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen case MAIL_INDEX_SYNC_TYPE_FLAGS:
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen if (!ctx->dirty_flag_updates)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen break;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen /* mark the changes as dirty */
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen (void)mail_index_lookup_seq_range(ctx->sync_view,
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen sync_rec->uid1,
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen sync_rec->uid2,
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen &seq1, &seq2);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(sync_rec);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen if (seq1 == 0)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen break;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen mail_index_update_flags_range(ctx->sync_trans,
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen seq1, seq2, MODIFY_ADD,
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen (enum mail_flags)MAIL_INDEX_MAIL_FLAG_DIRTY);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen break;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen if (!*sync_expunge_r && orig_count > 0) {
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen *sync_expunge_r =
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen index_sync_changes_have_expunges(ctx, orig_count,
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen expunged_guid_128_r);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen}
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainenbool index_sync_changes_have(struct index_sync_changes_context *ctx)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen{
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen return array_count(&ctx->syncs) > 0;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen}
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainenuint32_t
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainenindex_sync_changes_get_next_uid(struct index_sync_changes_context *ctx)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen{
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen return ctx->sync_rec.uid1;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen}
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainenvoid index_sync_changes_apply(struct index_sync_changes_context *ctx,
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen pool_t pool, uint8_t *flags,
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen ARRAY_TYPE(keyword_indexes) *keywords,
389e0ad41d4dd6acf50f855ecd5f0651082c9f31Timo Sirainen enum mail_index_sync_type *sync_type_r)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen{
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen const struct mail_index_sync_rec *syncs;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen unsigned int i, count;
65e42545a6ac907687b8e3b949e0e58af79a472eTimo Sirainen enum mail_index_sync_type sync_type = 0;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen syncs = array_get(&ctx->syncs, &count);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen for (i = 0; i < count; i++) {
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen switch (syncs[i].type) {
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen case MAIL_INDEX_SYNC_TYPE_FLAGS:
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen mail_index_sync_flags_apply(&syncs[i], flags);
389e0ad41d4dd6acf50f855ecd5f0651082c9f31Timo Sirainen sync_type |= MAIL_INDEX_SYNC_TYPE_FLAGS;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen break;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen if (!array_is_created(keywords)) {
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen /* no existing keywords */
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen if (syncs[i].type !=
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen break;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen /* adding, create the array */
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen p_array_init(keywords, pool,
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen I_MIN(10, count - i));
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen if (mail_index_sync_keywords_apply(&syncs[i], keywords))
389e0ad41d4dd6acf50f855ecd5f0651082c9f31Timo Sirainen sync_type |= syncs[i].type;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen break;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen default:
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen break;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen *sync_type_r = sync_type;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen}