fts-storage.c revision c63c3c4d548416914b8c6734fe18dd69bb900775
/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.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-storage.h"
#include "fts-plugin.h"
#include <stdlib.h>
#define FTS_CONTEXT(obj) \
#define FTS_MAIL_CONTEXT(obj) \
#define FTS_SEARCH_NONBLOCK_COUNT 10
#define FTS_BUILD_NOTIFY_INTERVAL_SECS 10
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;
};
struct fts_transaction_context {
struct fts_storage_build_context *build_ctx;
unsigned int free_mail:1;
unsigned int expunges:1;
};
{
int ret;
return ret;
}
{
return 0;
return -1;
return 0;
}
{
MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0;
}
const struct message_block *block)
{
/* hdr->full_value is always set because we get the block from
message_decoder */
if (!hdr->no_newline)
}
{
struct message_parser_ctx *parser;
struct message_decoder_context *decoder;
int ret;
return -1;
0);
for (;;) {
if (ret < 0) {
if (input->stream_errno == 0)
ret = 0;
break;
}
/* skipping this body */
continue;
}
&block))
continue;
/* end of headers */
} else {
FALSE) < 0) {
ret = -1;
break;
}
}
}
if (ret == 0) {
/* Index all headers at the end. This is required for Squat,
because it can handle only incremental UIDs. */
}
return ret;
}
{
struct mailbox_transaction_context *t = fctx->t;
struct fts_storage_build_context *ctx;
struct fts_backend_build_context *build;
struct mail_search_seqset seqset;
return -1;
/* no new messages */
return 0;
}
/* we're not updating the index just for header lookups */
return 0;
}
return -1;
if (last_uid != last_uid_locked) {
/* changed, need to get again the sequences */
/* no new messages */
(void)fts_backend_build_deinit(&build);
return 0;
}
}
return 0;
}
{
int ret = 0;
ret = -1;
ret = -1;
/* we notified at least once */
}
return ret;
}
{
float percentage;
/* set the search time in here, in case a plugin
already spent some time indexing the mailbox */
T_BEGIN {
const char *text;
"ETA %d:%02d", (int)percentage,
} T_END;
}
}
{
unsigned int count = 0;
int ret;
T_BEGIN {
} T_END;
if (ret < 0)
return -1;
if (++count == FTS_SEARCH_NONBLOCK_COUNT)
return 0;
}
return 1;
}
{
return TRUE;
}
/* this process is already building the indexes */
return FALSE;
}
if (fts_build_init(fctx) < 0) {
return TRUE;
}
/* the index was up to date */
}
return TRUE;
}
static struct mail_search_context *
const enum mail_sort_type *sort_program)
{
struct mail_search_context *ctx;
struct fts_search_context *fctx;
fctx->t = t;
return ctx;
(void)fts_try_build_init(fctx);
return ctx;
}
{
int ret;
if (!fctx->build_initialized) {
/* we're still waiting for this process (but another command)
to finish building the indexes */
if (!fts_try_build_init(fctx)) {
*tryagain_r = TRUE;
return 0;
}
}
/* this command is still building the indexes */
if (ret == 0) {
*tryagain_r = TRUE;
return 0;
}
/* finished / error */
if (ret > 0)
}
/* if we're here, the indexes are either built or they're not used */
}
static void
{
struct mail_search_arg *arg;
case SEARCH_TEXT:
case SEARCH_BODY:
case SEARCH_BODY_FAST:
case SEARCH_TEXT_FAST:
break;
default:
break;
}
}
}
{
unsigned int def_count, maybe_count;
bool use_maybe;
int ret;
/* fts_search_lookup() was called successfully */
for (;;) {
&def_count);
&maybe_count);
/* if we're ahead of current positions, skip them */
fctx->definite_idx++;
/* we're finished */
return 0;
}
} else {
}
if (use_maybe)
else
/* current sequence is already larger than where
range begins, so use the current sequence. */
} else {
}
/* ctx->seq points to previous sequence we want */
break;
}
if (!use_maybe) {
/* we have definite results, update args */
}
return ret;
}
{
/* the search was cancelled */
}
}
{
}
static struct mail *
fts_mail_alloc(struct mailbox_transaction_context *t,
struct mailbox_header_lookup_ctx *wanted_headers)
{
union mail_module_context *fmail;
struct mail_private *mail;
}
return _mail;
}
{
struct fts_backend *backend;
const char *const *tmp;
continue;
FTS_BACKEND_FLAG_SUBSTRING_LOOKUPS) != 0) {
i_fatal("fts: duplicate substring 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
{
}
static void
bool committed)
{
}
}
}
static void fts_transaction_rollback(struct mailbox_transaction_context *t)
{
}
}
static int fts_transaction_commit(struct mailbox_transaction_context *t,
{
int ret;
}
return ret;
}
{
struct fts_mailbox *fbox;
const char *env;
if (fts_next_hook_mailbox_opened != NULL)
return;
}