fts-api.c revision de62ce819d59a529530da4b57be1b8d6dad13d6b
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2006-2011 Dovecot authors, see the included COPYING file */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "lib.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "array.h"
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#include "hex-binary.h"
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#include "mail-index.h"
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#include "mail-storage-private.h"
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#include "mail-search.h"
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#include "../virtual/virtual-storage.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "fts-api-private.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenstatic ARRAY_DEFINE(backends, const struct fts_backend *);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenvoid fts_backend_register(const struct fts_backend *backend)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
3fb1c1f0375ec0a2b00be90b5d61fbc8374e9b90Timo Sirainen if (!array_is_created(&backends))
3fb1c1f0375ec0a2b00be90b5d61fbc8374e9b90Timo Sirainen i_array_init(&backends, 4);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen array_append(&backends, &backend, 1);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenvoid fts_backend_unregister(const char *name)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen const struct fts_backend *const *be;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen unsigned int i, count;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen be = array_get(&backends, &count);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen for (i = 0; i < count; i++) {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (strcmp(be[i]->name, name) == 0) {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen array_delete(&backends, i, 1);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen break;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (i == count)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen i_panic("fts_backend_unregister(%s): unknown backend", name);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (count == 1)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen array_free(&backends);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainenstatic const struct fts_backend *
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainenfts_backend_class_lookup(const char *backend_name)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen const struct fts_backend *const *be;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen unsigned int i, count;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
c63544d7d2580c680b07f9569e87e9cebee383d5Timo Sirainen if (array_is_created(&backends)) {
c63544d7d2580c680b07f9569e87e9cebee383d5Timo Sirainen be = array_get(&backends, &count);
c63544d7d2580c680b07f9569e87e9cebee383d5Timo Sirainen for (i = 0; i < count; i++) {
c63544d7d2580c680b07f9569e87e9cebee383d5Timo Sirainen if (strcmp(be[i]->name, backend_name) == 0)
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainen return be[i];
c63544d7d2580c680b07f9569e87e9cebee383d5Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen return NULL;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_init(const char *backend_name, struct mail_namespace *ns,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char **error_r, struct fts_backend **backend_r)
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainen{
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainen const struct fts_backend *be;
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainen struct fts_backend *backend;
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainen
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainen be = fts_backend_class_lookup(backend_name);
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainen if (be == NULL) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *error_r = "Unknown backend";
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainen }
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen backend = be->v.alloc();
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen backend->ns = ns;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (backend->v.init(backend, error_r) < 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_free(backend);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *backend_r = backend;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return 0;
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainen}
459c61c9a0beaa6986958d55b059b2d246032c4cTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenvoid fts_backend_deinit(struct fts_backend **_backend)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen struct fts_backend *backend = *_backend;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen *_backend = NULL;
e80307fd7345f60540c7d83c38952603d2df9e9bTimo Sirainen backend->v.deinit(backend);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_get_last_uid(struct fts_backend *backend, struct mailbox *box,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen uint32_t *last_uid_r)
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (strcmp(box->storage->name, VIRTUAL_STORAGE_NAME) == 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* virtual mailboxes themselves don't have any indexes,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen so catch this call here */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!fts_index_get_last_uid(box, last_uid_r))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *last_uid_r = 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return backend->v.get_last_uid(backend, box, last_uid_r);
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen}
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool fts_backend_is_updating(struct fts_backend *backend)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return backend->updating;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen}
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct fts_backend_update_context *
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenfts_backend_update_init(struct fts_backend *backend)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_assert(!backend->updating);
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen backend->updating = TRUE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return backend->v.update_init(backend);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void fts_backend_set_cur_mailbox(struct fts_backend_update_context *ctx)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_backend_update_unset_build_key(ctx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (ctx->backend_box != ctx->cur_box) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ctx->backend->v.update_set_mailbox(ctx, ctx->cur_box);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ctx->backend_box = ctx->cur_box;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen}
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_update_deinit(struct fts_backend_update_context **_ctx)
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_backend_update_context *ctx = *_ctx;
cea6742c34fcf3f62c30aab4d2120a689d5b1844Timo Sirainen struct fts_backend *backend = ctx->backend;
cea6742c34fcf3f62c30aab4d2120a689d5b1844Timo Sirainen int ret;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *_ctx = NULL;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ctx->cur_box = NULL;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_backend_set_cur_mailbox(ctx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
cea6742c34fcf3f62c30aab4d2120a689d5b1844Timo Sirainen ret = backend->v.update_deinit(ctx);
cea6742c34fcf3f62c30aab4d2120a689d5b1844Timo Sirainen backend->updating = FALSE;
cea6742c34fcf3f62c30aab4d2120a689d5b1844Timo Sirainen return ret;
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen}
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid fts_backend_update_set_mailbox(struct fts_backend_update_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mailbox *box)
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (ctx->backend_box != NULL && box != ctx->backend_box) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* make sure we don't reference the backend box anymore */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ctx->backend->v.update_set_mailbox(ctx, NULL);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ctx->backend_box = NULL;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ctx->cur_box = box;
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen}
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid fts_backend_update_expunge(struct fts_backend_update_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen uint32_t uid)
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_backend_set_cur_mailbox(ctx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ctx->backend->v.update_expunge(ctx, uid);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool fts_backend_update_set_build_key(struct fts_backend_update_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const struct fts_backend_build_key *key)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fts_backend_set_cur_mailbox(ctx);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!ctx->backend->v.update_set_build_key(ctx, key))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ctx->build_key_open = TRUE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return TRUE;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid fts_backend_update_unset_build_key(struct fts_backend_update_context *ctx)
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (ctx->build_key_open) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ctx->backend->v.update_unset_build_key(ctx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ctx->build_key_open = FALSE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen}
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_update_build_more(struct fts_backend_update_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const unsigned char *data, size_t size)
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_assert(ctx->build_key_open);
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return ctx->backend->v.update_build_more(ctx, data, size);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen}
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
de11cf486e0d0448537b1b5d546496ab85e7cda8Timo Sirainenint fts_backend_refresh(struct fts_backend *backend)
3d4450c252790b03bb5ce054987ac91110f1ff62Timo Sirainen{
de11cf486e0d0448537b1b5d546496ab85e7cda8Timo Sirainen return backend->v.refresh(backend);
3d4450c252790b03bb5ce054987ac91110f1ff62Timo Sirainen}
3d4450c252790b03bb5ce054987ac91110f1ff62Timo Sirainen
a569c6df4ffe05acc242e269d926449e50702d59Timo Sirainenint fts_backend_rescan(struct fts_backend *backend)
a569c6df4ffe05acc242e269d926449e50702d59Timo Sirainen{
a569c6df4ffe05acc242e269d926449e50702d59Timo Sirainen return backend->v.rescan == NULL ? 0 :
a569c6df4ffe05acc242e269d926449e50702d59Timo Sirainen backend->v.rescan(backend);
a569c6df4ffe05acc242e269d926449e50702d59Timo Sirainen}
a569c6df4ffe05acc242e269d926449e50702d59Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_optimize(struct fts_backend *backend)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return backend->v.optimize == NULL ? 0 :
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen backend->v.optimize(backend);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenstatic void
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenfts_merge_maybies(ARRAY_TYPE(seq_range) *dest_maybe,
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen const ARRAY_TYPE(seq_range) *dest_definite,
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen const ARRAY_TYPE(seq_range) *src_maybe,
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen const ARRAY_TYPE(seq_range) *src_definite)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen{
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen ARRAY_TYPE(seq_range) src_unwanted;
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen const struct seq_range *range;
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen struct seq_range new_range;
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen unsigned int i, count;
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen uint32_t seq;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* add/leave to dest_maybe if at least one list has maybe,
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen and no lists have none */
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen /* create unwanted sequences list from both sources */
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen t_array_init(&src_unwanted, 128);
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen new_range.seq1 = 0; new_range.seq2 = (uint32_t)-1;
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen array_append(&src_unwanted, &new_range, 1);
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen seq_range_array_remove_seq_range(&src_unwanted, src_maybe);
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen seq_range_array_remove_seq_range(&src_unwanted, src_definite);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* drop unwanted uids */
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen seq_range_array_remove_seq_range(dest_maybe, &src_unwanted);
7bc564062f3bef44c61f4e83ccdd9c5eaa433253Timo Sirainen
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen /* add uids that are in dest_definite and src_maybe lists */
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen range = array_get(dest_definite, &count);
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen for (i = 0; i < count; i++) {
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen for (seq = range[i].seq1; seq <= range[i].seq2; seq++) {
a1f517528af314cb6f5f39187a71dbed8a6e1152Timo Sirainen if (seq_range_exists(src_maybe, seq))
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen seq_range_array_add(dest_maybe, 0, seq);
7bc564062f3bef44c61f4e83ccdd9c5eaa433253Timo Sirainen }
7bc564062f3bef44c61f4e83ccdd9c5eaa433253Timo Sirainen }
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen}
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
809923ba26218971792182ae8894936f9ac99364Timo Sirainenvoid fts_filter_uids(ARRAY_TYPE(seq_range) *definite_dest,
809923ba26218971792182ae8894936f9ac99364Timo Sirainen const ARRAY_TYPE(seq_range) *definite_filter,
809923ba26218971792182ae8894936f9ac99364Timo Sirainen ARRAY_TYPE(seq_range) *maybe_dest,
809923ba26218971792182ae8894936f9ac99364Timo Sirainen const ARRAY_TYPE(seq_range) *maybe_filter)
809923ba26218971792182ae8894936f9ac99364Timo Sirainen{
809923ba26218971792182ae8894936f9ac99364Timo Sirainen T_BEGIN {
809923ba26218971792182ae8894936f9ac99364Timo Sirainen fts_merge_maybies(maybe_dest, definite_dest,
809923ba26218971792182ae8894936f9ac99364Timo Sirainen maybe_filter, definite_filter);
809923ba26218971792182ae8894936f9ac99364Timo Sirainen } T_END;
809923ba26218971792182ae8894936f9ac99364Timo Sirainen /* keep only what exists in both lists. the rest is in
809923ba26218971792182ae8894936f9ac99364Timo Sirainen maybies or not wanted */
809923ba26218971792182ae8894936f9ac99364Timo Sirainen seq_range_array_intersect(definite_dest, definite_filter);
809923ba26218971792182ae8894936f9ac99364Timo Sirainen}
809923ba26218971792182ae8894936f9ac99364Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool fts_backend_default_can_lookup(struct fts_backend *backend,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const struct mail_search_arg *args)
809923ba26218971792182ae8894936f9ac99364Timo Sirainen{
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_backend_default_can_lookup(backend,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen args->value.subargs))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return TRUE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen break;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen case SEARCH_HEADER:
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen case SEARCH_HEADER_ADDRESS:
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen case SEARCH_HEADER_COMPRESS_LWSP:
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen case SEARCH_BODY:
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen case SEARCH_TEXT:
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return TRUE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen default:
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen break;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
809923ba26218971792182ae8894936f9ac99364Timo Sirainen}
809923ba26218971792182ae8894936f9ac99364Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool fts_backend_can_lookup(struct fts_backend *backend,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const struct mail_search_arg *args)
809923ba26218971792182ae8894936f9ac99364Timo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return backend->v.can_lookup(backend, args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
809923ba26218971792182ae8894936f9ac99364Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic int fts_score_map_sort(const struct fts_score_map *m1,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const struct fts_score_map *m2)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (m1->uid < m2->uid)
809923ba26218971792182ae8894936f9ac99364Timo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (m1->uid > m2->uid)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return 1;
809923ba26218971792182ae8894936f9ac99364Timo Sirainen return 0;
809923ba26218971792182ae8894936f9ac99364Timo Sirainen}
809923ba26218971792182ae8894936f9ac99364Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_lookup(struct fts_backend *backend, struct mailbox *box,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_search_arg *args, bool and_args,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_result *result)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_clear(&result->definite_uids);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_clear(&result->maybe_uids);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_clear(&result->scores);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (backend->v.lookup(backend, box, args, and_args, result) < 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!result->scores_sorted && array_is_created(&result->scores)) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_sort(&result->scores, fts_score_map_sort);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen result->scores_sorted = TRUE;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return 0;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
809923ba26218971792182ae8894936f9ac99364Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_lookup_multi(struct fts_backend *backend,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mailbox *const boxes[],
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_search_arg *args, bool and_args,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_multi_result *result)
809923ba26218971792182ae8894936f9ac99364Timo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_assert(boxes[0] != NULL);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return backend->v.lookup_multi(backend, boxes, args, and_args, result);
809923ba26218971792182ae8894936f9ac99364Timo Sirainen}
809923ba26218971792182ae8894936f9ac99364Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic bool
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenfts_index_get_header(struct mailbox *box, struct fts_index_header *hdr_r,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen uint32_t *ext_id_r)
809923ba26218971792182ae8894936f9ac99364Timo Sirainen{
403762eeaebbedce130b1cec435441b22ee8f349Timo Sirainen struct mail_index_view *view;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const void *data;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen size_t data_size;
403762eeaebbedce130b1cec435441b22ee8f349Timo Sirainen bool ret;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
403762eeaebbedce130b1cec435441b22ee8f349Timo Sirainen (void)mail_index_refresh(box->index);
403762eeaebbedce130b1cec435441b22ee8f349Timo Sirainen view = mail_index_view_open(box->index);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *ext_id_r = mail_index_ext_register(box->index, "fts",
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen sizeof(struct fts_index_header),
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen 0, 0);
403762eeaebbedce130b1cec435441b22ee8f349Timo Sirainen mail_index_get_header_ext(view, *ext_id_r, &data, &data_size);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (data_size < sizeof(*hdr_r)) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen memset(hdr_r, 0, sizeof(*hdr_r));
403762eeaebbedce130b1cec435441b22ee8f349Timo Sirainen ret = FALSE;
403762eeaebbedce130b1cec435441b22ee8f349Timo Sirainen } else {
403762eeaebbedce130b1cec435441b22ee8f349Timo Sirainen memcpy(hdr_r, data, data_size);
403762eeaebbedce130b1cec435441b22ee8f349Timo Sirainen ret = TRUE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
403762eeaebbedce130b1cec435441b22ee8f349Timo Sirainen mail_index_view_close(&view);
403762eeaebbedce130b1cec435441b22ee8f349Timo Sirainen return ret;
809923ba26218971792182ae8894936f9ac99364Timo Sirainen}
809923ba26218971792182ae8894936f9ac99364Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool fts_index_get_last_uid(struct mailbox *box, uint32_t *last_uid_r)
809923ba26218971792182ae8894936f9ac99364Timo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_index_header hdr;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen uint32_t ext_id;
809923ba26218971792182ae8894936f9ac99364Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!fts_index_get_header(box, &hdr, &ext_id)) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *last_uid_r = 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
809923ba26218971792182ae8894936f9ac99364Timo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *last_uid_r = hdr.last_indexed_uid;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return TRUE;
809923ba26218971792182ae8894936f9ac99364Timo Sirainen}
809923ba26218971792182ae8894936f9ac99364Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_index_set_last_uid(struct mailbox *box, uint32_t last_uid)
809923ba26218971792182ae8894936f9ac99364Timo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_index_transaction *trans;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_index_header hdr;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen uint32_t ext_id;
809923ba26218971792182ae8894936f9ac99364Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen (void)fts_index_get_header(box, &hdr, &ext_id);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen hdr.last_indexed_uid = last_uid;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen trans = mail_index_transaction_begin(box->view, 0);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_index_update_header_ext(trans, ext_id, 0, &hdr, sizeof(hdr));
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return mail_index_transaction_commit(&trans);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic const char *indexed_headers[] = {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "From", "To", "Cc", "Bcc", "Subject"
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen};
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool fts_header_want_indexed(const char *hdr_name)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen unsigned int i;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen for (i = 0; i < N_ELEMENTS(indexed_headers); i++) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (strcasecmp(hdr_name, indexed_headers[i]) == 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return TRUE;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return FALSE;
809923ba26218971792182ae8894936f9ac99364Timo Sirainen}
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_mailbox_get_guid(struct mailbox *box, const char **guid_r)
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mailbox_metadata metadata;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen *guid_r = guid_128_to_string(metadata.guid);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return 0;
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen}