Esempio n. 1
0
void fts_mailbox_allocated(struct mailbox *box)
{
	struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(box->list);
	struct mailbox_vfuncs *v = box->vlast;
	struct fts_mailbox *fbox;

	if (flist == NULL)
		return;

	fbox = p_new(box->pool, struct fts_mailbox, 1);
	fbox->module_ctx.super = *v;
	box->vlast = &fbox->module_ctx.super;

	v->get_status = fts_mailbox_get_status;
	v->search_init = fts_mailbox_search_init;
	v->search_next_nonblock = fts_mailbox_search_next_nonblock;
	v->search_next_update_seq = fts_mailbox_search_next_update_seq;
	v->search_deinit = fts_mailbox_search_deinit;
	v->transaction_begin = fts_transaction_begin;
	v->transaction_rollback = fts_transaction_rollback;
	v->transaction_commit = fts_transaction_commit;
	v->sync_notify = fts_mailbox_sync_notify;
	v->sync_deinit = fts_sync_deinit;
	v->save_finish = fts_save_finish;
	v->copy = fts_copy;

	MODULE_CONTEXT_SET(box, fts_storage_module, fbox);
}
Esempio n. 2
0
static void fts_mailbox_list_deinit(struct mailbox_list *list)
{
	struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(list);

	fts_backend_deinit(&flist->backend);
	flist->module_ctx.super.deinit(list);
}
Esempio n. 3
0
static int fts_sync_deinit(struct mailbox_sync_context *ctx,
			   struct mailbox_sync_status *status_r)
{
	struct mailbox *box = ctx->box;
	struct fts_mailbox *fbox = FTS_CONTEXT(box);
	struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(box->list);
	bool optimize;
	int ret = 0;

	optimize = (ctx->flags & (MAILBOX_SYNC_FLAG_FORCE_RESYNC |
				  MAILBOX_SYNC_FLAG_OPTIMIZE)) != 0;
	if (fbox->module_ctx.super.sync_deinit(ctx, status_r) < 0)
		return -1;
	ctx = NULL;

	if (optimize) {
		if (fts_backend_optimize(flist->backend) < 0) {
			mail_storage_set_critical(box->storage,
				"FTS optimize for mailbox %s failed",
				box->vname);
			ret = -1;
		}
	}
	return ret;
}
Esempio n. 4
0
static void fts_mailbox_sync_notify(struct mailbox *box, uint32_t uid,
				    enum mailbox_sync_type sync_type)
{
	struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(box->list);
	struct fts_mailbox *fbox = FTS_CONTEXT(box);

	if (fbox->module_ctx.super.sync_notify != NULL)
		fbox->module_ctx.super.sync_notify(box, uid, sync_type);

	if (sync_type != MAILBOX_SYNC_TYPE_EXPUNGE) {
		if (uid == 0 && fbox->sync_update_ctx != NULL) {
			/* this sync is finished */
			(void)fts_backend_update_deinit(&fbox->sync_update_ctx);
		}
		return;
	}

	if (fbox->sync_update_ctx == NULL) {
		if (fts_backend_is_updating(flist->backend)) {
			/* FIXME: maildir workaround - we could get here
			   because we're building an index, which doesn't find
			   some mail and starts syncing the mailbox.. */
			return;
		}
		fbox->sync_update_ctx = fts_backend_update_init(flist->backend);
		fts_backend_update_set_mailbox(fbox->sync_update_ctx, box);
	}
	fts_backend_update_expunge(fbox->sync_update_ctx, uid);
}
Esempio n. 5
0
static int fts_transaction_end(struct mailbox_transaction_context *t, const char **error_r)
{
	struct fts_transaction_context *ft = FTS_CONTEXT(t);
	struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(t->box->list);
	int ret = ft->failed ? -1 : 0;

	if (ft->failed)
		*error_r = "transaction context";

	if (ft->precached) {
		i_assert(flist->update_ctx_refcount > 0);
		if (--flist->update_ctx_refcount == 0) {
			if (fts_backend_update_deinit(&flist->update_ctx) < 0) {
				ret = -1;
				*error_r = "backend deinit";
			}
		}
	} else if (ft->highest_virtual_uid > 0) {
		if (fts_index_set_last_uid(t->box, ft->highest_virtual_uid) < 0) {
			ret = -1;
			*error_r = "index last uid setting";
		}
	}
	if (ft->scores != NULL)
		fts_scores_unref(&ft->scores);
	i_free(ft);
	return ret;
}
Esempio n. 6
0
static struct mail_search_context *
fts_mailbox_search_init(struct mailbox_transaction_context *t,
			struct mail_search_args *args,
			const enum mail_sort_type *sort_program,
			enum mail_fetch_field wanted_fields,
			struct mailbox_header_lookup_ctx *wanted_headers)
{
	struct fts_transaction_context *ft = FTS_CONTEXT(t);
	struct fts_mailbox *fbox = FTS_CONTEXT(t->box);
	struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(t->box->list);
	struct mail_search_context *ctx;
	struct fts_search_context *fctx;

	ctx = fbox->module_ctx.super.search_init(t, args, sort_program,
						 wanted_fields, wanted_headers);

	if (!fts_backend_can_lookup(flist->backend, args->args))
		return ctx;

	fctx = i_new(struct fts_search_context, 1);
	fctx->box = t->box;
	fctx->backend = flist->backend;
	fctx->t = t;
	fctx->args = args;
	fctx->result_pool = pool_alloconly_create("fts results", 1024*64);
	fctx->orig_matches = buffer_create_dynamic(default_pool, 64);
	fctx->virtual_mailbox =
		strcmp(t->box->storage->name, VIRTUAL_STORAGE_NAME) == 0;
	fctx->enforced =
		mail_user_plugin_getenv(t->box->storage->user,
					"fts_enforced") != NULL;
	i_array_init(&fctx->levels, 8);
	fctx->scores = i_new(struct fts_scores, 1);
	fctx->scores->refcount = 1;
	i_array_init(&fctx->scores->score_map, 64);
	MODULE_CONTEXT_SET(ctx, fts_storage_module, fctx);

	/* FIXME: we'll assume that all the args are fuzzy. not good,
	   but would require much more work to fix it. */
	if (!fts_args_have_fuzzy(args->args) &&
	    mail_user_plugin_getenv(t->box->storage->user,
				    "fts_no_autofuzzy") != NULL)
		fctx->flags |= FTS_LOOKUP_FLAG_NO_AUTO_FUZZY;
	/* transaction contains the last search's scores. they can be
	   queried later with mail_get_special() */
	if (ft->scores != NULL)
		fts_scores_unref(&ft->scores);
	ft->scores = fctx->scores;
	ft->scores->refcount++;

	if (fctx->enforced || fts_want_build_args(args->args))
		fts_try_build_init(ctx, fctx);
	else
		fts_search_lookup(fctx);
	return ctx;
}
Esempio n. 7
0
static int fts_mail_precache_init(struct mail *_mail)
{
	struct fts_transaction_context *ft = FTS_CONTEXT(_mail->transaction);
	struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(_mail->box->list);
	uint32_t last_seq;

	if (fts_mailbox_get_last_cached_seq(_mail->box, &last_seq) < 0)
		return -1;

	ft->precached = TRUE;
	ft->next_index_seq = last_seq + 1;
	if (flist->update_ctx == NULL)
		flist->update_ctx = fts_backend_update_init(flist->backend);
	flist->update_ctx_refcount++;
	return 0;
}
Esempio n. 8
0
static int fts_mailbox_get_last_cached_seq(struct mailbox *box, uint32_t *seq_r)
{
	struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(box->list);
	uint32_t seq1, seq2, last_uid;

	if (fts_backend_get_last_uid(flist->backend, box, &last_uid) < 0) {
		mail_storage_set_internal_error(box->storage);
		return -1;
	}

	if (last_uid == 0)
		*seq_r = 0;
	else {
		mailbox_get_seq_range(box, 1, last_uid, &seq1, &seq2);
		*seq_r = seq2;
	}
	return 0;
}
Esempio n. 9
0
static void fts_mail_index(struct mail *_mail)
{
	struct fts_transaction_context *ft = FTS_CONTEXT(_mail->transaction);
	struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(_mail->box->list);

	if (ft->failed)
		return;

	if (!ft->precached) {
		if (fts_mail_precache_init(_mail) < 0) {
			ft->failed = TRUE;
			return;
		}
	}
	if (ft->next_index_seq < _mail->seq) {
		/* most likely a virtual mailbox. we'll first need to
		   index all mails up to the current one. */
		fts_backend_update_set_mailbox(flist->update_ctx, _mail->box);
		if (fts_mail_precache_range(_mail->transaction,
					    flist->update_ctx,
					    ft->next_index_seq,
					    _mail->seq-1) < 0) {
			ft->failed = TRUE;
			return;
		}
	}

	if (ft->next_index_seq == _mail->seq) {
		fts_backend_update_set_mailbox(flist->update_ctx, _mail->box);
		if (fts_build_mail(flist->update_ctx, _mail) < 0) {
			mail_storage_set_internal_error(_mail->box->storage);
			ft->failed = TRUE;
		}
		ft->next_index_seq = _mail->seq + 1;
	}
}
Esempio n. 10
0
struct fts_backend *fts_list_backend(struct mailbox_list *list)
{
	struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(list);

	return flist == NULL ? NULL : flist->backend;
}
Esempio n. 11
0
struct fts_backend *fts_mailbox_backend(struct mailbox *box)
{
	struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(box->list);

	return flist->backend;
}