# HG changeset patch # User Timo Sirainen # Date 1487349051 -7200 # Node ID 15e700c083c0473a48619779093686d2a8a3a5b0 # Parent 236081fab146b8560504ade0387e83a77c742a6b lib-storage: Fix error handling when searching mails Only expunge errors and failures caused by lookup_abort should be ignored. The rest of the mail errors mean that the search result might not be correct. We'll still run the search as fully as possible, but we just return an error at the end. diff -r 236081fab146 -r 15e700c083c0 src/lib-storage/index/index-search.c --- a/src/lib-storage/index/index-search.c Fri Feb 17 18:24:31 2017 +0200 +++ b/src/lib-storage/index/index-search.c Fri Feb 17 18:30:51 2017 +0200 @@ -66,6 +66,31 @@ { } +static void search_set_failed(struct index_search_context *ctx) +{ + if (ctx->failed) + return; + + /* remember the first failure */ + mail_storage_last_error_push(ctx->box->storage); + ctx->failed = TRUE; +} + +static void search_cur_mail_failed(struct index_search_context *ctx) +{ + switch (mailbox_get_last_mail_error(ctx->cur_mail->box)) { + case MAIL_ERROR_EXPUNGED: + ctx->mail_ctx.seen_lost_data = TRUE; + break; + case MAIL_ERROR_NOTPOSSIBLE: + /* lookup_abort hit */ + break; + default: + search_set_failed(ctx); + break; + } +} + static void search_init_arg(struct mail_search_arg *arg, struct index_search_context *ctx) { @@ -255,8 +280,10 @@ if (strcmp(box->vname, arg->value.str) == 0) return 1; if (mail_get_special(ctx->cur_mail, MAIL_FETCH_MAILBOX_NAME, - &str) < 0) + &str) < 0) { + search_cur_mail_failed(ctx); return -1; + } if (strcasecmp(str, "INBOX") == 0) return strcasecmp(arg->value.str, "INBOX") == 0; @@ -265,8 +292,10 @@ if (imap_match(arg->initialized.mailbox_glob, box->vname) == IMAP_MATCH_YES) return 1; if (mail_get_special(ctx->cur_mail, MAIL_FETCH_MAILBOX_NAME, - &str) < 0) + &str) < 0) { + search_cur_mail_failed(ctx); return -1; + } return imap_match(arg->initialized.mailbox_glob, str) == IMAP_MATCH_YES; default: return -1; @@ -308,17 +337,23 @@ have_tz_offset = FALSE; tz_offset = 0; date = (time_t)-1; switch (arg->value.date_type) { case MAIL_SEARCH_DATE_TYPE_SENT: - if (mail_get_date(ctx->cur_mail, &date, &tz_offset) < 0) + if (mail_get_date(ctx->cur_mail, &date, &tz_offset) < 0) { + search_cur_mail_failed(ctx); return -1; + } have_tz_offset = TRUE; break; case MAIL_SEARCH_DATE_TYPE_RECEIVED: - if (mail_get_received_date(ctx->cur_mail, &date) < 0) + if (mail_get_received_date(ctx->cur_mail, &date) < 0) { + search_cur_mail_failed(ctx); return -1; + } break; case MAIL_SEARCH_DATE_TYPE_SAVED: - if (mail_get_save_date(ctx->cur_mail, &date) < 0) + if (mail_get_save_date(ctx->cur_mail, &date) < 0) { + search_cur_mail_failed(ctx); return -1; + } break; } @@ -347,8 +382,10 @@ /* sizes */ case SEARCH_SMALLER: case SEARCH_LARGER: - if (mail_get_virtual_size(ctx->cur_mail, &virtual_size) < 0) + if (mail_get_virtual_size(ctx->cur_mail, &virtual_size) < 0) { + search_cur_mail_failed(ctx); return -1; + } if (arg->type == SEARCH_SMALLER) return virtual_size < arg->value.size; @@ -356,14 +393,18 @@ return virtual_size > arg->value.size; case SEARCH_GUID: - if (mail_get_special(ctx->cur_mail, MAIL_FETCH_GUID, &str) < 0) + if (mail_get_special(ctx->cur_mail, MAIL_FETCH_GUID, &str) < 0) { + search_cur_mail_failed(ctx); return -1; + } return strcmp(str, arg->value.str) == 0; case SEARCH_REAL_UID: { struct mail *real_mail; - if (mail_get_backend_mail(ctx->cur_mail, &real_mail) < 0) + if (mail_get_backend_mail(ctx->cur_mail, &real_mail) < 0) { + search_cur_mail_failed(ctx); return -1; + } return seq_range_exists(&arg->value.seqset, real_mail->uid); } default: @@ -688,8 +729,10 @@ hdr_ctx.index_ctx = ctx; /* hdr_ctx.imail is different from imail for mails in virtual mailboxes */ - if (mail_get_backend_mail(ctx->cur_mail, &real_mail) < 0) + if (mail_get_backend_mail(ctx->cur_mail, &real_mail) < 0) { + search_cur_mail_failed(ctx); return -1; + } hdr_ctx.imail = (struct index_mail *)real_mail; hdr_ctx.custom_header = TRUE; hdr_ctx.args = args; @@ -703,9 +746,10 @@ i_assert(*headers != NULL); if (mail_get_header_stream(ctx->cur_mail, headers_ctx, - &input) < 0) + &input) < 0) { + search_cur_mail_failed(ctx); failed = TRUE; - else { + } else { message_parse_header(input, NULL, hdr_parser_flags, search_header, &hdr_ctx); } @@ -715,9 +759,10 @@ ret = have_body ? mail_get_stream_because(ctx->cur_mail, NULL, NULL, "search", &input) : mail_get_hdr_stream_because(ctx->cur_mail, NULL, "search", &input); - if (ret < 0) + if (ret < 0) { + search_cur_mail_failed(ctx); failed = TRUE; - else { + } else { hdr_ctx.parse_headers = index_mail_want_parse_headers(hdr_ctx.imail); if (hdr_ctx.parse_headers) { @@ -732,6 +777,7 @@ i_stream_get_name(input), i_stream_get_error(input)); failed = TRUE; + search_set_failed(ctx); } } } @@ -766,8 +812,10 @@ /* we didn't search headers. */ struct message_size hdr_size; - if (mail_get_stream_because(ctx->cur_mail, &hdr_size, NULL, "search", &input) < 0) + if (mail_get_stream_because(ctx->cur_mail, &hdr_size, NULL, "search", &input) < 0) { + search_cur_mail_failed(ctx); return -1; + } i_stream_seek(input, hdr_size.physical_size); } @@ -1239,9 +1287,9 @@ mail_search_args_reset(ctx->mail_ctx.args->args, TRUE); if (args->have_inthreads) { if (mail_thread_init(t->box, NULL, &ctx->thread_ctx) < 0) - ctx->failed = TRUE; + search_set_failed(ctx); if (search_build_inthreads(ctx, args->args) < 0) - ctx->failed = TRUE; + search_set_failed(ctx); } if (sort_program != NULL) { @@ -1303,6 +1351,9 @@ imail->search_mail = FALSE; mail_free(mailp); } + + if (ctx->failed) + mail_storage_last_error_pop(ctx->box->storage); array_free(&ctx->mails); i_free(ctx); return ret; @@ -1393,9 +1444,6 @@ static void search_match_finish(struct index_search_context *ctx, int match) { - if (ctx->cur_mail->expunged) - ctx->mail_ctx.seen_lost_data = TRUE; - if (match == 0 && search_has_static_nonmatches(ctx->mail_ctx.args->args)) { /* if there are saved search results remember @@ -1748,8 +1796,6 @@ returning the messages. */ ctx->sorted = TRUE; index_sort_list_finish(_ctx->sort_program); - if (ctx->failed) - return FALSE; } /* everything searched at this point already. just returning