static int index_mailbox_precache(struct master_connection *conn, struct mailbox *box) { struct mail_storage *storage = mailbox_get_storage(box); const char *username = mail_storage_get_user(storage)->username; const char *box_vname = mailbox_get_vname(box); struct mailbox_status status; struct mailbox_transaction_context *trans; struct mail_search_args *search_args; struct mail_search_context *ctx; struct mail *mail; struct mailbox_metadata metadata; uint32_t seq, first_uid = 0, last_uid = 0; char percentage_str[2+1+1]; unsigned int counter = 0, max, percentage, percentage_sent = 0; int ret = 0; if (mailbox_get_metadata(box, MAILBOX_METADATA_PRECACHE_FIELDS, &metadata) < 0) { i_error("Mailbox %s: Precache-fields lookup failed: %s", mailbox_get_vname(box), mailbox_get_last_internal_error(box, NULL)); return -1; } if (mailbox_get_status(box, STATUS_MESSAGES | STATUS_LAST_CACHED_SEQ, &status) < 0) { i_error("Mailbox %s: Status lookup failed: %s", mailbox_get_vname(box), mailbox_get_last_internal_error(box, NULL)); return -1; } seq = status.last_cached_seq + 1; trans = mailbox_transaction_begin(box, MAILBOX_TRANSACTION_FLAG_NO_CACHE_DEC, "indexing"); search_args = mail_search_build_init(); mail_search_build_add_seqset(search_args, seq, status.messages); ctx = mailbox_search_init(trans, search_args, NULL, metadata.precache_fields, NULL); mail_search_args_unref(&search_args); max = status.messages + 1 - seq; while (mailbox_search_next(ctx, &mail)) { if (first_uid == 0) first_uid = mail->uid; last_uid = mail->uid; mail_precache(mail); if (++counter % 100 == 0) { percentage = counter*100 / max; if (percentage != percentage_sent && percentage < 100) { percentage_sent = percentage; if (i_snprintf(percentage_str, sizeof(percentage_str), "%u\n", percentage) < 0) i_unreached(); (void)write_full(conn->fd, percentage_str, strlen(percentage_str)); } indexer_worker_refresh_proctitle(username, box_vname, counter, max); } } if (mailbox_search_deinit(&ctx) < 0) { i_error("Mailbox %s: Mail search failed: %s", mailbox_get_vname(box), mailbox_get_last_internal_error(box, NULL)); ret = -1; } const char *uids = first_uid == 0 ? "" : t_strdup_printf(" (UIDs %u..%u)", first_uid, last_uid); if (mailbox_transaction_commit(&trans) < 0) { i_error("Mailbox %s: Transaction commit failed: %s" " (attempted to index %u messages%s)", mailbox_get_vname(box), mailbox_get_last_internal_error(box, NULL), counter, uids); ret = -1; } else { i_info("Indexed %u messages in %s%s", counter, mailbox_get_vname(box), uids); } return ret; }
static int virtual_size_add_new(struct mailbox *box, struct index_vsize_header *vsize_hdr) { struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box); const struct mail_index_header *hdr; struct mailbox_transaction_context *trans; struct mail_search_context *search_ctx; struct mail_search_args *search_args; struct mail *mail; uint32_t seq1, seq2; uoff_t vsize; int ret = 0; hdr = mail_index_get_header(box->view); if (vsize_hdr->highest_uid == 0) seq2 = 0; else if (!mail_index_lookup_seq_range(box->view, 1, vsize_hdr->highest_uid, &seq1, &seq2)) seq2 = 0; if (vsize_hdr->message_count != seq2) { if (vsize_hdr->message_count < seq2) { mail_storage_set_critical(box->storage, "vsize-hdr has invalid message-count (%u < %u)", vsize_hdr->message_count, seq2); } else { /* some messages have been expunged, rescan */ } memset(vsize_hdr, 0, sizeof(*vsize_hdr)); seq2 = 0; } search_args = mail_search_build_init(); mail_search_build_add_seqset(search_args, seq2 + 1, hdr->messages_count); trans = mailbox_transaction_begin(box, 0); search_ctx = mailbox_search_init(trans, search_args, NULL, MAIL_FETCH_VIRTUAL_SIZE, NULL); while (mailbox_search_next(search_ctx, &mail)) { if (mail_get_virtual_size(mail, &vsize) < 0) { if (mail->expunged) continue; ret = -1; break; } vsize_hdr->vsize += vsize; vsize_hdr->highest_uid = mail->uid; vsize_hdr->message_count++; } if (mailbox_search_deinit(&search_ctx) < 0) ret = -1; mail_search_args_unref(&search_args); if (ret == 0) { /* success, cache all */ vsize_hdr->highest_uid = hdr->next_uid - 1; } else { /* search failed, cache only up to highest seen uid */ } mail_index_update_header_ext(trans->itrans, ibox->vsize_hdr_ext_id, 0, vsize_hdr, sizeof(*vsize_hdr)); (void)mailbox_transaction_commit(&trans); return ret; }