bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2006-2018 Dovecot authors, see the included COPYING file */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "lib.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "array.h"
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen#include "net.h"
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen#include "str.h"
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen#include "strescape.h"
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen#include "write-full.h"
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang#include "wildcard-match.h"
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen#include "mail-search-build.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "mail-storage-private.h"
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen#include "mailbox-list-private.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "fts-api-private.h"
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen#include "fts-tokenizer.h"
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen#include "fts-indexer.h"
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen#include "fts-build-mail.h"
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#include "fts-search-serialize.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "fts-plugin.h"
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#include "fts-storage.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#define FTS_CONTEXT(obj) \
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT(obj, fts_storage_module)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi#define FTS_CONTEXT_REQUIRE(obj) \
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi MODULE_CONTEXT_REQUIRE(obj, fts_storage_module)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#define FTS_MAIL_CONTEXT(obj) \
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi MODULE_CONTEXT_REQUIRE(obj, fts_mail_module)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#define FTS_LIST_CONTEXT(obj) \
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen MODULE_CONTEXT(obj, fts_mailbox_list_module)
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi#define FTS_LIST_CONTEXT_REQUIRE(obj) \
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi MODULE_CONTEXT_REQUIRE(obj, fts_mailbox_list_module)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen#define INDEXER_SOCKET_NAME "indexer"
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen#define INDEXER_HANDSHAKE "VERSION\tindexer\t1\t0\n"
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct fts_mailbox_list {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen union mailbox_list_module_context module_ctx;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_backend *backend;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi const char *backend_name;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct fts_backend_update_context *update_ctx;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen unsigned int update_ctx_refcount;
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi bool failed:1;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen};
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct fts_mailbox {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen union mailbox_module_context module_ctx;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_backend_update_context *sync_update_ctx;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang bool fts_mailbox_excluded;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen};
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainenstruct fts_transaction_context {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mailbox_transaction_module_context module_ctx;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_scores *scores;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen uint32_t next_index_seq;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen uint32_t highest_virtual_uid;
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen unsigned int precache_extra_count;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool precached:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool mails_saved:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool failed:1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen};
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct fts_mail {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen union mail_module_context module_ctx;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen char score[30];
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool virtual_mail:1;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen};
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(fts_storage_module,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen &mail_storage_module_register);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(fts_mail_module, &mail_module_register);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(fts_mailbox_list_module,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen &mailbox_list_module_register);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic int fts_mailbox_get_last_cached_seq(struct mailbox *box, uint32_t *seq_r)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen{
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox_list *flist = FTS_LIST_CONTEXT_REQUIRE(box->list);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen uint32_t seq1, seq2, last_uid;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
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 return -1;
e7f8009c974ed6a6a5a0e88633d98fff2867fa92Timo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (last_uid == 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen *seq_r = 0;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen else {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen mailbox_get_seq_range(box, 1, last_uid, &seq1, &seq2);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen *seq_r = seq2;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return 0;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic int
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenfts_mailbox_get_status(struct mailbox *box, enum mailbox_status_items items,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mailbox_status *status_r)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen{
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(box);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen uint32_t seq;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fbox->module_ctx.super.get_status(box, items, status_r) < 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return -1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if ((items & STATUS_LAST_CACHED_SEQ) != 0) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fts_mailbox_get_last_cached_seq(box, &seq) < 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return -1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
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
f5a00a8bc68cb246bfe9265e7f66856db98f5f7dTimo Sirainen deleted. */
f5a00a8bc68cb246bfe9265e7f66856db98f5f7dTimo Sirainen status_r->last_cached_seq = seq;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return 0;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void fts_scores_unref(struct fts_scores **_scores)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_scores *scores = *_scores;
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *_scores = NULL;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (--scores->refcount == 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_free(&scores->score_map);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_free(scores);
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen }
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen}
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic void fts_try_build_init(struct mail_search_context *ctx,
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen struct fts_search_context *fctx)
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen{
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen int ret;
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_assert(!fts_backend_is_updating(fctx->backend));
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen ret = fts_indexer_init(fctx->backend, ctx->transaction->box,
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen &fctx->indexer_ctx);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (ret < 0)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen return;
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (ret == 0) {
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen /* the index was up to date */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_search_lookup(fctx);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen } else {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* hide "searching" notifications while building index */
d54ab8987e482a8df250615b44f41fa040c38741Timo Sirainen ctx->progress_hidden = TRUE;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen }
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen}
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic bool fts_want_build_args(const struct mail_search_arg *args)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
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 */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen for (; args != NULL; args = args->next) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen switch (args->type) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen case SEARCH_OR:
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen case SEARCH_SUB:
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen case SEARCH_INTHREAD:
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (fts_want_build_args(args->value.subargs))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return TRUE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen break;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen case SEARCH_BODY:
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen case SEARCH_TEXT:
cbc8f9d71483a2cf71610f7e7e1f2dc9884bd556Baofeng Wang if (!args->no_fts)
cbc8f9d71483a2cf71610f7e7e1f2dc9884bd556Baofeng Wang return TRUE;
cbc8f9d71483a2cf71610f7e7e1f2dc9884bd556Baofeng Wang break;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen default:
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen break;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainenstatic bool fts_args_have_fuzzy(const struct mail_search_arg *args)
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen{
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen for (; args != NULL; args = args->next) {
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen if (args->fuzzy)
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen return TRUE;
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen switch (args->type) {
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen case SEARCH_OR:
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen case SEARCH_SUB:
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen case SEARCH_INTHREAD:
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen if (fts_args_have_fuzzy(args->value.subargs))
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen return TRUE;
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen break;
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen default:
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen break;
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen }
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen }
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen return FALSE;
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen}
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenstatic struct mail_search_context *
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenfts_mailbox_search_init(struct mailbox_transaction_context *t,
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen struct mail_search_args *args,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen const enum mail_sort_type *sort_program,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen enum mail_fetch_field wanted_fields,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen{
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);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct mail_search_context *ctx;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct fts_search_context *fctx;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen ctx = fbox->module_ctx.super.search_init(t, args, sort_program,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen wanted_fields, wanted_headers);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!fts_backend_can_lookup(flist->backend, args->args))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return ctx;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen fctx = i_new(struct fts_search_context, 1);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fctx->box = t->box;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fctx->backend = flist->backend;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen fctx->t = t;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen fctx->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;
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen fctx->enforced =
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang mail_user_plugin_getenv_bool(t->box->storage->user,
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang "fts_enforced");
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_array_init(&fctx->levels, 8);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fctx->scores = i_new(struct fts_scores, 1);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fctx->scores->refcount = 1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_array_init(&fctx->scores->score_map, 64);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET(ctx, fts_storage_module, fctx);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
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. */
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen if (!fts_args_have_fuzzy(args->args) &&
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang mail_user_plugin_getenv_bool(t->box->storage->user,
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang "fts_no_autofuzzy"))
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainen fctx->flags |= FTS_LOOKUP_FLAG_NO_AUTO_FUZZY;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* transaction contains the last search's scores. they can be
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen queried later with mail_get_special() */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (ft->scores != NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_scores_unref(&ft->scores);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ft->scores = fctx->scores;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ft->scores->refcount++;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen if (fctx->enforced || fts_want_build_args(args->args))
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen fts_try_build_init(ctx, fctx);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen else
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_search_lookup(fctx);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen return ctx;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic bool fts_mailbox_build_continue(struct mail_search_context *ctx)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen{
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_search_context *fctx = FTS_CONTEXT_REQUIRE(ctx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen int ret;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen ret = fts_indexer_more(fctx->indexer_ctx);
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen if (ret == 0)
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen return FALSE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen /* indexing finished */
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen ctx->progress_hidden = FALSE;
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen if (fts_indexer_deinit(&fctx->indexer_ctx) < 0)
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen ret = -1;
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen if (ret > 0)
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen fts_search_lookup(fctx);
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen if (ret < 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
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen if indexing failed for any other reason, just
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen fallback to searching the slow way. */
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen fctx->indexing_timed_out =
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen mailbox_get_last_mail_error(fctx->box) == MAIL_ERROR_INUSE;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return TRUE;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen}
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenstatic bool
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenfts_mailbox_search_next_nonblock(struct mail_search_context *ctx,
437a8b0fe254057b0c1f1723d689bafa91cae2abTimo Sirainen struct mail **mail_r, bool *tryagain_r)
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen{
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
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen if (fctx == NULL && ft->failed) {
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen /* precaching already failed - stop now instead of potentially
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen going through the same failure for all the mails */
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen return FALSE;
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen }
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
2e5170d1dce33cf055cfc2f6fa4b4a61df35d1c5Timo Sirainen if (fctx != NULL && fctx->indexer_ctx != NULL) {
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen /* this command is still building the indexes */
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen if (!fts_mailbox_build_continue(ctx)) {
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen *tryagain_r = TRUE;
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen return FALSE;
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen }
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen if (fctx->indexing_timed_out) {
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen *tryagain_r = FALSE;
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen return FALSE;
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen }
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen }
2e5170d1dce33cf055cfc2f6fa4b4a61df35d1c5Timo Sirainen if (fctx != NULL && !fctx->fts_lookup_success && fctx->enforced)
2e5170d1dce33cf055cfc2f6fa4b4a61df35d1c5Timo Sirainen return FALSE;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return fbox->module_ctx.super.
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen search_next_nonblock(ctx, mail_r, tryagain_r);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen}
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenstatic void
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenfts_search_apply_results_level(struct mail_search_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_search_arg *args, unsigned int *idx)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen{
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_search_context *fctx = FTS_CONTEXT_REQUIRE(ctx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const struct fts_search_level *level;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen level = array_idx(&fctx->levels, *idx);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
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);
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen for (; args != NULL; args = args->next) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (args->type != SEARCH_OR && args->type != SEARCH_SUB)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen continue;
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *idx += 1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_search_apply_results_level(ctx, args->value.subargs, idx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen}
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainenstatic bool fts_mailbox_search_next_update_seq(struct mail_search_context *ctx)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(ctx->transaction->box);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct fts_search_context *fctx = FTS_CONTEXT(ctx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen unsigned int idx;
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (fctx == NULL || !fctx->fts_lookup_success) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* fts lookup not done for this search */
009ec18ed6bc25a0331d8645a5d4380cb6f70c7bTimo Sirainen if (fctx != NULL && fctx->indexing_timed_out)
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen return FALSE;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return fbox->module_ctx.super.search_next_update_seq(ctx);
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen }
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* restore original [non]matches */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_search_deserialize(ctx->args->args, fctx->orig_matches);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!fbox->module_ctx.super.search_next_update_seq(ctx))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (ctx->seq >= fctx->first_unindexed_seq) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* we've not indexed this far */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return TRUE;
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* apply [non]matches based on the FTS lookup results */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen idx = 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_search_apply_results_level(ctx, ctx->args->args, &idx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return TRUE;
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen}
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenstatic int fts_mailbox_search_deinit(struct mail_search_context *ctx)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
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);
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen int ret = 0;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (fctx != NULL) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fctx->indexer_ctx != NULL) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fts_indexer_deinit(&fctx->indexer_ctx) < 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ft->failed = TRUE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen if (fctx->indexing_timed_out)
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen ret = -1;
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);
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen ret = -1;
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen }
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen buffer_free(&fctx->orig_matches);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_free(&fctx->levels);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen pool_unref(&fctx->result_pool);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_scores_unref(&fctx->scores);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_free(fctx);
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen } else {
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen if (ft->failed)
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen ret = -1;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen }
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen if (fbox->module_ctx.super.search_deinit(ctx) < 0)
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen ret = -1;
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen return ret;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenstatic int fts_score_cmp(const uint32_t *uid, const struct fts_score_map *score)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen{
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen return *uid < score->uid ? -1 :
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen (*uid > score->uid ? 1 : 0);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen}
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenstatic int fts_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen const char **value_r)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen{
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);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen const struct fts_score_map *scores;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
fd14806f879f6cd4f023750e0c4cac27a7f94fbbTimo Sirainen if (field != MAIL_FETCH_SEARCH_RELEVANCY || ft->scores == NULL)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen scores = NULL;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen else {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen scores = array_bsearch(&ft->scores->score_map, &_mail->uid,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen fts_score_cmp);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen }
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen if (scores != NULL) {
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen i_assert(scores->uid == _mail->uid);
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen (void)i_snprintf(fmail->score, sizeof(fmail->score),
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen "%f", scores->score);
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen *value_r = fmail->score;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen return 0;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen }
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen return fmail->module_ctx.super.get_special(_mail, field, value_r);
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen}
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic int
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{
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mail_search_args *search_args;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mail_search_context *ctx;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mail *mail;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen int ret = 0;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen search_args = mail_search_build_init();
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen mail_search_build_add_seqset(search_args, seq1, seq2);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ctx = mailbox_search_init(trans, search_args, NULL,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen MAIL_FETCH_STREAM_HEADER |
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen MAIL_FETCH_STREAM_BODY, NULL);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen mail_search_args_unref(&search_args);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen while (mailbox_search_next(ctx, &mail)) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fts_build_mail(update_ctx, mail) < 0) {
4462eb835e9681dd1110e10f557d4dea3bf61f78Timo Sirainen mail_storage_set_internal_error(trans->box->storage);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ret = -1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen break;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen mail_precache(mail);
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen *extra_count += 1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (mailbox_search_deinit(&ctx) < 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ret = -1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return ret;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic int fts_mail_precache_init(struct mail *_mail)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen{
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 uint32_t last_seq;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fts_mailbox_get_last_cached_seq(_mail->box, &last_seq) < 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return -1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ft->precached = TRUE;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ft->next_index_seq = last_seq + 1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (flist->update_ctx == NULL)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen flist->update_ctx = fts_backend_update_init(flist->backend);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen flist->update_ctx_refcount++;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return 0;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic void fts_mail_index(struct mail *_mail)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen{
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
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (ft->failed)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (!ft->precached) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fts_mail_precache_init(_mail) < 0) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ft->failed = TRUE;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (ft->next_index_seq < _mail->seq) {
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 flist->update_ctx,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ft->next_index_seq,
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen _mail->seq-1,
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen &ft->precache_extra_count) < 0) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ft->failed = TRUE;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (ft->next_index_seq == _mail->seq) {
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 Sirainen ft->failed = TRUE;
4462eb835e9681dd1110e10f557d4dea3bf61f78Timo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ft->next_index_seq = _mail->seq + 1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic void fts_mail_precache(struct mail *_mail)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen{
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);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen fmail->module_ctx.super.precache(_mail);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fmail->virtual_mail) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (ft->highest_virtual_uid < _mail->uid)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ft->highest_virtual_uid = _mail->uid;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen } else T_BEGIN {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen fts_mail_index(_mail);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen } T_END;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainenvoid fts_mail_allocated(struct mail *_mail)
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen{
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct mail_vfuncs *v = mail->vlast;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct fts_mailbox *fbox = FTS_CONTEXT(_mail->box);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen struct fts_mail *fmail;
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (fbox == NULL)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen return;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen fmail = p_new(mail->pool, struct fts_mail, 1);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen fmail->module_ctx.super = *v;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen mail->vlast = &fmail->module_ctx.super;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen fmail->virtual_mail = _mail->box->virtual_vfuncs != NULL;
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->get_special = fts_mail_get_special;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen v->precache = fts_mail_precache;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen MODULE_CONTEXT_SET(mail, fts_mail_module, fmail);
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen}
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainenstatic struct mailbox_transaction_context *
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainenfts_transaction_begin(struct mailbox *box,
c6ce2e251ac75fa650c7fbfa52150eae69386293Martti Rannanjärvi enum mailbox_transaction_flags flags,
c6ce2e251ac75fa650c7fbfa52150eae69386293Martti Rannanjärvi const char *reason)
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen{
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(box);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen struct mailbox_transaction_context *t;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen struct fts_transaction_context *ft;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen ft = i_new(struct fts_transaction_context, 1);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
c6ce2e251ac75fa650c7fbfa52150eae69386293Martti Rannanjärvi t = fbox->module_ctx.super.transaction_begin(box, flags, reason);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET(t, fts_storage_module, ft);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen return t;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen}
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmodystatic int fts_transaction_end(struct mailbox_transaction_context *t, const char **error_r)
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen{
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);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen int ret = ft->failed ? -1 : 0;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody if (ft->failed)
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody *error_r = "transaction context";
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (ft->precached) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_assert(flist->update_ctx_refcount > 0);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (--flist->update_ctx_refcount == 0) {
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody if (fts_backend_update_deinit(&flist->update_ctx) < 0) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ret = -1;
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody *error_r = "backend deinit";
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen } else if (ft->highest_virtual_uid > 0) {
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody if (fts_index_set_last_uid(t->box, ft->highest_virtual_uid) < 0) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ret = -1;
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody *error_r = "index last uid setting";
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (ft->scores != NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_scores_unref(&ft->scores);
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen if (ft->precache_extra_count > 0) {
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen if (ret < 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 } else {
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen i_info("fts: Indexed %u extra mails internally in %s",
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen ft->precache_extra_count, t->box->vname);
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen }
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen }
a7061727e8f1378228f110b23d816329d39ce82bTimo Sirainen i_free(ft);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return ret;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic void fts_transaction_rollback(struct mailbox_transaction_context *t)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen{
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(t->box);
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody const char *error;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody (void)fts_transaction_end(t, &error);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen fbox->module_ctx.super.transaction_rollback(t);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen}
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainenstatic void fts_queue_index(struct mailbox *box)
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen{
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen struct mail_user *user = box->storage->user;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen string_t *str = t_str_new(256);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen const char *path, *value;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen unsigned int max_recent_msgs;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen int fd;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen path = t_strconcat(user->set->base_dir, "/"INDEXER_SOCKET_NAME, NULL);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen fd = net_connect_unix(path);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen if (fd == -1) {
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen i_error("net_connect_unix(%s) failed: %m", path);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen return;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen }
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen
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)
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen max_recent_msgs = 0;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen str_append(str, INDEXER_HANDSHAKE);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen str_append(str, "APPEND\t0\t");
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen str_append_tabescaped(str, user->username);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen str_append_c(str, '\t');
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen str_append_tabescaped(str, box->vname);
a8dcd4e2332c73087e9b148d34259230a77edb28Timo Sirainen str_printfa(str, "\t%u", max_recent_msgs);
a8dcd4e2332c73087e9b148d34259230a77edb28Timo Sirainen str_append_c(str, '\t');
a8dcd4e2332c73087e9b148d34259230a77edb28Timo Sirainen str_append_tabescaped(str, box->storage->user->session_id);
a8dcd4e2332c73087e9b148d34259230a77edb28Timo Sirainen str_append_c(str, '\n');
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen if (write_full(fd, str_data(str), str_len(str)) < 0)
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen i_error("write(%s) failed: %m", path);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen i_close_fd(&fd);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen}
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainenstatic int
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainenfts_transaction_commit(struct mailbox_transaction_context *t,
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen struct mail_transaction_commit_changes *changes_r)
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen{
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_transaction_context *ft = FTS_CONTEXT_REQUIRE(t);
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(t->box);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen struct mailbox *box = t->box;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen bool autoindex;
78199a8ade26f7694010f1096c6fdf055a5553bdTimo Sirainen int ret = 0;
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody const char *error;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang autoindex = ft->mails_saved && !fbox->fts_mailbox_excluded &&
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang mail_user_plugin_getenv_bool(box->storage->user,
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang "fts_autoindex");
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody if (fts_transaction_end(t, &error) < 0) {
78199a8ade26f7694010f1096c6fdf055a5553bdTimo Sirainen mail_storage_set_error(t->box->storage, MAIL_ERROR_TEMP,
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody t_strdup_printf("FTS transaction commit failed: %s",
27fdbf79a2abd6feb7c503e46e63878c8a17127bPhil Carmody error));
78199a8ade26f7694010f1096c6fdf055a5553bdTimo Sirainen ret = -1;
78199a8ade26f7694010f1096c6fdf055a5553bdTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (fbox->module_ctx.super.transaction_commit(t, changes_r) < 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ret = -1;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen if (ret < 0)
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen return -1;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen if (autoindex)
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen fts_queue_index(box);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen return 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void fts_mailbox_sync_notify(struct mailbox *box, uint32_t uid,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen enum mailbox_sync_type sync_type)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
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
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (fbox->module_ctx.super.sync_notify != NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fbox->module_ctx.super.sync_notify(box, uid, sync_type);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (sync_type != MAILBOX_SYNC_TYPE_EXPUNGE) {
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);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen }
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (fbox->sync_update_ctx == NULL) {
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.. */
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainen return;
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainen }
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 }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_backend_update_expunge(fbox->sync_update_ctx, uid);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen}
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenstatic int fts_sync_deinit(struct mailbox_sync_context *ctx,
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen struct mailbox_sync_status *status_r)
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen{
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen struct mailbox *box = ctx->box;
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox *fbox = FTS_CONTEXT_REQUIRE(box);
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(box->list);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen bool optimize;
a0475b241a56220714d96a41f11a174c11a48bfaTimo Sirainen int ret = 0;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
20eafc2a848865ce7bf5e8c609e3b0bbd9077ec2Timo Sirainen optimize = (ctx->flags & (MAILBOX_SYNC_FLAG_FORCE_RESYNC |
20eafc2a848865ce7bf5e8c609e3b0bbd9077ec2Timo Sirainen MAILBOX_SYNC_FLAG_OPTIMIZE)) != 0;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen if (fbox->module_ctx.super.sync_deinit(ctx, status_r) < 0)
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen return -1;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen ctx = NULL;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
20eafc2a848865ce7bf5e8c609e3b0bbd9077ec2Timo Sirainen if (optimize) {
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi i_assert(flist != NULL);
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen if (fts_backend_optimize(flist->backend) < 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box, "FTS optimize failed");
a0475b241a56220714d96a41f11a174c11a48bfaTimo Sirainen ret = -1;
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen }
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen }
a0475b241a56220714d96a41f11a174c11a48bfaTimo Sirainen return ret;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen}
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainenstatic int fts_save_finish(struct mail_save_context *ctx)
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen{
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
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen if (fbox->module_ctx.super.save_finish(ctx) < 0)
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen return -1;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen ft->mails_saved = TRUE;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen return 0;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen}
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainenstatic int fts_copy(struct mail_save_context *ctx, struct mail *mail)
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen{
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
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen if (fbox->module_ctx.super.copy(ctx, mail) < 0)
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen return -1;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen ft->mails_saved = TRUE;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen return 0;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen}
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wangstatic const char *const *fts_exclude_get_patterns(struct mail_user *user)
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang{
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang ARRAY_TYPE(const_string) patterns;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang const char *str;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang char set_name[21+MAX_INT_STRLEN+1];
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang unsigned int i;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang str = mail_user_plugin_getenv(user, "fts_autoindex_exclude");
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang if (str == NULL)
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang return NULL;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang t_array_init(&patterns, 16);
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang for (i = 2; str != NULL; i++) {
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang array_append(&patterns, &str, 1);
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang if (i_snprintf(set_name, sizeof(set_name),
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang "fts_autoindex_exclude%u", i) < 0)
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang i_unreached();
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang str = mail_user_plugin_getenv(user, set_name);
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang }
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang array_append_zero(&patterns);
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang return array_idx(&patterns, 0);
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang}
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wangstatic bool fts_autoindex_exclude_match(struct mailbox *box)
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang{
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang const char *const *exclude_list;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang unsigned int i;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang const struct mailbox_settings *set;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang const char *const *special_use;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang struct mail_user *user = box->storage->user;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang exclude_list = fts_exclude_get_patterns(user);
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang if (exclude_list == NULL)
2e6356f8d3aeb71c24662ae8bba7679ae1c79807Timo Sirainen return FALSE;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang set = mailbox_settings_find(mailbox_get_namespace(box),
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang mailbox_get_vname(box));
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang special_use = set == NULL ? NULL :
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang t_strsplit_spaces(set->special_use, " ");
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang for (i = 0; exclude_list[i] != NULL; i++) {
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang if (exclude_list[i][0] == '\\') {
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang /* \Special-use flag */
766ba3eed8b1c011a7a14c11cda6256ca2c25be4Timo Sirainen if (special_use != NULL &&
766ba3eed8b1c011a7a14c11cda6256ca2c25be4Timo Sirainen str_array_icase_find(special_use, exclude_list[i]))
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang return TRUE;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang } else {
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang /* mailbox name with wildcards */
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang if (wildcard_match(box->name, exclude_list[i]))
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang return TRUE;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang }
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang }
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang return FALSE;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang}
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid fts_mailbox_allocated(struct mailbox *box)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(box->list);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct mailbox_vfuncs *v = box->vlast;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct fts_mailbox *fbox;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi if (flist == NULL || flist->failed)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fbox = p_new(box->pool, struct fts_mailbox, 1);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen fbox->module_ctx.super = *v;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen box->vlast = &fbox->module_ctx.super;
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang fbox->fts_mailbox_excluded = fts_autoindex_exclude_match(box);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen v->get_status = fts_mailbox_get_status;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->search_init = fts_mailbox_search_init;
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->search_deinit = fts_mailbox_search_deinit;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->transaction_begin = fts_transaction_begin;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->transaction_rollback = fts_transaction_rollback;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->transaction_commit = fts_transaction_commit;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen v->sync_notify = fts_mailbox_sync_notify;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen v->sync_deinit = fts_sync_deinit;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen v->save_finish = fts_save_finish;
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen v->copy = fts_copy;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET(box, fts_storage_module, fbox);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void fts_mailbox_list_deinit(struct mailbox_list *list)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox_list *flist = FTS_LIST_CONTEXT_REQUIRE(list);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
de5d6bb50931ea243f582ace5a31abb11b619ffeAki Tuomi if (flist->backend != NULL)
de5d6bb50931ea243f582ace5a31abb11b619ffeAki Tuomi fts_backend_deinit(&flist->backend);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen flist->module_ctx.super.deinit(list);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomistatic int
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomifts_init_namespace(struct fts_mailbox_list *flist, struct mail_namespace *ns,
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi const char **error_r)
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi{
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi struct fts_backend *backend;
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi if (fts_backend_init(flist->backend_name, ns, error_r, &backend) < 0) {
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi flist->failed = TRUE;
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi return -1;
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi }
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi flist->backend = backend;
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi if ((flist->backend->flags & FTS_BACKEND_FLAG_FUZZY_SEARCH) != 0)
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi ns->user->fuzzy_search = TRUE;
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi return 0;
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi}
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomivoid fts_mail_namespaces_added(struct mail_namespace *ns)
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi{
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi while(ns != NULL) {
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(ns->list);
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi const char *error;
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi if (flist != NULL && !flist->failed && flist->backend == NULL &&
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi fts_init_namespace(flist, ns, &error) < 0) {
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi i_error("fts: Failed to initialize backend '%s': %s",
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi flist->backend_name, error);
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi }
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi ns = ns->next;
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi }
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi}
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi
79195413c349af7f9ce26871bf79c70af07ea7ceAki Tuomivoid
79195413c349af7f9ce26871bf79c70af07ea7ceAki Tuomifts_mailbox_list_created(struct mailbox_list *list)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
79195413c349af7f9ce26871bf79c70af07ea7ceAki Tuomi const char *name = mail_user_plugin_getenv(list->ns->user, "fts");
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi const char *path;
79195413c349af7f9ce26871bf79c70af07ea7ceAki Tuomi
79195413c349af7f9ce26871bf79c70af07ea7ceAki Tuomi if (name == NULL || name[0] == '\0') {
79195413c349af7f9ce26871bf79c70af07ea7ceAki Tuomi if (list->mail_set->mail_debug)
79195413c349af7f9ce26871bf79c70af07ea7ceAki Tuomi i_debug("fts: No fts setting - plugin disabled");
79195413c349af7f9ce26871bf79c70af07ea7ceAki Tuomi return;
79195413c349af7f9ce26871bf79c70af07ea7ceAki Tuomi }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_INDEX, &path)) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (list->mail_set->mail_debug) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_debug("fts: Indexes disabled for namespace '%s'",
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list->ns->prefix);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
c42ec3faf1c0d2bf65b8ef5e524d0c18992e7454Aki Tuomi struct fts_mailbox_list *flist;
c42ec3faf1c0d2bf65b8ef5e524d0c18992e7454Aki Tuomi struct mailbox_list_vfuncs *v = list->vlast;
c42ec3faf1c0d2bf65b8ef5e524d0c18992e7454Aki Tuomi
c42ec3faf1c0d2bf65b8ef5e524d0c18992e7454Aki Tuomi flist = p_new(list->pool, struct fts_mailbox_list, 1);
c42ec3faf1c0d2bf65b8ef5e524d0c18992e7454Aki Tuomi flist->module_ctx.super = *v;
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi flist->backend_name = name;
c42ec3faf1c0d2bf65b8ef5e524d0c18992e7454Aki Tuomi list->vlast = &flist->module_ctx.super;
c42ec3faf1c0d2bf65b8ef5e524d0c18992e7454Aki Tuomi v->deinit = fts_mailbox_list_deinit;
c42ec3faf1c0d2bf65b8ef5e524d0c18992e7454Aki Tuomi MODULE_CONTEXT_SET(list, fts_mailbox_list_module, flist);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct fts_backend *fts_mailbox_backend(struct mailbox *box)
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen{
084431105a179063aeb08f45eb5f506c61ea8602Aki Tuomi struct fts_mailbox_list *flist = FTS_LIST_CONTEXT_REQUIRE(box->list);
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return flist->backend;
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen}
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainenstruct fts_backend *fts_list_backend(struct mailbox_list *list)
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen{
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(list);
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen return flist == NULL ? NULL : flist->backend;
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen}