virtual-sync.c revision e8bff8f8293e741385bd96420010ee70f7f7c5d4
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2008 Dovecot authors, see the included COPYING file */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "lib.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "array.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "bsearch-insert-pos.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "ioloop.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "str.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "mail-index-modseq.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "mail-search-build.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "mailbox-search-result-private.h"
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch#include "index-search-result.h"
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch#include "virtual-storage.h"
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch#include <stdlib.h>
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Boschstruct virtual_add_record {
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch struct virtual_mail_index_record rec;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch time_t received_date;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch};
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Boschstruct virtual_sync_mail {
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch uint32_t vseq;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch struct virtual_mail_index_record vrec;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch};
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Boschstruct virtual_sync_context {
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch struct virtual_mailbox *mbox;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch struct mail_index_sync_ctx *index_sync_ctx;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch struct mail_index *index;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch struct mail_index_view *sync_view;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch struct mail_index_transaction *trans;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch const char *const *kw_all;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch /* messages expunged within this sync */
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch ARRAY_TYPE(seq_range) sync_expunges;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch ARRAY_DEFINE(all_adds, struct virtual_add_record);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch enum mailbox_sync_flags flags;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch uint32_t uid_validity;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch unsigned int ext_header_changed:1;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch unsigned int ext_header_rewrite:1;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch unsigned int expunge_removed:1;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch unsigned int retry:1;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch};
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Boschstatic void virtual_sync_set_uidvalidity(struct virtual_sync_context *ctx)
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch{
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch uint32_t uid_validity = ioloop_time;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch mail_index_update_header(ctx->trans,
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch offsetof(struct mail_index_header, uid_validity),
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch &uid_validity, sizeof(uid_validity), TRUE);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch ctx->uid_validity = uid_validity;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch}
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Boschstatic void virtual_sync_external_flags(struct virtual_sync_context *ctx,
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch struct virtual_backend_box *bbox,
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch uint32_t vseq, uint32_t real_uid)
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch{
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch enum mail_flags flags;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch const char *const *kw_names;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch struct mail_keywords *keywords;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch if (!mail_set_uid(bbox->sync_mail, real_uid))
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch i_panic("UID lost unexpectedly");
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch /* copy flags */
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch flags = mail_get_flags(bbox->sync_mail);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch mail_index_update_flags(ctx->trans, vseq, MODIFY_REPLACE, flags);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch /* copy keywords */
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch kw_names = mail_get_keywords(bbox->sync_mail);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch keywords = mail_index_keywords_create(ctx->index, kw_names);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch mail_index_update_keywords(ctx->trans, vseq, MODIFY_REPLACE, keywords);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch mail_index_keywords_free(&keywords);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch}
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Boschstatic int virtual_sync_mail_cmp(const void *p1, const void *p2)
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const struct virtual_sync_mail *m1 = p1, *m2 = p2;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (m1->vrec.mailbox_id < m2->vrec.mailbox_id)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return -1;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (m1->vrec.mailbox_id > m2->vrec.mailbox_id)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 1;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (m1->vrec.real_uid < m2->vrec.real_uid)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return -1;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (m1->vrec.real_uid > m2->vrec.real_uid)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 1;
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch /* broken */
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch return 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschvirtual_backend_box_sync_mail_set(struct virtual_backend_box *bbox)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch struct mailbox_transaction_context *trans;
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch if (bbox->sync_mail == NULL) {
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch trans = mailbox_transaction_begin(bbox->box, 0);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch bbox->sync_mail = mail_alloc(trans, 0, NULL);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch }
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschvirtual_backend_box_sync_mail_unset(struct virtual_backend_box *bbox)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch struct mailbox_transaction_context *trans;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (bbox->sync_mail != NULL) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch trans = bbox->sync_mail->transaction;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mail_free(&bbox->sync_mail);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch (void)mailbox_transaction_commit(&trans);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic int bbox_mailbox_id_cmp(const void *p1, const void *p2)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const struct virtual_backend_box *const *b1 = p1, *const *b2 = p2;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((*b1)->mailbox_id < (*b2)->mailbox_id)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return -1;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((*b1)->mailbox_id > (*b2)->mailbox_id)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 1;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic bool virtual_sync_ext_header_read(struct virtual_sync_context *ctx)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const struct virtual_mail_index_header *ext_hdr;
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch const struct mail_index_header *hdr;
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch const struct virtual_mail_index_mailbox_record *mailboxes;
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch struct virtual_backend_box *bbox, **bboxes;
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch const void *ext_data;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch size_t ext_size;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch unsigned int i, count, ext_name_offset, ext_mailbox_count;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uint32_t prev_mailbox_id;
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch bool ret;
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch hdr = mail_index_get_header(ctx->sync_view);
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch mail_index_get_header_ext(ctx->sync_view, ctx->mbox->virtual_ext_id,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch &ext_data, &ext_size);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ext_hdr = ext_data;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (ctx->mbox->sync_initialized &&
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ctx->mbox->prev_uid_validity == hdr->uid_validity &&
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ext_size >= sizeof(*ext_hdr) &&
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ctx->mbox->prev_change_counter == ext_hdr->change_counter) {
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen /* fully refreshed */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return TRUE;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ctx->mbox->sync_initialized = TRUE;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ctx->mbox->prev_uid_validity = hdr->uid_validity;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (ext_hdr == NULL ||
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ctx->mbox->search_args_crc32 != ext_hdr->search_args_crc32) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mailboxes = NULL;
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen ext_name_offset = 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ext_mailbox_count = 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } else {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ctx->mbox->prev_change_counter = ext_hdr->change_counter;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mailboxes = (const void *)(ext_hdr + 1);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ext_name_offset = sizeof(*ext_hdr) +
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ext_hdr->mailbox_count * sizeof(*mailboxes);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (ext_name_offset >= ext_size ||
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ext_hdr->mailbox_count > INT_MAX/sizeof(*mailboxes)) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_error("virtual %s: Broken mailbox_count header",
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ctx->mbox->path);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ext_mailbox_count = 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } else {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ext_mailbox_count = ext_hdr->mailbox_count;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch /* update mailbox backends */
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch prev_mailbox_id = 0;
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch for (i = 0; i < ext_mailbox_count; i++) {
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch if (mailboxes[i].id > ext_hdr->highest_mailbox_id ||
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch mailboxes[i].id <= prev_mailbox_id) {
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch i_error("virtual %s: Broken mailbox id",
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ctx->mbox->path);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch break;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (mailboxes[i].name_len == 0 ||
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mailboxes[i].name_len > ext_size) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_error("virtual %s: Broken mailbox name_len",
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch ctx->mbox->path);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch break;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (ext_name_offset + mailboxes[i].name_len > ext_size) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_error("virtual %s: Broken mailbox list",
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ctx->mbox->path);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch break;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch T_BEGIN {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const unsigned char *nameptr;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const char *name;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch nameptr = CONST_PTR_OFFSET(ext_data, ext_name_offset);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch name = t_strndup(nameptr, mailboxes[i].name_len);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bbox = virtual_backend_box_lookup_name(ctx->mbox, name);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } T_END;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (bbox == NULL) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* mailbox no longer exists */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ret = FALSE;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } else {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bbox->mailbox_id = mailboxes[i].id;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bbox->sync_uid_validity = mailboxes[i].uid_validity;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bbox->sync_highest_modseq = mailboxes[i].highest_modseq;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bbox->sync_next_uid = mailboxes[i].next_uid;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bbox->sync_mailbox_idx = i;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ext_name_offset += mailboxes[i].name_len;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch prev_mailbox_id = mailboxes[i].id;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch if (ext_hdr == NULL) {
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch ret = TRUE;
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch ctx->mbox->highest_mailbox_id = 0;
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch } else {
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch ret = i == ext_hdr->mailbox_count;
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch ctx->mbox->highest_mailbox_id = ext_hdr->highest_mailbox_id;
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch }
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch /* assign new mailbox IDs if any are missing */
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch bboxes = array_get_modifiable(&ctx->mbox->backend_boxes, &count);
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch for (i = 0; i < count; i++) {
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch if (bboxes[i]->mailbox_id == 0) {
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch bboxes[i]->mailbox_id = ++ctx->mbox->highest_mailbox_id;
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch ret = FALSE;
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch }
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch }
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch /* sort the backend mailboxes by mailbox_id. */
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch qsort(bboxes, count, sizeof(*bboxes), bbox_mailbox_id_cmp);
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch return ret;
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch}
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Boschstatic void virtual_sync_ext_header_rewrite(struct virtual_sync_context *ctx)
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch{
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch struct virtual_mail_index_header ext_hdr;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct virtual_mail_index_mailbox_record mailbox;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct virtual_backend_box **bboxes;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch buffer_t *buf;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const void *ext_data;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch size_t ext_size;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch unsigned int i, mailbox_pos, name_pos, count;
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bboxes = array_get_modifiable(&ctx->mbox->backend_boxes, &count);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mailbox_pos = sizeof(ext_hdr);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch name_pos = mailbox_pos + sizeof(mailbox) * count;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch memset(&ext_hdr, 0, sizeof(ext_hdr));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch memset(&mailbox, 0, sizeof(mailbox));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ext_hdr.change_counter = ++ctx->mbox->prev_change_counter;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ext_hdr.mailbox_count = count;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ext_hdr.highest_mailbox_id = ctx->mbox->highest_mailbox_id;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ext_hdr.search_args_crc32 = ctx->mbox->search_args_crc32;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch buf = buffer_create_dynamic(pool_datastack_create(), name_pos + 256);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch buffer_append(buf, &ext_hdr, sizeof(ext_hdr));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch for (i = 0; i < count; i++) {
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch i_assert(i == 0 ||
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch bboxes[i]->mailbox_id > bboxes[i-1]->mailbox_id);
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bboxes[i]->sync_mailbox_idx = i;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mailbox.id = bboxes[i]->mailbox_id;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mailbox.name_len = strlen(bboxes[i]->name);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mailbox.uid_validity = bboxes[i]->sync_uid_validity;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mailbox.highest_modseq = bboxes[i]->sync_highest_modseq;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mailbox.next_uid = bboxes[i]->sync_next_uid;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch buffer_write(buf, mailbox_pos, &mailbox, sizeof(mailbox));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch buffer_write(buf, name_pos, bboxes[i]->name, mailbox.name_len);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen mailbox_pos += sizeof(mailbox);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch name_pos += mailbox.name_len;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_assert(buf->used == name_pos);
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mail_index_get_header_ext(ctx->sync_view, ctx->mbox->virtual_ext_id,
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch &ext_data, &ext_size);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (ext_size < name_pos) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mail_index_ext_resize(ctx->trans, ctx->mbox->virtual_ext_id,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch name_pos,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch sizeof(struct virtual_mail_index_record),
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch sizeof(uint32_t));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext_id,
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch 0, buf->data, name_pos);
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Boschstatic void virtual_sync_ext_header_update(struct virtual_sync_context *ctx)
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch{
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch struct virtual_mail_index_header ext_hdr;
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch if (!ctx->ext_header_changed)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return;
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* we changed something - update the change counter in header */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ext_hdr.change_counter = ++ctx->mbox->prev_change_counter;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext_id,
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch offsetof(struct virtual_mail_index_header, change_counter),
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch &ext_hdr.change_counter, sizeof(ext_hdr.change_counter));
639bb36b12b9f9bb54c8bb1be50eac623622f8a0Timo Sirainen}
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Boschstatic void virtual_sync_index_rec(struct virtual_sync_context *ctx,
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch const struct mail_index_sync_rec *sync_rec)
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch{
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch uint32_t virtual_ext_id = ctx->mbox->virtual_ext_id;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct virtual_backend_box *bbox;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const struct virtual_mail_index_record *vrec;
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch const void *data;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch enum mail_flags flags;
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch struct mail_keywords *keywords;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch enum modify_type modify_type;
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch const char *kw_names[2];
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch uint32_t vseq, seq1, seq2;
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch bool expunged;
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch switch (sync_rec->type) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch case MAIL_INDEX_SYNC_TYPE_APPEND:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* don't care */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch case MAIL_INDEX_SYNC_TYPE_FLAGS:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
0e702716169a158b87d08e21d1a128eb99e23fa1Phil Carmody case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch break;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!mail_index_lookup_seq_range(ctx->sync_view,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch sync_rec->uid1, sync_rec->uid2,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch &seq1, &seq2)) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* already expunged, nothing to do. */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch for (vseq = seq1; vseq <= seq2; vseq++) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mail_index_lookup_ext(ctx->sync_view, vseq, virtual_ext_id,
639bb36b12b9f9bb54c8bb1be50eac623622f8a0Timo Sirainen &data, &expunged);
0e702716169a158b87d08e21d1a128eb99e23fa1Phil Carmody vrec = data;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bbox = virtual_backend_box_lookup(ctx->mbox, vrec->mailbox_id);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (bbox == NULL)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch continue;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch virtual_backend_box_sync_mail_set(bbox);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!mail_set_uid(bbox->sync_mail, vrec->real_uid))
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_panic("UID lost unexpectedly");
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch switch (sync_rec->type) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mail_expunge(bbox->sync_mail);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch break;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch case MAIL_INDEX_SYNC_TYPE_FLAGS:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch flags = sync_rec->add_flags & MAIL_FLAGS_NONRECENT;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (flags != 0) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mail_update_flags(bbox->sync_mail,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch MODIFY_ADD, flags);
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch flags = sync_rec->remove_flags & MAIL_FLAGS_NONRECENT;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (flags != 0) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mail_update_flags(bbox->sync_mail,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch MODIFY_REMOVE, flags);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch break;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch kw_names[0] = ctx->kw_all[sync_rec->keyword_idx];
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch kw_names[1] = NULL;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch keywords = mailbox_keywords_create_valid(bbox->box,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch kw_names);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch modify_type = sync_rec->type ==
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD ?
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch MODIFY_ADD : MODIFY_REMOVE;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mail_update_keywords(bbox->sync_mail,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch modify_type, keywords);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mailbox_keywords_free(bbox->box, &keywords);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch break;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch kw_names[0] = NULL;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch keywords = mailbox_keywords_create_valid(bbox->box,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch kw_names);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mail_update_keywords(bbox->sync_mail, MODIFY_REPLACE,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch keywords);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mailbox_keywords_free(bbox->box, &keywords);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch break;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch case MAIL_INDEX_SYNC_TYPE_APPEND:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_unreached();
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Boschstatic void virtual_sync_index_changes(struct virtual_sync_context *ctx)
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const ARRAY_TYPE(keywords) *keywords;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct mail_index_sync_rec sync_rec;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch keywords = mail_index_get_keywords(ctx->index);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ctx->kw_all = array_count(keywords) == 0 ? NULL :
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch array_idx(keywords, 0);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch while (mail_index_sync_next(ctx->index_sync_ctx, &sync_rec))
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch virtual_sync_index_rec(ctx, &sync_rec);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void virtual_sync_index_finish(struct virtual_sync_context *ctx)
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch{
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch struct mailbox *box = &ctx->mbox->ibox.box;
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch const struct mail_index_header *hdr;
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch uint32_t seq1, seq2;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch hdr = mail_index_get_header(ctx->sync_view);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (hdr->uid_validity != 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ctx->uid_validity = hdr->uid_validity;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch else
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch virtual_sync_set_uidvalidity(ctx);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* mark the newly seen messages as recent */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (mail_index_lookup_seq_range(ctx->sync_view, hdr->first_recent_uid,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch hdr->next_uid, &seq1, &seq2)) {
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch index_mailbox_set_recent_seq(&ctx->mbox->ibox, ctx->sync_view,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch seq1, seq2);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (ctx->ext_header_rewrite) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* entire mailbox list needs to be rewritten */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch virtual_sync_ext_header_rewrite(ctx);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } else {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* update only changed parts in the header */
f3cf2f02155c4bac23fd50f0de96c0cae9c46478Stephan Bosch virtual_sync_ext_header_update(ctx);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch if (box->v.sync_notify != NULL)
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch box->v.sync_notify(box, 0, 0);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch}
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Boschstatic int virtual_sync_backend_box_init(struct virtual_backend_box *bbox)
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch{
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch struct mailbox_transaction_context *trans;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch struct mail_search_context *search_ctx;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch struct mail *mail;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch struct virtual_backend_uidmap uidmap;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch enum mailbox_search_result_flags result_flags;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch int ret;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch trans = mailbox_transaction_begin(bbox->box, 0);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch mail = mail_alloc(trans, 0, NULL);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch mail_search_args_init(bbox->search_args, bbox->box, FALSE, NULL);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch search_ctx = mailbox_search_init(trans, bbox->search_args, NULL);
14383bf2be0296954609df5afd3c63c6555815f9Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch /* save the result and keep it updated */
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch result_flags = MAILBOX_SEARCH_RESULT_FLAG_UPDATE |
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch MAILBOX_SEARCH_RESULT_FLAG_QUEUE_SYNC;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch bbox->search_result =
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch mailbox_search_result_save(search_ctx, result_flags);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch /* add the found UIDs to uidmap. virtual_uid gets assigned later. */
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch memset(&uidmap, 0, sizeof(uidmap));
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch array_clear(&bbox->uids);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch while (mailbox_search_next(search_ctx, mail) > 0) {
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch uidmap.real_uid = mail->uid;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch array_append(&bbox->uids, &uidmap, 1);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch }
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch ret = mailbox_search_deinit(&search_ctx);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch mail_free(&mail);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch mail_search_args_deinit(bbox->search_args);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch (void)mailbox_transaction_commit(&trans);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return ret;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch}
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Boschstatic int virtual_backend_uidmap_cmp(const void *p1, const void *p2)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch{
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch const struct virtual_backend_uidmap *u1 = p1, *u2 = p2;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (u1->real_uid < u2->real_uid)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return -1;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (u1->real_uid > u2->real_uid)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return 1;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return 0;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch}
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Boschstatic void
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Boschvirtual_sync_backend_add_existing_uids(struct virtual_sync_context *ctx,
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch struct virtual_backend_box *bbox,
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch struct mail_search_result *result)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch{
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch struct virtual_backend_uidmap uidmap, *uids;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch const struct virtual_mail_index_record *vrec;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch const void *data;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch uint32_t vseq, vuid, messages;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch unsigned int uid_count;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch bool expunged;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch /* add the currently existing UIDs to uidmap. */
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch memset(&uidmap, 0, sizeof(uidmap));
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch array_clear(&bbox->uids);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch messages = mail_index_view_get_messages_count(ctx->sync_view);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch for (vseq = 1; vseq <= messages; vseq++) {
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch mail_index_lookup_uid(ctx->sync_view, vseq, &vuid);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch mail_index_lookup_ext(ctx->sync_view, vseq,
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch ctx->mbox->virtual_ext_id,
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch &data, &expunged);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch vrec = data;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (vrec->mailbox_id == bbox->mailbox_id) {
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch seq_range_array_add(&result->uids, 0, vrec->real_uid);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch uidmap.real_uid = vrec->real_uid;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch uidmap.virtual_uid = vuid;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch array_append(&bbox->uids, &uidmap, 1);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch }
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch }
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch /* the uidmap must be sorted by real_uids */
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch uids = array_get_modifiable(&bbox->uids, &uid_count);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch qsort(uids, uid_count, sizeof(*uids), virtual_backend_uidmap_cmp);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch}
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Boschstatic void
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Boschvirtual_sync_backend_remove_expunged_uids(struct mail_search_result *result)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch{
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch struct index_mailbox *ibox = (struct index_mailbox *)result->box;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch const struct seq_range *range;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch unsigned int i, count;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch uint32_t seq, uid;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch range = array_get(&result->uids, &count);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch for (i = 0; i < count; i++) {
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch for (uid = range[i].seq1; uid <= range[i].seq2; uid++) {
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (!mail_index_lookup_seq(ibox->view, uid, &seq))
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch mailbox_search_result_remove(result, uid);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch }
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch }
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch}
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Boschstatic int virtual_sync_backend_box_continue(struct virtual_sync_context *ctx,
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch struct virtual_backend_box *bbox)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch{
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch const enum mailbox_search_result_flags result_flags =
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch MAILBOX_SEARCH_RESULT_FLAG_UPDATE |
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch MAILBOX_SEARCH_RESULT_FLAG_QUEUE_SYNC;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch struct index_mailbox *ibox = (struct index_mailbox *)bbox->box;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch struct mail_search_result *result;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch ARRAY_TYPE(seq_range) flag_updates;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch uint64_t modseq;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch uint32_t seq, old_msg_count;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch /* build the initial search result from the existing UIDs */
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch result = mailbox_search_result_alloc(bbox->box, bbox->search_args,
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch result_flags);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch mailbox_search_result_initial_done(result);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch virtual_sync_backend_add_existing_uids(ctx, bbox, result);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch /* changes done from now on must update the sync queue */
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch virtual_sync_backend_remove_expunged_uids(result);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch /* get list of changed messages */
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (bbox->sync_next_uid <= 1 ||
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch !mail_index_lookup_seq_range(ibox->view, 1, bbox->sync_next_uid-1,
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch &seq, &old_msg_count))
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch old_msg_count = 0;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch t_array_init(&flag_updates, I_MIN(128, old_msg_count));
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch for (seq = 1; seq <= old_msg_count; seq++) {
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch modseq = mail_index_modseq_lookup(ibox->view, seq);
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch if (modseq > bbox->sync_highest_modseq)
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch seq_range_array_add(&flag_updates, 0, seq);
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch }
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch if (index_search_result_update_flags(result, &flag_updates) < 0 ||
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch index_search_result_update_appends(result, old_msg_count) < 0) {
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch mailbox_search_result_free(&result);
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch return -1;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch }
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch bbox->search_result = result;
f95afa9df14bee49d82baa3679fc94ef3a101d92Stephan Bosch return 0;
f95afa9df14bee49d82baa3679fc94ef3a101d92Stephan Bosch}
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Boschstatic int virtual_backend_uidmap_bsearch_cmp(const void *key, const void *data)
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const uint32_t *uidp = key;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const struct virtual_backend_uidmap *uidmap = data;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return *uidp < uidmap->real_uid ? -1 :
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch (*uidp > uidmap->real_uid ? 1 : 0);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschvirtual_sync_mailbox_box_remove(struct virtual_sync_context *ctx,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct virtual_backend_box *bbox,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const ARRAY_TYPE(seq_range) *removed_uids)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const struct seq_range *uids;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct virtual_backend_uidmap *uidmap;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch unsigned int i, src, dest, uid_count, rec_count, left;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uint32_t uid, vseq;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uids = array_get(removed_uids, &uid_count);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (uid_count == 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* everything in removed_uids should exist in bbox->uids */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uidmap = array_get_modifiable(&bbox->uids, &rec_count);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_assert(rec_count >= uid_count);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* find the first uidmap record to be removed */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!bsearch_insert_pos(&uids[0].seq1, uidmap, rec_count,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch sizeof(*uidmap),
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch virtual_backend_uidmap_bsearch_cmp, &src))
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_unreached();
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* remove the unwanted messages */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch for (i = src = dest = 0; i < uid_count; i++) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uid = uids[i].seq1;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch while (uidmap[src].real_uid != uid) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uidmap[dest++] = uidmap[src++];
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_assert(src < rec_count);
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch for (; uid <= uids[i].seq2; uid++, src++) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!mail_index_lookup_seq(ctx->sync_view,
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch uidmap[src].virtual_uid,
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen &vseq))
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_unreached();
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mail_index_expunge(ctx->trans, vseq);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch }
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch left = rec_count - src;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch memmove(uidmap + dest, uidmap + src, left);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch array_delete(&bbox->uids, dest + left, src - dest);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Boschstatic void
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Boschvirtual_sync_mailbox_box_add(struct virtual_sync_context *ctx,
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch struct virtual_backend_box *bbox,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const ARRAY_TYPE(seq_range) *added_uids)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const struct seq_range *uids;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct virtual_backend_uidmap *uidmap;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct virtual_add_record rec;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch unsigned int i, src, dest, uid_count, add_count, rec_count;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uint32_t uid;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uids = array_get(added_uids, &uid_count);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (uid_count == 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch add_count = seq_range_count(added_uids);
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch /* none of added_uids should exist in bbox->uids. find the position
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch of the first inserted index. */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uidmap = array_get_modifiable(&bbox->uids, &rec_count);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (rec_count == 0 || uids[0].seq1 > uidmap[rec_count-1].real_uid) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* fast path: usually messages are appended */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch dest = rec_count;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } else if (bsearch_insert_pos(&uids[0].seq1, uidmap, rec_count,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch sizeof(*uidmap),
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch virtual_backend_uidmap_bsearch_cmp,
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch &dest))
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch i_unreached();
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch /* make space for all added UIDs. */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch array_copy(&bbox->uids.arr, dest + add_count,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch &bbox->uids.arr, dest, rec_count - dest);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uidmap = array_get_modifiable(&bbox->uids, &rec_count);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch src = dest + add_count;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* add/move the UIDs to their correct positions */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch memset(&rec, 0, sizeof(rec));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch rec.rec.mailbox_id = bbox->mailbox_id;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch for (i = 0; i < uid_count; i++) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uid = uids[i].seq1;
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch while (src < rec_count && uidmap[src].real_uid < uid) {
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch uidmap[dest++] = uidmap[src++];
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch i_assert(src < rec_count);
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch for (; uid <= uids[i].seq2; uid++, dest++) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uidmap[dest].real_uid = uid;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uidmap[dest].virtual_uid = 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch rec.rec.real_uid = uid;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch array_append(&ctx->all_adds, &rec, 1);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch }
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch }
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch}
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch
f3cf2f02155c4bac23fd50f0de96c0cae9c46478Stephan Boschstatic void virtual_sync_mailbox_box_update(struct virtual_sync_context *ctx,
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch struct virtual_backend_box *bbox)
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ARRAY_TYPE(seq_range) removed_uids, added_uids, temp_uids;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch unsigned int count1, count2;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch t_array_init(&removed_uids, 128);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch t_array_init(&added_uids, 128);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch mailbox_search_result_sync(bbox->search_result,
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch &removed_uids, &added_uids);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch /* if any of the pending removes came back, we don't want to expunge
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch them anymore. also since they already exist, remove them from
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch added_uids. */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch count1 = array_count(&bbox->sync_pending_removes);
009217abb57a24a4076092e8e4e165545747839eStephan Bosch count2 = array_count(&added_uids);
009217abb57a24a4076092e8e4e165545747839eStephan Bosch if (count1 > 0 && count2 > 0) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch t_array_init(&temp_uids, count1);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch array_append_array(&temp_uids, &bbox->sync_pending_removes);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (seq_range_array_remove_seq_range(
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch &bbox->sync_pending_removes, &added_uids) > 0) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch seq_range_array_remove_seq_range(&added_uids,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch &temp_uids);
009217abb57a24a4076092e8e4e165545747839eStephan Bosch }
009217abb57a24a4076092e8e4e165545747839eStephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
009217abb57a24a4076092e8e4e165545747839eStephan Bosch if (!ctx->expunge_removed) {
009217abb57a24a4076092e8e4e165545747839eStephan Bosch /* delay removing messages that don't match the search
009217abb57a24a4076092e8e4e165545747839eStephan Bosch criteria, but don't delay removing expunged messages */
009217abb57a24a4076092e8e4e165545747839eStephan Bosch if (array_count(&ctx->sync_expunges) > 0) {
009217abb57a24a4076092e8e4e165545747839eStephan Bosch seq_range_array_remove_seq_range(&removed_uids,
009217abb57a24a4076092e8e4e165545747839eStephan Bosch &ctx->sync_expunges);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch virtual_sync_mailbox_box_remove(ctx, bbox,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch &ctx->sync_expunges);
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch }
009217abb57a24a4076092e8e4e165545747839eStephan Bosch seq_range_array_merge(&bbox->sync_pending_removes,
009217abb57a24a4076092e8e4e165545747839eStephan Bosch &removed_uids);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } else if (array_count(&bbox->sync_pending_removes) > 0) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* remove all current and old */
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch seq_range_array_merge(&bbox->sync_pending_removes,
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch &removed_uids);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch virtual_sync_mailbox_box_remove(ctx, bbox,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch &bbox->sync_pending_removes);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch array_clear(&bbox->sync_pending_removes);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } else {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch virtual_sync_mailbox_box_remove(ctx, bbox, &removed_uids);
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch virtual_sync_mailbox_box_add(ctx, bbox, &added_uids);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic bool virtual_sync_find_seqs(struct virtual_backend_box *bbox,
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch const struct mailbox_sync_rec *sync_rec,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch unsigned int *idx1_r,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch unsigned int *idx2_r)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct index_mailbox *ibox = (struct index_mailbox *)bbox->box;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const struct virtual_backend_uidmap *uidmap;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch unsigned int idx, count;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uint32_t uid1, uid2;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch mail_index_lookup_uid(ibox->view, sync_rec->seq1, &uid1);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mail_index_lookup_uid(ibox->view, sync_rec->seq2, &uid2);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uidmap = array_get_modifiable(&bbox->uids, &count);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch (void)bsearch_insert_pos(&uid1, uidmap, count, sizeof(*uidmap),
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch virtual_backend_uidmap_bsearch_cmp, &idx);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (idx == count || uidmap[idx].real_uid > uid2)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return FALSE;
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch *idx1_r = idx;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch while (idx < count && uidmap[idx].real_uid <= uid2) idx++;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch *idx2_r = idx - 1;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return TRUE;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch}
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch
f3cf2f02155c4bac23fd50f0de96c0cae9c46478Stephan Boschstatic int virtual_sync_backend_box_sync(struct virtual_sync_context *ctx,
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch struct virtual_backend_box *bbox,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch enum mailbox_sync_flags sync_flags)
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch{
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch struct mailbox_sync_context *sync_ctx;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch const struct virtual_backend_uidmap *uidmap;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch struct mailbox_sync_rec sync_rec;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch unsigned int idx1, idx2;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch uint32_t vseq, vuid;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch sync_ctx = mailbox_sync_init(bbox->box, sync_flags);
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch virtual_backend_box_sync_mail_set(bbox);
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch while (mailbox_sync_next(sync_ctx, &sync_rec)) {
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch switch (sync_rec.type) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch case MAILBOX_SYNC_TYPE_EXPUNGE:
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch if (ctx->expunge_removed) {
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch /* no need to keep track of expunges */
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch break;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch }
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch seq_range_array_add_range(&ctx->sync_expunges,
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch sync_rec.seq1, sync_rec.seq2);
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch break;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch case MAILBOX_SYNC_TYPE_FLAGS:
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch if (!virtual_sync_find_seqs(bbox, &sync_rec,
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch &idx1, &idx2))
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch break;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch uidmap = array_idx(&bbox->uids, 0);
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch for (; idx1 <= idx2; idx1++) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch vuid = uidmap[idx1].virtual_uid;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!mail_index_lookup_seq(ctx->sync_view,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch vuid, &vseq))
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch i_unreached();
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch virtual_sync_external_flags(ctx, bbox, vseq,
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch uidmap[idx1].real_uid);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch }
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch break;
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch case MAILBOX_SYNC_TYPE_MODSEQ:
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch break;
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch }
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch }
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch return mailbox_sync_deinit(&sync_ctx, 0, NULL);
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch}
3ec5378aadaa699c38b2e02be30aae1add36eb7cTimo Sirainen
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Boschstatic void virtual_sync_backend_ext_header(struct virtual_sync_context *ctx,
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch struct virtual_backend_box *bbox)
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch{
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch const unsigned int uidval_pos =
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch offsetof(struct virtual_mail_index_mailbox_record,
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch uid_validity);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch struct mailbox_status status;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch struct virtual_mail_index_mailbox_record mailbox;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch unsigned int mailbox_offset;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch mailbox_get_status(bbox->box, STATUS_UIDVALIDITY |
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch STATUS_HIGHESTMODSEQ, &status);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch if (bbox->sync_uid_validity == status.uidvalidity &&
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch bbox->sync_next_uid == status.uidnext &&
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch bbox->sync_highest_modseq == status.highest_modseq)
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch return;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch /* mailbox changed - update extension header */
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch bbox->sync_uid_validity = status.uidvalidity;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch bbox->sync_highest_modseq = status.highest_modseq;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch bbox->sync_next_uid = status.uidnext;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch if (!ctx->ext_header_rewrite) {
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch /* we'll rewrite the entire header later */
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch return;
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch }
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch memset(&mailbox, 0, sizeof(mailbox));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mailbox.uid_validity = bbox->sync_uid_validity;
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch mailbox.highest_modseq = bbox->sync_highest_modseq;
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch mailbox.next_uid = bbox->sync_next_uid;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch mailbox_offset = sizeof(struct virtual_mail_index_header) +
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch bbox->sync_mailbox_idx * sizeof(mailbox);
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext_id,
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch mailbox_offset + uidval_pos,
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch CONST_PTR_OFFSET(&mailbox, uidval_pos),
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch sizeof(mailbox) - uidval_pos);
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch ctx->ext_header_changed = TRUE;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Boschstatic int virtual_sync_backend_box(struct virtual_sync_context *ctx,
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch struct virtual_backend_box *bbox)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct index_mailbox *ibox = (struct index_mailbox *)bbox->box;
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch enum mailbox_sync_flags sync_flags;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct mailbox_status status;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch int ret;
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch if (!bbox->box->opened)
dbbdcc1224f81a40e746a09e6d44af7c4f24ff71Stephan Bosch index_storage_mailbox_open(ibox);
dbbdcc1224f81a40e746a09e6d44af7c4f24ff71Stephan Bosch
dbbdcc1224f81a40e746a09e6d44af7c4f24ff71Stephan Bosch /* if we already did some changes to index, commit them before
dbbdcc1224f81a40e746a09e6d44af7c4f24ff71Stephan Bosch syncing starts. */
dbbdcc1224f81a40e746a09e6d44af7c4f24ff71Stephan Bosch virtual_backend_box_sync_mail_unset(bbox);
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch /* we use modseqs for speeding up initial search result build.
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch make sure the backend has them enabled. */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mail_index_modseq_enable(ibox->index);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch sync_flags = ctx->flags & (MAILBOX_SYNC_FLAG_FULL_READ |
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch MAILBOX_SYNC_FLAG_FULL_WRITE |
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch MAILBOX_SYNC_FLAG_FAST);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (bbox->search_result == NULL) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* first sync in this process */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_assert(ctx->expunge_removed);
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (mailbox_sync(bbox->box, sync_flags, STATUS_UIDVALIDITY,
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch &status) < 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return -1;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch virtual_backend_box_sync_mail_set(bbox);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (status.uidvalidity != bbox->sync_uid_validity) {
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch /* UID validity changed since last sync (or this is
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch the first sync), do a full search */
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen ret = virtual_sync_backend_box_init(bbox);
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch } else {
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch /* build the initial search using the saved modseq.
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch we can't directly update the search result because
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch uidmap isn't finished for all messages yet, so
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch mark the sync to be retried. */
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch ret = virtual_sync_backend_box_continue(ctx, bbox);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ctx->retry = TRUE;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } else {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* sync using the existing search result */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_array_init(&ctx->sync_expunges, 32);
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch ret = virtual_sync_backend_box_sync(ctx, bbox, sync_flags);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (ret == 0) T_BEGIN {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch virtual_sync_mailbox_box_update(ctx, bbox);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } T_END;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch array_free(&ctx->sync_expunges);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch virtual_sync_backend_ext_header(ctx, bbox);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return ret;
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch}
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Boschstatic void virtual_sync_backend_map_uids(struct virtual_sync_context *ctx)
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch{
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch uint32_t virtual_ext_id = ctx->mbox->virtual_ext_id;
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch struct virtual_sync_mail *vmails;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch struct virtual_backend_box *bbox, *const *bboxes;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch struct virtual_backend_uidmap *uidmap = NULL;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch struct virtual_add_record add_rec;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch const struct virtual_mail_index_record *vrec;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch const void *data;
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch bool expunged;
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch uint32_t i, vseq, vuid, messages, count;
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch unsigned int j = 0, uidmap_count = 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch messages = mail_index_view_get_messages_count(ctx->sync_view);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch /* sort the messages in current view by their backend mailbox and
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch real UID */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch vmails = messages == 0 ? NULL :
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_new(struct virtual_sync_mail, messages);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch for (vseq = 1; vseq <= messages; vseq++) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch mail_index_lookup_ext(ctx->sync_view, vseq, virtual_ext_id,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch &data, &expunged);
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch vrec = data;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch vmails[vseq-1].vseq = vseq;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch vmails[vseq-1].vrec = *vrec;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch }
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch qsort(vmails, messages, sizeof(*vmails), virtual_sync_mail_cmp);
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* create real mailbox uid -> virtual uid mapping and expunge
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch messages no longer matching the search rule */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch memset(&add_rec, 0, sizeof(add_rec));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bbox = NULL;
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch for (i = 0; i < messages; i++) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch vseq = vmails[i].vseq;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch vrec = &vmails[i].vrec;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (bbox == NULL || bbox->mailbox_id != vrec->mailbox_id) {
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch /* add the rest of the newly seen messages */
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch for (; j < uidmap_count; j++) {
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch add_rec.rec.real_uid = uidmap[j].real_uid;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch array_append(&ctx->all_adds, &add_rec, 1);
62aa68310d6f42467ca26880f678173bf1d26a83Stephan Bosch }
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch bbox = virtual_backend_box_lookup(ctx->mbox,
62aa68310d6f42467ca26880f678173bf1d26a83Stephan Bosch vrec->mailbox_id);
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch if (bbox == NULL) {
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch /* the entire mailbox is lost */
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch mail_index_expunge(ctx->trans, vseq);
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch continue;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch }
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch uidmap = array_get_modifiable(&bbox->uids,
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch &uidmap_count);
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch j = 0;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch add_rec.rec.mailbox_id = bbox->mailbox_id;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch bbox->sync_seen = TRUE;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch }
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch mail_index_lookup_uid(ctx->sync_view, vseq, &vuid);
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch /* if virtual record doesn't exist in uidmap, it's expunged */
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch for (; j < uidmap_count; j++) {
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch if (uidmap[j].real_uid >= vrec->real_uid)
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch break;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* newly seen message */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch add_rec.rec.real_uid = uidmap[j].real_uid;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch array_append(&ctx->all_adds, &add_rec, 1);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch if (uidmap[j].real_uid != vrec->real_uid)
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch mail_index_expunge(ctx->trans, vseq);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch else {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* exists - update uidmap and flags */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uidmap[j++].virtual_uid = vuid;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch virtual_sync_external_flags(ctx, bbox, vseq,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch vrec->real_uid);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch i_free(vmails);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch /* if there are any mailboxes we didn't yet sync, add new messages in
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch them */
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch bboxes = array_get(&ctx->mbox->backend_boxes, &count);
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch for (i = 0; i < count; i++) {
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch if (bboxes[i]->sync_seen)
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch continue;
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch add_rec.rec.mailbox_id = bboxes[i]->mailbox_id;
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch uidmap = array_get_modifiable(&bboxes[i]->uids, &uidmap_count);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch for (j = 0; j < uidmap_count; j++) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch add_rec.rec.real_uid = uidmap[j].real_uid;
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch array_append(&ctx->all_adds, &add_rec, 1);
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic int virtual_add_record_cmp(const void *p1, const void *p2)
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch{
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch const struct virtual_add_record *add1 = p1, *add2 = p2;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch if (add1->received_date < add2->received_date)
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch return -1;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (add1->received_date > add2->received_date)
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch return 1;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* if they're in same mailbox, we can order them correctly by the UID.
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if they're in different mailboxes, ordering by UID doesn't really
639bb36b12b9f9bb54c8bb1be50eac623622f8a0Timo Sirainen help but it doesn't really harm either. */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (add1->rec.real_uid < add2->rec.real_uid)
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch return -1;
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch if (add1->rec.real_uid > add2->rec.real_uid)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 1;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* two messages in different mailboxes have the same received date
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch and UID. */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void virtual_sync_backend_sort_new(struct virtual_sync_context *ctx)
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct virtual_backend_box *bbox;
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch struct virtual_add_record *adds;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const struct virtual_mail_index_record *vrec;
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch unsigned int i, count;
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch /* get all messages' received dates */
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch adds = array_get_modifiable(&ctx->all_adds, &count);
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch for (bbox = NULL, i = 0; i < count; i++) {
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch vrec = &adds[i].rec;
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (bbox == NULL || bbox->mailbox_id != vrec->mailbox_id) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bbox = virtual_backend_box_lookup(ctx->mbox,
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch vrec->mailbox_id);
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!mail_set_uid(bbox->sync_mail, vrec->real_uid))
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch i_unreached();
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (mail_get_received_date(bbox->sync_mail,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch &adds[i].received_date) < 0) {
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch /* probably expunged already, just add it somewhere */
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch adds[i].received_date = 0;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch }
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch }
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch qsort(adds, count, sizeof(*adds), virtual_add_record_cmp);
61f962e8f32a4870d08fb6f2189fdf6a10fd1abbStephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void virtual_sync_backend_add_new(struct virtual_sync_context *ctx)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
a643e1e3e5d9d8a60eeff83601f86ee00c26332aStephan Bosch uint32_t virtual_ext_id = ctx->mbox->virtual_ext_id;
a643e1e3e5d9d8a60eeff83601f86ee00c26332aStephan Bosch struct virtual_add_record *adds;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct virtual_backend_box *bbox;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct virtual_backend_uidmap *uidmap;
a643e1e3e5d9d8a60eeff83601f86ee00c26332aStephan Bosch const struct virtual_mail_index_record *vrec;
a643e1e3e5d9d8a60eeff83601f86ee00c26332aStephan Bosch unsigned int i, count, idx, uid_count;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch uint32_t vseq, first_uid, next_uid;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
a643e1e3e5d9d8a60eeff83601f86ee00c26332aStephan Bosch adds = array_get_modifiable(&ctx->all_adds, &count);
a643e1e3e5d9d8a60eeff83601f86ee00c26332aStephan Bosch if (count == 0)
a643e1e3e5d9d8a60eeff83601f86ee00c26332aStephan Bosch return;
a643e1e3e5d9d8a60eeff83601f86ee00c26332aStephan Bosch
a643e1e3e5d9d8a60eeff83601f86ee00c26332aStephan Bosch if (adds[0].rec.mailbox_id == adds[count-1].rec.mailbox_id) {
a643e1e3e5d9d8a60eeff83601f86ee00c26332aStephan Bosch /* all messages are from a single mailbox. add them in
a643e1e3e5d9d8a60eeff83601f86ee00c26332aStephan Bosch the same order. */
a643e1e3e5d9d8a60eeff83601f86ee00c26332aStephan Bosch } else {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* sort new messages by received date to get the add order */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch virtual_sync_backend_sort_new(ctx);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch for (bbox = NULL, i = 0; i < count; i++) {
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen vrec = &adds[i].rec;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (bbox == NULL || bbox->mailbox_id != vrec->mailbox_id) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bbox = virtual_backend_box_lookup(ctx->mbox,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch vrec->mailbox_id);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch mail_index_append(ctx->trans, 0, &vseq);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch mail_index_update_ext(ctx->trans, vseq, virtual_ext_id,
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch vrec, NULL);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch virtual_sync_external_flags(ctx, bbox, vseq, vrec->real_uid);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch }
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch /* assign UIDs to new messages */
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch first_uid = mail_index_get_header(ctx->sync_view)->next_uid;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch mail_index_append_assign_uids(ctx->trans, first_uid, &next_uid);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch /* update virtual UIDs in uidmap */
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch for (bbox = NULL, i = 0; i < count; i++) {
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch vrec = &adds[i].rec;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch if (bbox == NULL || bbox->mailbox_id != vrec->mailbox_id) {
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch bbox = virtual_backend_box_lookup(ctx->mbox,
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch vrec->mailbox_id);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch }
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch uidmap = array_get_modifiable(&bbox->uids, &uid_count);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch if (!bsearch_insert_pos(&vrec->real_uid, uidmap, uid_count,
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch sizeof(*uidmap),
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch virtual_backend_uidmap_bsearch_cmp,
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch &idx))
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch i_unreached();
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch i_assert(uidmap[idx].virtual_uid == 0);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch uidmap[idx].virtual_uid = first_uid + i;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch }
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch}
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Boschstatic int virtual_sync_backend_boxes(struct virtual_sync_context *ctx)
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch{
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch struct virtual_backend_box *const *bboxes;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch unsigned int i, count;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch i_array_init(&ctx->all_adds, 128);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch bboxes = array_get(&ctx->mbox->backend_boxes, &count);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch for (i = 0; i < count; i++) {
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch if (virtual_sync_backend_box(ctx, bboxes[i]) < 0)
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch return -1;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch }
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch if (!ctx->mbox->uids_mapped) {
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch /* initial sync: assign virtual UIDs to existing messages and
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch sync all flags */
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch ctx->mbox->uids_mapped = TRUE;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch virtual_sync_backend_map_uids(ctx);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch }
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch virtual_sync_backend_add_new(ctx);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch array_free(&ctx->all_adds);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch return 0;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch}
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Boschstatic void virtual_sync_backend_boxes_finish(struct virtual_sync_context *ctx)
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch{
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch struct virtual_backend_box *const *bboxes;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch unsigned int i, count;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch bboxes = array_get(&ctx->mbox->backend_boxes, &count);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch for (i = 0; i < count; i++)
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch virtual_backend_box_sync_mail_unset(bboxes[i]);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch}
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Boschstatic int virtual_sync_finish(struct virtual_sync_context *ctx, bool success)
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch{
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch int ret = success ? 0 : -1;
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch virtual_sync_backend_boxes_finish(ctx);
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch if (success) {
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch if (mail_index_sync_commit(&ctx->index_sync_ctx) < 0) {
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch mail_storage_set_index_error(&ctx->mbox->ibox);
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch ret = -1;
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch }
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch } else {
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch mail_index_sync_rollback(&ctx->index_sync_ctx);
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch }
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch i_free(ctx);
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch return 0;
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch}
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Boschstatic int virtual_sync(struct virtual_mailbox *mbox,
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch enum mailbox_sync_flags flags)
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch{
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch struct virtual_sync_context *ctx;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch enum mail_index_sync_flags index_sync_flags;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch int ret;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch ctx = i_new(struct virtual_sync_context, 1);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch ctx->mbox = mbox;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch ctx->flags = flags;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch ctx->index = mbox->ibox.index;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch /* Removed messages are expunged when
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch a) EXPUNGE is used
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch b) Mailbox is being opened (FIX_INCONSISTENT is set) */
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch ctx->expunge_removed =
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch (ctx->flags & (MAILBOX_SYNC_FLAG_EXPUNGE |
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch MAILBOX_SYNC_FLAG_FIX_INCONSISTENT)) != 0;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch index_sync_flags = MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY |
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch MAIL_INDEX_SYNC_FLAG_AVOID_FLAG_UPDATES;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch if (!mbox->ibox.keep_recent)
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch index_sync_flags |= MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch ret = mail_index_sync_begin(ctx->index, &ctx->index_sync_ctx,
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch &ctx->sync_view, &ctx->trans,
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch index_sync_flags);
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch if (ret <= 0) {
458d877d84f62005e0ffc338f8591a8e2a36adadStephan Bosch if (ret < 0)
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch mail_storage_set_index_error(&mbox->ibox);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch i_free(ctx);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch return ret;
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch }
e4e9ba5f43f9bf7e072d7d9fcc3259a42ecb15c8Stephan Bosch
e4e9ba5f43f9bf7e072d7d9fcc3259a42ecb15c8Stephan Bosch if (!virtual_sync_ext_header_read(ctx))
e4e9ba5f43f9bf7e072d7d9fcc3259a42ecb15c8Stephan Bosch ctx->ext_header_rewrite = TRUE;
e4e9ba5f43f9bf7e072d7d9fcc3259a42ecb15c8Stephan Bosch /* apply changes from virtual index to backend mailboxes */
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch virtual_sync_index_changes(ctx);
af53c056cf1e3d133a78c201e72a678b5431d0fbStephan Bosch /* update list of UIDs in backend mailboxes */
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch ret = virtual_sync_backend_boxes(ctx);
af53c056cf1e3d133a78c201e72a678b5431d0fbStephan Bosch if (ctx->retry && ret == 0) {
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch ctx->retry = FALSE;
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch ret = virtual_sync_backend_boxes(ctx);
4e52bade0f83746405ecc1d0396e9b2ac7b98cd8Stephan Bosch i_assert(!ctx->retry);
af53c056cf1e3d133a78c201e72a678b5431d0fbStephan Bosch }
af53c056cf1e3d133a78c201e72a678b5431d0fbStephan Bosch if (ret < 0)
787d28c5d61cf24582b96d7275aee001e03520ddTimo Sirainen return virtual_sync_finish(ctx, FALSE);
af53c056cf1e3d133a78c201e72a678b5431d0fbStephan Bosch
af53c056cf1e3d133a78c201e72a678b5431d0fbStephan Bosch virtual_sync_index_finish(ctx);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch return virtual_sync_finish(ctx, TRUE);
af53c056cf1e3d133a78c201e72a678b5431d0fbStephan Bosch}
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Boschstruct mailbox_sync_context *
af53c056cf1e3d133a78c201e72a678b5431d0fbStephan Boschvirtual_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
af53c056cf1e3d133a78c201e72a678b5431d0fbStephan Bosch{
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch int ret = 0;
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch if (!box->opened)
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch index_storage_mailbox_open(&mbox->ibox);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch if (index_mailbox_want_full_sync(&mbox->ibox, flags))
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch ret = virtual_sync(mbox, flags);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch return index_mailbox_sync_init(box, flags, ret < 0);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch}
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch