2867N/A/* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING file */
2867N/A
2867N/A#include "lib.h"
2867N/A#include "array.h"
2867N/A#include "mail-storage-private.h"
2867N/A#include "mail-search.h"
2867N/A#include "mailbox-search-result-private.h"
2867N/A
2867N/Astatic void
2867N/Amailbox_search_result_analyze_args(struct mail_search_result *result,
2867N/A struct mail_search_arg *arg)
2867N/A{
2867N/A for (; arg != NULL; arg = arg->next) {
2867N/A switch (arg->type) {
2867N/A case SEARCH_OR:
2867N/A case SEARCH_SUB:
2867N/A mailbox_search_result_analyze_args(result,
2867N/A arg->value.subargs);
2867N/A break;
2867N/A case SEARCH_FLAGS:
2867N/A result->args_have_flags = TRUE;
3156N/A break;
2867N/A case SEARCH_KEYWORDS:
2867N/A result->args_have_keywords = TRUE;
2867N/A break;
2867N/A case SEARCH_MODSEQ:
2867N/A result->args_have_modseq = TRUE;
2867N/A break;
2867N/A default:
2867N/A break;
2867N/A }
2867N/A }
2867N/A}
2867N/A
2867N/Astruct mail_search_result *
2867N/Amailbox_search_result_alloc(struct mailbox *box, struct mail_search_args *args,
2867N/A enum mailbox_search_result_flags flags)
2867N/A{
2867N/A struct mail_search_result *result;
2867N/A
2867N/A result = i_new(struct mail_search_result, 1);
2867N/A result->box = box;
2867N/A result->flags = flags;
2867N/A i_array_init(&result->uids, 32);
2867N/A i_array_init(&result->never_uids, 128);
2867N/A
2867N/A if ((result->flags & MAILBOX_SEARCH_RESULT_FLAG_UPDATE) != 0) {
2867N/A result->search_args = args;
2867N/A mail_search_args_ref(result->search_args);
2867N/A mailbox_search_result_analyze_args(result, args->args);
2867N/A }
2867N/A
2867N/A array_append(&result->box->search_results, &result, 1);
2867N/A return result;
2867N/A}
2867N/A
2867N/Avoid mailbox_search_result_free(struct mail_search_result **_result)
2867N/A{
2867N/A struct mail_search_result *result = *_result;
2867N/A struct mail_search_result *const *results;
2867N/A unsigned int i, count;
2867N/A
2867N/A *_result = NULL;
2867N/A
2867N/A results = array_get(&result->box->search_results, &count);
2867N/A for (i = 0; i < count; i++) {
2867N/A if (results[i] == result) {
2867N/A array_delete(&result->box->search_results, i, 1);
2867N/A break;
2867N/A }
2867N/A }
2867N/A i_assert(i != count);
2867N/A
2867N/A if (result->search_args != NULL)
2867N/A mail_search_args_unref(&result->search_args);
2867N/A
2867N/A array_free(&result->uids);
2867N/A array_free(&result->never_uids);
2867N/A if (array_is_created(&result->removed_uids)) {
2867N/A array_free(&result->removed_uids);
2867N/A array_free(&result->added_uids);
2867N/A }
2867N/A i_free(result);
2867N/A}
2867N/A
2867N/Astruct mail_search_result *
2867N/Amailbox_search_result_save(struct mail_search_context *ctx,
2867N/A enum mailbox_search_result_flags flags)
2867N/A{
2867N/A struct mail_search_result *result;
2867N/A
2867N/A result = mailbox_search_result_alloc(ctx->transaction->box,
2867N/A ctx->args, flags);
2867N/A array_append(&ctx->results, &result, 1);
2867N/A return result;
2867N/A}
2867N/A
2867N/Avoid mailbox_search_result_initial_done(struct mail_search_result *result)
2867N/A{
2867N/A if ((result->flags & MAILBOX_SEARCH_RESULT_FLAG_QUEUE_SYNC) != 0) {
2867N/A i_array_init(&result->removed_uids, 32);
2867N/A i_array_init(&result->added_uids, 32);
2867N/A }
2867N/A mail_search_args_seq2uid(result->search_args);
2867N/A}
2867N/A
2867N/Avoid mailbox_search_results_initial_done(struct mail_search_context *ctx)
2867N/A{
2867N/A struct mail_search_result *const *results;
2867N/A unsigned int i, count;
2867N/A
2867N/A results = array_get(&ctx->results, &count);
2867N/A for (i = 0; i < count; i++)
2867N/A mailbox_search_result_initial_done(results[i]);
2867N/A}
2867N/A
2867N/Avoid mailbox_search_result_add(struct mail_search_result *result, uint32_t uid)
2867N/A{
2867N/A i_assert(uid > 0);
2867N/A
2867N/A if (seq_range_exists(&result->uids, uid))
2867N/A return;
2867N/A
2867N/A seq_range_array_add(&result->uids, uid);
2867N/A if (array_is_created(&result->added_uids)) {
2867N/A seq_range_array_add(&result->added_uids, uid);
2867N/A seq_range_array_remove(&result->removed_uids, uid);
2867N/A }
2867N/A}
2867N/A
2867N/Avoid mailbox_search_result_remove(struct mail_search_result *result,
2867N/A uint32_t uid)
2867N/A{
2867N/A if (seq_range_array_remove(&result->uids, uid)) {
2867N/A if (array_is_created(&result->removed_uids)) {
2867N/A seq_range_array_add(&result->removed_uids, uid);
2867N/A seq_range_array_remove(&result->added_uids, uid);
2867N/A }
2867N/A }
2867N/A}
2867N/A
2867N/Avoid mailbox_search_results_add(struct mail_search_context *ctx, uint32_t uid)
2867N/A{
2867N/A struct mail_search_result *const *results;
2867N/A unsigned int i, count;
2867N/A
2867N/A results = array_get(&ctx->results, &count);
2867N/A for (i = 0; i < count; i++)
2867N/A mailbox_search_result_add(results[i], uid);
2867N/A}
2867N/A
2867N/Avoid mailbox_search_results_remove(struct mailbox *box, uint32_t uid)
2867N/A{
3018N/A struct mail_search_result *const *results;
2867N/A unsigned int i, count;
2867N/A
2867N/A results = array_get(&box->search_results, &count);
2867N/A for (i = 0; i < count; i++)
2867N/A mailbox_search_result_remove(results[i], uid);
2867N/A}
2867N/A
2867N/Avoid mailbox_search_result_never(struct mail_search_result *result,
2867N/A uint32_t uid)
2867N/A{
2867N/A seq_range_array_add(&result->never_uids, uid);
2867N/A}
2867N/A
2867N/Avoid mailbox_search_results_never(struct mail_search_context *ctx,
2867N/A uint32_t uid)
2867N/A{
2867N/A struct mail_search_result *const *results;
2867N/A unsigned int i, count;
2867N/A
2872N/A if (ctx->update_result != NULL)
2872N/A mailbox_search_result_never(ctx->update_result, uid);
2872N/A
2872N/A results = array_get(&ctx->results, &count);
2872N/A for (i = 0; i < count; i++)
2867N/A mailbox_search_result_never(results[i], uid);
2867N/A}
2867N/A
2867N/Aconst ARRAY_TYPE(seq_range) *
2867N/Amailbox_search_result_get(struct mail_search_result *result)
2867N/A{
2867N/A return &result->uids;
2867N/A}
2867N/A
2867N/Avoid mailbox_search_result_sync(struct mail_search_result *result,
3017N/A ARRAY_TYPE(seq_range) *removed_uids,
3017N/A ARRAY_TYPE(seq_range) *added_uids)
3017N/A{
3017N/A array_clear(removed_uids);
3017N/A array_clear(added_uids);
3017N/A
2867N/A array_append_array(removed_uids, &result->removed_uids);
2867N/A array_append_array(added_uids, &result->added_uids);
2867N/A
3017N/A array_clear(&result->removed_uids);
3017N/A array_clear(&result->added_uids);
3017N/A}
3017N/A