dovecot-1.1: sort index: Try to catch broken sort_ids and recrea...

dovecot at dovecot.org dovecot at dovecot.org
Fri Jun 6 20:08:27 EEST 2008


details:   http://hg.dovecot.org/dovecot-1.1/rev/dd899a1841d9
changeset: 7614:dd899a1841d9
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Jun 06 20:08:23 2008 +0300
description:
sort index: Try to catch broken sort_ids and recreate them correctly instead
of assert-crashing.

diffstat:

1 file changed, 50 insertions(+), 19 deletions(-)
src/lib-storage/index/index-sort-string.c |   69 +++++++++++++++++++++--------

diffs (136 lines):

diff -r 63602977ca9b -r dd899a1841d9 src/lib-storage/index/index-sort-string.c
--- a/src/lib-storage/index/index-sort-string.c	Fri Jun 06 20:07:45 2008 +0300
+++ b/src/lib-storage/index/index-sort-string.c	Fri Jun 06 20:08:23 2008 +0300
@@ -471,7 +471,7 @@ static void index_sort_merge(struct sort
 	ctx->nonzero_nodes = ctx->sorted_nodes;
 }
 
-static void
+static int
 index_sort_add_ids_range(struct sort_string_context *ctx,
 			 unsigned int left_idx, unsigned int right_idx)
 {
@@ -481,6 +481,7 @@ index_sort_add_ids_range(struct sort_str
 	const char *left_str = NULL, *right_str = NULL, *str;
 	uint32_t left_sort_id, right_sort_id, diff;
 	bool no_left_str = FALSE, no_right_str = FALSE;
+	int ret;
 
 	nodes = array_get_modifiable(&ctx->sorted_nodes, &count);
 	rightmost_idx = count - 1;
@@ -496,7 +497,7 @@ index_sort_add_ids_range(struct sort_str
 			nodes[i].sort_id = left_sort_id;
 			nodes[i].sort_id_changed = TRUE;
 		}
-		return;
+		return 0;
 	}
 
 	if (left_sort_id == 0) {
@@ -585,9 +586,14 @@ index_sort_add_ids_range(struct sort_str
 			continue;
 		}
 
-		if (left_str != NULL && strcmp(str, left_str) == 0)
+		ret = left_str == NULL ? 1 : strcmp(str, left_str);
+		if (ret <= 0) {
+			if (ret < 0) {
+				/* broken sort_ids */
+				return -1;
+			}
 			nodes[i].sort_id = left_sort_id;
-		else if (right_str != NULL && strcmp(str, right_str) == 0) {
+		} else if (right_str != NULL && strcmp(str, right_str) == 0) {
 			/* the rest of the sort IDs should be the same */
 			nodes[i].sort_id = right_sort_id;
 			left_sort_id = right_sort_id;
@@ -595,10 +601,6 @@ index_sort_add_ids_range(struct sort_str
 			/* divide the available space equally. leave the same
 			   sized space also between the first and the last
 			   messages */
-			if (left_str != NULL)
-				i_assert(strcmp(left_str, str) < 0);
-			if (right_str != NULL)
-				i_assert(strcmp(right_str, str) > 0);
 			skip = (right_sort_id - left_sort_id) /
 				(right_idx - i + 2);
 			i_assert(skip > 0);
@@ -610,9 +612,10 @@ index_sort_add_ids_range(struct sort_str
 		}
 		nodes[i].sort_id_changed = TRUE;
 	}
-}
-
-static void
+	return right_str == NULL || strcmp(str, right_str) < 0 ? 0 : -1;
+}
+
+static int
 index_sort_add_sort_ids(struct sort_string_context *ctx)
 {
 	const struct mail_sort_node *nodes;
@@ -632,8 +635,10 @@ index_sort_add_sort_ids(struct sort_stri
 		if (right_idx == count)
 			right_idx--;
 		left_idx = i == 0 ? 0 : i - 1;
-		index_sort_add_ids_range(ctx, left_idx, right_idx);
-	}
+		if (index_sort_add_ids_range(ctx, left_idx, right_idx) < 0)
+			return -1;
+	}
+	return 0;
 }
 
 static void index_sort_write_changed_sort_ids(struct sort_string_context *ctx)
@@ -710,6 +715,26 @@ static void index_sort_add_missing(struc
 	}
 }
 
+static void index_sort_list_reset_broken(struct sort_string_context *ctx)
+{
+	struct mailbox *box = ctx->program->t->box;
+	struct mail_sort_node *nodes;
+	unsigned int i, count;
+
+	mail_storage_set_critical(box->storage,
+				  "Sort IDs %u broken in mailbox %s, reseting",
+				  ctx->ext_id, box->name);
+
+	array_clear(&ctx->zero_nodes);
+	array_append_array(&ctx->zero_nodes,
+			   &ctx->nonzero_nodes);
+	array_clear(&ctx->nonzero_nodes);
+
+	nodes = array_get_modifiable(&ctx->zero_nodes, &count);
+	for (i = 0; i < count; i++)
+		nodes[i].sort_id = 0;
+}
+
 void index_sort_list_finish_string(struct mail_search_sort_program *program)
 {
 	struct sort_string_context *ctx = program->context;
@@ -742,12 +767,18 @@ void index_sort_list_finish_string(struc
 		nodes = array_get_modifiable(&ctx->nonzero_nodes, &count);
 		qsort(nodes, count, sizeof(struct mail_sort_node),
 		      sort_node_cmp);
-		/* sort all messages without sort IDs */
-		index_sort_zeroes(ctx);
-		/* merge zero and non-zero arrays into sorted_nodes */
-		index_sort_merge(ctx);
-		/* give sort IDs to messages missing them */
-		index_sort_add_sort_ids(ctx);
+		for (;;) {
+			/* sort all messages without sort IDs */
+			index_sort_zeroes(ctx);
+			/* 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 */
+			index_sort_list_reset_broken(ctx);
+		}
 		index_sort_write_changed_sort_ids(ctx);
 
 		nodes = array_get_modifiable(&ctx->sorted_nodes, &count);


More information about the dovecot-cvs mailing list