dovecot: SEARCH_KEYWORDS now uses struct mail_keywords instead o...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Dec 8 19:21:30 EET 2007
details: http://hg.dovecot.org/dovecot/rev/ae369569e7de
changeset: 6965:ae369569e7de
user: Timo Sirainen <tss at iki.fi>
date: Sat Dec 08 19:21:27 2007 +0200
description:
SEARCH_KEYWORDS now uses struct mail_keywords instead of a string array.
diffstat:
6 files changed, 147 insertions(+), 19 deletions(-)
src/imap/cmd-search.c | 13 ++++---
src/imap/imap-search.c | 41 +++++++++++++++++++++-
src/imap/imap-search.h | 2 +
src/lib-storage/index/index-search.c | 44 +++++++++++++++++------
src/lib-storage/mail-search.c | 63 ++++++++++++++++++++++++++++++++++
src/lib-storage/mail-search.h | 3 +
diffs (truncated from 323 to 300 lines):
diff -r b9d674728523 -r ae369569e7de src/imap/cmd-search.c
--- a/src/imap/cmd-search.c Sat Dec 08 19:08:41 2007 +0200
+++ b/src/imap/cmd-search.c Sat Dec 08 19:21:27 2007 +0200
@@ -9,9 +9,11 @@
#define OUTBUF_SIZE 65536
struct imap_search_context {
- struct mailbox_transaction_context *trans;
+ struct mailbox *box;
+ struct mailbox_transaction_context *trans;
struct mail_search_context *search_ctx;
struct mail *mail;
+ struct mail_search_arg *sargs;
struct timeout *to;
string_t *output_buf;
@@ -22,13 +24,15 @@ struct imap_search_context {
};
static struct imap_search_context *
-imap_search_init(struct client_command_context *cmd, const char *charset,
- struct mail_search_arg *sargs)
+imap_search_init(struct client_command_context *cmd, struct mailbox *box,
+ const char *charset, struct mail_search_arg *sargs)
{
struct imap_search_context *ctx;
ctx = p_new(cmd->pool, struct imap_search_context, 1);
+ ctx->box = box;
ctx->trans = mailbox_transaction_begin(cmd->client->mailbox, 0);
+ ctx->sargs = sargs;
ctx->search_ctx = mailbox_search_init(ctx->trans, charset, sargs, NULL);
ctx->mail = mail_alloc(ctx->trans, 0, NULL);
(void)gettimeofday(&ctx->start_time, NULL);
@@ -58,6 +62,7 @@ static int imap_search_deinit(struct cli
if (ctx->to != NULL)
timeout_remove(&ctx->to);
str_free(&ctx->output_buf);
+ imap_search_args_free(ctx->box, ctx->sargs);
cmd->context = NULL;
return ret;
@@ -183,7 +188,7 @@ bool cmd_search(struct client_command_co
return TRUE;
}
- ctx = imap_search_init(cmd, charset, sargs);
+ ctx = imap_search_init(cmd, cmd->client->mailbox, charset, sargs);
cmd->func = cmd_search_more;
cmd->context = ctx;
diff -r b9d674728523 -r ae369569e7de src/imap/imap-search.c
--- a/src/imap/imap-search.c Sat Dec 08 19:08:41 2007 +0200
+++ b/src/imap/imap-search.c Sat Dec 08 19:21:27 2007 +0200
@@ -125,6 +125,32 @@ arg_new_flags(struct search_build_data *
return TRUE;
}
+static bool
+arg_new_keyword(struct search_build_data *data,
+ const struct imap_arg **args,
+ struct mail_search_arg **next_sarg)
+{
+ struct mail_search_arg *sarg;
+ const char *value, *keywords[2];
+ struct mail_storage *storage;
+ enum mail_error error;
+
+ *next_sarg = sarg = search_arg_new(data->pool, SEARCH_KEYWORDS);
+ if (!arg_get_next(data, args, &value))
+ return FALSE;
+
+ keywords[0] = value;
+ keywords[1] = NULL;
+
+ if (mailbox_keywords_create(data->box, keywords,
+ &sarg->value.keywords) < 0) {
+ storage = mailbox_get_storage(data->box);
+ data->error = mail_storage_get_last_error(storage, &error);
+ return FALSE;
+ }
+ return TRUE;
+}
+
#define ARG_NEW_SIZE(type) \
arg_new_size(data, args, next_sarg, type)
static bool
@@ -304,7 +330,7 @@ static bool search_arg_build(struct sear
case 'K':
if (strcmp(str, "KEYWORD") == 0) {
/* <flag> */
- return ARG_NEW_STR(SEARCH_KEYWORD);
+ return arg_new_keyword(data, args, next_sarg);
}
break;
case 'L':
@@ -446,7 +472,7 @@ static bool search_arg_build(struct sear
return TRUE;
} else if (strcmp(str, "UNKEYWORD") == 0) {
/* <flag> */
- if (!ARG_NEW_STR(SEARCH_KEYWORD))
+ if (!arg_new_keyword(data, args, next_sarg))
return FALSE;
(*next_sarg)->not = TRUE;
return TRUE;
@@ -515,6 +541,7 @@ imap_search_args_build(pool_t pool, stru
first_sarg = NULL; sargs = &first_sarg;
while (args->type != IMAP_ARG_EOL) {
if (!search_arg_build(&data, &args, sargs)) {
+ imap_search_args_free(box, first_sarg);
*error_r = data.error;
return NULL;
}
@@ -552,6 +579,16 @@ static int imap_search_get_msgset_arg(st
return 0;
}
+void imap_search_args_free(struct mailbox *box, struct mail_search_arg *args)
+{
+ for (; args != NULL; args = args->next) {
+ if (args->type == SEARCH_KEYWORDS)
+ mailbox_keywords_free(box, &args->value.keywords);
+ else if (args->type == SEARCH_SUB || args->type == SEARCH_OR)
+ imap_search_args_free(box, args->value.subargs);
+ }
+}
+
static int
imap_search_get_uidset_arg(pool_t pool, struct mailbox *box, const char *uidset,
struct mail_search_arg **arg_r, const char **error_r)
diff -r b9d674728523 -r ae369569e7de src/imap/imap-search.h
--- a/src/imap/imap-search.h Sat Dec 08 19:08:41 2007 +0200
+++ b/src/imap/imap-search.h Sat Dec 08 19:21:27 2007 +0200
@@ -9,6 +9,8 @@ struct mail_search_arg *
struct mail_search_arg *
imap_search_args_build(pool_t pool, struct mailbox *box,
const struct imap_arg *args, const char **error_r);
+/* Free allocated keywords */
+void imap_search_args_free(struct mailbox *box, struct mail_search_arg *args);
struct mail_search_arg *
imap_search_get_arg(struct client_command_context *cmd,
diff -r b9d674728523 -r ae369569e7de src/lib-storage/index/index-search.c
--- a/src/lib-storage/index/index-search.c Sat Dec 08 19:08:41 2007 +0200
+++ b/src/lib-storage/index/index-search.c Sat Dec 08 19:21:27 2007 +0200
@@ -78,30 +78,50 @@ static int seqset_contains(struct mail_s
return FALSE;
}
+static int search_arg_match_keywords(struct index_mail *imail,
+ struct mail_search_arg *arg)
+{
+ ARRAY_TYPE(keyword_indexes) keyword_indexes_arr;
+ const struct mail_keywords *search_kws = arg->value.keywords;
+ const unsigned int *keyword_indexes;
+ unsigned int i, j, count;
+
+ t_array_init(&keyword_indexes_arr, 128);
+ mail_index_lookup_keywords(imail->ibox->view, imail->mail.mail.seq,
+ &keyword_indexes_arr);
+ keyword_indexes = array_get(&keyword_indexes_arr, &count);
+
+ /* there probably aren't many keywords, so O(n*m) for now */
+ for (i = 0; i < search_kws->count; i++) {
+ for (j = 0; j < count; j++) {
+ if (search_kws->idx[i] == keyword_indexes[j])
+ break;
+ }
+ if (j == count)
+ return 0;
+ }
+ return 1;
+}
+
/* Returns >0 = matched, 0 = not matched, -1 = unknown */
static int search_arg_match_index(struct index_mail *imail,
struct mail_search_arg *arg)
{
enum mail_flags flags;
- const char *const *keywords;
+ int ret;
switch (arg->type) {
- /* flags */
case SEARCH_FLAGS:
flags = imail->data.flags;
if ((arg->value.flags & MAIL_RECENT) != 0 &&
- index_mailbox_is_recent(imail->ibox,
- imail->mail.mail.uid))
+ index_mailbox_is_recent(imail->ibox, imail->mail.mail.uid))
flags |= MAIL_RECENT;
return (flags & arg->value.flags) == arg->value.flags;
- case SEARCH_KEYWORD:
- keywords = mail_get_keywords(&imail->mail.mail);
- while (*keywords != NULL) {
- if (strcasecmp(*keywords, arg->value.str) == 0)
- return 1;
- keywords++;
- }
- return 0;
+ case SEARCH_KEYWORDS:
+ T_FRAME(
+ ret = search_arg_match_keywords(imail, arg);
+ );
+ return ret;
default:
return -1;
diff -r b9d674728523 -r ae369569e7de src/lib-storage/mail-search.c
--- a/src/lib-storage/mail-search.c Sat Dec 08 19:08:41 2007 +0200
+++ b/src/lib-storage/mail-search.c Sat Dec 08 19:21:27 2007 +0200
@@ -1,7 +1,9 @@
/* Copyright (c) 2002-2007 Dovecot authors, see the included COPYING file */
#include "lib.h"
+#include "array.h"
#include "buffer.h"
+#include "mail-index.h"
#include "mail-search.h"
void mail_search_args_reset(struct mail_search_arg *args, bool full_reset)
@@ -177,13 +179,46 @@ mail_search_args_analyze(struct mail_sea
return buffer_get_data(headers, NULL);
}
+static struct mail_keywords *
+mail_search_keywords_merge(struct mail_keywords **_kw1,
+ struct mail_keywords **_kw2)
+{
+ struct mail_keywords *kw1 = *_kw1, *kw2 = *_kw2;
+ struct mail_keywords *new_kw;
+
+ i_assert(kw1->index == kw2->index);
+ T_FRAME_BEGIN {
+ ARRAY_TYPE(keyword_indexes) new_indexes;
+ unsigned int i, j;
+
+ t_array_init(&new_indexes, kw1->count + kw2->count + 1);
+ array_append(&new_indexes, kw1->idx, kw1->count);
+ for (i = 0; i < kw2->count; i++) {
+ /* don't add duplicates */
+ for (j = 0; j < kw1->count; j++) {
+ if (kw1->idx[j] == kw2->idx[i])
+ break;
+ }
+ if (j == kw1->count)
+ array_append(&new_indexes, kw2->idx+i, 1);
+ }
+ new_kw = mail_index_keywords_create_from_indexes(kw1->index,
+ &new_indexes);
+ } T_FRAME_END;
+ mail_index_keywords_free(_kw1);
+ mail_index_keywords_free(_kw2);
+ return new_kw;
+}
+
static void
mail_search_args_simplify_sub(struct mail_search_arg *args, bool parent_and)
{
struct mail_search_arg *sub, *prev = NULL;
struct mail_search_arg *prev_flags_arg, *prev_not_flags_arg;
+ struct mail_search_arg *prev_kw_arg, *prev_not_kw_arg;
prev_flags_arg = prev_not_flags_arg = NULL;
+ prev_kw_arg = prev_not_kw_arg = NULL;
for (; args != NULL;) {
if (args->not && (args->type == SEARCH_SUB ||
args->type == SEARCH_OR)) {
@@ -237,6 +272,34 @@ mail_search_args_simplify_sub(struct mai
}
}
+ /* merge all keywords arguments */
+ if (args->type == SEARCH_KEYWORDS && !args->not && parent_and) {
+ if (prev_kw_arg == NULL)
+ prev_kw_arg = args;
+ else {
+ prev_kw_arg->value.keywords =
+ mail_search_keywords_merge(
+ &prev_kw_arg->value.keywords,
+ &args->value.keywords);
+ prev->next = args->next;
+ args = args->next;
+ continue;
+ }
+ } else if (args->type == SEARCH_KEYWORDS && args->not &&
+ !parent_and) {
+ if (prev_not_kw_arg == NULL)
+ prev_not_kw_arg = args;
+ else {
+ prev_not_kw_arg->value.keywords =
+ mail_search_keywords_merge(
+ &prev_not_kw_arg->value.keywords,
+ &args->value.keywords);
+ prev->next = args->next;
+ args = args->next;
+ continue;
+ }
+ }
+
More information about the dovecot-cvs
mailing list