virtual-sync.c revision 6cd263d9a9812174a63e852ad6a9a8cdf63cfd8e
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */
d99107ddf4d9bccb710994482daf65276a9d6321Timo Sirainen const char *const *kw_all;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* messages expunged within this sync */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen ARRAY_DEFINE(all_adds, struct virtual_add_record);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenstatic void virtual_sync_set_uidvalidity(struct virtual_sync_context *ctx)
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch offsetof(struct mail_index_header, uid_validity),
04eb0abcf8f8b0c014499b5c5bae89484553613fStephan Boschstatic void virtual_sync_external_flags(struct virtual_sync_context *ctx,
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen const char *const *kw_names;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if (!mail_set_uid(bbox->sync_mail, real_uid)) {
f32d0295c90ed810889504cdfa5e1a25a415f65fStephan Bosch /* copy flags */
f32d0295c90ed810889504cdfa5e1a25a415f65fStephan Bosch mail_index_update_flags(ctx->trans, vseq, MODIFY_REPLACE, flags);
04eb0abcf8f8b0c014499b5c5bae89484553613fStephan Bosch /* copy keywords */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen kw_names = mail_get_keywords(bbox->sync_mail);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen keywords = mail_index_keywords_create(ctx->index, kw_names);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen mail_index_update_keywords(ctx->trans, vseq, MODIFY_REPLACE, keywords);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic int virtual_sync_mail_cmp(const void *p1, const void *p2)
d694a52bce62c52080c3f87a56dcf77030fd2712Timo Sirainen const struct virtual_sync_mail *m1 = p1, *m2 = p2;
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen if (m1->vrec.mailbox_id < m2->vrec.mailbox_id)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (m1->vrec.mailbox_id > m2->vrec.mailbox_id)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenvirtual_backend_box_sync_mail_set(struct virtual_backend_box *bbox)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen trans = mailbox_transaction_begin(bbox->box, 0);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenvirtual_backend_box_sync_mail_unset(struct virtual_backend_box *bbox)
2b96880f2d789d125aff6a95eaa7b51f558a6a1cTimo Sirainenstatic int bbox_mailbox_id_cmp(struct virtual_backend_box *const *b1,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenvirtual_sync_get_backend_box(struct virtual_sync_context *ctx, const char *name,
64e244defe74f513ce94f33d000a048ddbe2ea23Timo Sirainen *bbox_r = virtual_backend_box_lookup_name(ctx->mbox, name);
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen if (*bbox_r != NULL || !ctx->mbox->sync_initialized)
009217abb57a24a4076092e8e4e165545747839eStephan Bosch /* another process just added a new mailbox.
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen we can't handle this currently. */
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen mail_storage_set_error(ctx->mbox->ibox.box.storage, MAIL_ERROR_TEMP,
8ce3071e80b9973230048ecadfcb073fb82cc69fTimo Sirainen "Backend mailbox added by another session. "
fe791e96fdf796f7d8997ee0515b163dc5eddd72Aki Tuomi "Reopen the virtual mailbox.");
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainenstatic int virtual_sync_ext_header_read(struct virtual_sync_context *ctx)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const struct virtual_mail_index_header *ext_hdr;
660b99a7059824676b2b8d6f79b8e15d47df25a2Timo Sirainen const struct virtual_mail_index_mailbox_record *mailboxes;
bbba7d0fce1b6ce5baa2d7ef946eb1b63e2ab518Timo Sirainen unsigned int i, count, ext_name_offset, ext_mailbox_count;
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen mail_index_get_header_ext(ctx->sync_view, ctx->mbox->virtual_ext_id,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen ctx->mbox->prev_uid_validity == hdr->uid_validity &&
7a94f950fd1dcc81537acfc8adb030b5e703d722Timo Sirainen ctx->mbox->prev_change_counter == ext_hdr->change_counter) {
aebfda1f6e3a924c31e8f54237b81fabf4b2264cTimo Sirainen /* fully refreshed */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen ctx->mbox->prev_uid_validity = hdr->uid_validity;
bf72c930996df0691932fb1143f360d260f27a06Timo Sirainen ctx->mbox->search_args_crc32 != ext_hdr->search_args_crc32) {
02ccba3d3be96444abd15b5254864c9151bbeb30Timo Sirainen ctx->mbox->prev_change_counter = ext_hdr->change_counter;
ce1a6c9b82117d253df9acd77e54ac84dd8a247eTimo Sirainen ext_hdr->mailbox_count > INT_MAX/sizeof(*mailboxes)) {
ce1a6c9b82117d253df9acd77e54ac84dd8a247eTimo Sirainen i_error("virtual index %s: Broken mailbox_count header",
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen /* update mailbox backends */
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen for (i = 0; i < ext_mailbox_count; i++) {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (mailboxes[i].id > ext_hdr->highest_mailbox_id ||
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen i_error("virtual index %s: Broken mailbox id",
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen i_error("virtual index %s: Broken mailbox name_len",
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen if (ext_name_offset + mailboxes[i].name_len > ext_size) {
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen i_error("virtual index %s: Broken mailbox list",
c5e62353a11087958ea4e619660e084a613e1a37Timo Sirainen const unsigned char *nameptr;
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen nameptr = CONST_PTR_OFFSET(ext_data, ext_name_offset);
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen name = t_strndup(nameptr, mailboxes[i].name_len);
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen if (virtual_sync_get_backend_box(ctx, name, &bbox) < 0)
f059a046515f4b2b15a6c2a10a6f12f6166e39a5Timo Sirainen /* mailbox no longer exists. */
a05fec120ecd8c4ed6331c42100cba42adf22893Stephan Bosch bbox->sync_uid_validity = mailboxes[i].uid_validity;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen bbox->sync_highest_modseq = mailboxes[i].highest_modseq;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen ctx->mbox->highest_mailbox_id = ext_hdr == NULL ? 0 :
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* assign new mailbox IDs if any are missing */
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen bboxes = array_get_modifiable(&ctx->mbox->backend_boxes, &count);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen for (i = 0; i < count; i++) {
6a9e034441607c0c5a61858ff559af4615ac31caTimo Sirainen bboxes[i]->mailbox_id = ++ctx->mbox->highest_mailbox_id;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* sort the backend mailboxes by mailbox_id. */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen array_sort(&ctx->mbox->backend_boxes, bbox_mailbox_id_cmp);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenstatic void virtual_sync_ext_header_rewrite(struct virtual_sync_context *ctx)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen struct virtual_mail_index_mailbox_record mailbox;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen bboxes = array_get_modifiable(&ctx->mbox->backend_boxes, &count);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen name_pos = mailbox_pos + sizeof(mailbox) * count;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen ext_hdr.change_counter = ++ctx->mbox->prev_change_counter;
c49a19168dab6fda80aee16ad799a8a56d3bc18fTimo Sirainen ext_hdr.highest_mailbox_id = ctx->mbox->highest_mailbox_id;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen ext_hdr.search_args_crc32 = ctx->mbox->search_args_crc32;
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(), name_pos + 256);
717bb0dbaf4bd3f745669570647845e6d493bfe0Timo Sirainen buffer_append(buf, &ext_hdr, sizeof(ext_hdr));
c5e62353a11087958ea4e619660e084a613e1a37Timo Sirainen for (i = 0; i < count; i++) {
c5e62353a11087958ea4e619660e084a613e1a37Timo Sirainen bboxes[i]->mailbox_id > bboxes[i-1]->mailbox_id);
sizeof(struct virtual_mail_index_record),
sizeof(uint32_t));
const void *data;
bool expunged;
if (flags != 0) {
if (flags != 0) {
kw_names);
kw_names);
keywords);
i_unreached();
int ret;
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;
bool expunged;
&seq)) {
old_msg_count = 0;
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;
&status) < 0)
} T_END;
return ret;
const void *data;
bool expunged;
unsigned int j = 0, uidmap_count = 0;
for (i = 0; i < messages; i++) {
for (; j < uidmap_count; j++) {
&uidmap_count);
for (; j < uidmap_count; j++) {
for (; j < uidmap_count; j++) {
for (i = 0; i < count; i++) {
for (j = 0; j < uidmap_count; j++) {
unsigned int i, count;
i_unreached();
if (count == 0) {
&idx))
i_unreached();
const void *data;
bool expunged;
const void *data;
bool expunged;
unsigned int i, count;
for (i = 0; i < count; i++) {
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;