bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING file */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "lib.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "array.h"
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#include "bsearch-insert-pos.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "ioloop.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "str.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "mail-index-modseq.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "mail-search-build.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "mailbox-search-result-private.h"
436adac819e7cbeef04af08dcc6a4f3ecd4a1d9eMartti Rannanjärvi#include "mailbox-recent-flags.h"
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen#include "index-sync-private.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "index-search-result.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "virtual-storage.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstruct virtual_add_record {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_mail_index_record rec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen time_t received_date;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen};
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstruct virtual_sync_mail {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen uint32_t vseq;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct virtual_mail_index_record vrec;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen};
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstruct virtual_sync_context {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct virtual_mailbox *mbox;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_index_sync_ctx *index_sync_ctx;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_index *index;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_index_view *sync_view;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_index_transaction *trans;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *const *kw_all;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* messages expunged within this sync */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen ARRAY_TYPE(seq_range) sync_expunges;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen ARRAY(struct virtual_add_record) all_adds;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen /* all messages in this sync, sorted by mailbox_id
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen (but unsorted inside it for now, since it doesn't matter) */
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen ARRAY(struct virtual_sync_mail) all_mails;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen uint32_t all_mails_idx, all_mails_prev_mailbox_id;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen enum mailbox_sync_flags flags;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen uint32_t uid_validity;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool ext_header_changed:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool expunge_removed:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool index_broken:1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen};
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainenstatic void virtual_sync_backend_box_deleted(struct virtual_sync_context *ctx,
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen struct virtual_backend_box *bbox);
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void virtual_sync_set_uidvalidity(struct virtual_sync_context *ctx)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen uint32_t uid_validity = ioloop_time;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_index_update_header(ctx->trans,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen offsetof(struct mail_index_header, uid_validity),
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen &uid_validity, sizeof(uid_validity), TRUE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ctx->uid_validity = uid_validity;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void virtual_sync_external_flags(struct virtual_sync_context *ctx,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct virtual_backend_box *bbox,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen uint32_t vseq, uint32_t real_uid)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen enum mail_flags flags;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *const *kw_names;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_keywords *keywords;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (!mail_set_uid(bbox->sync_mail, real_uid)) {
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen /* we may have reopened the mailbox, which could have
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen caused the mail to be expunged already. */
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen return;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* copy flags */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen flags = mail_get_flags(bbox->sync_mail);
9badddc243d1a9925586c785a838b3bd81bacc7eAki Tuomi
9badddc243d1a9925586c785a838b3bd81bacc7eAki Tuomi /* we don't need to keep recent flags here */
9badddc243d1a9925586c785a838b3bd81bacc7eAki Tuomi mail_index_update_flags(ctx->trans, vseq, MODIFY_REPLACE, flags & ~(MAIL_RECENT));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* copy keywords */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen kw_names = mail_get_keywords(bbox->sync_mail);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen keywords = mail_index_keywords_create(ctx->index, kw_names);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mail_index_update_keywords(ctx->trans, vseq, MODIFY_REPLACE, keywords);
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen mail_index_keywords_unref(&keywords);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainenstatic int virtual_sync_mail_uid_cmp(const void *p1, const void *p2)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct virtual_sync_mail *m1 = p1, *m2 = p2;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (m1->vrec.mailbox_id < m2->vrec.mailbox_id)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return -1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (m1->vrec.mailbox_id > m2->vrec.mailbox_id)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return 1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (m1->vrec.real_uid < m2->vrec.real_uid)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return -1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (m1->vrec.real_uid > m2->vrec.real_uid)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return 1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* broken */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic void
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvirtual_backend_box_sync_mail_set(struct virtual_backend_box *bbox)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct mailbox_transaction_context *trans;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (bbox->sync_mail == NULL) {
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi trans = mailbox_transaction_begin(bbox->box, 0, __func__);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen bbox->sync_mail = mail_alloc(trans, 0, NULL);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainenstatic int bbox_mailbox_id_cmp(struct virtual_backend_box *const *b1,
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen struct virtual_backend_box *const *b2)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen if ((*b1)->mailbox_id < (*b2)->mailbox_id)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return -1;
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen if ((*b1)->mailbox_id > (*b2)->mailbox_id)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return 1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainenstatic int
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainenvirtual_sync_get_backend_box(struct virtual_mailbox *mbox, const char *name,
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen struct virtual_backend_box **bbox_r)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen{
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen *bbox_r = virtual_backend_box_lookup_name(mbox, name);
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen if (*bbox_r != NULL || !mbox->sync_initialized)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return 0;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen /* another process just added a new mailbox.
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen we can't handle this currently. */
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen mbox->inconsistent = TRUE;
8f90ef65db62946aabe1969755edcdefb4eb430aTimo Sirainen mail_storage_set_error(mbox->box.storage, MAIL_ERROR_TEMP, t_strdup_printf(
8f90ef65db62946aabe1969755edcdefb4eb430aTimo Sirainen "Backend mailbox '%s' added by another session. "
8f90ef65db62946aabe1969755edcdefb4eb430aTimo Sirainen "Reopen the virtual mailbox.", name));
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return -1;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen}
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainenint virtual_mailbox_ext_header_read(struct virtual_mailbox *mbox,
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen struct mail_index_view *view,
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen bool *broken_r)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen const char *box_path = mailbox_get_path(&mbox->box);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const struct virtual_mail_index_header *ext_hdr;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const struct mail_index_header *hdr;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const struct virtual_mail_index_mailbox_record *mailboxes;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct virtual_backend_box *bbox, **bboxes;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const void *ext_data;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen size_t ext_size;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen unsigned int i, count, ext_name_offset, ext_mailbox_count;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen uint32_t prev_mailbox_id;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen int ret = 1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
504337186520df7012315687fc0f88c945775471Timo Sirainen *broken_r = FALSE;
504337186520df7012315687fc0f88c945775471Timo Sirainen
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen hdr = mail_index_get_header(view);
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen mail_index_get_header_ext(view, mbox->virtual_ext_id,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen &ext_data, &ext_size);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ext_hdr = ext_data;
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen if (mbox->sync_initialized &&
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen mbox->prev_uid_validity == hdr->uid_validity &&
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ext_size >= sizeof(*ext_hdr) &&
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen mbox->prev_change_counter == ext_hdr->change_counter) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* fully refreshed */
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen return 1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen mbox->prev_uid_validity = hdr->uid_validity;
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen if (ext_hdr == NULL ||
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen mbox->search_args_crc32 != ext_hdr->search_args_crc32) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailboxes = NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ext_name_offset = 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ext_mailbox_count = 0;
7fa9d523d96b3002620cc1ff463f1d4ad2d90129Aki Tuomi ret = 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen } else {
825b0e819a7c48a366ddca23ec78b87e8c30e9b4Aki Tuomi const void *guid_data;
825b0e819a7c48a366ddca23ec78b87e8c30e9b4Aki Tuomi size_t guid_size;
825b0e819a7c48a366ddca23ec78b87e8c30e9b4Aki Tuomi mail_index_get_header_ext(view, mbox->virtual_guid_ext_id,
825b0e819a7c48a366ddca23ec78b87e8c30e9b4Aki Tuomi &guid_data, &guid_size);
825b0e819a7c48a366ddca23ec78b87e8c30e9b4Aki Tuomi if (guid_size >= GUID_128_SIZE)
825b0e819a7c48a366ddca23ec78b87e8c30e9b4Aki Tuomi guid_128_copy(mbox->guid, guid_data);
825b0e819a7c48a366ddca23ec78b87e8c30e9b4Aki Tuomi
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen mbox->prev_change_counter = ext_hdr->change_counter;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailboxes = (const void *)(ext_hdr + 1);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ext_name_offset = sizeof(*ext_hdr) +
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ext_hdr->mailbox_count * sizeof(*mailboxes);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (ext_name_offset >= ext_size ||
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ext_hdr->mailbox_count > INT_MAX/sizeof(*mailboxes)) {
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen i_error("virtual index %s: Broken mailbox_count header",
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen box_path);
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen *broken_r = TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ext_mailbox_count = 0;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen ret = 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen } else {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ext_mailbox_count = ext_hdr->mailbox_count;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* update mailbox backends */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen prev_mailbox_id = 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen for (i = 0; i < ext_mailbox_count; i++) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (mailboxes[i].id > ext_hdr->highest_mailbox_id ||
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailboxes[i].id <= prev_mailbox_id) {
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen i_error("virtual index %s: Broken mailbox id",
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen box_path);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen break;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (mailboxes[i].name_len == 0 ||
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailboxes[i].name_len > ext_size) {
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen i_error("virtual index %s: Broken mailbox name_len",
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen box_path);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen break;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (ext_name_offset + mailboxes[i].name_len > ext_size) {
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen i_error("virtual index %s: Broken mailbox list",
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen box_path);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen break;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen T_BEGIN {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const unsigned char *nameptr;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *name;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen nameptr = CONST_PTR_OFFSET(ext_data, ext_name_offset);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen name = t_strndup(nameptr, mailboxes[i].name_len);
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen if (virtual_sync_get_backend_box(mbox, name, &bbox) < 0)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen ret = -1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen } T_END;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (bbox == NULL) {
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (ret < 0)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return -1;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen /* mailbox no longer exists. */
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen ret = 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen } else {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen bbox->mailbox_id = mailboxes[i].id;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen bbox->sync_uid_validity = mailboxes[i].uid_validity;
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen bbox->ondisk_highest_modseq =
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen bbox->sync_highest_modseq =
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen mailboxes[i].highest_modseq;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen bbox->sync_next_uid = mailboxes[i].next_uid;
9599d7ecbc84e9d33295e1e9a9be937faddce68aTimo Sirainen bbox->sync_mailbox_idx1 = i+1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ext_name_offset += mailboxes[i].name_len;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen prev_mailbox_id = mailboxes[i].id;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen if (i < ext_mailbox_count) {
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen *broken_r = TRUE;
bc7d7e41fe00f76c38d1a5194c130c983487911bTimo Sirainen mbox->ext_header_rewrite = TRUE;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen ret = 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen mbox->highest_mailbox_id = ext_hdr == NULL ? 0 :
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen ext_hdr->highest_mailbox_id;
59a236b2ed657d694ab35242614dca32be4944daAki Tuomi /* do not mark it initialized if it's broken */
59a236b2ed657d694ab35242614dca32be4944daAki Tuomi mbox->sync_initialized = !*broken_r;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* assign new mailbox IDs if any are missing */
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen bboxes = array_get_modifiable(&mbox->backend_boxes, &count);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen for (i = 0; i < count; i++) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (bboxes[i]->mailbox_id == 0) {
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen bboxes[i]->mailbox_id = ++mbox->highest_mailbox_id;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen ret = 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* sort the backend mailboxes by mailbox_id. */
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen array_sort(&mbox->backend_boxes, bbox_mailbox_id_cmp);
bc7d7e41fe00f76c38d1a5194c130c983487911bTimo Sirainen if (ret == 0)
bc7d7e41fe00f76c38d1a5194c130c983487911bTimo Sirainen mbox->ext_header_rewrite = TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return ret;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic void virtual_sync_ext_header_rewrite(struct virtual_sync_context *ctx)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct virtual_mail_index_header ext_hdr;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct virtual_mail_index_mailbox_record mailbox;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct virtual_backend_box **bboxes;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen buffer_t *buf;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const void *ext_data;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen size_t ext_size;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen unsigned int i, mailbox_pos, name_pos, count;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen bboxes = array_get_modifiable(&ctx->mbox->backend_boxes, &count);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailbox_pos = sizeof(ext_hdr);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen name_pos = mailbox_pos + sizeof(mailbox) * count;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&ext_hdr);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&mailbox);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ext_hdr.change_counter = ++ctx->mbox->prev_change_counter;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ext_hdr.mailbox_count = count;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ext_hdr.highest_mailbox_id = ctx->mbox->highest_mailbox_id;
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen ext_hdr.search_args_crc32 = ctx->mbox->search_args_crc32;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi buf = t_buffer_create(name_pos + 256);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen buffer_append(buf, &ext_hdr, sizeof(ext_hdr));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen for (i = 0; i < count; i++) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(i == 0 ||
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen bboxes[i]->mailbox_id > bboxes[i-1]->mailbox_id);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
9599d7ecbc84e9d33295e1e9a9be937faddce68aTimo Sirainen bboxes[i]->sync_mailbox_idx1 = i+1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailbox.id = bboxes[i]->mailbox_id;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailbox.name_len = strlen(bboxes[i]->name);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailbox.uid_validity = bboxes[i]->sync_uid_validity;
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen mailbox.highest_modseq = bboxes[i]->ondisk_highest_modseq;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailbox.next_uid = bboxes[i]->sync_next_uid;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen buffer_write(buf, mailbox_pos, &mailbox, sizeof(mailbox));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen buffer_write(buf, name_pos, bboxes[i]->name, mailbox.name_len);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailbox_pos += sizeof(mailbox);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen name_pos += mailbox.name_len;
4299aef7cde9dcd3dd40fdb9fd1114f939754759Aki Tuomi
4299aef7cde9dcd3dd40fdb9fd1114f939754759Aki Tuomi /* repair the value */
4299aef7cde9dcd3dd40fdb9fd1114f939754759Aki Tuomi if (ctx->mbox->highest_mailbox_id < mailbox.id)
4299aef7cde9dcd3dd40fdb9fd1114f939754759Aki Tuomi ctx->mbox->highest_mailbox_id = mailbox.id;
4299aef7cde9dcd3dd40fdb9fd1114f939754759Aki Tuomi }
4299aef7cde9dcd3dd40fdb9fd1114f939754759Aki Tuomi if (ctx->mbox->highest_mailbox_id != ext_hdr.highest_mailbox_id) {
4299aef7cde9dcd3dd40fdb9fd1114f939754759Aki Tuomi ext_hdr.highest_mailbox_id = ctx->mbox->highest_mailbox_id;
4299aef7cde9dcd3dd40fdb9fd1114f939754759Aki Tuomi buffer_write(buf, 0, &ext_hdr, sizeof(ext_hdr));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(buf->used == name_pos);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mail_index_get_header_ext(ctx->sync_view, ctx->mbox->virtual_ext_id,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen &ext_data, &ext_size);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (ext_size < name_pos) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mail_index_ext_resize(ctx->trans, ctx->mbox->virtual_ext_id,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen name_pos,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sizeof(struct virtual_mail_index_record),
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sizeof(uint32_t));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext_id,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen 0, buf->data, name_pos);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic void virtual_sync_ext_header_update(struct virtual_sync_context *ctx)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct virtual_mail_index_header ext_hdr;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (!ctx->ext_header_changed)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* we changed something - update the change counter in header */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ext_hdr.change_counter = ++ctx->mbox->prev_change_counter;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext_id,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen offsetof(struct virtual_mail_index_header, change_counter),
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen &ext_hdr.change_counter, sizeof(ext_hdr.change_counter));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainenstatic int virtual_sync_index_rec(struct virtual_sync_context *ctx,
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen const struct mail_index_sync_rec *sync_rec)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen uint32_t virtual_ext_id = ctx->mbox->virtual_ext_id;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct virtual_backend_box *bbox;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct virtual_mail_index_record *vrec;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const void *data;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen enum mail_flags flags;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_keywords *keywords;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen enum modify_type modify_type;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *kw_names[2];
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen uint32_t vseq, seq1, seq2;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen switch (sync_rec->type) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case MAIL_INDEX_SYNC_TYPE_FLAGS:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (!mail_index_lookup_seq_range(ctx->sync_view,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen sync_rec->uid1, sync_rec->uid2,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen &seq1, &seq2)) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* already expunged, nothing to do. */
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen return 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (vseq = seq1; vseq <= seq2; vseq++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_index_lookup_ext(ctx->sync_view, vseq, virtual_ext_id,
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainen &data, NULL);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen vrec = data;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen bbox = virtual_backend_box_lookup(ctx->mbox, vrec->mailbox_id);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (bbox == NULL)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen continue;
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen if (!bbox->box->opened) {
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if (virtual_backend_box_open(ctx->mbox, bbox) < 0) {
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen virtual_box_copy_error(&ctx->mbox->box,
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen bbox->box);
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen return -1;
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen }
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen } else {
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen virtual_backend_box_accessed(ctx->mbox, bbox);
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen virtual_backend_box_sync_mail_set(bbox);
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen if (!mail_set_uid(bbox->sync_mail, vrec->real_uid)) {
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen /* message is already expunged from backend mailbox. */
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen continue;
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen switch (sync_rec->type) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_expunge(bbox->sync_mail);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case MAIL_INDEX_SYNC_TYPE_FLAGS:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen flags = sync_rec->add_flags & MAIL_FLAGS_NONRECENT;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (flags != 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_update_flags(bbox->sync_mail,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen MODIFY_ADD, flags);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen flags = sync_rec->remove_flags & MAIL_FLAGS_NONRECENT;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (flags != 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_update_flags(bbox->sync_mail,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen MODIFY_REMOVE, flags);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen kw_names[0] = ctx->kw_all[sync_rec->keyword_idx];
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen kw_names[1] = NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen keywords = mailbox_keywords_create_valid(bbox->box,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen kw_names);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen modify_type = sync_rec->type ==
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD ?
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen MODIFY_ADD : MODIFY_REMOVE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_update_keywords(bbox->sync_mail,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen modify_type, keywords);
4182d8cd818e76856a5a1e25b343fe5ddf69fd8eTimo Sirainen mailbox_keywords_unref(&keywords);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen return 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainenstatic int virtual_sync_index_changes(struct virtual_sync_context *ctx)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const ARRAY_TYPE(keywords) *keywords;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct mail_index_sync_rec sync_rec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen keywords = mail_index_get_keywords(ctx->index);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen ctx->kw_all = array_count(keywords) == 0 ? NULL :
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen array_idx(keywords, 0);
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen while (mail_index_sync_next(ctx->index_sync_ctx, &sync_rec)) {
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen if (virtual_sync_index_rec(ctx, &sync_rec) < 0)
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen return -1;
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen }
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen return 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic void virtual_sync_index_finish(struct virtual_sync_context *ctx)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mailbox *box = &ctx->mbox->box;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct mail_index_header *hdr;
cff36c02dd80217d0c6615c614d5b5cc642df066Aki Tuomi struct mail_index_view *view;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen uint32_t seq1, seq2;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
cff36c02dd80217d0c6615c614d5b5cc642df066Aki Tuomi view = mail_index_transaction_open_updated_view(ctx->trans);
cff36c02dd80217d0c6615c614d5b5cc642df066Aki Tuomi
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen hdr = mail_index_get_header(ctx->sync_view);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (hdr->uid_validity != 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ctx->uid_validity = hdr->uid_validity;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen else
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen virtual_sync_set_uidvalidity(ctx);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* mark the newly seen messages as recent */
cff36c02dd80217d0c6615c614d5b5cc642df066Aki Tuomi if (mail_index_lookup_seq_range(view, hdr->first_recent_uid,
cff36c02dd80217d0c6615c614d5b5cc642df066Aki Tuomi (uint32_t)-1, &seq1, &seq2)) {
cff36c02dd80217d0c6615c614d5b5cc642df066Aki Tuomi mailbox_recent_flags_set_seqs(&ctx->mbox->box, view,
817d027593510c3ba70ad542ce0011f5f6916d1eTimo Sirainen seq1, seq2);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
cff36c02dd80217d0c6615c614d5b5cc642df066Aki Tuomi
cff36c02dd80217d0c6615c614d5b5cc642df066Aki Tuomi mail_index_view_close(&view);
cff36c02dd80217d0c6615c614d5b5cc642df066Aki Tuomi
bc7d7e41fe00f76c38d1a5194c130c983487911bTimo Sirainen if (ctx->mbox->ext_header_rewrite) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* entire mailbox list needs to be rewritten */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen virtual_sync_ext_header_rewrite(ctx);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen } else {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* update only changed parts in the header */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen virtual_sync_ext_header_update(ctx);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (box->v.sync_notify != NULL)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen box->v.sync_notify(box, 0, 0);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic int virtual_sync_backend_box_init(struct virtual_backend_box *bbox)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mailbox_transaction_context *trans;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_search_context *search_ctx;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail *mail;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_backend_uidmap uidmap;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen enum mailbox_search_result_flags result_flags;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen int ret;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi trans = mailbox_transaction_begin(bbox->box, 0, __func__);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen if (!bbox->search_args_initialized) {
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen mail_search_args_init(bbox->search_args, bbox->box, FALSE, NULL);
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen bbox->search_args_initialized = TRUE;
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen }
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen search_ctx = mailbox_search_init(trans, bbox->search_args, NULL,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen 0, NULL);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* save the result and keep it updated */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen result_flags = MAILBOX_SEARCH_RESULT_FLAG_UPDATE |
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen MAILBOX_SEARCH_RESULT_FLAG_QUEUE_SYNC;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen bbox->search_result =
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mailbox_search_result_save(search_ctx, result_flags);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* add the found UIDs to uidmap. virtual_uid gets assigned later. */
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&uidmap);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen array_clear(&bbox->uids);
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen while (mailbox_search_next(search_ctx, &mail)) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uidmap.real_uid = mail->uid;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen array_append(&bbox->uids, &uidmap, 1);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ret = mailbox_search_deinit(&search_ctx);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen (void)mailbox_transaction_commit(&trans);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return ret;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenstatic int
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenvirtual_backend_uidmap_bsearch_cmp(const uint32_t *uidp,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen const struct virtual_backend_uidmap *uidmap)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return *uidp < uidmap->real_uid ? -1 :
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen (*uidp > uidmap->real_uid ? 1 : 0);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic void
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvirtual_sync_mailbox_box_remove(struct virtual_sync_context *ctx,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_backend_box *bbox,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const ARRAY_TYPE(seq_range) *removed_uids)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const struct seq_range *uids;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_backend_uidmap *uidmap;
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen unsigned int i, src, dest, uid_count, rec_count;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uint32_t uid, vseq;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uids = array_get(removed_uids, &uid_count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (uid_count == 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* everything in removed_uids should exist in bbox->uids */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uidmap = array_get_modifiable(&bbox->uids, &rec_count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(rec_count >= uid_count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* find the first uidmap record to be removed */
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen if (!array_bsearch_insert_pos(&bbox->uids, &uids[0].seq1,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen virtual_backend_uidmap_bsearch_cmp, &src))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_unreached();
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* remove the unwanted messages */
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen dest = src;
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen for (i = 0; i < uid_count; i++) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uid = uids[i].seq1;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen while (uidmap[src].real_uid != uid) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uidmap[dest++] = uidmap[src++];
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(src < rec_count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (; uid <= uids[i].seq2; uid++, src++) {
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen i_assert(src < rec_count);
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen i_assert(uidmap[src].real_uid == uid);
781a9337941148bf1fb69bc55b205ab27fd08af0Aki Tuomi if (uidmap[src].virtual_uid == 0) {
781a9337941148bf1fb69bc55b205ab27fd08af0Aki Tuomi /* has not been assigned yet */
781a9337941148bf1fb69bc55b205ab27fd08af0Aki Tuomi continue;
781a9337941148bf1fb69bc55b205ab27fd08af0Aki Tuomi }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (mail_index_lookup_seq(ctx->sync_view,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen uidmap[src].virtual_uid,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen &vseq))
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen mail_index_expunge(ctx->trans, vseq);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
fb7dd075cf883e5e7defbc0c8fb8326e30bdccdeTimo Sirainen array_delete(&bbox->uids, dest, src - dest);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic void
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvirtual_sync_mailbox_box_add(struct virtual_sync_context *ctx,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_backend_box *bbox,
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen const ARRAY_TYPE(seq_range) *added_uids_arr)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen const struct seq_range *added_uids;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_backend_uidmap *uidmap;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_add_record rec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int i, src, dest, uid_count, add_count, rec_count;
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen uint32_t add_uid;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen added_uids = array_get(added_uids_arr, &uid_count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (uid_count == 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return;
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen add_count = seq_range_count(added_uids_arr);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* none of added_uids should exist in bbox->uids. find the position
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen of the first inserted index. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uidmap = array_get_modifiable(&bbox->uids, &rec_count);
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen if (rec_count == 0 ||
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen added_uids[0].seq1 > uidmap[rec_count-1].real_uid) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* fast path: usually messages are appended */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen dest = rec_count;
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen } else if (array_bsearch_insert_pos(&bbox->uids, &added_uids[0].seq1,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen virtual_backend_uidmap_bsearch_cmp,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen &dest))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_unreached();
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* make space for all added UIDs. */
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen if (rec_count == dest)
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen array_idx_clear(&bbox->uids, dest + add_count-1);
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen else {
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen array_copy(&bbox->uids.arr, dest + add_count,
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen &bbox->uids.arr, dest, rec_count - dest);
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uidmap = array_get_modifiable(&bbox->uids, &rec_count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen src = dest + add_count;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* add/move the UIDs to their correct positions */
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&rec);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen rec.rec.mailbox_id = bbox->mailbox_id;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (i = 0; i < uid_count; i++) {
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen add_uid = added_uids[i].seq1;
41955c400476941fa274f18b106a5922866fd780Timo Sirainen while (src < rec_count && uidmap[src].real_uid < add_uid)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uidmap[dest++] = uidmap[src++];
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen for (; add_uid <= added_uids[i].seq2; add_uid++, dest++) {
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen i_assert(dest < rec_count);
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen uidmap[dest].real_uid = add_uid;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uidmap[dest].virtual_uid = 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen if (ctx->mbox->uids_mapped) {
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen rec.rec.real_uid = add_uid;
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen array_append(&ctx->all_adds, &rec, 1);
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomistatic void
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomivirtual_sync_mailbox_box_update_flags(struct virtual_sync_context *ctx,
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi struct virtual_backend_box *bbox,
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi const ARRAY_TYPE(seq_range) *uids_arr)
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi{
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi unsigned int i, uid, vseq;
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi struct virtual_backend_uidmap *vuid;
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi struct seq_range_iter iter;
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi i = 0;
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi seq_range_array_iter_init(&iter, uids_arr);
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi while(seq_range_array_iter_nth(&iter, i++, &uid)) {
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi vuid = array_bsearch(&bbox->uids, &uid,
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi virtual_backend_uidmap_bsearch_cmp);
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi if (vuid == NULL ||
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi vuid->virtual_uid == 0 ||
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi !mail_index_lookup_seq(ctx->sync_view,
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi vuid->virtual_uid, &vseq)) {
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi /* the entry has been already removed either by
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi us or some other session. doesn't matter,
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi we don't need to update the flags.
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi it might also have not yet been assigned a uid
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi so we don't want to update the flags then either.
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi */
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi continue;
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi }
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi virtual_sync_external_flags(ctx, bbox, vseq,
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi vuid->real_uid);
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi }
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi}
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainenstatic int virtual_backend_uidmap_cmp(const struct virtual_backend_uidmap *u1,
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen const struct virtual_backend_uidmap *u2)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (u1->real_uid < u2->real_uid)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return -1;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (u1->real_uid > u2->real_uid)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return 1;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return 0;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenstatic void virtual_sync_bbox_uids_sort(struct virtual_backend_box *bbox)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* the uidmap must be sorted by real_uids */
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen array_sort(&bbox->uids, virtual_backend_uidmap_cmp);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen bbox->uids_nonsorted = FALSE;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenstatic void virtual_sync_backend_boxes_sort_uids(struct virtual_mailbox *mbox)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen struct virtual_backend_box *const *bboxes;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen unsigned int i, count;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen for (i = 0; i < count; i++) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (bboxes[i]->uids_nonsorted)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen virtual_sync_bbox_uids_sort(bboxes[i]);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainenstatic void
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainenvirtual_sync_backend_add_vmsgs_results(struct virtual_sync_context *ctx,
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen struct virtual_backend_box *bbox,
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen uint32_t real_uid,
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen struct mail_search_result *result,
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen const uint32_t vseq)
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen{
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen struct virtual_backend_uidmap uidmap;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen uint32_t vuid, seq;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen mail_index_lookup_uid(ctx->sync_view, vseq, &vuid);
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&uidmap);
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen uidmap.real_uid = real_uid;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen uidmap.virtual_uid = vuid;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen array_append(&bbox->uids, &uidmap, 1);
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen if (result == NULL)
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen ;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen else if (mail_index_lookup_seq(bbox->box->view, real_uid, &seq))
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen seq_range_array_add(&result->uids, real_uid);
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen else
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen seq_range_array_add(&result->removed_uids, real_uid);
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen}
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenstatic void
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenvirtual_sync_backend_handle_old_vmsgs(struct virtual_sync_context *ctx,
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen struct virtual_backend_box *bbox,
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen struct mail_search_result *result)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen{
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen const struct virtual_mail_index_record *vrec;
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen const struct virtual_sync_mail *sync_mail, *sync_mails;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen const void *data;
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen uint32_t i, vseq, messages;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen /* find the messages that currently exist in virtual index and add them
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen to the backend mailbox's list of uids. */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen array_clear(&bbox->uids);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen if (array_is_created(&ctx->all_mails)) {
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen i_assert(ctx->all_mails_prev_mailbox_id < bbox->mailbox_id);
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen sync_mails = array_get(&ctx->all_mails, &messages);
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen for (i = ctx->all_mails_idx; i < messages; i++) {
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen sync_mail = &sync_mails[i];
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen if (sync_mail->vrec.mailbox_id != bbox->mailbox_id) {
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen if (sync_mail->vrec.mailbox_id < bbox->mailbox_id) {
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen /* stale mailbox_id, ignore */
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen continue;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen }
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen /* Should be in mailbox_id order,
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen so skip to next box */
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen break;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen }
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen virtual_sync_backend_add_vmsgs_results(ctx, bbox,
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen sync_mail->vrec.real_uid, result, sync_mail->vseq);
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen }
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen ctx->all_mails_idx = i;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen ctx->all_mails_prev_mailbox_id = bbox->mailbox_id;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen } else {
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen /* there should be only a single backend mailbox, but in the
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen existing index there may be stale mailbox_ids that we'll
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen just skip over. */
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen messages = mail_index_view_get_messages_count(ctx->sync_view);
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen for (vseq = 1; vseq <= messages; vseq++) {
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen mail_index_lookup_ext(ctx->sync_view, vseq,
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen ctx->mbox->virtual_ext_id, &data, NULL);
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen vrec = data;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen if (vrec->mailbox_id == bbox->mailbox_id) {
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen virtual_sync_backend_add_vmsgs_results(ctx,
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen bbox, vrec->real_uid, result, vseq);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen virtual_sync_bbox_uids_sort(bbox);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenstatic int virtual_sync_backend_box_continue(struct virtual_sync_context *ctx,
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen struct virtual_backend_box *bbox)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen const enum mailbox_search_result_flags result_flags =
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen MAILBOX_SEARCH_RESULT_FLAG_UPDATE |
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen MAILBOX_SEARCH_RESULT_FLAG_QUEUE_SYNC;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen struct mail_index_view *view = bbox->box->view;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen struct mail_search_result *result;
7bdd29cf24fa3feaef27dcd28679b1cf00357541Timo Sirainen ARRAY_TYPE(seq_range) expunged_uids = ARRAY_INIT, removed_uids;
7bdd29cf24fa3feaef27dcd28679b1cf00357541Timo Sirainen ARRAY_TYPE(seq_range) added_uids, flag_update_uids;
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen uint64_t modseq, old_highest_modseq;
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen uint32_t seq, uid, old_msg_count;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* initialize the search result from all the existing messages in
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen virtual index. */
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen if (!bbox->search_args_initialized) {
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen mail_search_args_init(bbox->search_args, bbox->box, FALSE, NULL);
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen bbox->search_args_initialized = TRUE;
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen result = mailbox_search_result_alloc(bbox->box, bbox->search_args,
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen result_flags);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen mailbox_search_result_initial_done(result);
7bdd29cf24fa3feaef27dcd28679b1cf00357541Timo Sirainen i_assert(array_count(&result->removed_uids) == 0);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen virtual_sync_backend_handle_old_vmsgs(ctx, bbox, result);
7bdd29cf24fa3feaef27dcd28679b1cf00357541Timo Sirainen if (array_count(&result->removed_uids) > 0) {
7bdd29cf24fa3feaef27dcd28679b1cf00357541Timo Sirainen /* these are all expunged messages. treat them separately from
7bdd29cf24fa3feaef27dcd28679b1cf00357541Timo Sirainen "no longer matching messages" (=removed_uids) */
7bdd29cf24fa3feaef27dcd28679b1cf00357541Timo Sirainen t_array_init(&expunged_uids, array_count(&result->removed_uids));
7bdd29cf24fa3feaef27dcd28679b1cf00357541Timo Sirainen array_append_array(&expunged_uids, &result->removed_uids);
7bdd29cf24fa3feaef27dcd28679b1cf00357541Timo Sirainen array_clear(&result->removed_uids);
7bdd29cf24fa3feaef27dcd28679b1cf00357541Timo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen /* get list of changed old messages (messages already once seen by
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen virtual index), based on modseq changes. (we'll assume all modseq
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen changes are due to flag changes, which may not be true in future) */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (bbox->sync_next_uid <= 1 ||
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen !mail_index_lookup_seq_range(view, 1, bbox->sync_next_uid-1,
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen &seq, &old_msg_count))
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen old_msg_count = 0;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen old_highest_modseq = mail_index_modseq_get_highest(view);
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen t_array_init(&flag_update_uids, I_MIN(128, old_msg_count));
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen if (bbox->sync_highest_modseq < old_highest_modseq) {
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen for (seq = 1; seq <= old_msg_count; seq++) {
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen modseq = mail_index_modseq_lookup(view, seq);
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen if (modseq > bbox->sync_highest_modseq) {
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen mail_index_lookup_uid(view, seq, &uid);
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen seq_range_array_add(&flag_update_uids, uid);
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen }
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* update the search result based on the flag changes and
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen new messages */
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen if (index_search_result_update_flags(result, &flag_update_uids) < 0 ||
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index_search_result_update_appends(result, old_msg_count) < 0) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen mailbox_search_result_free(&result);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return -1;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen t_array_init(&removed_uids, 128);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen t_array_init(&added_uids, 128);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen mailbox_search_result_sync(result, &removed_uids, &added_uids);
7bdd29cf24fa3feaef27dcd28679b1cf00357541Timo Sirainen if (array_is_created(&expunged_uids)) {
7bdd29cf24fa3feaef27dcd28679b1cf00357541Timo Sirainen seq_range_array_remove_seq_range(&removed_uids, &expunged_uids);
7bdd29cf24fa3feaef27dcd28679b1cf00357541Timo Sirainen virtual_sync_mailbox_box_remove(ctx, bbox, &expunged_uids);
7bdd29cf24fa3feaef27dcd28679b1cf00357541Timo Sirainen }
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen if (ctx->expunge_removed)
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen virtual_sync_mailbox_box_remove(ctx, bbox, &removed_uids);
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen else {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen /* delayed remove */
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen seq_range_array_merge(&bbox->sync_pending_removes,
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen &removed_uids);
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen virtual_sync_mailbox_box_add(ctx, bbox, &added_uids);
5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9Aki Tuomi virtual_sync_mailbox_box_update_flags(ctx, bbox, &flag_update_uids);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen bbox->search_result = result;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return 0;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenstatic void virtual_sync_drop_existing(struct virtual_backend_box *bbox,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen ARRAY_TYPE(seq_range) *added_uids)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen ARRAY_TYPE(seq_range) drop_uids;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen const struct virtual_backend_uidmap *uidmap;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen struct seq_range_iter iter;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen unsigned int i, n = 0, count;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen uint32_t add_uid;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen seq_range_array_iter_init(&iter, added_uids);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (!seq_range_array_iter_nth(&iter, n++, &add_uid))
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen (void)array_bsearch_insert_pos(&bbox->uids, &add_uid,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen virtual_backend_uidmap_bsearch_cmp, &i);
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen uidmap = array_get_modifiable(&bbox->uids, &count);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (i == count)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen t_array_init(&drop_uids, array_count(added_uids));
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen for (; i < count; ) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (uidmap[i].real_uid < add_uid) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i++;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen continue;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (uidmap[i].real_uid == add_uid) {
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen seq_range_array_add(&drop_uids, add_uid);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i++;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (!seq_range_array_iter_nth(&iter, n++, &add_uid))
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen break;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen seq_range_array_remove_seq_range(added_uids, &drop_uids);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainenstatic void virtual_sync_drop_nonexistent(struct virtual_backend_box *bbox,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen ARRAY_TYPE(seq_range) *removed_uids)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen ARRAY_TYPE(seq_range) drop_uids;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen const struct virtual_backend_uidmap *uidmap;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen struct seq_range_iter iter;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen unsigned int i, n = 0, count;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen uint32_t remove_uid;
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen bool iter_done = FALSE;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen seq_range_array_iter_init(&iter, removed_uids);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (!seq_range_array_iter_nth(&iter, n++, &remove_uid))
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen (void)array_bsearch_insert_pos(&bbox->uids, &remove_uid,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen virtual_backend_uidmap_bsearch_cmp, &i);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen t_array_init(&drop_uids, array_count(removed_uids)); iter_done = FALSE;
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen uidmap = array_get_modifiable(&bbox->uids, &count);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen for (; i < count; ) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (uidmap[i].real_uid < remove_uid) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i++;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen continue;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen if (uidmap[i].real_uid != remove_uid)
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen seq_range_array_add(&drop_uids, remove_uid);
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen else
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i++;
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen if (!seq_range_array_iter_nth(&iter, n++, &remove_uid)) {
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen iter_done = TRUE;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen break;
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen }
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen }
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen if (!iter_done) {
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen do {
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen seq_range_array_add(&drop_uids, remove_uid);
280b771b7ec7e49caa399540dfe8faf42999a1adTimo Sirainen } while (seq_range_array_iter_nth(&iter, n++, &remove_uid));
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen seq_range_array_remove_seq_range(removed_uids, &drop_uids);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic void virtual_sync_mailbox_box_update(struct virtual_sync_context *ctx,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_backend_box *bbox)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen ARRAY_TYPE(seq_range) removed_uids, added_uids, temp_uids;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int count1, count2;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen t_array_init(&removed_uids, 128);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen t_array_init(&added_uids, 128);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mailbox_search_result_sync(bbox->search_result,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen &removed_uids, &added_uids);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (array_is_created(&bbox->sync_outside_expunges)) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen seq_range_array_remove_seq_range(&bbox->sync_outside_expunges,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen &added_uids);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen seq_range_array_merge(&removed_uids,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen &bbox->sync_outside_expunges);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen array_clear(&bbox->sync_outside_expunges);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen virtual_sync_drop_existing(bbox, &added_uids);
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen virtual_sync_drop_nonexistent(bbox, &removed_uids);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* if any of the pending removes came back, we don't want to expunge
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen them anymore. also since they already exist, remove them from
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen added_uids. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen count1 = array_count(&bbox->sync_pending_removes);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen count2 = array_count(&added_uids);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (count1 > 0 && count2 > 0) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen t_array_init(&temp_uids, count1);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen array_append_array(&temp_uids, &bbox->sync_pending_removes);
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainen if (seq_range_array_remove_seq_range(
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen &bbox->sync_pending_removes, &added_uids) > 0) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen seq_range_array_remove_seq_range(&added_uids,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen &temp_uids);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (!ctx->expunge_removed) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* delay removing messages that don't match the search
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen criteria, but don't delay removing expunged messages */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (array_count(&ctx->sync_expunges) > 0) {
41955c400476941fa274f18b106a5922866fd780Timo Sirainen seq_range_array_remove_seq_range(&bbox->sync_pending_removes,
41955c400476941fa274f18b106a5922866fd780Timo Sirainen &ctx->sync_expunges);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen seq_range_array_remove_seq_range(&removed_uids,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen &ctx->sync_expunges);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen virtual_sync_mailbox_box_remove(ctx, bbox,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen &ctx->sync_expunges);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen seq_range_array_merge(&bbox->sync_pending_removes,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen &removed_uids);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen } else if (array_count(&bbox->sync_pending_removes) > 0) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* remove all current and old */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen seq_range_array_merge(&bbox->sync_pending_removes,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen &removed_uids);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen virtual_sync_mailbox_box_remove(ctx, bbox,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen &bbox->sync_pending_removes);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen array_clear(&bbox->sync_pending_removes);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen } else {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen virtual_sync_mailbox_box_remove(ctx, bbox, &removed_uids);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen virtual_sync_mailbox_box_add(ctx, bbox, &added_uids);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic bool virtual_sync_find_seqs(struct virtual_backend_box *bbox,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const struct mailbox_sync_rec *sync_rec,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int *idx1_r,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int *idx2_r)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const struct virtual_backend_uidmap *uidmap;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int idx, count;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uint32_t uid1, uid2;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen mail_index_lookup_uid(bbox->box->view, sync_rec->seq1, &uid1);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen mail_index_lookup_uid(bbox->box->view, sync_rec->seq2, &uid2);
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen (void)array_bsearch_insert_pos(&bbox->uids, &uid1,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen virtual_backend_uidmap_bsearch_cmp,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen &idx);
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uidmap = array_get_modifiable(&bbox->uids, &count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (idx == count || uidmap[idx].real_uid > uid2)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return FALSE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen *idx1_r = idx;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen while (idx < count && uidmap[idx].real_uid <= uid2) idx++;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen *idx2_r = idx - 1;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
41955c400476941fa274f18b106a5922866fd780Timo Sirainenstatic void virtual_sync_expunge_add(struct virtual_sync_context *ctx,
41955c400476941fa274f18b106a5922866fd780Timo Sirainen struct virtual_backend_box *bbox,
41955c400476941fa274f18b106a5922866fd780Timo Sirainen const struct mailbox_sync_rec *sync_rec)
41955c400476941fa274f18b106a5922866fd780Timo Sirainen{
41955c400476941fa274f18b106a5922866fd780Timo Sirainen struct virtual_backend_uidmap *uidmap;
41955c400476941fa274f18b106a5922866fd780Timo Sirainen uint32_t uid1, uid2;
41955c400476941fa274f18b106a5922866fd780Timo Sirainen unsigned int i, idx1, count;
41955c400476941fa274f18b106a5922866fd780Timo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen mail_index_lookup_uid(bbox->box->view, sync_rec->seq1, &uid1);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen mail_index_lookup_uid(bbox->box->view, sync_rec->seq2, &uid2);
41955c400476941fa274f18b106a5922866fd780Timo Sirainen
41955c400476941fa274f18b106a5922866fd780Timo Sirainen /* remember only the expunges for messages that
41955c400476941fa274f18b106a5922866fd780Timo Sirainen already exist for this mailbox */
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen (void)array_bsearch_insert_pos(&bbox->uids, &uid1,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen virtual_backend_uidmap_bsearch_cmp,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen &idx1);
41955c400476941fa274f18b106a5922866fd780Timo Sirainen uidmap = array_get_modifiable(&bbox->uids, &count);
41955c400476941fa274f18b106a5922866fd780Timo Sirainen for (i = idx1; i < count; i++) {
41955c400476941fa274f18b106a5922866fd780Timo Sirainen if (uidmap[i].real_uid > uid2)
41955c400476941fa274f18b106a5922866fd780Timo Sirainen break;
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen seq_range_array_add(&ctx->sync_expunges, uidmap[i].real_uid);
41955c400476941fa274f18b106a5922866fd780Timo Sirainen }
41955c400476941fa274f18b106a5922866fd780Timo Sirainen}
41955c400476941fa274f18b106a5922866fd780Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic int virtual_sync_backend_box_sync(struct virtual_sync_context *ctx,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_backend_box *bbox,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen enum mailbox_sync_flags sync_flags)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct mailbox_sync_context *sync_ctx;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const struct virtual_backend_uidmap *uidmap;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct mailbox_sync_rec sync_rec;
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen struct mailbox_sync_status sync_status;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int idx1, idx2;
41955c400476941fa274f18b106a5922866fd780Timo Sirainen uint32_t vseq, vuid;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen sync_ctx = mailbox_sync_init(bbox->box, sync_flags);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen virtual_backend_box_sync_mail_set(bbox);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen while (mailbox_sync_next(sync_ctx, &sync_rec)) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen switch (sync_rec.type) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen case MAILBOX_SYNC_TYPE_EXPUNGE:
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (ctx->expunge_removed) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* no need to keep track of expunges */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen break;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
41955c400476941fa274f18b106a5922866fd780Timo Sirainen virtual_sync_expunge_add(ctx, bbox, &sync_rec);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen break;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen case MAILBOX_SYNC_TYPE_FLAGS:
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (!virtual_sync_find_seqs(bbox, &sync_rec,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen &idx1, &idx2))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen break;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uidmap = array_idx(&bbox->uids, 0);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (; idx1 <= idx2; idx1++) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vuid = uidmap[idx1].virtual_uid;
781a9337941148bf1fb69bc55b205ab27fd08af0Aki Tuomi if (vuid == 0) {
781a9337941148bf1fb69bc55b205ab27fd08af0Aki Tuomi /* has not been even assigned yet */
781a9337941148bf1fb69bc55b205ab27fd08af0Aki Tuomi continue;
781a9337941148bf1fb69bc55b205ab27fd08af0Aki Tuomi }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (!mail_index_lookup_seq(ctx->sync_view,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen vuid, &vseq)) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* expunged by another session,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen but we haven't yet updated
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen bbox->uids. */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen continue;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen virtual_sync_external_flags(ctx, bbox, vseq,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uidmap[idx1].real_uid);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen break;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen case MAILBOX_SYNC_TYPE_MODSEQ:
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen break;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen if (mailbox_sync_deinit(&sync_ctx, &sync_status) < 0) {
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen if (mailbox_get_last_mail_error(bbox->box) != MAIL_ERROR_NOTFOUND)
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen return -1;
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen /* mailbox was deleted */
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen virtual_sync_backend_box_deleted(ctx, bbox);
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen return 0;
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen }
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen return 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic void virtual_sync_backend_ext_header(struct virtual_sync_context *ctx,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct virtual_backend_box *bbox)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const unsigned int uidval_pos =
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen offsetof(struct virtual_mail_index_mailbox_record,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen uid_validity);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct mailbox_status status;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct virtual_mail_index_mailbox_record mailbox;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen unsigned int mailbox_offset;
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen uint64_t wanted_ondisk_highest_modseq;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen mailbox_get_open_status(bbox->box, STATUS_UIDVALIDITY |
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen STATUS_HIGHESTMODSEQ, &status);
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen wanted_ondisk_highest_modseq =
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen array_count(&bbox->sync_pending_removes) > 0 ? 0 :
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen status.highest_modseq;
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (bbox->sync_uid_validity == status.uidvalidity &&
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen bbox->sync_next_uid == status.uidnext &&
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen bbox->sync_highest_modseq == status.highest_modseq &&
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen bbox->ondisk_highest_modseq == wanted_ondisk_highest_modseq)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* mailbox changed - update extension header */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen bbox->sync_uid_validity = status.uidvalidity;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen bbox->sync_highest_modseq = status.highest_modseq;
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen bbox->ondisk_highest_modseq = wanted_ondisk_highest_modseq;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen bbox->sync_next_uid = status.uidnext;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
bc7d7e41fe00f76c38d1a5194c130c983487911bTimo Sirainen if (ctx->mbox->ext_header_rewrite) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* we'll rewrite the entire header later */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&mailbox);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailbox.uid_validity = bbox->sync_uid_validity;
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen mailbox.highest_modseq = bbox->ondisk_highest_modseq;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailbox.next_uid = bbox->sync_next_uid;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
9599d7ecbc84e9d33295e1e9a9be937faddce68aTimo Sirainen i_assert(bbox->sync_mailbox_idx1 > 0);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailbox_offset = sizeof(struct virtual_mail_index_header) +
9599d7ecbc84e9d33295e1e9a9be937faddce68aTimo Sirainen (bbox->sync_mailbox_idx1-1) * sizeof(mailbox);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext_id,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailbox_offset + uidval_pos,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen CONST_PTR_OFFSET(&mailbox, uidval_pos),
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sizeof(mailbox) - uidval_pos);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ctx->ext_header_changed = TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainenstatic void virtual_sync_backend_box_deleted(struct virtual_sync_context *ctx,
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen struct virtual_backend_box *bbox)
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen{
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen ARRAY_TYPE(seq_range) removed_uids;
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen const struct virtual_backend_uidmap *uidmap;
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen /* delay its full removal until the next time we open the virtual
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen mailbox. for now just treat it as if it was empty. */
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen t_array_init(&removed_uids, 128);
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen array_foreach(&bbox->uids, uidmap)
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen seq_range_array_add(&removed_uids, uidmap->real_uid);
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen virtual_sync_mailbox_box_remove(ctx, bbox, &removed_uids);
76fd7aa24526db6fd8c78a2f0b71facf76bf4b5aTimo Sirainen
76fd7aa24526db6fd8c78a2f0b71facf76bf4b5aTimo Sirainen bbox->deleted = TRUE;
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen}
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainenstatic int
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainenvirtual_try_open_and_sync_backend_box(struct virtual_sync_context *ctx,
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen struct virtual_backend_box *bbox,
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen enum mailbox_sync_flags sync_flags)
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen{
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen int ret = 0;
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen if (!bbox->box->opened)
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen ret = virtual_backend_box_open(ctx->mbox, bbox);
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen if (ret == 0)
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen ret = mailbox_sync(bbox->box, sync_flags);
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen if (ret < 0) {
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen if (mailbox_get_last_mail_error(bbox->box) != MAIL_ERROR_NOTFOUND)
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen return -1;
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen /* mailbox was deleted */
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen virtual_sync_backend_box_deleted(ctx, bbox);
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen return 0;
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen }
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen return 1;
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen}
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic int virtual_sync_backend_box(struct virtual_sync_context *ctx,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_backend_box *bbox)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen enum mailbox_sync_flags sync_flags;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct mailbox_status status;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen int ret;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
76fd7aa24526db6fd8c78a2f0b71facf76bf4b5aTimo Sirainen if (bbox->deleted)
76fd7aa24526db6fd8c78a2f0b71facf76bf4b5aTimo Sirainen return 0;
76fd7aa24526db6fd8c78a2f0b71facf76bf4b5aTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* if we already did some changes to index, commit them before
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen syncing starts. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen virtual_backend_box_sync_mail_unset(bbox);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen sync_flags = ctx->flags & (MAILBOX_SYNC_FLAG_FULL_READ |
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen MAILBOX_SYNC_FLAG_FULL_WRITE |
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen MAILBOX_SYNC_FLAG_FAST);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (bbox->search_result == NULL) {
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen /* a) first sync in this process.
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen b) we had auto-closed this backend mailbox.
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen first try to quickly check if the mailbox has changed.
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen if we can do that check from mailbox list index, we don't
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen even need to open the mailbox. */
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen i_assert(array_count(&bbox->sync_pending_removes) == 0);
1ce59b0bd89ab1b90d38fa9b9d51a92bf99bb73aTimo Sirainen if (bbox->box->opened || bbox->open_failed) {
a385399497bdb50d4dfce729ffc852b75ed46a36Timo Sirainen /* a) index already opened, refresh it
a385399497bdb50d4dfce729ffc852b75ed46a36Timo Sirainen b) delayed error handling for mailbox_open()
a385399497bdb50d4dfce729ffc852b75ed46a36Timo Sirainen that failed in virtual_notify_changes() */
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen if ((ret = virtual_try_open_and_sync_backend_box(ctx, bbox, sync_flags)) <= 0)
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen return ret;
a385399497bdb50d4dfce729ffc852b75ed46a36Timo Sirainen bbox->open_failed = FALSE;
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen if (mailbox_get_status(bbox->box, STATUS_UIDVALIDITY |
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen STATUS_UIDNEXT | STATUS_HIGHESTMODSEQ,
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen &status) < 0) {
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen if (mailbox_get_last_mail_error(bbox->box) != MAIL_ERROR_NOTFOUND)
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen return -1;
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen /* mailbox was deleted */
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen virtual_sync_backend_box_deleted(ctx, bbox);
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen return 0;
e5536fd672aa08bce4bd57ca6a844d8d97991b6fTimo Sirainen }
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen if (status.uidvalidity == bbox->sync_uid_validity &&
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen status.uidnext == bbox->sync_next_uid &&
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen status.highest_modseq == bbox->sync_highest_modseq) {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen /* mailbox hasn't changed since we last opened it,
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen skip it for now.
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen we'll still need to create the bbox->uids mapping
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen using the current index. */
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen if (array_count(&bbox->uids) == 0)
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen virtual_sync_backend_handle_old_vmsgs(ctx, bbox, NULL);
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen return 0;
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen }
1ce59b0bd89ab1b90d38fa9b9d51a92bf99bb73aTimo Sirainen if (!bbox->box->opened) {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen /* first time we're opening the index */
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen if ((ret = virtual_try_open_and_sync_backend_box(ctx, bbox, sync_flags)) <= 0)
5b7ff90a6c078b07406bce434c719017a0f51825Timo Sirainen return ret;
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen virtual_backend_box_sync_mail_set(bbox);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (status.uidvalidity != bbox->sync_uid_validity) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* UID validity changed since last sync (or this is
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen the first sync), do a full search */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ret = virtual_sync_backend_box_init(bbox);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen } else {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* build the initial search using the saved modseq. */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ret = virtual_sync_backend_box_continue(ctx, bbox);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen i_assert(bbox->search_result != NULL || ret < 0);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen } else {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* sync using the existing search result */
1ce59b0bd89ab1b90d38fa9b9d51a92bf99bb73aTimo Sirainen i_assert(bbox->box->opened);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_array_init(&ctx->sync_expunges, 32);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen ret = virtual_sync_backend_box_sync(ctx, bbox, sync_flags);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (ret == 0) T_BEGIN {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen virtual_sync_mailbox_box_update(ctx, bbox);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen } T_END;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen array_free(&ctx->sync_expunges);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen virtual_sync_backend_ext_header(ctx, bbox);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return ret;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic void virtual_sync_backend_map_uids(struct virtual_sync_context *ctx)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uint32_t virtual_ext_id = ctx->mbox->virtual_ext_id;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_sync_mail *vmails;
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen struct virtual_backend_box *bbox;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_backend_uidmap *uidmap = NULL;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_add_record add_rec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const struct virtual_mail_index_record *vrec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const void *data;
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen uint32_t i, vseq, vuid, messages;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int j = 0, uidmap_count = 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen messages = mail_index_view_get_messages_count(ctx->sync_view);
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen if (messages == 0)
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen return;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* sort the messages in current view by their backend mailbox and
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen real UID */
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen vmails = i_new(struct virtual_sync_mail, messages);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (vseq = 1; vseq <= messages; vseq++) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mail_index_lookup_ext(ctx->sync_view, vseq, virtual_ext_id,
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainen &data, NULL);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vrec = data;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vmails[vseq-1].vseq = vseq;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vmails[vseq-1].vrec = *vrec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen qsort(vmails, messages, sizeof(*vmails), virtual_sync_mail_uid_cmp);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* create real mailbox uid -> virtual uid mapping and expunge
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen messages no longer matching the search rule */
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&add_rec);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen bbox = NULL;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (i = 0; i < messages; i++) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vseq = vmails[i].vseq;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vrec = &vmails[i].vrec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (bbox == NULL || bbox->mailbox_id != vrec->mailbox_id) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* add the rest of the newly seen messages */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (; j < uidmap_count; j++) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen add_rec.rec.real_uid = uidmap[j].real_uid;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen array_append(&ctx->all_adds, &add_rec, 1);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen bbox = virtual_backend_box_lookup(ctx->mbox,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vrec->mailbox_id);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (bbox == NULL) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* the entire mailbox is lost */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mail_index_expunge(ctx->trans, vseq);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen continue;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uidmap = array_get_modifiable(&bbox->uids,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen &uidmap_count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen j = 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen add_rec.rec.mailbox_id = bbox->mailbox_id;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen bbox->sync_seen = TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mail_index_lookup_uid(ctx->sync_view, vseq, &vuid);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* if virtual record doesn't exist in uidmap, it's expunged */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (; j < uidmap_count; j++) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (uidmap[j].real_uid >= vrec->real_uid)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen break;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* newly seen message */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen add_rec.rec.real_uid = uidmap[j].real_uid;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen array_append(&ctx->all_adds, &add_rec, 1);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (j == uidmap_count || uidmap[j].real_uid != vrec->real_uid)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mail_index_expunge(ctx->trans, vseq);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen else {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* exists - update uidmap and flags */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uidmap[j++].virtual_uid = vuid;
96d85fb3606d13a38dac1b2def55eff414b2b31eTimo Sirainen if (bbox->search_result == NULL) {
96d85fb3606d13a38dac1b2def55eff414b2b31eTimo Sirainen /* mailbox is completely unchanged since last
96d85fb3606d13a38dac1b2def55eff414b2b31eTimo Sirainen sync - no need to sync flags */
96d85fb3606d13a38dac1b2def55eff414b2b31eTimo Sirainen } else {
96d85fb3606d13a38dac1b2def55eff414b2b31eTimo Sirainen virtual_sync_external_flags(ctx, bbox, vseq,
96d85fb3606d13a38dac1b2def55eff414b2b31eTimo Sirainen vrec->real_uid);
96d85fb3606d13a38dac1b2def55eff414b2b31eTimo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_free(vmails);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
2b9fd042e701cfe7d79c4294a5ab401d6ec9ce18Timo Sirainen /* finish adding messages to the last mailbox */
2b9fd042e701cfe7d79c4294a5ab401d6ec9ce18Timo Sirainen for (; j < uidmap_count; j++) {
2b9fd042e701cfe7d79c4294a5ab401d6ec9ce18Timo Sirainen add_rec.rec.real_uid = uidmap[j].real_uid;
2b9fd042e701cfe7d79c4294a5ab401d6ec9ce18Timo Sirainen array_append(&ctx->all_adds, &add_rec, 1);
2b9fd042e701cfe7d79c4294a5ab401d6ec9ce18Timo Sirainen }
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen}
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainenstatic void virtual_sync_new_backend_boxes(struct virtual_sync_context *ctx)
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen{
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen struct virtual_backend_box *const *bboxes;
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen struct virtual_add_record add_rec;
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen struct virtual_backend_uidmap *uidmap;
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen unsigned int i, j, count, uidmap_count;
2b9fd042e701cfe7d79c4294a5ab401d6ec9ce18Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* if there are any mailboxes we didn't yet sync, add new messages in
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen them */
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&add_rec);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen bboxes = array_get(&ctx->mbox->backend_boxes, &count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (i = 0; i < count; i++) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (bboxes[i]->sync_seen)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen continue;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen add_rec.rec.mailbox_id = bboxes[i]->mailbox_id;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen uidmap = array_get_modifiable(&bboxes[i]->uids, &uidmap_count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (j = 0; j < uidmap_count; j++) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen add_rec.rec.real_uid = uidmap[j].real_uid;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen array_append(&ctx->all_adds, &add_rec, 1);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainenstatic int virtual_add_record_cmp(const struct virtual_add_record *add1,
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen const struct virtual_add_record *add2)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (add1->received_date < add2->received_date)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return -1;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (add1->received_date > add2->received_date)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return 1;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* if they're in same mailbox, we can order them correctly by the UID.
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if they're in different mailboxes, ordering by UID doesn't really
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen help but it doesn't really harm either. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (add1->rec.real_uid < add2->rec.real_uid)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return -1;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (add1->rec.real_uid > add2->rec.real_uid)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return 1;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* two messages in different mailboxes have the same received date
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen and UID. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainenstatic int virtual_sync_backend_sort_new(struct virtual_sync_context *ctx)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_backend_box *bbox;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_add_record *adds;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const struct virtual_mail_index_record *vrec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int i, count;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* get all messages' received dates */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen adds = array_get_modifiable(&ctx->all_adds, &count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (bbox = NULL, i = 0; i < count; i++) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vrec = &adds[i].rec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (bbox == NULL || bbox->mailbox_id != vrec->mailbox_id) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen bbox = virtual_backend_box_lookup(ctx->mbox,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vrec->mailbox_id);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if (!bbox->box->opened &&
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen virtual_backend_box_open(ctx->mbox, bbox) < 0)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen return -1;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen virtual_backend_box_sync_mail_set(bbox);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if (!mail_set_uid(bbox->sync_mail, vrec->real_uid)) {
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen /* we may have reopened the mailbox, which could have
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen caused the mail to be expunged already. */
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen adds[i].received_date = 0;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen } else if (mail_get_received_date(bbox->sync_mail,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen &adds[i].received_date) < 0) {
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if (!bbox->sync_mail->expunged)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen return -1;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen /* expunged already, just add it somewhere */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen adds[i].received_date = 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen array_sort(&ctx->all_adds, virtual_add_record_cmp);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen return 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainenstatic int virtual_sync_backend_add_new(struct virtual_sync_context *ctx)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uint32_t virtual_ext_id = ctx->mbox->virtual_ext_id;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_add_record *adds;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_backend_box *bbox;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct virtual_backend_uidmap *uidmap;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen const struct mail_index_header *hdr;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const struct virtual_mail_index_record *vrec;
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen unsigned int i, count, idx;
e5601cd11edce275b4c423523bd00ee3e4eeae42Timo Sirainen ARRAY_TYPE(seq_range) saved_uids;
e5601cd11edce275b4c423523bd00ee3e4eeae42Timo Sirainen uint32_t vseq, first_uid;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen hdr = mail_index_get_header(ctx->sync_view);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen adds = array_get_modifiable(&ctx->all_adds, &count);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (count == 0) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen ctx->mbox->sync_virtual_next_uid = hdr->next_uid;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen return 0;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (adds[0].rec.mailbox_id == adds[count-1].rec.mailbox_id) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* all messages are from a single mailbox. add them in
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen the same order. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen } else {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* sort new messages by received date to get the add order */
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if (virtual_sync_backend_sort_new(ctx) < 0)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen return -1;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (bbox = NULL, i = 0; i < count; i++) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vrec = &adds[i].rec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (bbox == NULL || bbox->mailbox_id != vrec->mailbox_id) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen bbox = virtual_backend_box_lookup(ctx->mbox,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vrec->mailbox_id);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if (!bbox->box->opened &&
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen virtual_backend_box_open(ctx->mbox, bbox) < 0)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen return -1;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen virtual_backend_box_sync_mail_set(bbox);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mail_index_append(ctx->trans, 0, &vseq);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mail_index_update_ext(ctx->trans, vseq, virtual_ext_id,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vrec, NULL);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen virtual_sync_external_flags(ctx, bbox, vseq, vrec->real_uid);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* assign UIDs to new messages */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen first_uid = hdr->next_uid;
e5601cd11edce275b4c423523bd00ee3e4eeae42Timo Sirainen t_array_init(&saved_uids, 1);
e5601cd11edce275b4c423523bd00ee3e4eeae42Timo Sirainen mail_index_append_finish_uids(ctx->trans, first_uid, &saved_uids);
e5601cd11edce275b4c423523bd00ee3e4eeae42Timo Sirainen i_assert(seq_range_count(&saved_uids) == count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* update virtual UIDs in uidmap */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (bbox = NULL, i = 0; i < count; i++) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vrec = &adds[i].rec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (bbox == NULL || bbox->mailbox_id != vrec->mailbox_id) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen bbox = virtual_backend_box_lookup(ctx->mbox,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vrec->mailbox_id);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen if (!array_bsearch_insert_pos(&bbox->uids, &vrec->real_uid,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen virtual_backend_uidmap_bsearch_cmp,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen &idx))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_unreached();
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen uidmap = array_idx_modifiable(&bbox->uids, idx);
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen i_assert(uidmap->virtual_uid == 0);
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen uidmap->virtual_uid = first_uid + i;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen ctx->mbox->sync_virtual_next_uid = first_uid + i;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen return 0;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainenstatic int
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenvirtual_sync_apply_existing_appends(struct virtual_sync_context *ctx)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen uint32_t virtual_ext_id = ctx->mbox->virtual_ext_id;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen struct virtual_backend_box *bbox = NULL;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen const struct mail_index_header *hdr;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen const struct virtual_mail_index_record *vrec;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen struct virtual_backend_uidmap uidmap;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen const void *data;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen uint32_t seq, seq2;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (!ctx->mbox->uids_mapped)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return 0;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen hdr = mail_index_get_header(ctx->sync_view);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (ctx->mbox->sync_virtual_next_uid >= hdr->next_uid)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return 0;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* another process added messages to virtual index. get backend boxes'
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen uid lists up-to-date by adding the new messages there. */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (!mail_index_lookup_seq_range(ctx->sync_view,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen ctx->mbox->sync_virtual_next_uid,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen (uint32_t)-1, &seq, &seq2))
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return 0;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&uidmap);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen for (; seq <= seq2; seq++) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen mail_index_lookup_ext(ctx->sync_view, seq, virtual_ext_id,
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainen &data, NULL);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen vrec = data;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen uidmap.real_uid = vrec->real_uid;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen mail_index_lookup_uid(ctx->sync_view, seq, &uidmap.virtual_uid);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (bbox == NULL || bbox->mailbox_id != vrec->mailbox_id) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen bbox = virtual_backend_box_lookup(ctx->mbox,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen vrec->mailbox_id);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (bbox == NULL) {
fc80e0a7e5ce4376b40cc635ce5c3d88099c95b6Aki Tuomi mail_index_expunge(ctx->trans, seq);
fc80e0a7e5ce4376b40cc635ce5c3d88099c95b6Aki Tuomi continue;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen array_append(&bbox->uids, &uidmap, 1);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen bbox->uids_nonsorted = TRUE;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen virtual_sync_backend_boxes_sort_uids(ctx->mbox);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return 0;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenstatic void
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenvirtual_sync_apply_existing_expunges(struct virtual_mailbox *mbox,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen struct mailbox_sync_context *sync_ctx)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen struct index_mailbox_sync_context *isync_ctx =
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen (struct index_mailbox_sync_context *)sync_ctx;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen struct virtual_backend_box *bbox = NULL;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen struct seq_range_iter iter;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen const struct virtual_mail_index_record *vrec;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen const void *data;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen unsigned int n = 0;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen uint32_t seq;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (isync_ctx->expunges == NULL)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen seq_range_array_iter_init(&iter, isync_ctx->expunges);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen while (seq_range_array_iter_nth(&iter, n++, &seq)) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_index_lookup_ext(mbox->box.view, seq,
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainen mbox->virtual_ext_id, &data, NULL);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen vrec = data;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (bbox == NULL || bbox->mailbox_id != vrec->mailbox_id) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen bbox = virtual_backend_box_lookup(mbox,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen vrec->mailbox_id);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (!array_is_created(&bbox->sync_outside_expunges))
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_array_init(&bbox->sync_outside_expunges, 32);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen seq_range_array_add(&bbox->sync_outside_expunges,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen vrec->real_uid);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainenstatic int virtual_sync_mail_mailbox_cmp(const struct virtual_sync_mail *m1,
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen const struct virtual_sync_mail *m2)
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen{
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen if (m1->vrec.mailbox_id < m2->vrec.mailbox_id)
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen return -1;
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen if (m1->vrec.mailbox_id > m2->vrec.mailbox_id)
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen return 1;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen return 0;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen}
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainenstatic void virtual_sync_bboxes_get_mails(struct virtual_sync_context *ctx)
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen{
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen uint32_t messages, vseq;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen const void *mail_data;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen const struct virtual_mail_index_record *vrec;
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen struct virtual_sync_mail *sync_mail;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen messages = mail_index_view_get_messages_count(ctx->sync_view);
66b9c9afe76f7bad6d2759d4113c4064ba081f7aTimo Sirainen i_array_init(&ctx->all_mails, messages);
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen for (vseq = 1; vseq <= messages; vseq++) {
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen mail_index_lookup_ext(ctx->sync_view, vseq,
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen ctx->mbox->virtual_ext_id, &mail_data, NULL);
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen vrec = mail_data;
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen sync_mail = array_append_space(&ctx->all_mails);
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen sync_mail->vseq = vseq;
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen sync_mail->vrec = *vrec;
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen }
7fc0ca6c1f664de6506afa816200d115f9f80391Timo Sirainen array_sort(&ctx->all_mails, virtual_sync_mail_mailbox_cmp);
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen}
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic int virtual_sync_backend_boxes(struct virtual_sync_context *ctx)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct virtual_backend_box *const *bboxes;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned int i, count;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen int ret;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (virtual_sync_apply_existing_appends(ctx) < 0)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return -1;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_array_init(&ctx->all_adds, 128);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen bboxes = array_get(&ctx->mbox->backend_boxes, &count);
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen /* we have different optimizations depending on whether the virtual
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen mailbox consists of multiple backend boxes or just one */
66b9c9afe76f7bad6d2759d4113c4064ba081f7aTimo Sirainen if (count > 1)
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen virtual_sync_bboxes_get_mails(ctx);
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (i = 0; i < count; i++) {
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen if (virtual_sync_backend_box(ctx, bboxes[i]) < 0) {
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen /* backend failed, copy the error */
d22301419109ed4a38351715e6760011421dadecTimo Sirainen virtual_box_copy_error(&ctx->mbox->box,
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen bboxes[i]->box);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return -1;
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (!ctx->mbox->uids_mapped) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* initial sync: assign virtual UIDs to existing messages and
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen sync all flags */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen ctx->mbox->uids_mapped = TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen virtual_sync_backend_map_uids(ctx);
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen virtual_sync_new_backend_boxes(ctx);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen ret = virtual_sync_backend_add_new(ctx);
a5a4433751bb3dce9c870ea95e1b69efe697d417Timo Sirainen#ifdef DEBUG
a5a4433751bb3dce9c870ea95e1b69efe697d417Timo Sirainen for (i = 0; i < count; i++) {
a5a4433751bb3dce9c870ea95e1b69efe697d417Timo Sirainen const struct virtual_backend_uidmap *uidmap;
a5a4433751bb3dce9c870ea95e1b69efe697d417Timo Sirainen
a5a4433751bb3dce9c870ea95e1b69efe697d417Timo Sirainen array_foreach(&bboxes[i]->uids, uidmap)
a5a4433751bb3dce9c870ea95e1b69efe697d417Timo Sirainen i_assert(uidmap->virtual_uid > 0);
a5a4433751bb3dce9c870ea95e1b69efe697d417Timo Sirainen }
a5a4433751bb3dce9c870ea95e1b69efe697d417Timo Sirainen#endif
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen array_free(&ctx->all_adds);
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen if (array_is_created(&ctx->all_mails))
5948e3e120c5dcaf0aeb44405566381045fa82d6Timo Sirainen array_free(&ctx->all_mails);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen return ret;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void virtual_sync_backend_boxes_finish(struct virtual_sync_context *ctx)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct virtual_backend_box *const *bboxes;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned int i, count;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen bboxes = array_get(&ctx->mbox->backend_boxes, &count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (i = 0; i < count; i++)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen virtual_backend_box_sync_mail_unset(bboxes[i]);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic int virtual_sync_finish(struct virtual_sync_context *ctx, bool success)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen int ret = success ? 0 : -1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen virtual_sync_backend_boxes_finish(ctx);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (success) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (mail_index_sync_commit(&ctx->index_sync_ctx) < 0) {
1f1ee8db68d9ae1604350801cd8dc33ebe29fe8aTimo Sirainen mailbox_set_index_error(&ctx->mbox->box);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ret = -1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
bc7d7e41fe00f76c38d1a5194c130c983487911bTimo Sirainen ctx->mbox->ext_header_rewrite = FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } else {
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen if (ctx->index_broken) {
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen /* make sure we don't complain about the same errors
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen over and over again. */
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen if (mail_index_unlink(ctx->index) < 0) {
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen i_error("virtual index %s: Failed to unlink() "
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen "broken indexes: %m",
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen mailbox_get_path(&ctx->mbox->box));
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen }
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_index_sync_rollback(&ctx->index_sync_ctx);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_free(ctx);
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen return ret;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic int virtual_sync(struct virtual_mailbox *mbox,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen enum mailbox_sync_flags flags)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct virtual_sync_context *ctx;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen enum mail_index_sync_flags index_sync_flags;
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen bool broken;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen int ret;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ctx = i_new(struct virtual_sync_context, 1);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ctx->mbox = mbox;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ctx->flags = flags;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ctx->index = mbox->box.index;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* Removed messages are expunged when
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen a) EXPUNGE is used
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen b) Mailbox is being opened (FIX_INCONSISTENT is set) */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ctx->expunge_removed =
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen (ctx->flags & (MAILBOX_SYNC_FLAG_EXPUNGE |
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen MAILBOX_SYNC_FLAG_FIX_INCONSISTENT)) != 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index_sync_flags = MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY |
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen MAIL_INDEX_SYNC_FLAG_AVOID_FLAG_UPDATES;
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen if ((mbox->box.flags & MAILBOX_FLAG_DROP_RECENT) != 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index_sync_flags |= MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ret = mail_index_sync_begin(ctx->index, &ctx->index_sync_ctx,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen &ctx->sync_view, &ctx->trans,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index_sync_flags);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (ret <= 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (ret < 0)
1f1ee8db68d9ae1604350801cd8dc33ebe29fe8aTimo Sirainen mailbox_set_index_error(&mbox->box);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_free(ctx);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return ret;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen ret = virtual_mailbox_ext_header_read(mbox, ctx->sync_view, &broken);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (ret < 0)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return virtual_sync_finish(ctx, FALSE);
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen if (broken)
d85a1a9d9af4a36ded4d30cb277905c807de2ec5Timo Sirainen ctx->index_broken = TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* apply changes from virtual index to backend mailboxes */
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen if (virtual_sync_index_changes(ctx) < 0)
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen return virtual_sync_finish(ctx, FALSE);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* update list of UIDs in backend mailboxes */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (virtual_sync_backend_boxes(ctx) < 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return virtual_sync_finish(ctx, FALSE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen virtual_sync_index_finish(ctx);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return virtual_sync_finish(ctx, TRUE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstruct mailbox_sync_context *
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvirtual_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen struct mailbox_sync_context *sync_ctx;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen int ret = 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (!box->opened) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (mailbox_open(box) < 0)
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen ret = -1;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (index_mailbox_want_full_sync(&mbox->box, flags) && ret == 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ret = virtual_sync(mbox, flags);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen sync_ctx = index_mailbox_sync_init(box, flags, ret < 0);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen virtual_sync_apply_existing_expunges(mbox, sync_ctx);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return sync_ctx;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}