Mercurial > dovecot > original-hg > dovecot-1.2
view src/plugins/fts-squat/fts-backend-squat.c @ 9532:00cd9aacd03c HEAD
Updated copyright notices to include year 2010.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 25 Jan 2010 01:18:58 +0200 |
parents | b9faf4db2a9f |
children |
line wrap: on
line source
/* Copyright (c) 2006-2010 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "array.h" #include "mail-storage-private.h" #include "mail-search-build.h" #include "squat-trie.h" #include "fts-squat-plugin.h" #include <stdlib.h> #define SQUAT_FILE_PREFIX "dovecot.index.search" struct squat_fts_backend { struct fts_backend backend; struct squat_trie *trie; }; struct squat_fts_backend_build_context { struct fts_backend_build_context ctx; struct squat_trie_build_context *build_ctx; }; static void fts_backend_squat_set(struct squat_fts_backend *backend, const char *str) { const char *const *tmp; int len; for (tmp = t_strsplit_spaces(str, " "); *tmp != NULL; tmp++) { if (strncmp(*tmp, "partial=", 8) == 0) { len = atoi(*tmp + 8); if (len <= 0) { i_fatal("fts_squat: Invalid partial len: %s", *tmp + 8); } squat_trie_set_partial_len(backend->trie, len); } else if (strncmp(*tmp, "full=", 5) == 0) { len = atoi(*tmp + 5); if (len <= 0) { i_fatal("fts_squat: Invalid full len: %s", *tmp + 5); } squat_trie_set_full_len(backend->trie, len); } else { i_fatal("fts_squat: Invalid setting: %s", *tmp); } } } static struct fts_backend *fts_backend_squat_init(struct mailbox *box) { struct squat_fts_backend *backend; struct mail_storage *storage; struct mailbox_status status; const char *path, *env; enum squat_index_flags flags = 0; storage = mailbox_get_storage(box); path = mail_storage_get_mailbox_index_dir(storage, mailbox_get_name(box)); if (*path == '\0') { /* in-memory indexes */ if ((storage->flags & MAIL_STORAGE_FLAG_DEBUG) != 0) i_info("fts squat: Disabled with in-memory indexes"); return NULL; } mailbox_get_status(box, STATUS_UIDVALIDITY, &status); if ((storage->flags & (MAIL_STORAGE_FLAG_MMAP_DISABLE | MAIL_STORAGE_FLAG_MMAP_NO_WRITE)) != 0) flags |= SQUAT_INDEX_FLAG_MMAP_DISABLE; if ((storage->flags & MAIL_STORAGE_FLAG_NFS_FLUSH_INDEX) != 0) flags |= SQUAT_INDEX_FLAG_NFS_FLUSH; if ((storage->flags & MAIL_STORAGE_FLAG_DOTLOCK_USE_EXCL) != 0) flags |= SQUAT_INDEX_FLAG_DOTLOCK_USE_EXCL; backend = i_new(struct squat_fts_backend, 1); backend->backend = fts_backend_squat; backend->trie = squat_trie_init(t_strconcat(path, "/"SQUAT_FILE_PREFIX, NULL), status.uidvalidity, storage->lock_method, flags, box->file_create_mode, box->file_create_gid); env = getenv("FTS_SQUAT"); if (env != NULL) fts_backend_squat_set(backend, env); return &backend->backend; } static void fts_backend_squat_deinit(struct fts_backend *_backend) { struct squat_fts_backend *backend = (struct squat_fts_backend *)_backend; squat_trie_deinit(&backend->trie); i_free(backend); } static int fts_backend_squat_get_last_uid(struct fts_backend *_backend, uint32_t *last_uid_r) { struct squat_fts_backend *backend = (struct squat_fts_backend *)_backend; return squat_trie_get_last_uid(backend->trie, last_uid_r); } static int fts_backend_squat_build_init(struct fts_backend *_backend, uint32_t *last_uid_r, struct fts_backend_build_context **ctx_r) { struct squat_fts_backend *backend = (struct squat_fts_backend *)_backend; struct squat_fts_backend_build_context *ctx; struct squat_trie_build_context *build_ctx; if (squat_trie_build_init(backend->trie, last_uid_r, &build_ctx) < 0) return -1; ctx = i_new(struct squat_fts_backend_build_context, 1); ctx->ctx.backend = _backend; ctx->build_ctx = build_ctx; *ctx_r = &ctx->ctx; return 0; } static int fts_backend_squat_build_more(struct fts_backend_build_context *_ctx, uint32_t uid, const unsigned char *data, size_t size, bool headers) { struct squat_fts_backend_build_context *ctx = (struct squat_fts_backend_build_context *)_ctx; enum squat_index_type squat_type; squat_type = headers ? SQUAT_INDEX_TYPE_HEADER : SQUAT_INDEX_TYPE_BODY; return squat_trie_build_more(ctx->build_ctx, uid, squat_type, data, size); } static int get_all_msg_uids(struct mailbox *box, ARRAY_TYPE(seq_range) *uids) { struct mailbox_transaction_context *t; struct mail_search_context *search_ctx; struct mail_search_args *search_args; struct mail *mail; int ret = 0; t = mailbox_transaction_begin(box, 0); mail = mail_alloc(t, 0, NULL); search_args = mail_search_build_init(); mail_search_build_add_all(search_args); search_ctx = mailbox_search_init(t, search_args, NULL); mail_search_args_unref(&search_args); while ((ret = mailbox_search_next(search_ctx, mail)) > 0) { /* *2 because even/odd is for body/header */ seq_range_array_add_range(uids, mail->uid * 2, mail->uid * 2 + 1); } if (mailbox_search_deinit(&search_ctx) < 0) ret = -1; mail_free(&mail); (void)mailbox_transaction_commit(&t); return ret; } static int fts_backend_squat_build_deinit(struct fts_backend_build_context *_ctx) { struct squat_fts_backend_build_context *ctx = (struct squat_fts_backend_build_context *)_ctx; ARRAY_TYPE(seq_range) uids; int ret; i_array_init(&uids, 1024); if (get_all_msg_uids(ctx->ctx.backend->box, &uids) < 0) ret = squat_trie_build_deinit(&ctx->build_ctx, NULL); else { seq_range_array_invert(&uids, 2, (uint32_t)-2); ret = squat_trie_build_deinit(&ctx->build_ctx, &uids); } array_free(&uids); i_free(ctx); return ret; } static void fts_backend_squat_expunge(struct fts_backend *_backend ATTR_UNUSED, struct mail *mail ATTR_UNUSED) { } static void fts_backend_squat_expunge_finish(struct fts_backend *_backend ATTR_UNUSED, struct mailbox *box ATTR_UNUSED, bool committed ATTR_UNUSED) { /* FIXME */ } static int fts_backend_squat_lock(struct fts_backend *_backend) { struct squat_fts_backend *backend = (struct squat_fts_backend *)_backend; squat_trie_refresh(backend->trie); return 1; } static void fts_backend_squat_unlock(struct fts_backend *_backend ATTR_UNUSED) { } static int fts_backend_squat_lookup(struct fts_backend *_backend, const char *key, enum fts_lookup_flags flags, ARRAY_TYPE(seq_range) *definite_uids, ARRAY_TYPE(seq_range) *maybe_uids) { struct squat_fts_backend *backend = (struct squat_fts_backend *)_backend; enum squat_index_type squat_type = 0; i_assert((flags & FTS_LOOKUP_FLAG_INVERT) == 0); if ((flags & FTS_LOOKUP_FLAG_HEADER) != 0) squat_type |= SQUAT_INDEX_TYPE_HEADER; if ((flags & FTS_LOOKUP_FLAG_BODY) != 0) squat_type |= SQUAT_INDEX_TYPE_BODY; i_assert(squat_type != 0); return squat_trie_lookup(backend->trie, key, squat_type, definite_uids, maybe_uids); } struct fts_backend fts_backend_squat = { MEMBER(name) "squat", MEMBER(flags) FTS_BACKEND_FLAG_SUBSTRING_LOOKUPS, { fts_backend_squat_init, fts_backend_squat_deinit, fts_backend_squat_get_last_uid, NULL, fts_backend_squat_build_init, fts_backend_squat_build_more, fts_backend_squat_build_deinit, fts_backend_squat_expunge, fts_backend_squat_expunge_finish, fts_backend_squat_lock, fts_backend_squat_unlock, fts_backend_squat_lookup, NULL, NULL } };