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