From: Timo Sirainen Date: Fri, 13 Jun 2008 01:39:49 +0000 (+0300) Subject: Reversing the primary sort criterion reversed also reversed secondary X-Git-Tag: 1.2.alpha1~302 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0ec26d0ba45ecb400e35d672d2a97a160527bd79;p=thirdparty%2Fdovecot%2Fcore.git Reversing the primary sort criterion reversed also reversed secondary criterions. Fixed reverse sorting the first condition. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/index-sort-private.h b/src/lib-storage/index/index-sort-private.h index 83e2cfb794..327332176d 100644 --- a/src/lib-storage/index/index-sort-private.h +++ b/src/lib-storage/index/index-sort-private.h @@ -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 --git a/src/lib-storage/index/index-sort-string.c b/src/lib-storage/index/index-sort-string.c index 81b837789e..dc17c83b71 100644 --- a/src/lib-storage/index/index-sort-string.c +++ b/src/lib-storage/index/index-sort-string.c @@ -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 mail_search_sort_program *program) } 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(const void *p1, const void *p2) 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_sort_ids(struct sort_string_context *ctx) 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 !ctx->reverse ? 1 : -1; - return index_sort_node_cmp_type(program->temp_mail, - program->sort_program + 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(struct mail_search_sort_program *program) 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,17 +771,35 @@ void index_sort_list_finish_string(struct mail_search_sort_program *program) 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); for (i = 0; i < count; i++) { diff --git a/src/lib-storage/index/index-sort.c b/src/lib-storage/index/index-sort.c index 7312daf402..58fdf05160 100644 --- a/src/lib-storage/index/index-sort.c +++ b/src/lib-storage/index/index-sort.c @@ -26,6 +26,7 @@ ARRAY_DEFINE_TYPE(mail_sort_node_size, struct mail_sort_node_size); 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 *p1, const void *p2) 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 *p1, const void *p2) 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_search_sort_program *program) 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_search_sort_program *program, { 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; + if (program->iter_idx == array_count(&program->seqs)) + return FALSE; - seqp = array_idx(&program->seqs, --program->iter_idx); - } + 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_transaction_context *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 *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;