virtual-sync.c revision 5fe2339f8ad2698f0ea7c87a968c8ed2b853bad9
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2008-2017 Dovecot authors, see the included COPYING file */
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen const char *const *kw_all;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen /* messages expunged within this sync */
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen /* all messages in this sync, sorted by mailbox_id
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen (but unsorted inside it for now, since it doesn't matter) */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen uint32_t all_mails_idx, all_mails_prev_mailbox_id;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainenstatic void virtual_sync_backend_box_deleted(struct virtual_sync_context *ctx,
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainenstatic void virtual_sync_set_uidvalidity(struct virtual_sync_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen offsetof(struct mail_index_header, uid_validity),
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainenstatic void virtual_sync_external_flags(struct virtual_sync_context *ctx,
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen const char *const *kw_names;
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen if (!mail_set_uid(bbox->sync_mail, real_uid)) {
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen /* we may have reopened the mailbox, which could have
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen caused the mail to be expunged already. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* copy flags */
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen /* we don't need to keep recent flags here */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_update_flags(ctx->trans, vseq, MODIFY_REPLACE, flags & ~(MAIL_RECENT));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* copy keywords */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen kw_names = mail_get_keywords(bbox->sync_mail);
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen keywords = mail_index_keywords_create(ctx->index, kw_names);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen mail_index_update_keywords(ctx->trans, vseq, MODIFY_REPLACE, keywords);
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainenstatic int virtual_sync_mail_uid_cmp(const void *p1, const void *p2)
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen const struct virtual_sync_mail *m1 = p1, *m2 = p2;
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen if (m1->vrec.mailbox_id < m2->vrec.mailbox_id)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (m1->vrec.mailbox_id > m2->vrec.mailbox_id)
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainenvirtual_backend_box_sync_mail_set(struct virtual_backend_box *bbox)
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen trans = mailbox_transaction_begin(bbox->box, 0);
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainenstatic int bbox_mailbox_id_cmp(struct virtual_backend_box *const *b1,
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainenvirtual_sync_get_backend_box(struct virtual_mailbox *mbox, const char *name,
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen *bbox_r = virtual_backend_box_lookup_name(mbox, name);
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen if (*bbox_r != NULL || !mbox->sync_initialized)
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen /* another process just added a new mailbox.
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen we can't handle this currently. */
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen mail_storage_set_error(mbox->box.storage, MAIL_ERROR_TEMP, t_strdup_printf(
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen "Backend mailbox '%s' added by another session. "
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainenint virtual_mailbox_ext_header_read(struct virtual_mailbox *mbox,
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen const char *box_path = mailbox_get_path(&mbox->box);
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen const struct virtual_mail_index_header *ext_hdr;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen const struct virtual_mail_index_mailbox_record *mailboxes;
faee566824fe3567c8beacf097f9dcfc0d3761b7Timo Sirainen unsigned int i, count, ext_name_offset, ext_mailbox_count;
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen mail_index_get_header_ext(view, mbox->virtual_ext_id,
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen mbox->prev_uid_validity == hdr->uid_validity &&
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen mbox->prev_change_counter == ext_hdr->change_counter) {
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen /* fully refreshed */
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen mbox->search_args_crc32 != ext_hdr->search_args_crc32) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen mail_index_get_header_ext(view, mbox->virtual_guid_ext_id,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen mbox->prev_change_counter = ext_hdr->change_counter;
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen ext_hdr->mailbox_count > INT_MAX/sizeof(*mailboxes)) {
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen i_error("virtual index %s: Broken mailbox_count header",
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* update mailbox backends */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen for (i = 0; i < ext_mailbox_count; i++) {
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (mailboxes[i].id > ext_hdr->highest_mailbox_id ||
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen i_error("virtual index %s: Broken mailbox id",
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen i_error("virtual index %s: Broken mailbox name_len",
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (ext_name_offset + mailboxes[i].name_len > ext_size) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen i_error("virtual index %s: Broken mailbox list",
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen const unsigned char *nameptr;
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen nameptr = CONST_PTR_OFFSET(ext_data, ext_name_offset);
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen name = t_strndup(nameptr, mailboxes[i].name_len);
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen if (virtual_sync_get_backend_box(mbox, name, &bbox) < 0)
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen /* mailbox no longer exists. */
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen bbox->sync_uid_validity = mailboxes[i].uid_validity;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen mbox->highest_mailbox_id = ext_hdr == NULL ? 0 :
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* do not mark it initialized if it's broken */
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen /* assign new mailbox IDs if any are missing */
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen bboxes = array_get_modifiable(&mbox->backend_boxes, &count);
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen for (i = 0; i < count; i++) {
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen bboxes[i]->mailbox_id = ++mbox->highest_mailbox_id;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen /* sort the backend mailboxes by mailbox_id. */
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen array_sort(&mbox->backend_boxes, bbox_mailbox_id_cmp);
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainenstatic void virtual_sync_ext_header_rewrite(struct virtual_sync_context *ctx)
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen struct virtual_mail_index_mailbox_record mailbox;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen bboxes = array_get_modifiable(&ctx->mbox->backend_boxes, &count);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen name_pos = mailbox_pos + sizeof(mailbox) * count;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen ext_hdr.change_counter = ++ctx->mbox->prev_change_counter;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen ext_hdr.highest_mailbox_id = ctx->mbox->highest_mailbox_id;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen ext_hdr.search_args_crc32 = ctx->mbox->search_args_crc32;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buf = buffer_create_dynamic(pool_datastack_create(), name_pos + 256);
7471f28b16b81f9af413c879b3efb16eeafd2bd9Timo Sirainen buffer_append(buf, &ext_hdr, sizeof(ext_hdr));
7471f28b16b81f9af413c879b3efb16eeafd2bd9Timo Sirainen for (i = 0; i < count; i++) {
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen bboxes[i]->mailbox_id > bboxes[i-1]->mailbox_id);
7471f28b16b81f9af413c879b3efb16eeafd2bd9Timo Sirainen mailbox.uid_validity = bboxes[i]->sync_uid_validity;
7471f28b16b81f9af413c879b3efb16eeafd2bd9Timo Sirainen mailbox.highest_modseq = bboxes[i]->ondisk_highest_modseq;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen buffer_write(buf, mailbox_pos, &mailbox, sizeof(mailbox));
527ed64bc924b4a13b570a8450f8be3efdf71879Timo Sirainen buffer_write(buf, name_pos, bboxes[i]->name, mailbox.name_len);
688f0fdfb7ca946e38ae34459b0ca30b71c8457cTimo Sirainen /* repair the value */
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen if (ctx->mbox->highest_mailbox_id < mailbox.id)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx->mbox->highest_mailbox_id != ext_hdr.highest_mailbox_id) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ext_hdr.highest_mailbox_id = ctx->mbox->highest_mailbox_id;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_write(buf, 0, &ext_hdr, sizeof(ext_hdr));
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen mail_index_get_header_ext(ctx->sync_view, ctx->mbox->virtual_ext_id,
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen mail_index_ext_resize(ctx->trans, ctx->mbox->virtual_ext_id,
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext_id,
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainenstatic void virtual_sync_ext_header_update(struct virtual_sync_context *ctx)
1e16e4fb4b1d99e835f19f0f5720d6c75d8c6783Timo Sirainen /* we changed something - update the change counter in header */
1e16e4fb4b1d99e835f19f0f5720d6c75d8c6783Timo Sirainen ext_hdr.change_counter = ++ctx->mbox->prev_change_counter;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext_id,
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen offsetof(struct virtual_mail_index_header, change_counter),
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen &ext_hdr.change_counter, sizeof(ext_hdr.change_counter));
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainenstatic int virtual_sync_index_rec(struct virtual_sync_context *ctx,
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen uint32_t virtual_ext_id = ctx->mbox->virtual_ext_id;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen if (!mail_index_lookup_seq_range(ctx->sync_view,
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen /* already expunged, nothing to do. */
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen mail_index_lookup_ext(ctx->sync_view, vseq, virtual_ext_id,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen bbox = virtual_backend_box_lookup(ctx->mbox, vrec->mailbox_id);
0fa842717a8b163252e55c229c37ca0c5d7ff056Timo Sirainen if (virtual_backend_box_open(ctx->mbox, bbox) < 0) {
096953143c4032bad154637f687551856f7946cbTimo Sirainen virtual_backend_box_accessed(ctx->mbox, bbox);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (!mail_set_uid(bbox->sync_mail, vrec->real_uid)) {
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen /* message is already expunged from backend mailbox. */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen flags = sync_rec->add_flags & MAIL_FLAGS_NONRECENT;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen flags = sync_rec->remove_flags & MAIL_FLAGS_NONRECENT;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen kw_names[0] = ctx->kw_all[sync_rec->keyword_idx];
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen keywords = mailbox_keywords_create_valid(bbox->box,
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainenstatic int virtual_sync_index_changes(struct virtual_sync_context *ctx)
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen keywords = mail_index_get_keywords(ctx->index);
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen ctx->kw_all = array_count(keywords) == 0 ? NULL :
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen while (mail_index_sync_next(ctx->index_sync_ctx, &sync_rec)) {
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen if (virtual_sync_index_rec(ctx, &sync_rec) < 0)
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainenstatic void virtual_sync_index_finish(struct virtual_sync_context *ctx)
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen view = mail_index_transaction_open_updated_view(ctx->trans);
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen /* mark the newly seen messages as recent */
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen if (mail_index_lookup_seq_range(view, hdr->first_recent_uid,
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen mailbox_recent_flags_set_seqs(&ctx->mbox->box, view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* entire mailbox list needs to be rewritten */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* update only changed parts in the header */
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainenstatic int virtual_sync_backend_box_init(struct virtual_backend_box *bbox)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mailbox_search_result_flags result_flags;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen trans = mailbox_transaction_begin(bbox->box, 0);
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen mail_search_args_init(bbox->search_args, bbox->box, FALSE, NULL);
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen search_ctx = mailbox_search_init(trans, bbox->search_args, NULL,
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen /* save the result and keep it updated */
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen result_flags = MAILBOX_SEARCH_RESULT_FLAG_UPDATE |
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen mailbox_search_result_save(search_ctx, result_flags);
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen /* add the found UIDs to uidmap. virtual_uid gets assigned later. */
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen while (mailbox_search_next(search_ctx, &mail)) {
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainenvirtual_backend_uidmap_bsearch_cmp(const uint32_t *uidp,
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainenvirtual_sync_mailbox_box_remove(struct virtual_sync_context *ctx,
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen unsigned int i, src, dest, uid_count, rec_count;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen /* everything in removed_uids should exist in bbox->uids */
b5ac20e30146562322ceb7939f044d52d1e51184Timo Sirainen uidmap = array_get_modifiable(&bbox->uids, &rec_count);
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen /* find the first uidmap record to be removed */
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen if (!array_bsearch_insert_pos(&bbox->uids, &uids[0].seq1,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* remove the unwanted messages */
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen for (i = 0; i < uid_count; i++) {
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen /* has not been assigned yet */
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainenvirtual_sync_mailbox_box_add(struct virtual_sync_context *ctx,
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen unsigned int i, src, dest, uid_count, add_count, rec_count;
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen added_uids = array_get(added_uids_arr, &uid_count);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* none of added_uids should exist in bbox->uids. find the position
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen of the first inserted index. */
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen uidmap = array_get_modifiable(&bbox->uids, &rec_count);
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen added_uids[0].seq1 > uidmap[rec_count-1].real_uid) {
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen /* fast path: usually messages are appended */
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen } else if (array_bsearch_insert_pos(&bbox->uids, &added_uids[0].seq1,
3281669db44d09a087a203201248abbc81b3cc1aTimo Sirainen /* make space for all added UIDs. */
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen array_idx_clear(&bbox->uids, dest + add_count-1);
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen uidmap = array_get_modifiable(&bbox->uids, &rec_count);
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen /* add/move the UIDs to their correct positions */
d200ae87140a1985fe527e6527bc4bd3035189b1Timo Sirainen for (i = 0; i < uid_count; i++) {
d200ae87140a1985fe527e6527bc4bd3035189b1Timo Sirainen while (src < rec_count && uidmap[src].real_uid < add_uid)
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen for (; add_uid <= added_uids[i].seq2; add_uid++, dest++) {
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainenvirtual_sync_mailbox_box_update_flags(struct virtual_sync_context *ctx,
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen while(seq_range_array_iter_nth(&iter, i++, &uid)) {
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen /* the entry has been already removed either by
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen us or some other session. doesn't matter,
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen we don't need to update the flags.
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen it might also have not yet been assigned a uid
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen so we don't want to update the flags then either.
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainenstatic int virtual_backend_uidmap_cmp(const struct virtual_backend_uidmap *u1,
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainenstatic void virtual_sync_bbox_uids_sort(struct virtual_backend_box *bbox)
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen /* the uidmap must be sorted by real_uids */
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen array_sort(&bbox->uids, virtual_backend_uidmap_cmp);
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainenstatic void virtual_sync_backend_boxes_sort_uids(struct virtual_mailbox *mbox)
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen unsigned int i, count;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen for (i = 0; i < count; i++) {
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainenvirtual_sync_backend_add_vmsgs_results(struct virtual_sync_context *ctx,
a8012fea2a7315033bc467acbf46be8e7323318cTimo Sirainen mail_index_lookup_uid(ctx->sync_view, vseq, &vuid);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen else if (mail_index_lookup_seq(bbox->box->view, real_uid, &seq))
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen seq_range_array_add(&result->removed_uids, real_uid);
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainenvirtual_sync_backend_handle_old_vmsgs(struct virtual_sync_context *ctx,
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen const struct virtual_sync_mail *sync_mail, *sync_mails;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen /* find the messages that currently exist in virtual index and add them
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen to the backend mailbox's list of uids. */
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen i_assert(ctx->all_mails_prev_mailbox_id < bbox->mailbox_id);
b7cf555b699d73f2d71de0dabc088af6a7be3627Timo Sirainen sync_mails = array_get(&ctx->all_mails, &messages);
b88c43d09a288e99d439c78de4cc613212ea924cTimo Sirainen for (i = ctx->all_mails_idx; i < messages; i++) {
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen if (sync_mail->vrec.mailbox_id != bbox->mailbox_id) {
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen if (sync_mail->vrec.mailbox_id < bbox->mailbox_id) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* stale mailbox_id, ignore */
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen /* Should be in mailbox_id order,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen so skip to next box */
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen virtual_sync_backend_add_vmsgs_results(ctx, bbox,
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen sync_mail->vrec.real_uid, result, sync_mail->vseq);
075912b4566a79c7bc59bf229c9f629ef7be0ea2Timo Sirainen ctx->all_mails_prev_mailbox_id = bbox->mailbox_id;
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen /* there should be only a single backend mailbox, but in the
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen existing index there may be stale mailbox_ids that we'll
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen just skip over. */
b5ac20e30146562322ceb7939f044d52d1e51184Timo Sirainen messages = mail_index_view_get_messages_count(ctx->sync_view);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainenstatic int virtual_sync_backend_box_continue(struct virtual_sync_context *ctx,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen const enum mailbox_search_result_flags result_flags =
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen struct mail_index_view *view = bbox->box->view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ARRAY_TYPE(seq_range) expunged_uids = ARRAY_INIT, removed_uids;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ARRAY_TYPE(seq_range) added_uids, flag_update_uids;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* initialize the search result from all the existing messages in
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen virtual index. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_search_args_init(bbox->search_args, bbox->box, FALSE, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen result = mailbox_search_result_alloc(bbox->box, bbox->search_args,
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen i_assert(array_count(&result->removed_uids) == 0);
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen virtual_sync_backend_handle_old_vmsgs(ctx, bbox, result);
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen /* these are all expunged messages. treat them separately from
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "no longer matching messages" (=removed_uids) */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_array_init(&expunged_uids, array_count(&result->removed_uids));
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen array_append_array(&expunged_uids, &result->removed_uids);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* get list of changed old messages (messages already once seen by
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen virtual index), based on modseq changes. (we'll assume all modseq
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen changes are due to flag changes, which may not be true in future) */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen !mail_index_lookup_seq_range(view, 1, bbox->sync_next_uid-1,
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen old_highest_modseq = mail_index_modseq_get_highest(view);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_array_init(&flag_update_uids, I_MIN(128, old_msg_count));
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen if (bbox->sync_highest_modseq < old_highest_modseq) {
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen /* update the search result based on the flag changes and
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen new messages */
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen if (index_search_result_update_flags(result, &flag_update_uids) < 0 ||
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen index_search_result_update_appends(result, old_msg_count) < 0) {
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen mailbox_search_result_sync(result, &removed_uids, &added_uids);
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen seq_range_array_remove_seq_range(&removed_uids, &expunged_uids);
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen virtual_sync_mailbox_box_remove(ctx, bbox, &expunged_uids);
&removed_uids);
unsigned int i, n = 0, count;
if (i == count)
for (; i < count; ) {
unsigned int i, n = 0, count;
for (; i < count; ) {
if (!iter_done) {
&added_uids);
&temp_uids);
&removed_uids);
&removed_uids);
unsigned int *idx1_r,
unsigned int *idx2_r)
&idx);
return FALSE;
return TRUE;
&idx1);
case MAILBOX_SYNC_TYPE_FLAGS:
if (vuid == 0) {
case MAILBOX_SYNC_TYPE_MODSEQ:
const unsigned int uidval_pos =
unsigned int mailbox_offset;
int ret = 0;
if (ret == 0)
if (ret < 0) {
int ret;
return ret;
&status) < 0) {
return ret;
} T_END;
return ret;
const void *data;
unsigned int j = 0, uidmap_count = 0;
if (messages == 0)
for (i = 0; i < messages; i++) {
for (; j < uidmap_count; j++) {
&uidmap_count);
for (; j < uidmap_count; j++) {
for (; j < uidmap_count; j++) {
for (i = 0; i < count; i++) {
for (j = 0; j < uidmap_count; j++) {
unsigned int i, count;
if (count == 0) {
&idx))
i_unreached();
const void *data;
const void *data;
const void *mail_data;
unsigned int i, count;
int ret;
for (i = 0; i < count; i++) {
#ifdef DEBUG
for (i = 0; i < count; i++) {
return ret;
unsigned int i, count;
for (i = 0; i < count; i++)
if (success) {
return ret;
bool broken;
int ret;
if (ret <= 0) {
if (ret < 0)
return ret;
if (ret < 0)
if (broken)
struct mailbox_sync_context *
int ret = 0;
return sync_ctx;