bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2006-2018 Dovecot authors, see the included COPYING file */
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi MODULE_CONTEXT_REQUIRE(obj, fts_mailbox_list_module)
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen#define INDEXER_HANDSHAKE "VERSION\tindexer\t1\t0\n"
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct fts_backend_update_context *update_ctx;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_backend_update_context *sync_update_ctx;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mailbox_transaction_module_context module_ctx;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(fts_storage_module,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(fts_mail_module, &mail_module_register);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(fts_mailbox_list_module,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic int fts_mailbox_get_last_cached_seq(struct mailbox *box, uint32_t *seq_r)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox_list *flist = FTS_LIST_CONTEXT_REQUIRE(box->list);
e7f8009c974ed6a6a5a0e88633d98fff2867fa92Timo Sirainen if (fts_backend_get_last_uid(flist->backend, box, &last_uid) < 0) {
e7f8009c974ed6a6a5a0e88633d98fff2867fa92Timo Sirainen mail_storage_set_internal_error(box->storage);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen mailbox_get_seq_range(box, 1, last_uid, &seq1, &seq2);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenfts_mailbox_get_status(struct mailbox *box, enum mailbox_status_items items,
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(box);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fbox->module_ctx.super.get_status(box, items, status_r) < 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fts_mailbox_get_last_cached_seq(box, &seq) < 0)
f5a00a8bc68cb246bfe9265e7f66856db98f5f7dTimo Sirainen /* Always use the FTS's last_cached_seq. This is because we
f5a00a8bc68cb246bfe9265e7f66856db98f5f7dTimo Sirainen don't want to reindex all mails to FTS if .cache file is
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void fts_scores_unref(struct fts_scores **_scores)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic void fts_try_build_init(struct mail_search_context *ctx,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_assert(!fts_backend_is_updating(fctx->backend));
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen ret = fts_indexer_init(fctx->backend, ctx->transaction->box,
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen /* the index was up to date */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* hide "searching" notifications while building index */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic bool fts_want_build_args(const struct mail_search_arg *args)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* we want to update index only when searching from message body.
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen it's not worth the wait for searching only from headers, which
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen could be in cache file already */
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainenstatic bool fts_args_have_fuzzy(const struct mail_search_arg *args)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenfts_mailbox_search_init(struct mailbox_transaction_context *t,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_transaction_context *ft = FTS_CONTEXT_REQUIRE(t);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(t->box);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox_list *flist = FTS_LIST_CONTEXT_REQUIRE(t->box->list);
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen ctx = fbox->module_ctx.super.search_init(t, args, sort_program,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!fts_backend_can_lookup(flist->backend, args->args))
a5e89374cb2fb2cad575fee6c3b33a9487ab9b3aTimo Sirainen fctx->result_pool = pool_alloconly_create("fts results", 1024*64);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fctx->orig_matches = buffer_create_dynamic(default_pool, 64);
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen fctx->virtual_mailbox = t->box->virtual_vfuncs != NULL;
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang mail_user_plugin_getenv_bool(t->box->storage->user,
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang "fts_enforced");
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET(ctx, fts_storage_module, fctx);
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen /* FIXME: we'll assume that all the args are fuzzy. not good,
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen but would require much more work to fix it. */
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang mail_user_plugin_getenv_bool(t->box->storage->user,
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang "fts_no_autofuzzy"))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* transaction contains the last search's scores. they can be
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen queried later with mail_get_special() */
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen if (fctx->enforced || fts_want_build_args(args->args))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic bool fts_mailbox_build_continue(struct mail_search_context *ctx)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_search_context *fctx = FTS_CONTEXT_REQUIRE(ctx);
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen /* indexing finished */
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen if (fts_indexer_deinit(&fctx->indexer_ctx) < 0)
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen /* if indexing timed out, it probably means that
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen the mailbox is still being indexed, but it's a large
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen mailbox and it takes a while. in this situation
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen we'll simply abort the search.
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen if indexing failed for any other reason, just
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen fallback to searching the slow way. */
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen mailbox_get_last_mail_error(fctx->box) == MAIL_ERROR_INUSE;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenfts_mailbox_search_next_nonblock(struct mail_search_context *ctx,
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(ctx->transaction->box);
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen struct fts_search_context *fctx = FTS_CONTEXT(ctx);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_transaction_context *ft = FTS_CONTEXT_REQUIRE(ctx->transaction);
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen /* precaching already failed - stop now instead of potentially
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen going through the same failure for all the mails */
2e5170d1dce33cf055cfc2f6fa4b4a61df35d1c5Timo Sirainen if (fctx != NULL && fctx->indexer_ctx != NULL) {
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen /* this command is still building the indexes */
2e5170d1dce33cf055cfc2f6fa4b4a61df35d1c5Timo Sirainen if (fctx != NULL && !fctx->fts_lookup_success && fctx->enforced)
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen search_next_nonblock(ctx, mail_r, tryagain_r);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenfts_search_apply_results_level(struct mail_search_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_search_arg *args, unsigned int *idx)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_search_context *fctx = FTS_CONTEXT_REQUIRE(ctx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (array_is_created(&level->definite_seqs) &&
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen seq_range_exists(&level->definite_seqs, ctx->seq))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_search_deserialize_add_matches(args, level->args_matches);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen else if (!array_is_created(&level->maybe_seqs) ||
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen !seq_range_exists(&level->maybe_seqs, ctx->seq))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_search_deserialize_add_nonmatches(args, level->args_matches);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (args->type != SEARCH_OR && args->type != SEARCH_SUB)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_search_apply_results_level(ctx, args->value.subargs, idx);
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainenstatic bool fts_mailbox_search_next_update_seq(struct mail_search_context *ctx)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(ctx->transaction->box);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct fts_search_context *fctx = FTS_CONTEXT(ctx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (fctx == NULL || !fctx->fts_lookup_success) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* fts lookup not done for this search */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return fbox->module_ctx.super.search_next_update_seq(ctx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* restore original [non]matches */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_search_deserialize(ctx->args->args, fctx->orig_matches);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!fbox->module_ctx.super.search_next_update_seq(ctx))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* we've not indexed this far */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* apply [non]matches based on the FTS lookup results */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_search_apply_results_level(ctx, ctx->args->args, &idx);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenstatic int fts_mailbox_search_deinit(struct mail_search_context *ctx)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(ctx->transaction->box);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_transaction_context *ft = FTS_CONTEXT_REQUIRE(ctx->transaction);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct fts_search_context *fctx = FTS_CONTEXT(ctx);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fts_indexer_deinit(&fctx->indexer_ctx) < 0)
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen if (!fctx->fts_lookup_success && fctx->enforced) {
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen /* FTS lookup failed and we didn't want to fallback to
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen opening all the mails and searching manually */
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen mail_storage_set_internal_error(ctx->transaction->box->storage);
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen if (fbox->module_ctx.super.search_deinit(ctx) < 0)
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenstatic int fts_score_cmp(const uint32_t *uid, const struct fts_score_map *score)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenstatic int fts_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen const char **value_r)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen struct fts_mail *fmail = FTS_MAIL_CONTEXT(mail);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_transaction_context *ft = FTS_CONTEXT_REQUIRE(_mail->transaction);
fd14806f879f6cd4f023750e0c4cac27a7f94fbbTimo Sirainen if (field != MAIL_FETCH_SEARCH_RELEVANCY || ft->scores == NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen scores = array_bsearch(&ft->scores->score_map, &_mail->uid,
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen (void)i_snprintf(fmail->score, sizeof(fmail->score),
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen return fmail->module_ctx.super.get_special(_mail, field, value_r);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenfts_mail_precache_range(struct mailbox_transaction_context *trans,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct fts_backend_update_context *update_ctx,
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen uint32_t seq1, uint32_t seq2, unsigned int *extra_count)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen mail_search_build_add_seqset(search_args, seq1, seq2);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ctx = mailbox_search_init(trans, search_args, NULL,
4462eb835e9681dd1110e10f557d4dea3bf61f78Timo Sirainen mail_storage_set_internal_error(trans->box->storage);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic int fts_mail_precache_init(struct mail *_mail)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_transaction_context *ft = FTS_CONTEXT_REQUIRE(_mail->transaction);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox_list *flist = FTS_LIST_CONTEXT_REQUIRE(_mail->box->list);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fts_mailbox_get_last_cached_seq(_mail->box, &last_seq) < 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen flist->update_ctx = fts_backend_update_init(flist->backend);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_transaction_context *ft = FTS_CONTEXT_REQUIRE(_mail->transaction);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox_list *flist = FTS_LIST_CONTEXT_REQUIRE(_mail->box->list);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* most likely a virtual mailbox. we'll first need to
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen index all mails up to the current one. */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen fts_backend_update_set_mailbox(flist->update_ctx, _mail->box);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fts_mail_precache_range(_mail->transaction,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen fts_backend_update_set_mailbox(flist->update_ctx, _mail->box);
4462eb835e9681dd1110e10f557d4dea3bf61f78Timo Sirainen if (fts_build_mail(flist->update_ctx, _mail) < 0) {
4462eb835e9681dd1110e10f557d4dea3bf61f78Timo Sirainen mail_storage_set_internal_error(_mail->box->storage);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic void fts_mail_precache(struct mail *_mail)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct fts_mail *fmail = FTS_MAIL_CONTEXT(mail);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_transaction_context *ft = FTS_CONTEXT_REQUIRE(_mail->transaction);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct fts_mailbox *fbox = FTS_CONTEXT(_mail->box);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen fmail = p_new(mail->pool, struct fts_mail, 1);
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen fmail->virtual_mail = _mail->box->virtual_vfuncs != NULL;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen MODULE_CONTEXT_SET(mail, fts_mail_module, fmail);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(box);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen ft = i_new(struct fts_transaction_context, 1);
c6ce2e251ac75fa650c7fbfa52150eae69386293Martti Rannanjärvi t = fbox->module_ctx.super.transaction_begin(box, flags, reason);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET(t, fts_storage_module, ft);
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmodystatic int fts_transaction_end(struct mailbox_transaction_context *t, const char **error_r)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_transaction_context *ft = FTS_CONTEXT_REQUIRE(t);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox_list *flist = FTS_LIST_CONTEXT_REQUIRE(t->box->list);
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody if (fts_backend_update_deinit(&flist->update_ctx) < 0) {
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody if (fts_index_set_last_uid(t->box, ft->highest_virtual_uid) < 0) {
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen i_error("fts: Failed after indexing %u extra mails internally in %s: %s",
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen ft->precache_extra_count, t->box->vname, *error_r);
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen i_info("fts: Indexed %u extra mails internally in %s",
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic void fts_transaction_rollback(struct mailbox_transaction_context *t)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(t->box);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen fbox->module_ctx.super.transaction_rollback(t);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainenstatic void fts_queue_index(struct mailbox *box)
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen path = t_strconcat(user->set->base_dir, "/"INDEXER_SOCKET_NAME, NULL);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen i_error("net_connect_unix(%s) failed: %m", path);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen value = mail_user_plugin_getenv(user, "fts_autoindex_max_recent_msgs");
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen if (value == NULL || str_to_uint(value, &max_recent_msgs) < 0)
a8dcd4e2332c73087e9b148d34259230a77edb28Timo Sirainen str_append_tabescaped(str, box->storage->user->session_id);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen if (write_full(fd, str_data(str), str_len(str)) < 0)
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainenfts_transaction_commit(struct mailbox_transaction_context *t,
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen struct mail_transaction_commit_changes *changes_r)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_transaction_context *ft = FTS_CONTEXT_REQUIRE(t);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(t->box);
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang autoindex = ft->mails_saved && !fbox->fts_mailbox_excluded &&
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang mail_user_plugin_getenv_bool(box->storage->user,
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang "fts_autoindex");
78199a8ade26f7694010f1096c6fdf055a5553bdTimo Sirainen mail_storage_set_error(t->box->storage, MAIL_ERROR_TEMP,
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody t_strdup_printf("FTS transaction commit failed: %s",
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fbox->module_ctx.super.transaction_commit(t, changes_r) < 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void fts_mailbox_sync_notify(struct mailbox *box, uint32_t uid,
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox_list *flist = FTS_LIST_CONTEXT_REQUIRE(box->list);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(box);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (fbox->module_ctx.super.sync_notify != NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fbox->module_ctx.super.sync_notify(box, uid, sync_type);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (uid == 0 && fbox->sync_update_ctx != NULL) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* this sync is finished */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen (void)fts_backend_update_deinit(&fbox->sync_update_ctx);
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainen if (fts_backend_is_updating(flist->backend)) {
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainen /* FIXME: maildir workaround - we could get here
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainen because we're building an index, which doesn't find
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainen some mail and starts syncing the mailbox.. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fbox->sync_update_ctx = fts_backend_update_init(flist->backend);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_backend_update_set_mailbox(fbox->sync_update_ctx, box);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_backend_update_expunge(fbox->sync_update_ctx, uid);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenstatic int fts_sync_deinit(struct mailbox_sync_context *ctx,
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(box);
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(box->list);
20eafc2a848865ce7bf5e8c609e3b0bbd9077ec2Timo Sirainen optimize = (ctx->flags & (MAILBOX_SYNC_FLAG_FORCE_RESYNC |
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen if (fbox->module_ctx.super.sync_deinit(ctx, status_r) < 0)
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen if (fts_backend_optimize(flist->backend) < 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box, "FTS optimize failed");
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainenstatic int fts_save_finish(struct mail_save_context *ctx)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_transaction_context *ft = FTS_CONTEXT_REQUIRE(ctx->transaction);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(ctx->transaction->box);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen if (fbox->module_ctx.super.save_finish(ctx) < 0)
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainenstatic int fts_copy(struct mail_save_context *ctx, struct mail *mail)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_transaction_context *ft = FTS_CONTEXT_REQUIRE(ctx->transaction);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(ctx->transaction->box);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen if (fbox->module_ctx.super.copy(ctx, mail) < 0)
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wangstatic const char *const *fts_exclude_get_patterns(struct mail_user *user)
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang unsigned int i;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang str = mail_user_plugin_getenv(user, "fts_autoindex_exclude");
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang "fts_autoindex_exclude%u", i) < 0)
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wangstatic bool fts_autoindex_exclude_match(struct mailbox *box)
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang unsigned int i;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang set = mailbox_settings_find(mailbox_get_namespace(box),
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang /* \Special-use flag */
766ba3eed8b1c011a7a14c11cda6256ca2c25be4Timo Sirainen str_array_icase_find(special_use, exclude_list[i]))
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang /* mailbox name with wildcards */
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang if (wildcard_match(box->name, exclude_list[i]))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid fts_mailbox_allocated(struct mailbox *box)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(box->list);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fbox = p_new(box->pool, struct fts_mailbox, 1);
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang fbox->fts_mailbox_excluded = fts_autoindex_exclude_match(box);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->search_next_nonblock = fts_mailbox_search_next_nonblock;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen v->search_next_update_seq = fts_mailbox_search_next_update_seq;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->transaction_rollback = fts_transaction_rollback;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->transaction_commit = fts_transaction_commit;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET(box, fts_storage_module, fbox);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void fts_mailbox_list_deinit(struct mailbox_list *list)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox_list *flist = FTS_LIST_CONTEXT_REQUIRE(list);
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomifts_init_namespace(struct fts_mailbox_list *flist, struct mail_namespace *ns,
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi const char **error_r)
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi if (fts_backend_init(flist->backend_name, ns, error_r, &backend) < 0) {
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi if ((flist->backend->flags & FTS_BACKEND_FLAG_FUZZY_SEARCH) != 0)
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomivoid fts_mail_namespaces_added(struct mail_namespace *ns)
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(ns->list);
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi if (flist != NULL && !flist->failed && flist->backend == NULL &&
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi i_error("fts: Failed to initialize backend '%s': %s",
79195413c349af7f9ce26871bf79c70af07ea7ceAki Tuomifts_mailbox_list_created(struct mailbox_list *list)
79195413c349af7f9ce26871bf79c70af07ea7ceAki Tuomi const char *name = mail_user_plugin_getenv(list->ns->user, "fts");
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_INDEX, &path)) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_debug("fts: Indexes disabled for namespace '%s'",
c42ec3faf1c0d2bf65b8ef5e524d0c18992e7454Aki Tuomi flist = p_new(list->pool, struct fts_mailbox_list, 1);
c42ec3faf1c0d2bf65b8ef5e524d0c18992e7454Aki Tuomi MODULE_CONTEXT_SET(list, fts_mailbox_list_module, flist);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct fts_backend *fts_mailbox_backend(struct mailbox *box)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox_list *flist = FTS_LIST_CONTEXT_REQUIRE(box->list);
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainenstruct fts_backend *fts_list_backend(struct mailbox_list *list)