dovecot-1.1: Added support for sorting by X-SCORE. Currently it'...
dovecot at dovecot.org
dovecot at dovecot.org
Sun Jul 13 20:13:33 EEST 2008
details: http://hg.dovecot.org/dovecot-1.1/rev/88256be2a59f
changeset: 7755:88256be2a59f
user: Timo Sirainen <tss at iki.fi>
date: Sun Jul 13 19:11:11 2008 +0300
description:
Added support for sorting by X-SCORE. Currently it's only set by fts-solr.
diffstat:
13 files changed, 227 insertions(+), 34 deletions(-)
src/imap/cmd-sort.c | 17 +++---
src/lib-storage/index/index-mail.c | 1
src/lib-storage/index/index-sort.c | 78 +++++++++++++++++++++++++++++++
src/lib-storage/mail-storage.h | 6 +-
src/plugins/fts-solr/fts-backend-solr.c | 11 ++--
src/plugins/fts-solr/solr-connection.c | 39 +++++++++++++--
src/plugins/fts-solr/solr-connection.h | 4 +
src/plugins/fts/fts-api-private.h | 3 -
src/plugins/fts/fts-api.c | 12 +++-
src/plugins/fts/fts-api.h | 9 +++
src/plugins/fts/fts-search.c | 15 ++++-
src/plugins/fts/fts-storage.c | 65 +++++++++++++++++++++++--
src/plugins/fts/fts-storage.h | 1
diffs (truncated from 624 to 300 lines):
diff -r 282b1ea973ef -r 88256be2a59f src/imap/cmd-sort.c
--- a/src/imap/cmd-sort.c Sun Jul 13 19:08:13 2008 +0300
+++ b/src/imap/cmd-sort.c Sun Jul 13 19:11:11 2008 +0300
@@ -12,15 +12,16 @@ struct sort_name {
};
static struct sort_name sort_names[] = {
- { MAIL_SORT_ARRIVAL, "arrival" },
- { MAIL_SORT_CC, "cc" },
- { MAIL_SORT_DATE, "date" },
- { MAIL_SORT_FROM, "from" },
- { MAIL_SORT_SIZE, "size" },
- { MAIL_SORT_SUBJECT, "subject" },
- { MAIL_SORT_TO, "to" },
+ { MAIL_SORT_ARRIVAL, "arrival" },
+ { MAIL_SORT_CC, "cc" },
+ { MAIL_SORT_DATE, "date" },
+ { MAIL_SORT_FROM, "from" },
+ { MAIL_SORT_SIZE, "size" },
+ { MAIL_SORT_SUBJECT, "subject" },
+ { MAIL_SORT_TO, "to" },
+ { MAIL_SORT_SEARCH_SCORE, "x-score" },
- { MAIL_SORT_END, NULL }
+ { MAIL_SORT_END, NULL }
};
static int
diff -r 282b1ea973ef -r 88256be2a59f src/lib-storage/index/index-mail.c
--- a/src/lib-storage/index/index-mail.c Sun Jul 13 19:08:13 2008 +0300
+++ b/src/lib-storage/index/index-mail.c Sun Jul 13 19:11:11 2008 +0300
@@ -993,6 +993,7 @@ int index_mail_get_special(struct mail *
case MAIL_FETCH_FROM_ENVELOPE:
case MAIL_FETCH_UIDL_FILE_NAME:
case MAIL_FETCH_UIDL_BACKEND:
+ case MAIL_FETCH_SEARCH_SCORE:
*value_r = "";
return 0;
case MAIL_FETCH_HEADER_MD5:
diff -r 282b1ea973ef -r 88256be2a59f src/lib-storage/index/index-sort.c
--- a/src/lib-storage/index/index-sort.c Sun Jul 13 19:08:13 2008 +0300
+++ b/src/lib-storage/index/index-sort.c Sun Jul 13 19:11:11 2008 +0300
@@ -23,6 +23,12 @@ struct mail_sort_node_size {
};
ARRAY_DEFINE_TYPE(mail_sort_node_size, struct mail_sort_node_size);
+struct mail_sort_node_float {
+ uint32_t seq;
+ float num;
+};
+ARRAY_DEFINE_TYPE(mail_sort_node_float, struct mail_sort_node_float);
+
struct sort_cmp_context {
struct mail_search_sort_program *program;
struct mail *mail;
@@ -74,6 +80,28 @@ index_sort_list_add_size(struct mail_sea
node->size = 0;
}
+static float index_sort_get_score(struct mail *mail)
+{
+ const char *str;
+
+ if (mail_get_special(mail, MAIL_FETCH_SEARCH_SCORE, &str) < 0)
+ return 0;
+ else
+ return strtod(str, NULL);
+}
+
+static void
+index_sort_list_add_score(struct mail_search_sort_program *program,
+ struct mail *mail)
+{
+ ARRAY_TYPE(mail_sort_node_float) *nodes = program->context;
+ struct mail_sort_node_float *node;
+
+ node = array_append_space(nodes);
+ node->seq = mail->seq;
+ node->num = index_sort_get_score(mail);
+}
+
void index_sort_list_add(struct mail_search_sort_program *program,
struct mail *mail)
{
@@ -137,6 +165,36 @@ index_sort_list_finish_size(struct mail_
size_nodes = array_get_modifiable(nodes, &count);
qsort(size_nodes, count, sizeof(struct mail_sort_node_size),
sort_node_size_cmp);
+ memcpy(&program->seqs, nodes, sizeof(program->seqs));
+ i_free(nodes);
+ program->context = NULL;
+}
+
+static int sort_node_float_cmp(const void *p1, const void *p2)
+{
+ struct sort_cmp_context *ctx = &static_node_cmp_context;
+ const struct mail_sort_node_float *n1 = p1, *n2 = p2;
+
+ if (n1->num < n2->num)
+ return !ctx->reverse ? -1 : 1;
+ if (n1->num > n2->num)
+ return !ctx->reverse ? 1 : -1;
+
+ return index_sort_node_cmp_type(ctx->mail,
+ ctx->program->sort_program + 1,
+ n1->seq, n2->seq);
+}
+
+static void
+index_sort_list_finish_float(struct mail_search_sort_program *program)
+{
+ ARRAY_TYPE(mail_sort_node_float) *nodes = program->context;
+ struct mail_sort_node_float *float_nodes;
+ unsigned int count;
+
+ float_nodes = array_get_modifiable(nodes, &count);
+ qsort(float_nodes, count, sizeof(struct mail_sort_node_float),
+ sort_node_float_cmp);
memcpy(&program->seqs, nodes, sizeof(program->seqs));
i_free(nodes);
program->context = NULL;
@@ -224,6 +282,16 @@ index_sort_program_init(struct mailbox_t
program->sort_list_finish = index_sort_list_finish_string;
index_sort_list_init_string(program);
break;
+ case MAIL_SORT_SEARCH_SCORE: {
+ ARRAY_TYPE(mail_sort_node_float) *nodes;
+
+ nodes = i_malloc(sizeof(*nodes));
+ i_array_init(nodes, 128);
+ program->sort_list_add = index_sort_list_add_score;
+ program->sort_list_finish = index_sort_list_finish_float;
+ program->context = nodes;
+ break;
+ }
default:
i_unreached();
}
@@ -303,6 +371,7 @@ int index_sort_node_cmp_type(struct mail
enum mail_sort_type sort_type;
time_t time1, time2;
uoff_t size1, size2;
+ float float1, float2;
int ret = 0;
sort_type = *sort_program & MAIL_SORT_MASK;
@@ -366,6 +435,15 @@ int index_sort_node_cmp_type(struct mail
ret = size1 < size2 ? -1 :
(size1 > size2 ? 1 : 0);
break;
+ case MAIL_SORT_SEARCH_SCORE:
+ mail_set_seq(mail, seq1);
+ float1 = index_sort_get_score(mail);
+ mail_set_seq(mail, seq2);
+ float2 = index_sort_get_score(mail);
+
+ ret = float1 < float2 ? -1 :
+ (float1 > float2 ? 1 : 0);
+ break;
case MAIL_SORT_END:
return seq1 < seq2 ? -1 :
(seq1 > seq2 ? 1 : 0);
diff -r 282b1ea973ef -r 88256be2a59f src/lib-storage/mail-storage.h
--- a/src/lib-storage/mail-storage.h Sun Jul 13 19:08:13 2008 +0300
+++ b/src/lib-storage/mail-storage.h Sun Jul 13 19:11:11 2008 +0300
@@ -69,7 +69,7 @@ enum mailbox_status_items {
enum mail_sort_type {
/* Maximum size for sort program (each one separately + END) */
-#define MAX_SORT_PROGRAM_SIZE (7 + 1)
+#define MAX_SORT_PROGRAM_SIZE (8 + 1)
MAIL_SORT_ARRIVAL = 0x0001,
MAIL_SORT_CC = 0x0002,
@@ -78,6 +78,7 @@ enum mail_sort_type {
MAIL_SORT_SIZE = 0x0010,
MAIL_SORT_SUBJECT = 0x0020,
MAIL_SORT_TO = 0x0040,
+ MAIL_SORT_SEARCH_SCORE = 0x0080,
MAIL_SORT_MASK = 0x0fff,
MAIL_SORT_FLAG_REVERSE = 0x1000, /* reverse this mask type */
@@ -108,7 +109,8 @@ enum mail_fetch_field {
MAIL_FETCH_FROM_ENVELOPE = 0x00008000,
MAIL_FETCH_HEADER_MD5 = 0x00010000,
MAIL_FETCH_UIDL_FILE_NAME = 0x00020000,
- MAIL_FETCH_UIDL_BACKEND = 0x00040000
+ MAIL_FETCH_UIDL_BACKEND = 0x00040000,
+ MAIL_FETCH_SEARCH_SCORE = 0x00100000
};
enum mailbox_transaction_flags {
diff -r 282b1ea973ef -r 88256be2a59f src/plugins/fts-solr/fts-backend-solr.c
--- a/src/plugins/fts-solr/fts-backend-solr.c Sun Jul 13 19:08:13 2008 +0300
+++ b/src/plugins/fts-solr/fts-backend-solr.c Sun Jul 13 19:11:11 2008 +0300
@@ -96,7 +96,7 @@ static int fts_backend_solr_get_last_uid
solr_quote_str(str, backend->box->storage->user);
t_array_init(&uids, 1);
- if (solr_connection_select(solr_conn, str_c(str), &uids) < 0)
+ if (solr_connection_select(solr_conn, str_c(str), &uids, NULL) < 0)
return -1;
uidvals = array_get(&uids, &count);
@@ -257,7 +257,8 @@ static void fts_backend_solr_unlock(stru
static int fts_backend_solr_lookup(struct fts_backend_lookup_context *ctx,
ARRAY_TYPE(seq_range) *definite_uids,
- ARRAY_TYPE(seq_range) *maybe_uids)
+ ARRAY_TYPE(seq_range) *maybe_uids,
+ ARRAY_TYPE(fts_score_map) *scores)
{
struct mailbox *box = ctx->backend->box;
const struct fts_backend_lookup_field *fields;
@@ -268,7 +269,8 @@ static int fts_backend_solr_lookup(struc
mailbox_get_status(box, STATUS_UIDVALIDITY, &status);
str = t_str_new(256);
- str_printfa(str, "fl=uid&rows=%u&q=", status.uidnext);
+ str_printfa(str, "fl=uid,score&rows=%u&sort=uid%%20asc&q=",
+ status.uidnext);
/* build a lucene search query from the fields */
fields = array_get(&ctx->fields, &count);
@@ -301,7 +303,8 @@ static int fts_backend_solr_lookup(struc
solr_quote_str(str, box->storage->user);
array_clear(maybe_uids);
- return solr_connection_select(solr_conn, str_c(str), definite_uids);
+ return solr_connection_select(solr_conn, str_c(str),
+ definite_uids, scores);
}
struct fts_backend fts_backend_solr = {
diff -r 282b1ea973ef -r 88256be2a59f src/plugins/fts-solr/solr-connection.c
--- a/src/plugins/fts-solr/solr-connection.c Sun Jul 13 19:08:13 2008 +0300
+++ b/src/plugins/fts-solr/solr-connection.c Sun Jul 13 19:11:11 2008 +0300
@@ -3,6 +3,7 @@
/* curl: 7.16.0 curl_multi_timeout */
#include "lib.h"
+#include "array.h"
#include "str.h"
#include "strescape.h"
#include "solr-connection.h"
@@ -29,7 +30,11 @@ struct solr_lookup_xml_context {
enum solr_xml_content_state content_state;
int depth;
+ uint32_t uid;
+ float score;
+
ARRAY_TYPE(seq_range) *uids;
+ ARRAY_TYPE(fts_score_map) *scores;
};
struct solr_connection_post {
@@ -225,8 +230,11 @@ solr_lookup_xml_start(void *context, con
ctx->state++;
break;
case SOLR_XML_RESPONSE_STATE_RESULT:
- if (strcmp(name, "doc") == 0)
+ if (strcmp(name, "doc") == 0) {
ctx->state++;
+ ctx->uid = 0;
+ ctx->score = 0;
+ }
break;
case SOLR_XML_RESPONSE_STATE_DOC:
name_attr = attrs_get_name(attrs);
@@ -243,6 +251,23 @@ solr_lookup_xml_start(void *context, con
}
}
+static void solr_lookup_add_doc(struct solr_lookup_xml_context *ctx)
+{
+ struct fts_score_map *score;
+
+ if (ctx->uid == 0) {
+ i_error("fts_solr: missing uid");
+ return;
+ }
+
+ seq_range_array_add(ctx->uids, 0, ctx->uid);
+ if (ctx->scores != NULL && ctx->score != 0) {
+ score = array_append_space(ctx->scores);
+ score->uid = ctx->uid;
+ score->score = ctx->score;
+ }
+}
+
static void solr_lookup_xml_end(void *context, const char *name ATTR_UNUSED)
{
struct solr_lookup_xml_context *ctx = context;
@@ -250,6 +275,8 @@ static void solr_lookup_xml_end(void *co
i_assert(ctx->depth >= (int)ctx->state);
if (ctx->depth == (int)ctx->state) {
+ if (ctx->state == SOLR_XML_RESPONSE_STATE_DOC)
+ solr_lookup_add_doc(ctx);
More information about the dovecot-cvs
mailing list