fts-storage.c revision bd1b2615928a1e8be190cb0405754f0aec8cac2f
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "lib.h"
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen#include "ioloop.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "array.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "str.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "istream.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "message-parser.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "message-decoder.h"
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen#include "mail-search-build.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "mail-storage-private.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "fts-api-private.h"
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen#include "fts-storage.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "fts-plugin.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include <stdlib.h>
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#define FTS_CONTEXT(obj) \
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT(obj, fts_storage_module)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#define FTS_MAIL_CONTEXT(obj) \
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT(obj, fts_mail_module)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen#define FTS_SEARCH_NONBLOCK_COUNT 10
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen#define FTS_BUILD_NOTIFY_INTERVAL_SECS 10
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenstruct fts_mail {
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen union mail_module_context module_ctx;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen char score[30];
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen};
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenstruct fts_storage_build_context {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct mail_search_context *search_ctx;
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen struct mail_search_args *search_args;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct mail *mail;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct fts_backend_build_context *build;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen struct timeval search_start_time, last_notify;
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen uint32_t uid;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen string_t *headers;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen};
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainenstruct fts_transaction_context {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mailbox_transaction_module_context module_ctx;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen struct fts_storage_build_context *build_ctx;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen ARRAY_TYPE(fts_score_map) *score_map;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen struct mail *mail;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen uint32_t last_uid;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen unsigned int free_mail:1;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen unsigned int expunges: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);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenstatic int fts_mailbox_close(struct mailbox *box)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct fts_mailbox *fbox = FTS_CONTEXT(box);
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen int ret;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (fbox->backend_substr != NULL)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen fts_backend_deinit(&fbox->backend_substr);
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen if (fbox->backend_fast != NULL)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen fts_backend_deinit(&fbox->backend_fast);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen ret = fbox->module_ctx.super.close(box);
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen i_free(fbox);
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen return ret;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainenstatic int fts_build_mail_flush_headers(struct fts_storage_build_context *ctx)
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen{
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen if (str_len(ctx->headers) == 0)
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen return 0;
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen if (fts_backend_build_more(ctx->build, ctx->uid, str_data(ctx->headers),
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen str_len(ctx->headers), TRUE) < 0)
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen return -1;
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen str_truncate(ctx->headers, 0);
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen return 0;
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen}
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainenstatic bool fts_build_want_index_part(const struct message_block *block)
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen{
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen /* we'll index only text/xxx and message/rfc822 parts for now */
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen return (block->part->flags &
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen (MESSAGE_PART_FLAG_TEXT |
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0;
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen}
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainenstatic void fts_build_mail_header(struct fts_storage_build_context *ctx,
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen const struct message_block *block)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen const struct message_header_line *hdr = block->hdr;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen /* hdr->full_value is always set because we get the block from
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen message_decoder */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen str_append(ctx->headers, hdr->name);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen str_append_n(ctx->headers, hdr->middle, hdr->middle_len);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen str_append_n(ctx->headers, hdr->full_value, hdr->full_value_len);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (!hdr->no_newline)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen str_append_c(ctx->headers, '\n');
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenstatic int fts_build_mail(struct fts_storage_build_context *ctx, uint32_t uid)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct istream *input;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct message_parser_ctx *parser;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct message_decoder_context *decoder;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct message_block raw_block, block;
992118a50af940482b6cf884a89be56d7015580aTimo Sirainen struct message_part *prev_part, *parts;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen int ret;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen ctx->uid = uid;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (mail_get_stream(ctx->mail, NULL, NULL, &input) < 0)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen return -1;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen prev_part = NULL;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen parser = message_parser_init(pool_datastack_create(), input,
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE,
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen 0);
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen decoder = message_decoder_init(TRUE);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen for (;;) {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen ret = message_parser_parse_next_block(parser, &raw_block);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen i_assert(ret != 0);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (ret < 0) {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (input->stream_errno == 0)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen ret = 0;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen break;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen if (raw_block.hdr == NULL && raw_block.size != 0 &&
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen !fts_build_want_index_part(&raw_block)) {
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen /* skipping this body */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen continue;
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (!message_decoder_decode_next_block(decoder, &raw_block,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen &block))
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen continue;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen if (block.hdr != NULL)
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen fts_build_mail_header(ctx, &block);
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen else if (block.size == 0) {
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen /* end of headers */
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen str_append_c(ctx->headers, '\n');
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen } else {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (fts_backend_build_more(ctx->build, ctx->uid,
20b136f04257b0ba338e49f31a999c0d4b243647Timo Sirainen block.data, block.size,
20b136f04257b0ba338e49f31a999c0d4b243647Timo Sirainen FALSE) < 0) {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen ret = -1;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen break;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
992118a50af940482b6cf884a89be56d7015580aTimo Sirainen if (message_parser_deinit(&parser, &parts) < 0)
992118a50af940482b6cf884a89be56d7015580aTimo Sirainen mail_set_cache_corrupted(ctx->mail, MAIL_FETCH_MESSAGE_PARTS);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen message_decoder_deinit(&decoder);
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen if (ret == 0) {
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen /* Index all headers at the end. This is required for Squat,
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen because it can handle only incremental UIDs. */
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen ret = fts_build_mail_flush_headers(ctx);
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen return ret;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainenstatic int fts_build_init(struct fts_search_context *fctx)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen struct mailbox_transaction_context *t = fctx->t;
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen struct mail_search_args *search_args;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen struct fts_backend *backend = fctx->build_backend;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct fts_storage_build_context *ctx;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct fts_backend_build_context *build;
1176124297af5c56e932c0863c6637ff21d8a0efTimo Sirainen uint32_t last_uid, last_uid_locked, seq1, seq2;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen if (fts_backend_get_last_uid(backend, &last_uid) < 0)
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen return -1;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainen mailbox_get_seq_range(t->box, last_uid+1, (uint32_t)-1, &seq1, &seq2);
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen fctx->first_nonindexed_seq = seq1;
1176124297af5c56e932c0863c6637ff21d8a0efTimo Sirainen if (seq1 == 0) {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen /* no new messages */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen return 0;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen
e22b857e838fe118de3f78513aad6a3c6f4306b3Timo Sirainen if (fctx->best_arg->type == SEARCH_HEADER ||
e22b857e838fe118de3f78513aad6a3c6f4306b3Timo Sirainen fctx->best_arg->type == SEARCH_HEADER_COMPRESS_LWSP) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* we're not updating the index just for header lookups */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen return 0;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (fts_backend_build_init(backend, &last_uid_locked, &build) < 0)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen return -1;
48566ca412a7cf3b42512fd0ec112744778e5da0Timo Sirainen if (last_uid != last_uid_locked && last_uid_locked != (uint32_t)-1) {
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen /* changed, need to get again the sequences */
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen i_assert(last_uid < last_uid_locked);
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen last_uid = last_uid_locked;
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainen mailbox_get_seq_range(t->box, last_uid+1, (uint32_t)-1,
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainen &seq1, &seq2);
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen fctx->first_nonindexed_seq = seq1;
1176124297af5c56e932c0863c6637ff21d8a0efTimo Sirainen if (seq1 == 0) {
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen /* no new messages */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen (void)fts_backend_build_deinit(&build);
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen return 0;
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen }
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen }
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen search_args = mail_search_build_init();
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen mail_search_build_add_seqset(search_args, seq1, seq2);
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen ctx = i_new(struct fts_storage_build_context, 1);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen ctx->build = build;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen ctx->headers = str_new(default_pool, 512);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen ctx->mail = mail_alloc(t, 0, NULL);
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen ctx->search_ctx = mailbox_search_init(t, search_args, NULL);
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen ctx->search_args = search_args;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen fctx->build_ctx = ctx;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen return 0;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen}
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenstatic int fts_build_deinit(struct fts_storage_build_context **_ctx)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen{
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen struct fts_storage_build_context *ctx = *_ctx;
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen struct mailbox *box = ctx->mail->transaction->box;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen int ret = 0;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen *_ctx = NULL;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (mailbox_search_deinit(&ctx->search_ctx) < 0)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen ret = -1;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen mail_free(&ctx->mail);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (fts_backend_build_deinit(&ctx->build) < 0)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen ret = -1;
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen if (ioloop_time - ctx->search_start_time.tv_sec >=
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen FTS_BUILD_NOTIFY_INTERVAL_SECS) {
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen /* we notified at least once */
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen box->storage->callbacks->
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen notify_ok(box, "Mailbox indexing finished",
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen box->storage->callback_context);
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen }
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen str_free(&ctx->headers);
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen mail_search_args_unref(&ctx->search_args);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen i_free(ctx);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen return ret;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainenstatic void fts_build_notify(struct fts_storage_build_context *ctx)
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen{
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen struct mailbox *box = ctx->mail->transaction->box;
1176124297af5c56e932c0863c6637ff21d8a0efTimo Sirainen const struct seq_range *range;
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen float percentage;
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen unsigned int msecs, secs;
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen if (ctx->last_notify.tv_sec == 0) {
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen /* set the search time in here, in case a plugin
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen already spent some time indexing the mailbox */
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen ctx->search_start_time = ioloop_timeval;
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen } else if (box->storage->callbacks->notify_ok != NULL) {
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen range = array_idx(&ctx->search_args->args->value.seqset, 0);
1176124297af5c56e932c0863c6637ff21d8a0efTimo Sirainen percentage = (ctx->mail->seq - range->seq1) * 100.0 /
1176124297af5c56e932c0863c6637ff21d8a0efTimo Sirainen (range->seq2 - range->seq1);
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen msecs = (ioloop_timeval.tv_sec -
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen ctx->search_start_time.tv_sec) * 1000 +
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen (ioloop_timeval.tv_usec -
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen ctx->search_start_time.tv_usec) / 1000;
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen secs = (msecs / (percentage / 100.0) - msecs) / 1000;
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen const char *text;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen text = t_strdup_printf("Indexed %d%% of the mailbox, "
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen "ETA %d:%02d", (int)percentage,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen secs/60, secs%60);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen box->storage->callbacks->
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen notify_ok(box, text,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen box->storage->callback_context);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen }
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen ctx->last_notify = ioloop_timeval;
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen}
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenstatic int fts_build_more(struct fts_storage_build_context *ctx)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen{
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen unsigned int count = 0;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen int ret;
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen if (ioloop_time - ctx->last_notify.tv_sec >=
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen FTS_BUILD_NOTIFY_INTERVAL_SECS)
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen fts_build_notify(ctx);
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen while (mailbox_search_next(ctx->search_ctx, ctx->mail) > 0) {
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ret = fts_build_mail(ctx, ctx->mail->uid);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (ret < 0)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen return -1;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (++count == FTS_SEARCH_NONBLOCK_COUNT)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen return 0;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen }
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen return 1;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainenstatic bool fts_try_build_init(struct fts_search_context *fctx)
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen{
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (fctx->build_backend == NULL) {
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen fctx->build_initialized = TRUE;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen return TRUE;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen }
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (fts_backend_is_building(fctx->build_backend)) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* this process is already building the indexes */
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen return FALSE;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen }
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen fctx->build_initialized = TRUE;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (fts_build_init(fctx) < 0) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen fctx->build_backend = NULL;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen return TRUE;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen }
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (fctx->build_ctx == NULL) {
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen /* the index was up to date */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen fts_search_lookup(fctx);
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen }
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen return TRUE;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen}
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenstatic struct mail_search_context *
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenfts_mailbox_search_init(struct mailbox_transaction_context *t,
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen struct mail_search_args *args,
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen const enum mail_sort_type *sort_program)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen{
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen struct fts_transaction_context *ft = FTS_CONTEXT(t);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct fts_mailbox *fbox = FTS_CONTEXT(t->box);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct mail_search_context *ctx;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct fts_search_context *fctx;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen ctx = fbox->module_ctx.super.search_init(t, args, sort_program);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen fctx = i_new(struct fts_search_context, 1);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen fctx->fbox = fbox;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen fctx->t = t;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen fctx->args = args;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET(ctx, fts_storage_module, fctx);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (fbox->backend_substr == NULL && fbox->backend_fast == NULL)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen return ctx;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen ft->score_map = &fctx->score_map;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen fts_search_analyze(fctx);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen (void)fts_try_build_init(fctx);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen return ctx;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenstatic int fts_mailbox_search_next_nonblock(struct mail_search_context *ctx,
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct mail *mail, bool *tryagain_r)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen{
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct fts_mailbox *fbox = FTS_CONTEXT(ctx->transaction->box);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct fts_search_context *fctx = FTS_CONTEXT(ctx);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen int ret;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen if (!fctx->build_initialized) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* we're still waiting for this process (but another command)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen to finish building the indexes */
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen if (!fts_try_build_init(fctx)) {
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen *tryagain_r = TRUE;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen return 0;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen }
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen }
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (fctx->build_ctx != NULL) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* this command is still building the indexes */
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen ret = fts_build_more(fctx->build_ctx);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (ret == 0) {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen *tryagain_r = TRUE;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen return 0;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen }
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen /* finished / error */
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen if (fts_build_deinit(&fctx->build_ctx) < 0)
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen ret = -1;
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen if (ret > 0) {
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen fctx->first_nonindexed_seq = 0;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen fts_search_lookup(fctx);
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen }
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen }
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* if we're here, the indexes are either built or they're not used */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return fbox->module_ctx.super.
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen search_next_nonblock(ctx, mail, tryagain_r);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen}
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenstatic void
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenfts_mailbox_search_args_definite_set(struct fts_search_context *fctx)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen{
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen struct mail_search_arg *arg;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen for (arg = fctx->args->args; arg != NULL; arg = arg->next) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen switch (arg->type) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen case SEARCH_TEXT:
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen case SEARCH_BODY:
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen case SEARCH_BODY_FAST:
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen case SEARCH_TEXT_FAST:
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen arg->result = 1;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen break;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen default:
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen break;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen }
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen }
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen}
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainenstatic bool fts_mailbox_search_next_update_seq(struct mail_search_context *ctx)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct fts_mailbox *fbox = FTS_CONTEXT(ctx->transaction->box);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct fts_search_context *fctx = FTS_CONTEXT(ctx);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen struct seq_range *def_range, *maybe_range, *range;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen unsigned int def_count, maybe_count;
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen uint32_t wanted_seq;
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainen bool use_maybe, ret;
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (!fctx->seqs_set)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return fbox->module_ctx.super.search_next_update_seq(ctx);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen wanted_seq = ctx->seq + 1;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* fts_search_lookup() was called successfully */
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen for (;;) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen def_range = array_get_modifiable(&fctx->definite_seqs,
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen &def_count);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen maybe_range = array_get_modifiable(&fctx->maybe_seqs,
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen &maybe_count);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* if we're ahead of current positions, skip them */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen while (fctx->definite_idx < def_count &&
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen wanted_seq > def_range[fctx->definite_idx].seq2)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen fctx->definite_idx++;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen while (fctx->maybe_idx < maybe_count &&
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen wanted_seq > maybe_range[fctx->maybe_idx].seq2)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen fctx->maybe_idx++;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* use whichever is lower of definite/maybe */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (fctx->definite_idx == def_count) {
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen if (fctx->maybe_idx == maybe_count) {
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen /* look for the non-indexed mails */
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen if (fctx->first_nonindexed_seq == 0)
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainen return FALSE;
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen fctx->seqs_set = FALSE;
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen ctx->seq = fctx->first_nonindexed_seq - 1;
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen return fbox->module_ctx.super.
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen search_next_update_seq(ctx);
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen }
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen use_maybe = TRUE;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen } else if (fctx->maybe_idx == maybe_count) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen use_maybe = FALSE;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen } else {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen use_maybe = maybe_range[fctx->maybe_idx].seq1 <
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen def_range[fctx->definite_idx].seq2;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (use_maybe)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen range = maybe_range + fctx->maybe_idx;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen else
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen range = def_range + fctx->definite_idx;
4bffa20ff6fc61ba7b47375722e38be7f87dfe64Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen i_assert(range->seq1 <= range->seq2);
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen if (wanted_seq > range->seq1) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* current sequence is already larger than where
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen range begins, so use the current sequence. */
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen range->seq1 = wanted_seq+1;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen } else {
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen wanted_seq = range->seq1;
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen range->seq1++;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen if (range->seq1 > range->seq2)
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen range->seq2 = 0;
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* ctx->seq points to previous sequence we want */
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen ctx->seq = wanted_seq - 1;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen ret = fbox->module_ctx.super.search_next_update_seq(ctx);
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainen if (!ret || wanted_seq == ctx->seq)
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen break;
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen wanted_seq = ctx->seq;
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen mail_search_args_reset(ctx->args->args, FALSE);
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen }
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (!use_maybe) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* we have definite results, update args */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen fts_mailbox_search_args_definite_set(fctx);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen }
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen return ret;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenstatic int fts_mailbox_search_deinit(struct mail_search_context *ctx)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen struct fts_transaction_context *ft = FTS_CONTEXT(ctx->transaction);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct fts_mailbox *fbox = FTS_CONTEXT(ctx->transaction->box);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct fts_search_context *fctx = FTS_CONTEXT(ctx);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen if (ft->score_map == &fctx->score_map)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen ft->score_map = NULL;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (fctx->build_ctx != NULL) {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen /* the search was cancelled */
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen (void)fts_build_deinit(&fctx->build_ctx);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen }
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (array_is_created(&fctx->definite_seqs))
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen array_free(&fctx->definite_seqs);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (array_is_created(&fctx->maybe_seqs))
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen array_free(&fctx->maybe_seqs);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen if (array_is_created(&fctx->score_map))
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen array_free(&fctx->score_map);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen i_free(fctx);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return fbox->module_ctx.super.search_deinit(ctx);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void fts_mail_expunge(struct mail *_mail)
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen{
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen struct fts_mail *fmail = FTS_MAIL_CONTEXT(mail);
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen struct fts_mailbox *fbox = FTS_CONTEXT(_mail->box);
a1761856683b4bf745eb4e32cefabeb851efb301Timo Sirainen struct fts_transaction_context *ft = FTS_CONTEXT(_mail->transaction);
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen
a1761856683b4bf745eb4e32cefabeb851efb301Timo Sirainen ft->expunges = TRUE;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (fbox->backend_substr != NULL)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen fts_backend_expunge(fbox->backend_substr, _mail);
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen if (fbox->backend_fast != NULL)
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen fts_backend_expunge(fbox->backend_fast, _mail);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen fmail->module_ctx.super.expunge(_mail);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen}
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenstatic int fts_score_cmp(const void *key, const void *data)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen{
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen const uint32_t *uid = key;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen const struct fts_score_map *score = data;
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);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen struct fts_transaction_context *ft = FTS_CONTEXT(_mail->transaction);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen const struct fts_score_map *scores;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen unsigned int count;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen if (field != MAIL_FETCH_SEARCH_SCORE || ft->score_map == NULL ||
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen !array_is_created(ft->score_map))
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen scores = NULL;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen else {
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen scores = array_get(ft->score_map, &count);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen scores = bsearch(&_mail->uid, scores, count, sizeof(*scores),
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen fts_score_cmp);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen }
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen if (scores != NULL) {
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen i_assert(scores->uid == _mail->uid);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen i_snprintf(fmail->score, sizeof(fmail->score),
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen "%f", scores->score);
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
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainenstatic struct mail *
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainenfts_mail_alloc(struct mailbox_transaction_context *t,
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen enum mail_fetch_field wanted_fields,
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen{
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen struct fts_mailbox *fbox = FTS_CONTEXT(t->box);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen struct fts_mail *fmail;
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen struct mail *_mail;
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen struct mail_private *mail;
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen _mail = fbox->module_ctx.super.
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mail_alloc(t, wanted_fields, wanted_headers);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (fbox->backend_substr != NULL || fbox->backend_fast != NULL) {
a1761856683b4bf745eb4e32cefabeb851efb301Timo Sirainen mail = (struct mail_private *)_mail;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen fmail = p_new(mail->pool, struct fts_mail, 1);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen fmail->module_ctx.super = mail->v;
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen
a1761856683b4bf745eb4e32cefabeb851efb301Timo Sirainen mail->v.expunge = fts_mail_expunge;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen mail->v.get_special = fts_mail_get_special;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen MODULE_CONTEXT_SET(mail, fts_mail_module, fmail);
a1761856683b4bf745eb4e32cefabeb851efb301Timo Sirainen }
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen return _mail;
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen}
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainenstatic void fts_box_backends_init(struct mailbox *box)
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen{
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen struct fts_mailbox *fbox = FTS_CONTEXT(box);
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen struct fts_backend *backend;
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen const char *const *tmp;
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen for (tmp = t_strsplit(fbox->env, ", "); *tmp != NULL; tmp++) {
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen backend = fts_backend_init(*tmp, box);
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen if (backend == NULL)
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen continue;
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen if ((backend->flags &
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen FTS_BACKEND_FLAG_SUBSTRING_LOOKUPS) != 0) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (fbox->backend_substr != NULL) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen i_fatal("fts: duplicate substring backend: %s",
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen *tmp);
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen }
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen fbox->backend_substr = backend;
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen } else {
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen if (fbox->backend_fast != NULL) {
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen i_fatal("fts: duplicate fast backend: %s",
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen *tmp);
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen }
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen fbox->backend_fast = backend;
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen }
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen }
14bb36cbb67b42e32105c3d843a8c974dc7ed436Timo Sirainen if ((box->storage->flags & MAIL_STORAGE_FLAG_DEBUG) != 0 &&
14bb36cbb67b42e32105c3d843a8c974dc7ed436Timo Sirainen fbox->backend_substr == NULL && fbox->backend_fast == NULL)
14bb36cbb67b42e32105c3d843a8c974dc7ed436Timo Sirainen i_info("fts: No backends enabled by the fts setting");
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen}
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainenstatic struct mailbox_transaction_context *
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainenfts_transaction_begin(struct mailbox *box,
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen enum mailbox_transaction_flags flags)
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen{
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen struct fts_mailbox *fbox = FTS_CONTEXT(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
a1761856683b4bf745eb4e32cefabeb851efb301Timo Sirainen /* the backend creation is delayed until the first transaction is
a1761856683b4bf745eb4e32cefabeb851efb301Timo Sirainen started. at that point the mailbox has been synced at least once. */
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen if (!fbox->backend_set) {
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen fts_box_backends_init(box);
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen fbox->backend_set = TRUE;
a1761856683b4bf745eb4e32cefabeb851efb301Timo Sirainen }
a1761856683b4bf745eb4e32cefabeb851efb301Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen t = fbox->module_ctx.super.transaction_begin(box, flags);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET(t, fts_storage_module, ft);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen return t;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen}
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenstatic void
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenfts_storage_build_context_deinit(struct fts_storage_build_context *build_ctx)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen{
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen (void)fts_backend_build_deinit(&build_ctx->build);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen str_free(&build_ctx->headers);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen i_free(build_ctx);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen}
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainenstatic void
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainenfts_transaction_finish(struct mailbox *box, struct fts_transaction_context *ft,
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen bool committed)
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen{
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen struct fts_mailbox *fbox = FTS_CONTEXT(box);
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen if (ft->expunges) {
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen if (fbox->backend_fast != NULL) {
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen fts_backend_expunge_finish(fbox->backend_fast,
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen box, committed);
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen }
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen }
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen i_free(ft);
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen}
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainenstatic void fts_transaction_rollback(struct mailbox_transaction_context *t)
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen{
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen struct mailbox *box = t->box;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen struct fts_mailbox *fbox = FTS_CONTEXT(box);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen struct fts_transaction_context *ft = FTS_CONTEXT(t);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (ft->build_ctx != NULL) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen fts_storage_build_context_deinit(ft->build_ctx);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen ft->build_ctx = NULL;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen }
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (ft->free_mail)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen mail_free(&ft->mail);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen fbox->module_ctx.super.transaction_rollback(t);
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen fts_transaction_finish(box, ft, FALSE);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen}
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainenstatic int fts_transaction_commit(struct mailbox_transaction_context *t,
d5e5981392f1a0be9152a9d5645b4609ccb9f76cTimo Sirainen uint32_t *uid_validity_r,
4d2211dac61c615c5bdfd501ea54d46c89d41b0fTimo Sirainen uint32_t *first_saved_uid_r,
4d2211dac61c615c5bdfd501ea54d46c89d41b0fTimo Sirainen uint32_t *last_saved_uid_r)
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen{
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen struct mailbox *box = t->box;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen struct fts_mailbox *fbox = FTS_CONTEXT(box);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen struct fts_transaction_context *ft = FTS_CONTEXT(t);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen int ret;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (ft->build_ctx != NULL) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen fts_storage_build_context_deinit(ft->build_ctx);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen ft->build_ctx = NULL;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen }
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (ft->free_mail)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen mail_free(&ft->mail);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
63f36c2b47217fc2dc4ed49cfc1907311d5ed366Timo Sirainen ret = fbox->module_ctx.super.transaction_commit(t,
d5e5981392f1a0be9152a9d5645b4609ccb9f76cTimo Sirainen uid_validity_r,
4d2211dac61c615c5bdfd501ea54d46c89d41b0fTimo Sirainen first_saved_uid_r,
4d2211dac61c615c5bdfd501ea54d46c89d41b0fTimo Sirainen last_saved_uid_r);
eb0ede66120bb63c0212bad69e67efca1eb47324Timo Sirainen fts_transaction_finish(box, ft, ret == 0);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen return ret;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen}
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainenstatic void fts_mailbox_init(struct mailbox *box, const char *env)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct fts_mailbox *fbox;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen fbox = i_new(struct fts_mailbox, 1);
a1761856683b4bf745eb4e32cefabeb851efb301Timo Sirainen fbox->env = env;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen fbox->module_ctx.super = box->v;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen box->v.close = fts_mailbox_close;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen box->v.search_init = fts_mailbox_search_init;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen box->v.search_next_nonblock = fts_mailbox_search_next_nonblock;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen box->v.search_next_update_seq = fts_mailbox_search_next_update_seq;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen box->v.search_deinit = fts_mailbox_search_deinit;
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen box->v.mail_alloc = fts_mail_alloc;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen box->v.transaction_begin = fts_transaction_begin;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen box->v.transaction_rollback = fts_transaction_rollback;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen box->v.transaction_commit = fts_transaction_commit;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET(box, fts_storage_module, fbox);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainenvoid fts_mailbox_opened(struct mailbox *box)
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen{
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen const char *env;
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen env = getenv("FTS");
14bb36cbb67b42e32105c3d843a8c974dc7ed436Timo Sirainen i_assert(env != NULL);
14bb36cbb67b42e32105c3d843a8c974dc7ed436Timo Sirainen fts_mailbox_init(box, env);
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen if (fts_next_hook_mailbox_opened != NULL)
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen fts_next_hook_mailbox_opened(box);
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen}