static int fts_mailbox_search_deinit(struct mail_search_context *ctx) { struct fts_mailbox *fbox = FTS_CONTEXT(ctx->transaction->box); struct fts_transaction_context *ft = FTS_CONTEXT(ctx->transaction); struct fts_search_context *fctx = FTS_CONTEXT(ctx); int ret = 0; if (fctx != NULL) { if (fctx->indexer_ctx != NULL) { if (fts_indexer_deinit(&fctx->indexer_ctx) < 0) ft->failed = TRUE; } if (fctx->indexing_timed_out) ret = -1; if (!fctx->fts_lookup_success && fctx->enforced) { /* FTS lookup failed and we didn't want to fallback to opening all the mails and searching manually */ mail_storage_set_internal_error(ctx->transaction->box->storage); ret = -1; } buffer_free(&fctx->orig_matches); array_free(&fctx->levels); pool_unref(&fctx->result_pool); fts_scores_unref(&fctx->scores); i_free(fctx); } else { if (ft->failed) ret = -1; } if (fbox->module_ctx.super.search_deinit(ctx) < 0) ret = -1; return ret; }
static int fts_transaction_end(struct mailbox_transaction_context *t, const char **error_r) { struct fts_transaction_context *ft = FTS_CONTEXT(t); struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(t->box->list); int ret = ft->failed ? -1 : 0; if (ft->failed) *error_r = "transaction context"; if (ft->precached) { i_assert(flist->update_ctx_refcount > 0); if (--flist->update_ctx_refcount == 0) { if (fts_backend_update_deinit(&flist->update_ctx) < 0) { ret = -1; *error_r = "backend deinit"; } } } else if (ft->highest_virtual_uid > 0) { if (fts_index_set_last_uid(t->box, ft->highest_virtual_uid) < 0) { ret = -1; *error_r = "index last uid setting"; } } if (ft->scores != NULL) fts_scores_unref(&ft->scores); i_free(ft); return ret; }
static struct mail_search_context * fts_mailbox_search_init(struct mailbox_transaction_context *t, struct mail_search_args *args, const enum mail_sort_type *sort_program, enum mail_fetch_field wanted_fields, struct mailbox_header_lookup_ctx *wanted_headers) { struct fts_transaction_context *ft = FTS_CONTEXT(t); struct fts_mailbox *fbox = FTS_CONTEXT(t->box); struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(t->box->list); struct mail_search_context *ctx; struct fts_search_context *fctx; ctx = fbox->module_ctx.super.search_init(t, args, sort_program, wanted_fields, wanted_headers); if (!fts_backend_can_lookup(flist->backend, args->args)) return ctx; fctx = i_new(struct fts_search_context, 1); fctx->box = t->box; fctx->backend = flist->backend; fctx->t = t; fctx->args = args; fctx->result_pool = pool_alloconly_create("fts results", 1024*64); fctx->orig_matches = buffer_create_dynamic(default_pool, 64); fctx->virtual_mailbox = strcmp(t->box->storage->name, VIRTUAL_STORAGE_NAME) == 0; fctx->enforced = mail_user_plugin_getenv(t->box->storage->user, "fts_enforced") != NULL; i_array_init(&fctx->levels, 8); fctx->scores = i_new(struct fts_scores, 1); fctx->scores->refcount = 1; i_array_init(&fctx->scores->score_map, 64); MODULE_CONTEXT_SET(ctx, fts_storage_module, fctx); /* FIXME: we'll assume that all the args are fuzzy. not good, but would require much more work to fix it. */ if (!fts_args_have_fuzzy(args->args) && mail_user_plugin_getenv(t->box->storage->user, "fts_no_autofuzzy") != NULL) fctx->flags |= FTS_LOOKUP_FLAG_NO_AUTO_FUZZY; /* transaction contains the last search's scores. they can be queried later with mail_get_special() */ if (ft->scores != NULL) fts_scores_unref(&ft->scores); ft->scores = fctx->scores; ft->scores->refcount++; if (fctx->enforced || fts_want_build_args(args->args)) fts_try_build_init(ctx, fctx); else fts_search_lookup(fctx); return ctx; }