fts-storage.c revision 88dc563319efecd6e68bad16b0d92672da05584a
/* Copyright (C) 2006 Timo Sirainen */
#include "lib.h"
#include "array.h"
#include "str.h"
#include "istream.h"
#include "message-parser.h"
#include "message-decoder.h"
#include "mail-search.h"
#include "mail-storage-private.h"
#include "fts-api-private.h"
#include "fts-plugin.h"
#include <stdlib.h>
#define FTS_CONTEXT(obj) \
#define FTS_SEARCH_NONBLOCK_COUNT 10
struct fts_mailbox {
struct mailbox_vfuncs super;
struct fts_backend *backend_exact;
struct fts_backend *backend_fast;
const char *env;
unsigned int backend_set:1;
};
struct fts_search_context {
unsigned int result_pos;
struct fts_backend *backend;
struct fts_storage_build_context *build_ctx;
unsigned int locked:1;
};
struct fts_storage_build_context {
struct mail_search_context *search_ctx;
struct mail_search_seqset seqset;
struct mail_search_arg search_arg;
struct fts_backend_build_context *build;
bool save_part;
};
struct fts_transaction_context {
bool expunges;
};
struct fts_mail {
struct mail_vfuncs super;
};
static unsigned int fts_storage_module_id = 0;
static bool fts_storage_module_id_set = FALSE;
{
int ret;
return ret;
}
{
unsigned int i, count;
for (i = 0; i < count; i++) {
return -1;
}
}
return 0;
}
{
return 1;
return -1;
return 1;
}
const struct message_block *block)
{
MESSAGE_PART_FLAG_MESSAGE_RFC822)) == 0)
return FALSE;
return TRUE;
}
const struct message_block *block)
{
/* hdr->full_value is always set because we get the block from
message_decoder */
if (!hdr->no_newline)
return 0;
}
return 1;
}
return fts_build_mail_flush(ctx);
}
{
struct message_parser_ctx *parser;
struct message_decoder_context *decoder;
int ret;
return -1;
for (;;) {
if (ret < 0) {
if (input->stream_errno == 0)
ret = 0;
break;
}
continue;
&block))
continue;
}
if (ret < 0)
break;
if (ret == 0)
/* end of headers */
if (ret < 0)
break;
}
} else {
ret = -1;
break;
}
}
}
(void)message_parser_deinit(&parser);
return ret;
}
struct mailbox_transaction_context *t)
{
struct fts_storage_build_context *ctx;
struct fts_backend_build_context *build;
struct mail_search_seqset seqset;
return -1;
return -1;
/* no new messages */
return 0;
}
if (last_uid != last_uid_locked) {
/* changed, need to get again the sequences */
(void)fts_backend_build_deinit(build);
return -1;
}
/* no new messages */
(void)fts_backend_build_deinit(build);
return 0;
}
}
return 0;
}
{
int ret = 0;
ret = -1;
ret = -1;
return ret;
}
{
unsigned int count = 0;
int ret;
t_push();
t_pop();
if (ret < 0)
return -1;
if (++count == FTS_SEARCH_NONBLOCK_COUNT)
return 0;
}
return 1;
}
struct mail_search_arg *args,
{
const char *key;
case SEARCH_BODY_FAST:
case SEARCH_TEXT_FAST:
break;
/* fall through */
case SEARCH_BODY:
case SEARCH_TEXT:
case SEARCH_HEADER:
/* already handled this one */
break;
}
if (*key == '\0') {
/* we're only checking the existence
of the header. */
}
uid_result) < 0) {
/* failed, but we already have limited
the search, so just ignore this */
break;
}
FTS_BACKEND_FLAG_DEFINITE_LOOKUPS) != 0) {
}
break;
case SEARCH_OR:
case SEARCH_SUB:
break;
default:
break;
}
}
}
struct fts_search_context *fctx)
{
const char *key;
if (fts_backend_lock(backend) <= 0)
return;
if (*key == '\0') {
/* we're only checking the existence
of the header. */
}
/* failed, fallback to reading everything */
return;
}
}
}
const struct mail_search_arg *old_arg)
{
return TRUE;
/* prefer not to use headers. they have a larger possibility of
having lots of identical strings */
return TRUE;
return FALSE;
}
bool *have_fast_r, bool *have_exact_r,
struct mail_search_arg **best_fast_arg,
struct mail_search_arg **best_exact_arg)
{
case SEARCH_BODY_FAST:
case SEARCH_TEXT_FAST:
/* this matches everything */
break;
}
*best_fast_arg = args;
*have_fast_r = TRUE;
}
break;
case SEARCH_BODY:
case SEARCH_TEXT:
/* this matches everything */
break;
}
case SEARCH_HEADER:
*best_exact_arg = args;
*have_exact_r = TRUE;
}
break;
case SEARCH_OR:
case SEARCH_SUB:
break;
default:
break;
}
}
}
static struct mail_search_context *
const enum mail_sort_type *sort_program)
{
struct mail_search_context *ctx;
struct fts_search_context *fctx;
bool have_fast, have_exact;
return ctx;
/* use fast backend whenever possible */
} else if (have_exact || have_fast) {
}
if (fts_build_init(fctx, t) < 0)
/* the index was up to date */
}
}
return ctx;
}
{
int ret;
/* still building the index */
if (ret == 0) {
*tryagain_r = TRUE;
return 0;
}
/* finished / error */
if (ret == 0)
}
}
{
unsigned int count;
int ret;
do {
fctx->result_pos++;
return 0;
else {
fctx->result_pos++;
else
}
return ret;
}
{
/* the search was cancelled */
}
}
{
return -1;
return 0;
}
static struct mail *
fts_mail_alloc(struct mailbox_transaction_context *t,
struct mailbox_header_lookup_ctx *wanted_headers)
{
struct mail_private *mail;
}
return _mail;
}
{
struct fts_backend *backend;
const char *const *tmp;
continue;
FTS_BACKEND_FLAG_EXACT_LOOKUPS) != 0) {
i_fatal("fts: duplicate exact backend: %s",
*tmp);
}
} else {
i_fatal("fts: duplicate fast backend: %s",
*tmp);
}
}
}
}
static struct mailbox_transaction_context *
{
struct mailbox_transaction_context *t;
struct fts_transaction_context *ft;
/* the backend creation is delayed until the first transaction is
started. at that point the mailbox has been synced at least once. */
if (!fbox->backend_set) {
}
return t;
}
static void
bool committed)
{
}
}
}
static void fts_transaction_rollback(struct mailbox_transaction_context *t)
{
}
static int fts_transaction_commit(struct mailbox_transaction_context *t,
enum mailbox_sync_flags flags)
{
int ret;
return ret;
}
{
struct fts_mailbox *fbox;
const char *env;
if (fts_next_hook_mailbox_opened != NULL)
return;
if (!fts_storage_module_id_set) {
}
}