# HG changeset patch # User Timo Sirainen # Date 1248652297 14400 # Node ID 88d4e83fcea5187af3d671a3950f5a15300f4438 # Parent b24bdff70c63a9f19ec7857d6c8e50f0b91985b5 virtual: If another session adds a new mailbox to index, handle it without crashing. For now we'll just disconnect the session. diff -r b24bdff70c63 -r 88d4e83fcea5 src/plugins/virtual/virtual-storage.c --- a/src/plugins/virtual/virtual-storage.c Sun Jul 26 19:37:05 2009 -0400 +++ b/src/plugins/virtual/virtual-storage.c Sun Jul 26 19:51:37 2009 -0400 @@ -630,6 +630,16 @@ array_append_array(excludes, &mbox->list_exclude_patterns); } +static bool virtual_is_inconsistent(struct mailbox *box) +{ + struct virtual_mailbox *mbox = (struct virtual_mailbox *)box; + + if (mbox->inconsistent) + return TRUE; + + return index_storage_is_inconsistent(box); +} + static void virtual_class_init(void) { virtual_transaction_class_init(); @@ -700,6 +710,6 @@ virtual_save_finish, virtual_save_cancel, mail_storage_copy, - index_storage_is_inconsistent + virtual_is_inconsistent } }; diff -r b24bdff70c63 -r 88d4e83fcea5 src/plugins/virtual/virtual-storage.h --- a/src/plugins/virtual/virtual-storage.h Sun Jul 26 19:37:05 2009 -0400 +++ b/src/plugins/virtual/virtual-storage.h Sun Jul 26 19:51:37 2009 -0400 @@ -124,6 +124,7 @@ unsigned int uids_mapped:1; unsigned int sync_initialized:1; + unsigned int inconsistent:1; }; extern MODULE_CONTEXT_DEFINE(virtual_storage_module, diff -r b24bdff70c63 -r 88d4e83fcea5 src/plugins/virtual/virtual-sync.c --- a/src/plugins/virtual/virtual-sync.c Sun Jul 26 19:37:05 2009 -0400 +++ b/src/plugins/virtual/virtual-sync.c Sun Jul 26 19:51:37 2009 -0400 @@ -130,7 +130,24 @@ return 0; } -static bool virtual_sync_ext_header_read(struct virtual_sync_context *ctx) +static int +virtual_sync_get_backend_box(struct virtual_sync_context *ctx, const char *name, + struct virtual_backend_box **bbox_r) +{ + *bbox_r = virtual_backend_box_lookup_name(ctx->mbox, name); + if (*bbox_r != NULL || !ctx->mbox->sync_initialized) + return 0; + + /* another process just added a new mailbox. + we can't handle this currently. */ + ctx->mbox->inconsistent = TRUE; + mail_storage_set_error(ctx->mbox->ibox.box.storage, MAIL_ERROR_TEMP, + "Backend mailbox added by another session. " + "Reopen the virtual mailbox."); + return -1; +} + +static int virtual_sync_ext_header_read(struct virtual_sync_context *ctx) { const struct virtual_mail_index_header *ext_hdr; const struct mail_index_header *hdr; @@ -140,7 +157,7 @@ size_t ext_size; unsigned int i, count, ext_name_offset, ext_mailbox_count; uint32_t prev_mailbox_id; - bool ret = TRUE; + int ret = 1; hdr = mail_index_get_header(ctx->sync_view); mail_index_get_header_ext(ctx->sync_view, ctx->mbox->virtual_ext_id, @@ -154,7 +171,6 @@ return TRUE; } - ctx->mbox->sync_initialized = TRUE; ctx->mbox->prev_uid_validity = hdr->uid_validity; if (ext_hdr == NULL || ctx->mbox->search_args_crc32 != ext_hdr->search_args_crc32) { @@ -172,7 +188,7 @@ ctx->mbox->path); ctx->index_broken = TRUE; ext_mailbox_count = 0; - ret = FALSE; + ret = 0; } else { ext_mailbox_count = ext_hdr->mailbox_count; } @@ -204,11 +220,15 @@ nameptr = CONST_PTR_OFFSET(ext_data, ext_name_offset); name = t_strndup(nameptr, mailboxes[i].name_len); - bbox = virtual_backend_box_lookup_name(ctx->mbox, name); + if (virtual_sync_get_backend_box(ctx, name, &bbox) < 0) + ret = -1; } T_END; + if (bbox == NULL) { - /* mailbox no longer exists */ - ret = FALSE; + if (ret < 0) + return -1; + /* mailbox no longer exists. */ + ret = 0; } else { bbox->mailbox_id = mailboxes[i].id; bbox->sync_uid_validity = mailboxes[i].uid_validity; @@ -221,17 +241,18 @@ } if (i < ext_mailbox_count) { ctx->index_broken = TRUE; - ret = FALSE; + ret = 0; } ctx->mbox->highest_mailbox_id = ext_hdr == NULL ? 0 : ext_hdr->highest_mailbox_id; + ctx->mbox->sync_initialized = TRUE; /* assign new mailbox IDs if any are missing */ bboxes = array_get_modifiable(&ctx->mbox->backend_boxes, &count); for (i = 0; i < count; i++) { if (bboxes[i]->mailbox_id == 0) { bboxes[i]->mailbox_id = ++ctx->mbox->highest_mailbox_id; - ret = FALSE; + ret = 0; } } /* sort the backend mailboxes by mailbox_id. */ @@ -1256,7 +1277,7 @@ ctx->mbox->sync_virtual_next_uid = first_uid + i; } -static void +static int virtual_sync_apply_existing_appends(struct virtual_sync_context *ctx) { uint32_t virtual_ext_id = ctx->mbox->virtual_ext_id; @@ -1269,18 +1290,18 @@ uint32_t seq, seq2; if (!ctx->mbox->uids_mapped) - return; + return 0; hdr = mail_index_get_header(ctx->sync_view); if (ctx->mbox->sync_virtual_next_uid >= hdr->next_uid) - return; + return 0; /* another process added messages to virtual index. get backend boxes' uid lists up-to-date by adding the new messages there. */ if (!mail_index_lookup_seq_range(ctx->sync_view, ctx->mbox->sync_virtual_next_uid, (uint32_t)-1, &seq, &seq2)) - return; + return 0; memset(&uidmap, 0, sizeof(uidmap)); for (; seq <= seq2; seq++) { @@ -1293,12 +1314,20 @@ if (bbox == NULL || bbox->mailbox_id != vrec->mailbox_id) { bbox = virtual_backend_box_lookup(ctx->mbox, vrec->mailbox_id); + if (bbox == NULL) { + mail_storage_set_critical( + ctx->mbox->ibox.box.storage, + "Mailbox ID %u unexpectedly lost", + vrec->mailbox_id); + return -1; + } } array_append(&bbox->uids, &uidmap, 1); bbox->uids_nonsorted = TRUE; } virtual_sync_backend_boxes_sort_uids(ctx->mbox); + return 0; } static void @@ -1341,7 +1370,8 @@ unsigned int i, count; int ret; - virtual_sync_apply_existing_appends(ctx); + if (virtual_sync_apply_existing_appends(ctx) < 0) + return -1; i_array_init(&ctx->all_adds, 128); bboxes = array_get(&ctx->mbox->backend_boxes, &count); @@ -1437,7 +1467,10 @@ return ret; } - if (!virtual_sync_ext_header_read(ctx)) + ret = virtual_sync_ext_header_read(ctx); + if (ret < 0) + return virtual_sync_finish(ctx, FALSE); + if (ret == 0) ctx->ext_header_rewrite = TRUE; /* apply changes from virtual index to backend mailboxes */ virtual_sync_index_changes(ctx);