diff src/lib-storage/index/index-sort.c @ 8006:0a3b5ddb0869 HEAD

Added support for sorting by X-SCORE. Currently it's only set by fts-solr.
author Timo Sirainen <tss@iki.fi>
date Sun, 13 Jul 2008 19:09:55 +0300
parents 439636cce455
children b9faf4db2a9f
line wrap: on
line diff
--- 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:09:55 2008 +0300
@@ -23,6 +23,12 @@
 };
 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 @@
 		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)
 {
@@ -142,6 +170,36 @@
 	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;
+}
+
 void index_sort_list_finish(struct mail_search_sort_program *program)
 {
 	memset(&static_node_cmp_context, 0, sizeof(static_node_cmp_context));
@@ -224,6 +282,16 @@
 		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 @@
 	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 @@
 		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);