dovecot-1.1: Reversing the primary sort criterion reversed also ...

dovecot at dovecot.org dovecot at dovecot.org
Fri Jun 13 04:39:54 EEST 2008


details:   http://hg.dovecot.org/dovecot-1.1/rev/5e5721c49d3d
changeset: 7659:5e5721c49d3d
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Jun 13 04:39:49 2008 +0300
description:
Reversing the primary sort criterion reversed also reversed secondary
criterions.
Fixed reverse sorting the first condition.

diffstat:

3 files changed, 41 insertions(+), 36 deletions(-)
src/lib-storage/index/index-sort-private.h |    2 -
src/lib-storage/index/index-sort-string.c  |   39 ++++++++++++++++++++--------
src/lib-storage/index/index-sort.c         |   36 ++++++++-----------------

diffs (205 lines):

diff -r 7f7de0ca30c5 -r 5e5721c49d3d src/lib-storage/index/index-sort-private.h
--- a/src/lib-storage/index/index-sort-private.h	Fri Jun 13 04:36:19 2008 +0300
+++ b/src/lib-storage/index/index-sort-private.h	Fri Jun 13 04:39:49 2008 +0300
@@ -15,8 +15,6 @@ struct mail_search_sort_program {
 
 	ARRAY_TYPE(uint32_t) seqs;
 	unsigned int iter_idx;
-
-	unsigned int reverse:1;
 };
 
 int index_sort_header_get(struct mail *mail, uint32_t seq,
diff -r 7f7de0ca30c5 -r 5e5721c49d3d src/lib-storage/index/index-sort-string.c
--- a/src/lib-storage/index/index-sort-string.c	Fri Jun 13 04:36:19 2008 +0300
+++ b/src/lib-storage/index/index-sort-string.c	Fri Jun 13 04:39:49 2008 +0300
@@ -39,11 +39,11 @@ struct sort_string_context {
 	unsigned int regetting:1;
 	unsigned int have_all_wanted:1;
 	unsigned int no_writing:1;
+	unsigned int reverse:1;
 };
 
 static char expunged_msg;
 static struct sort_string_context *static_zero_cmp_context;
-static struct mail_search_sort_program *static_sort_node_cmp_context;
 
 static void index_sort_node_add(struct sort_string_context *ctx,
 				struct mail_sort_node *node);
@@ -72,6 +72,7 @@ void index_sort_list_init_string(struct 
 	}
 
 	program->context = ctx = i_new(struct sort_string_context, 1);
+	ctx->reverse = (program->sort_program[0] & MAIL_SORT_FLAG_REVERSE) != 0;
 	ctx->program = program;
 	ctx->ext_id = mail_index_ext_register(ibox->index, name, 0,
 					      sizeof(uint32_t),
@@ -219,7 +220,7 @@ static int sort_node_zero_string_cmp(con
 
 	ret = strcmp(ctx->sort_strings[n1->seq], ctx->sort_strings[n2->seq]);
 	if (ret != 0)
-		return ret;
+		return !ctx->reverse ? ret : -ret;
 
 	return index_sort_node_cmp_type(ctx->program->temp_mail,
 					ctx->program->sort_program + 1,
@@ -671,16 +672,16 @@ static void index_sort_write_changed_sor
 
 static int sort_node_cmp(const void *p1, const void *p2)
 {
-	struct mail_search_sort_program *program = static_sort_node_cmp_context;
+	struct sort_string_context *ctx = static_zero_cmp_context;
 	const struct mail_sort_node *n1 = p1, *n2 = p2;
 
 	if (n1->sort_id < n2->sort_id)
-		return -1;
+		return !ctx->reverse ? -1 : 1;
 	if (n1->sort_id > n2->sort_id)
-		return 1;
-
-	return index_sort_node_cmp_type(program->temp_mail,
-					program->sort_program + 1,
+		return !ctx->reverse ? 1 : -1;
+
+	return index_sort_node_cmp_type(ctx->program->temp_mail,
+					ctx->program->sort_program + 1,
 					n1->seq, n2->seq);
 }
 
@@ -744,7 +745,7 @@ void index_sort_list_finish_string(struc
 
 	nodes = array_get_modifiable(&ctx->nonzero_nodes, &count);
 
-	static_sort_node_cmp_context = program;
+	static_zero_cmp_context = ctx;
 	if (array_count(&ctx->zero_nodes) == 0) {
 		/* fast path: we have all sort IDs */
 		qsort(nodes, count, sizeof(struct mail_sort_node),
@@ -770,16 +771,34 @@ void index_sort_list_finish_string(struc
 		for (;;) {
 			/* sort all messages without sort IDs */
 			index_sort_zeroes(ctx);
+
+			if (ctx->reverse) {
+				/* sort lists are descending currently, but
+				   merging and sort ID assigning works only
+				   with ascending lists. reverse the lists
+				   temporarily. we can't do this while earlier
+				   because secondary sort conditions must not
+				   be reversed in results (but while assigning
+				   sort IDs it doesn't matter). */
+				array_reverse(&ctx->nonzero_nodes);
+				array_reverse(&ctx->zero_nodes);
+			}
+
 			/* merge zero and non-zero arrays into sorted_nodes */
 			index_sort_merge(ctx);
 			/* give sort IDs to messages missing them */
 			if (index_sort_add_sort_ids(ctx) == 0)
 				break;
 
-			/* broken, try again */
+			/* broken, try again with sort IDs reset */
 			index_sort_list_reset_broken(ctx);
 		}
 		index_sort_write_changed_sort_ids(ctx);
+
+		if (ctx->reverse) {
+			/* restore the correct sort order */
+			array_reverse(&ctx->sorted_nodes);
+		}
 
 		nodes = array_get_modifiable(&ctx->sorted_nodes, &count);
 		array_clear(&program->seqs);
diff -r 7f7de0ca30c5 -r 5e5721c49d3d src/lib-storage/index/index-sort.c
--- a/src/lib-storage/index/index-sort.c	Fri Jun 13 04:36:19 2008 +0300
+++ b/src/lib-storage/index/index-sort.c	Fri Jun 13 04:39:49 2008 +0300
@@ -26,6 +26,7 @@ struct sort_cmp_context {
 struct sort_cmp_context {
 	struct mail_search_sort_program *program;
 	struct mail *mail;
+	bool reverse;
 };
 
 static struct sort_cmp_context static_node_cmp_context;
@@ -87,9 +88,9 @@ static int sort_node_date_cmp(const void
 	const struct mail_sort_node_date *n1 = p1, *n2 = p2;
 
 	if (n1->date < n2->date)
-		return -1;
+		return !ctx->reverse ? -1 : 1;
 	if (n1->date > n2->date)
-		return 1;
+		return !ctx->reverse ? 1 : -1;
 
 	return index_sort_node_cmp_type(ctx->mail,
 					ctx->program->sort_program + 1,
@@ -117,9 +118,9 @@ static int sort_node_size_cmp(const void
 	const struct mail_sort_node_size *n1 = p1, *n2 = p2;
 
 	if (n1->size < n2->size)
-		return -1;
+		return !ctx->reverse ? -1 : 1;
 	if (n1->size > n2->size)
-		return 1;
+		return !ctx->reverse ? 1 : -1;
 
 	return index_sort_node_cmp_type(ctx->mail,
 					ctx->program->sort_program + 1,
@@ -146,11 +147,10 @@ void index_sort_list_finish(struct mail_
 	memset(&static_node_cmp_context, 0, sizeof(static_node_cmp_context));
 	static_node_cmp_context.program = program;
 	static_node_cmp_context.mail = program->temp_mail;
+	static_node_cmp_context.reverse =
+		(program->sort_program[0] & MAIL_SORT_FLAG_REVERSE) != 0;
 
 	program->sort_list_finish(program);
-
-	if (program->reverse)
-		program->iter_idx = array_count(&program->seqs);
 }
 
 bool index_sort_list_next(struct mail_search_sort_program *program,
@@ -158,17 +158,10 @@ bool index_sort_list_next(struct mail_se
 {
 	const uint32_t *seqp;
 
-	if (!program->reverse) {
-		if (program->iter_idx == array_count(&program->seqs))
-			return FALSE;
-
-		seqp = array_idx(&program->seqs, program->iter_idx++);
-	} else {
-		if (program->iter_idx == 0)
-			return FALSE;
-
-		seqp = array_idx(&program->seqs, --program->iter_idx);
-	}
+	if (program->iter_idx == array_count(&program->seqs))
+		return FALSE;
+
+	seqp = array_idx(&program->seqs, program->iter_idx++);
 	mail_set_seq(mail, *seqp);
 	return TRUE;
 }
@@ -188,11 +181,7 @@ index_sort_program_init(struct mailbox_t
 	program->t = t;
 	program->temp_mail = mail_alloc(t, 0, NULL);
 
-	/* primary reversion isn't stored to sort_program. we handle it by
-	   iterating backwards at the end. */
-	program->reverse = (sort_program[0] & MAIL_SORT_FLAG_REVERSE) != 0;
-	program->sort_program[0] = sort_program[0] & ~MAIL_SORT_FLAG_REVERSE;
-	for (i = 1; i < MAX_SORT_PROGRAM_SIZE; i++) {
+	for (i = 0; i < MAX_SORT_PROGRAM_SIZE; i++) {
 		program->sort_program[i] = sort_program[i];
 		if (sort_program[i] == MAIL_SORT_END)
 			break;
@@ -387,7 +376,6 @@ int index_sort_node_cmp_type(struct mail
 						seq1, seq2);
 	}
 
-	/* primary reversion isn't in sort_program */
 	if ((*sort_program & MAIL_SORT_FLAG_REVERSE) != 0)
 		ret = ret < 0 ? 1 : -1;
 	return ret;


More information about the dovecot-cvs mailing list