Skip to content

Commit

Permalink
lib-storage: Add details to "Broken sort-* indexes" error
Browse files Browse the repository at this point in the history
  • Loading branch information
sirainen authored and GitLab committed Jun 9, 2017
1 parent 7aa2660 commit 96c7d2a
Showing 1 changed file with 50 additions and 14 deletions.
64 changes: 50 additions & 14 deletions src/lib-storage/index/index-sort-string.c
Expand Up @@ -47,7 +47,8 @@ struct sort_string_context {

static struct sort_string_context *static_zero_cmp_context;

static void index_sort_list_reset_broken(struct sort_string_context *ctx);
static void index_sort_list_reset_broken(struct sort_string_context *ctx,
const char *reason);
static void index_sort_node_add(struct sort_string_context *ctx,
struct mail_sort_node *node);

Expand Down Expand Up @@ -183,7 +184,16 @@ static void index_sort_node_add(struct sort_string_context *ctx,
ctx->lowest_nonexpunged_zero = node->seq;
} else if (ctx->lowest_nonexpunged_zero != 0 &&
ctx->lowest_nonexpunged_zero <= node->seq) {
index_sort_list_reset_broken(ctx);
uint32_t nonzero_uid, zero_uid;

mail_index_lookup_uid(ctx->program->t->view,
node->seq, &nonzero_uid);
mail_index_lookup_uid(ctx->program->t->view,
ctx->lowest_nonexpunged_zero, &zero_uid);
index_sort_list_reset_broken(ctx, t_strdup_printf(
"sort_id=0 found in the middle "
"(uid=%u has sort_id, uid=%u doesn't)",
nonzero_uid, zero_uid));
ctx->broken = TRUE;
node->sort_id = 0;
}
Expand Down Expand Up @@ -523,13 +533,14 @@ static void index_sort_merge(struct sort_string_context *ctx)

static int
index_sort_add_ids_range(struct sort_string_context *ctx,
unsigned int left_idx, unsigned int right_idx)
unsigned int left_idx, unsigned int right_idx,
const char **reason_r)
{

struct mail_sort_node *nodes;
unsigned int i, count, rightmost_idx, skip;
const char *left_str = NULL, *right_str = NULL, *str = NULL;
uint32_t left_sort_id, right_sort_id, diff;
uint32_t left_sort_id, right_sort_id, diff, left_str_idx = 0;
bool no_left_str = FALSE, no_right_str = FALSE;
int ret;

Expand Down Expand Up @@ -609,6 +620,8 @@ index_sort_add_ids_range(struct sort_string_context *ctx,
&nodes[left_idx], &left_str)) {
/* not equivalent with any message */
left_str = NULL;
} else {
left_str_idx = left_idx;
}
left_idx++;
}
Expand Down Expand Up @@ -640,6 +653,16 @@ index_sort_add_ids_range(struct sort_string_context *ctx,
if (ret <= 0) {
if (ret < 0) {
/* broken sort_ids */
uint32_t str_uid, left_str_uid;

mail_index_lookup_uid(ctx->program->t->view,
nodes[i].seq, &str_uid);
mail_index_lookup_uid(ctx->program->t->view,
nodes[left_str_idx].seq, &left_str_uid);
*reason_r = t_strdup_printf(
"(idx=%u, seq=%u, uid=%u) '%s' < left string (idx=%u, seq=%u, uid=%u) '%s'",
i, nodes[i].seq, str_uid, str,
left_str_idx, nodes[left_str_idx].seq, left_str_uid, left_str);
return -1;
}
nodes[i].sort_id = left_sort_id;
Expand All @@ -656,25 +679,36 @@ index_sort_add_ids_range(struct sort_string_context *ctx,
if (skip == 0) {
/* broken sort IDs (we previously assigned
left_sort_id=right_sort_id) */
uint32_t uid;
mail_index_lookup_uid(ctx->program->t->view,
nodes[i].seq, &uid);
*reason_r = t_strdup_printf(
"no sort_id space for uid=%u", uid);
return -1;
}
left_sort_id += skip;
i_assert(left_sort_id < right_sort_id);

nodes[i].sort_id = left_sort_id;
left_str = str;
left_str_idx = i;
}
nodes[i].sort_id_changed = TRUE;
}
i_assert(str != NULL);

return right_str == NULL || strcmp(str, right_str) < 0 ||
(strcmp(str, right_str) == 0 &&
nodes[i-1].sort_id == right_sort_id) ? 0 : -1;
if (right_str == NULL || strcmp(str, right_str) < 0 ||
(strcmp(str, right_str) == 0 &&
nodes[i-1].sort_id == right_sort_id))
return 0;

*reason_r = t_strdup_printf("Invalid sort_id order ('%s' > '%s')",
str, right_str);
return -1;
}

static int
index_sort_add_sort_ids(struct sort_string_context *ctx)
index_sort_add_sort_ids(struct sort_string_context *ctx, const char **reason_r)
{
const struct mail_sort_node *nodes;
unsigned int i, left_idx, right_idx, count;
Expand All @@ -693,7 +727,7 @@ index_sort_add_sort_ids(struct sort_string_context *ctx)
if (right_idx == count)
right_idx--;
left_idx = i == 0 ? 0 : i - 1;
if (index_sort_add_ids_range(ctx, left_idx, right_idx) < 0)
if (index_sort_add_ids_range(ctx, left_idx, right_idx, reason_r) < 0)
return -1;
}
return 0;
Expand Down Expand Up @@ -773,14 +807,15 @@ static void index_sort_add_missing(struct sort_string_context *ctx)
}
}

static void index_sort_list_reset_broken(struct sort_string_context *ctx)
static void index_sort_list_reset_broken(struct sort_string_context *ctx,
const char *reason)
{
struct mailbox *box = ctx->program->t->box;
struct mail_sort_node *node;

mail_storage_set_critical(box->storage,
"%s: Broken %s indexes, resetting",
box->name, ctx->primary_sort_name);
"%s: Broken %s indexes, resetting: %s",
box->name, ctx->primary_sort_name, reason);

array_clear(&ctx->zero_nodes);
array_append_array(&ctx->zero_nodes,
Expand All @@ -796,6 +831,7 @@ void index_sort_list_finish_string(struct mail_search_sort_program *program)
struct sort_string_context *ctx = program->context;
const struct mail_sort_node *nodes;
unsigned int i, count;
const char *reason;
uint32_t seq;

static_zero_cmp_context = ctx;
Expand Down Expand Up @@ -848,11 +884,11 @@ void index_sort_list_finish_string(struct mail_search_sort_program *program)
/* 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)
if (index_sort_add_sort_ids(ctx, &reason) == 0)
break;

/* broken, try again with sort IDs reset */
index_sort_list_reset_broken(ctx);
index_sort_list_reset_broken(ctx, reason);
}
index_sort_write_changed_sort_ids(ctx);

Expand Down

0 comments on commit 96c7d2a

Please sign in to comment.