virtual-sync.c revision 074055dadbca01626437cc4724853a374acab6a8
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (c) 2008-2014 Dovecot authors, see the included COPYING file */
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen const char *const *kw_all;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen /* messages expunged within this sync */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void virtual_sync_set_uidvalidity(struct virtual_sync_context *ctx)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen offsetof(struct mail_index_header, uid_validity),
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainenstatic void virtual_sync_external_flags(struct virtual_sync_context *ctx,
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen const char *const *kw_names;
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainen if (!mail_set_uid(bbox->sync_mail, real_uid)) {
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainen /* we may have reopened the mailbox, which could have
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen caused the mail to be expunged already. */
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen /* copy flags */
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen mail_index_update_flags(ctx->trans, vseq, MODIFY_REPLACE, flags);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* copy keywords */
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen kw_names = mail_get_keywords(bbox->sync_mail);
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainen keywords = mail_index_keywords_create(ctx->index, kw_names);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen mail_index_update_keywords(ctx->trans, vseq, MODIFY_REPLACE, keywords);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainenstatic int virtual_sync_mail_cmp(const void *p1, const void *p2)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen const struct virtual_sync_mail *m1 = p1, *m2 = p2;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (m1->vrec.mailbox_id < m2->vrec.mailbox_id)
9f131c8b6d88ffc65d94eae63e0b3c11d7c24cb9Timo Sirainen if (m1->vrec.mailbox_id > m2->vrec.mailbox_id)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenvirtual_backend_box_sync_mail_set(struct virtual_backend_box *bbox)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen trans = mailbox_transaction_begin(bbox->box, 0);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int bbox_mailbox_id_cmp(struct virtual_backend_box *const *b1,
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainenvirtual_sync_get_backend_box(struct virtual_sync_context *ctx, const char *name,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen *bbox_r = virtual_backend_box_lookup_name(ctx->mbox, name);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (*bbox_r != NULL || !ctx->mbox->sync_initialized)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* another process just added a new mailbox.
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen we can't handle this currently. */
411d6baa37f31d90730e90c4a28c43e1974bbe58Timo Sirainen mail_storage_set_error(ctx->mbox->box.storage, MAIL_ERROR_TEMP,
4ae354df6e08998137b527f495bfaaf3daf9eddcTimo Sirainen "Backend mailbox added by another session. "
4ae354df6e08998137b527f495bfaaf3daf9eddcTimo Sirainen "Reopen the virtual mailbox.");
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainenstatic int virtual_sync_ext_header_read(struct virtual_sync_context *ctx)
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainen const char *box_path = mailbox_get_path(&ctx->mbox->box);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const struct virtual_mail_index_header *ext_hdr;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen const struct virtual_mail_index_mailbox_record *mailboxes;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen unsigned int i, count, ext_name_offset, ext_mailbox_count;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen mail_index_get_header_ext(ctx->sync_view, ctx->mbox->virtual_ext_id,
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen ctx->mbox->prev_uid_validity == hdr->uid_validity &&
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen ctx->mbox->prev_change_counter == ext_hdr->change_counter) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* fully refreshed */
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen ctx->mbox->prev_uid_validity = hdr->uid_validity;
e17d72cec1c75554483d692edd687b411526f312Timo Sirainen ctx->mbox->search_args_crc32 != ext_hdr->search_args_crc32) {
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen ctx->mbox->prev_change_counter = ext_hdr->change_counter;
e17d72cec1c75554483d692edd687b411526f312Timo Sirainen ext_hdr->mailbox_count > INT_MAX/sizeof(*mailboxes)) {
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen i_error("virtual index %s: Broken mailbox_count header",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* update mailbox backends */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen for (i = 0; i < ext_mailbox_count; i++) {
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen if (mailboxes[i].id > ext_hdr->highest_mailbox_id ||
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_error("virtual index %s: Broken mailbox id",
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen i_error("virtual index %s: Broken mailbox name_len",
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen if (ext_name_offset + mailboxes[i].name_len > ext_size) {
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen i_error("virtual index %s: Broken mailbox list",
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen const unsigned char *nameptr;
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen nameptr = CONST_PTR_OFFSET(ext_data, ext_name_offset);
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen name = t_strndup(nameptr, mailboxes[i].name_len);
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen if (virtual_sync_get_backend_box(ctx, name, &bbox) < 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* mailbox no longer exists. */
da2aa032ccfa8e7e4a4380ef738014549f4d2c2dTimo Sirainen bbox->sync_uid_validity = mailboxes[i].uid_validity;
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen ctx->mbox->highest_mailbox_id = ext_hdr == NULL ? 0 :
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen /* assign new mailbox IDs if any are missing */
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen bboxes = array_get_modifiable(&ctx->mbox->backend_boxes, &count);
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen for (i = 0; i < count; i++) {
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen bboxes[i]->mailbox_id = ++ctx->mbox->highest_mailbox_id;
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen /* sort the backend mailboxes by mailbox_id. */
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen array_sort(&ctx->mbox->backend_boxes, bbox_mailbox_id_cmp);
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainenstatic void virtual_sync_ext_header_rewrite(struct virtual_sync_context *ctx)
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen struct virtual_mail_index_mailbox_record mailbox;
for (i = 0; i < count; i++) {
i_assert(i == 0 ||
sizeof(struct virtual_mail_index_record),
sizeof(uint32_t));
const void *data;
if (flags != 0) {
if (flags != 0) {
kw_names);
int ret;
0, NULL);
return ret;
if (uid_count == 0)
i_unreached();
for (i = 0; i < uid_count; i++) {
&vseq))
if (uid_count == 0)
if (rec_count == 0 ||
&dest))
i_unreached();
for (i = 0; i < uid_count; i++) {
unsigned int i, count;
for (i = 0; i < count; i++) {
const void *data;
old_msg_count = 0;
&removed_uids);
unsigned int i, n = 0, count;
if (i == count)
for (; i < count; ) {
unsigned int i, n = 0, count;
for (; i < count; ) {
if (!iter_done) {
&added_uids);
&temp_uids);
&removed_uids);
&removed_uids);
unsigned int *idx1_r,
unsigned int *idx2_r)
&idx);
return FALSE;
return TRUE;
&idx1);
case MAILBOX_SYNC_TYPE_FLAGS:
case MAILBOX_SYNC_TYPE_MODSEQ:
const unsigned int uidval_pos =
unsigned int mailbox_offset;
int ret;
if (!bbox_index_opened) {
&status);
if (ret < 0)
if (!bbox_index_opened) {
} T_END;
return ret;
const void *data;
unsigned int j = 0, uidmap_count = 0;
if (messages == 0)
for (i = 0; i < messages; i++) {
for (; j < uidmap_count; j++) {
&uidmap_count);
j = uidmap_count;
for (; j < uidmap_count; j++) {
for (; j < uidmap_count; j++) {
for (i = 0; i < count; i++) {
for (j = 0; j < uidmap_count; j++) {
unsigned int i, count;
if (count == 0) {
&idx))
i_unreached();
const void *data;
const void *data;
unsigned int i, count;
int ret;
for (i = 0; i < count; i++) {
return ret;
unsigned int i, count;
for (i = 0; i < count; i++)
if (success) {
return ret;
int ret;
if (ret <= 0) {
if (ret < 0)
return ret;
if (ret < 0)
if (ret == 0)
struct mailbox_sync_context *
int ret = 0;
return sync_ctx;