c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen#ifndef FTS_API_H
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen#define FTS_API_H
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainenstruct mail;
c63544d7d2580c680b07f9569e87e9cebee383d5Timo Sirainenstruct mailbox;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct mail_namespace;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct mail_search_arg;
c63544d7d2580c680b07f9569e87e9cebee383d5Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct fts_backend;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#include "seq-range-array.h"
12055678401e913f4be130fa41b22fbeb626cc7eTimo Sirainen
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainenenum fts_lookup_flags {
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainen /* Specifies if the args should be ANDed or ORed together. */
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainen FTS_LOOKUP_FLAG_AND_ARGS = 0x01,
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainen /* Require exact matching for non-fuzzy search args by returning all
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainen such matches as maybe_uids instead of definite_uids */
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainen FTS_LOOKUP_FLAG_NO_AUTO_FUZZY = 0x02
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainen};
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenenum fts_backend_build_key_type {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* Header */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen FTS_BACKEND_BUILD_KEY_HDR,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* MIME part header */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen FTS_BACKEND_BUILD_KEY_MIME_HDR,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* MIME body part */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen FTS_BACKEND_BUILD_KEY_BODY_PART,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* Binary MIME body part, if backend supports binary data */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen FTS_BACKEND_BUILD_KEY_BODY_PART_BINARY
20b136f04257b0ba338e49f31a999c0d4b243647Timo Sirainen};
20b136f04257b0ba338e49f31a999c0d4b243647Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct fts_backend_build_key {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen uint32_t uid;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen enum fts_backend_build_key_type type;
69111aa5f9df3c49aeefbe0ac6118cf80c7520f1Timo Sirainen struct message_part *part;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* for _KEY_HDR: */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char *hdr_name;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* for _KEY_BODY_PART and _KEY_BODY_PART_BINARY: */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* Contains a valid parsed "type/subtype" string. For messages without
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen (valid) Content-Type: header, it's set to "text/plain". */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char *body_content_type;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* Content-Disposition: header without parsing/validation if it exists,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen otherwise NULL. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char *body_content_disposition;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen};
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenstruct fts_score_map {
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen uint32_t uid;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen float score;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen};
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo SirainenARRAY_DEFINE_TYPE(fts_score_map, struct fts_score_map);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct fts_result {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mailbox *box;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ARRAY_TYPE(seq_range) definite_uids;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* The maybe_uids is useful with backends that can only filter out
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen messages, but can't definitively say if the search matched a
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen message. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ARRAY_TYPE(seq_range) maybe_uids;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ARRAY_TYPE(fts_score_map) scores;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen bool scores_sorted;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen};
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct fts_multi_result {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen pool_t pool;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* box=NULL-terminated array of mailboxes and matching UIDs,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen all allocated from the given pool. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_result *box_results;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen};
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo 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);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenvoid fts_backend_deinit(struct fts_backend **backend);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen/* Get the last_uid for the mailbox. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_get_last_uid(struct fts_backend *backend, struct mailbox *box,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen uint32_t *last_uid_r);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen/* Returns TRUE if there exists an update context. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool fts_backend_is_updating(struct fts_backend *backend);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen/* Start an index update. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct fts_backend_update_context *
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenfts_backend_update_init(struct fts_backend *backend);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen/* Finish an index update. Returns 0 if ok, -1 if some updates failed.
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen If updates failed, the index is in unspecified state. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_update_deinit(struct fts_backend_update_context **ctx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen/* Switch to updating the specified mailbox. box may also be set to NULL to
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen make sure the previous mailbox won't tried to be accessed anymore. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid fts_backend_update_set_mailbox(struct fts_backend_update_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mailbox *box);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen/* Expunge the specified mail. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid fts_backend_update_expunge(struct fts_backend_update_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen uint32_t uid);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen/* Switch to building index for specified key. If backend doesn't want to
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen index this key, it can return FALSE and caller will skip to next key. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool fts_backend_update_set_build_key(struct fts_backend_update_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const struct fts_backend_build_key *key);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen/* Make sure that if _build_more() is called, we'll assert-crash. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid fts_backend_update_unset_build_key(struct fts_backend_update_context *ctx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen/* Add more content to the index for the currently specified build key.
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen Non-BODY_PART_BINARY data must contain only full valid UTF-8 characters,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen but it doesn't need to be NUL-terminated. size contains the data size in
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen bytes, not characters. This function may be called many times and the data
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen block sizes may be small. Backend returns 0 if ok, -1 if build should be
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen aborted. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_update_build_more(struct fts_backend_update_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const unsigned char *data, size_t size);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen/* Refresh index to make sure we see latest changes from lookups.
de11cf486e0d0448537b1b5d546496ab85e7cda8Timo Sirainen Returns 0 if ok, -1 if error. */
de11cf486e0d0448537b1b5d546496ab85e7cda8Timo Sirainenint fts_backend_refresh(struct fts_backend *backend);
a569c6df4ffe05acc242e269d926449e50702d59Timo Sirainen/* Go through the entire index and make sure all mails are indexed,
a569c6df4ffe05acc242e269d926449e50702d59Timo Sirainen and delete any extra mails in the index. */
a569c6df4ffe05acc242e269d926449e50702d59Timo Sirainenint fts_backend_rescan(struct fts_backend *backend);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen/* Optimize the index. This can be a somewhat heavy operation. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_optimize(struct fts_backend *backend);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen/* Returns TRUE if fts_backend_lookup() should even be tried for the
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen given args. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool fts_backend_can_lookup(struct fts_backend *backend,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const struct mail_search_arg *args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen/* Do a FTS lookup for the given search args. Backends can support different
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen kinds of search arguments, so match_always=TRUE must be set to all search
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen args that were actually used to produce the search results. The other args
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen are handled by the regular search code. The backends MUST ignore all args
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen that have subargs (SEARCH_OR, SEARCH_SUB), since they are looked up
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen separately.
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen The arrays in result must be initialized by caller. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_lookup(struct fts_backend *backend, struct mailbox *box,
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainen struct mail_search_arg *args,
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainen enum fts_lookup_flags flags,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_result *result);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen/* Search from multiple mailboxes. result->pool must be initialized. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenint fts_backend_lookup_multi(struct fts_backend *backend,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mailbox *const boxes[],
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainen struct mail_search_arg *args,
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainen enum fts_lookup_flags flags,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct fts_multi_result *result);
b7fdf4fe23801de680e0be5aca0596a3c9ea3f8fTimo Sirainen/* Called after the lookups are done. The next lookup will be preceded by a
b7fdf4fe23801de680e0be5aca0596a3c9ea3f8fTimo Sirainen refresh. */
b7fdf4fe23801de680e0be5aca0596a3c9ea3f8fTimo Sirainenvoid fts_backend_lookup_done(struct fts_backend *backend);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#endif