Skip to content

Commit cab52d3

Browse files
Rebuild vy_run index in case of run recover error
Rebuild vy_run index error in case of vy_run_recover error. Old index file will be deleted and a new index file will be created. Issue #2253
1 parent 857e642 commit cab52d3

File tree

9 files changed

+505
-53
lines changed

9 files changed

+505
-53
lines changed

src/box/vy_index.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <small/rlist.h>
4444

4545
#include "assoc.h"
46+
#include "cfg.h"
4647
#include "diag.h"
4748
#include "errcode.h"
4849
#include "histogram.h"
@@ -436,7 +437,14 @@ vy_index_recovery_cb(const struct vy_log_record *record, void *cb_arg)
436437
goto out;
437438
run->dump_lsn = record->dump_lsn;
438439
if (vy_run_recover(run, index->env->path,
439-
index->space_id, index->id) != 0) {
440+
index->space_id, index->id) != 0 &&
441+
(cfg_geti("force_recovery") == false ||
442+
vy_run_rebuild_index(run, index->env->path,
443+
index->space_id, index->id,
444+
index->cmp_def, index->key_def,
445+
index->space_format,
446+
index->upsert_format,
447+
&index->opts) != 0)) {
440448
vy_run_unref(run);
441449
goto out;
442450
}

src/box/vy_run.c

Lines changed: 190 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -202,19 +202,12 @@ vy_run_env_enable_coio(struct vy_run_env *env, int threads)
202202
*/
203203
static int
204204
vy_page_info_create(struct vy_page_info *page_info, uint64_t offset,
205-
const struct tuple *min_key, const struct key_def *cmp_def)
205+
const char *min_key)
206206
{
207207
memset(page_info, 0, sizeof(*page_info));
208208
page_info->offset = offset;
209209
page_info->unpacked_size = 0;
210-
struct region *region = &fiber()->gc;
211-
size_t used = region_used(region);
212-
uint32_t size;
213-
const char *region_key = tuple_extract_key(min_key, cmp_def, &size);
214-
if (region_key == NULL)
215-
return -1;
216-
page_info->min_key = vy_key_dup(region_key);
217-
region_truncate(region, used);
210+
page_info->min_key = vy_key_dup(min_key);
218211
return page_info->min_key == NULL ? -1 : 0;
219212
}
220213

@@ -247,22 +240,33 @@ vy_run_new(int64_t id)
247240
return run;
248241
}
249242

250-
void
251-
vy_run_delete(struct vy_run *run)
243+
static void
244+
vy_run_clear(struct vy_run *run)
252245
{
253-
assert(run->refs == 0);
254-
if (run->fd >= 0 && close(run->fd) < 0)
255-
say_syserror("close failed");
256246
if (run->page_info != NULL) {
257247
uint32_t page_no;
258248
for (page_no = 0; page_no < run->info.page_count; ++page_no)
259249
vy_page_info_destroy(run->page_info + page_no);
260250
free(run->page_info);
261251
}
252+
run->page_info = NULL;
253+
run->info.page_count = 0;
262254
if (run->info.has_bloom)
263255
bloom_destroy(&run->info.bloom, runtime.quota);
256+
run->info.has_bloom = false;
264257
free(run->info.min_key);
258+
run->info.min_key = NULL;
265259
free(run->info.max_key);
260+
run->info.max_key = NULL;
261+
}
262+
263+
void
264+
vy_run_delete(struct vy_run *run)
265+
{
266+
assert(run->refs == 0);
267+
if (run->fd >= 0 && close(run->fd) < 0)
268+
say_syserror("close failed");
269+
vy_run_clear(run);
266270
TRASH(run);
267271
free(run);
268272
}
@@ -723,9 +727,7 @@ vy_page_stmt(struct vy_page *page, uint32_t stmt_no,
723727
struct xrow_header xrow;
724728
if (vy_page_xrow(page, stmt_no, &xrow) != 0)
725729
return NULL;
726-
struct tuple_format *format_to_use = (xrow.type == IPROTO_UPSERT)
727-
? upsert_format : format;
728-
return vy_stmt_decode(&xrow, cmp_def, format_to_use, is_primary);
730+
return vy_stmt_decode(&xrow, cmp_def, format, upsert_format, is_primary);
729731
}
730732

731733
/**
@@ -1962,9 +1964,10 @@ vy_run_recover(struct vy_run *run, const char *dir,
19621964
xlog_cursor_close(&cursor, true);
19631965
return 0;
19641966

1965-
fail_close:
1967+
fail_close:
19661968
xlog_cursor_close(&cursor, false);
1967-
fail:
1969+
fail:
1970+
vy_run_clear(run);
19681971
return -1;
19691972
}
19701973

@@ -2031,6 +2034,26 @@ vy_row_index_encode(const uint32_t *row_index, uint32_t row_count,
20312034
return 0;
20322035
}
20332036

2037+
/**
2038+
* Helper to extend run page info array
2039+
*/
2040+
static inline int
2041+
vy_run_alloc_page_info(struct vy_run *run, uint32_t *page_info_capacity)
2042+
{
2043+
uint32_t cap = *page_info_capacity > 0 ?
2044+
*page_info_capacity * 2 : 16;
2045+
struct vy_page_info *page_info = realloc(run->page_info,
2046+
cap * sizeof(*page_info));
2047+
if (page_info == NULL) {
2048+
diag_set(OutOfMemory, cap * sizeof(*page_info),
2049+
"realloc", "struct vy_page_info");
2050+
return -1;
2051+
}
2052+
run->page_info = page_info;
2053+
*page_info_capacity = cap;
2054+
return 0;
2055+
}
2056+
20342057
/**
20352058
* Write statements from the iterator to a new page in the run,
20362059
* update page and run statistics.
@@ -2060,34 +2083,26 @@ vy_run_write_page(struct vy_run *run, struct xlog *data_xlog,
20602083
struct ibuf row_index_buf;
20612084
ibuf_create(&row_index_buf, &cord()->slabc, sizeof(uint32_t) * 4096);
20622085

2063-
if (run->info.page_count >= *page_info_capacity) {
2064-
uint32_t cap = *page_info_capacity > 0 ?
2065-
*page_info_capacity * 2 : 16;
2066-
struct vy_page_info *page_info = realloc(run->page_info,
2067-
cap * sizeof(*page_info));
2068-
if (page_info == NULL) {
2069-
diag_set(OutOfMemory, cap * sizeof(*page_info),
2070-
"realloc", "struct vy_page_info");
2071-
goto error_row_index;
2072-
}
2073-
run->page_info = page_info;
2074-
*page_info_capacity = cap;
2075-
}
2086+
if (run->info.page_count >= *page_info_capacity &&
2087+
vy_run_alloc_page_info(run, page_info_capacity) != 0)
2088+
goto error_row_index;
20762089
assert(*page_info_capacity >= run->info.page_count);
20772090

2091+
/* See comment to run_info->max_key allocation below. */
2092+
region_key = tuple_extract_key(*curr_stmt, cmp_def, NULL);
2093+
if (region_key == NULL)
2094+
goto error_row_index;
2095+
20782096
if (run->info.page_count == 0) {
2079-
/* See comment to run_info->max_key allocation below. */
2080-
region_key = tuple_extract_key(*curr_stmt, cmp_def, NULL);
2081-
if (region_key == NULL)
2082-
goto error_row_index;
20832097
assert(run->info.min_key == NULL);
20842098
run->info.min_key = vy_key_dup(region_key);
20852099
if (run->info.min_key == NULL)
20862100
goto error_row_index;
20872101
}
20882102

20892103
page = run->page_info + run->info.page_count;
2090-
vy_page_info_create(page, data_xlog->offset, *curr_stmt, cmp_def);
2104+
if (vy_page_info_create(page, data_xlog->offset, region_key) != 0)
2105+
goto error_row_index;
20912106
xlog_tx_begin(data_xlog);
20922107

20932108
do {
@@ -2456,6 +2471,9 @@ static int
24562471
vy_run_write_index(struct vy_run *run, const char *dirpath,
24572472
uint32_t space_id, uint32_t iid)
24582473
{
2474+
struct region *region = &fiber()->gc;
2475+
size_t mem_used = region_used(region);
2476+
24592477
char path[PATH_MAX];
24602478
vy_run_snprint_path(path, sizeof(path), dirpath,
24612479
space_id, iid, run->id, VY_FILE_INDEX);
@@ -2489,10 +2507,10 @@ vy_run_write_index(struct vy_run *run, const char *dirpath,
24892507
xlog_rename(&index_xlog) < 0)
24902508
goto fail;
24912509
xlog_close(&index_xlog, false);
2492-
fiber_gc();
2510+
region_truncate(region, mem_used);
24932511
return 0;
2494-
fail:
2495-
fiber_gc();
2512+
fail:
2513+
region_truncate(region, mem_used);
24962514
xlog_tx_rollback(&index_xlog);
24972515
xlog_close(&index_xlog, false);
24982516
unlink(path);
@@ -2533,6 +2551,138 @@ vy_run_write(struct vy_run *run, const char *dirpath,
25332551
return 0;
25342552
}
25352553

2554+
int
2555+
vy_run_rebuild_index(struct vy_run *run, const char *dir,
2556+
uint32_t space_id, uint32_t iid,
2557+
const struct key_def *cmp_def,
2558+
const struct key_def *key_def,
2559+
struct tuple_format *space_format,
2560+
struct tuple_format *upsert_format,
2561+
const struct index_opts *opts)
2562+
{
2563+
assert(run->info.has_bloom == false);
2564+
assert(run->page_info == NULL);
2565+
struct region *region = &fiber()->gc;
2566+
size_t mem_used = region_used(region);
2567+
2568+
struct xlog_cursor cursor;
2569+
char path[PATH_MAX];
2570+
vy_run_snprint_path(path, sizeof(path), dir,
2571+
space_id, iid, run->id, VY_FILE_RUN);
2572+
2573+
say_warn("Rebuilding run index from %s data file", path);
2574+
if (xlog_cursor_open(&cursor, path))
2575+
return -1;
2576+
2577+
int rc = 0;
2578+
uint32_t page_info_capacity = 0;
2579+
uint32_t run_row_count = 0;
2580+
2581+
const char *key = NULL;
2582+
int64_t max_lsn = 0;
2583+
int64_t min_lsn = INT64_MAX;
2584+
2585+
off_t page_offset, next_page_offset = xlog_cursor_pos(&cursor);
2586+
while ((rc = xlog_cursor_next_tx(&cursor)) == 0) {
2587+
page_offset = next_page_offset;
2588+
next_page_offset = xlog_cursor_pos(&cursor);
2589+
2590+
if (run->info.page_count == page_info_capacity &&
2591+
vy_run_alloc_page_info(run, &page_info_capacity) != 0)
2592+
goto close_err;
2593+
const char *page_min_key = NULL;
2594+
uint32_t page_row_count = 0;
2595+
uint64_t page_row_index_offset = 0;
2596+
uint64_t row_offset = xlog_cursor_tx_pos(&cursor);
2597+
2598+
struct xrow_header xrow;
2599+
while ((rc = xlog_cursor_next_row(&cursor, &xrow)) == 0) {
2600+
if (xrow.type == VY_RUN_ROW_INDEX) {
2601+
page_row_index_offset = row_offset;
2602+
row_offset = xlog_cursor_tx_pos(&cursor);
2603+
continue;
2604+
}
2605+
++page_row_count;
2606+
key = vy_stmt_extract_key(&xrow, cmp_def,
2607+
space_format, upsert_format,
2608+
iid == 0);
2609+
if (key == NULL)
2610+
goto close_err;
2611+
if (run->info.min_key == NULL) {
2612+
run->info.min_key = vy_key_dup(key);
2613+
if (run->info.min_key == NULL)
2614+
goto close_err;
2615+
}
2616+
if (page_min_key == NULL)
2617+
page_min_key = key;
2618+
if (xrow.lsn > max_lsn)
2619+
max_lsn = xrow.lsn;
2620+
if (xrow.lsn < min_lsn)
2621+
min_lsn = xrow.lsn;
2622+
row_offset = xlog_cursor_tx_pos(&cursor);
2623+
}
2624+
struct vy_page_info *info;
2625+
info = run->page_info + run->info.page_count;
2626+
if (vy_page_info_create(info, page_offset, page_min_key) != 0)
2627+
goto close_err;
2628+
info->row_count = page_row_count;
2629+
info->size = next_page_offset - page_offset;
2630+
info->unpacked_size = xlog_cursor_tx_pos(&cursor);
2631+
info->row_index_offset = page_row_index_offset;
2632+
++run->info.page_count;
2633+
run_row_count += page_row_count;
2634+
region_truncate(region, mem_used);
2635+
}
2636+
2637+
if (key != NULL) {
2638+
run->info.max_key = vy_key_dup(key);
2639+
if (run->info.max_key == NULL)
2640+
goto close_err;
2641+
}
2642+
run->info.max_lsn = max_lsn;
2643+
run->info.min_lsn = min_lsn;
2644+
if (xlog_cursor_reset(&cursor) != 0)
2645+
goto close_err;
2646+
if (bloom_create(&run->info.bloom, run_row_count,
2647+
opts->bloom_fpr, runtime.quota) != 0) {
2648+
diag_set(OutOfMemory, 0,
2649+
"bloom_create", "bloom");
2650+
goto close_err;
2651+
}
2652+
struct xrow_header xrow;
2653+
while ((rc = xlog_cursor_next(&cursor, &xrow, false)) == 0) {
2654+
if (xrow.type == VY_RUN_ROW_INDEX)
2655+
continue;
2656+
2657+
struct tuple *tuple = vy_stmt_decode(&xrow, cmp_def, space_format,
2658+
upsert_format, iid == 0);
2659+
if (tuple == NULL)
2660+
goto close_err;
2661+
bloom_add(&run->info.bloom, tuple_hash(tuple, key_def));
2662+
}
2663+
run->info.has_bloom = true;
2664+
2665+
region_truncate(region, mem_used);
2666+
run->fd = cursor.fd;
2667+
xlog_cursor_close(&cursor, true);
2668+
/* New run index is ready for write, unlink old file if exists */
2669+
vy_run_snprint_path(path, sizeof(path), dir,
2670+
space_id, iid, run->id, VY_FILE_INDEX);
2671+
if (unlink(path) < 0 && errno != ENOENT) {
2672+
diag_set(SystemError, "failed to unlink file '%s'",
2673+
path);
2674+
goto close_err;
2675+
}
2676+
if (vy_run_write_index(run, dir, space_id, iid) != 0)
2677+
goto close_err;
2678+
return 0;
2679+
close_err:
2680+
vy_run_clear(run);
2681+
region_truncate(region, mem_used);
2682+
xlog_cursor_close(&cursor, false);
2683+
return -1;
2684+
}
2685+
25362686
/**
25372687
* Read a page with stream->page_no from the run and save it in stream->page.
25382688
* Support function of slice stream.

src/box/vy_run.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,25 @@ int
350350
vy_run_recover(struct vy_run *run, const char *dir,
351351
uint32_t space_id, uint32_t iid);
352352

353+
/**
354+
* Rebuild vy_run index
355+
* @param run - run to laod
356+
* @param dir - path to the vinyl directory
357+
* @param space_id - space id
358+
* @param iid - index id
359+
* @param key_def index key definition
360+
* @param bloom_fpr bloom filter param
361+
* @return - 0 on sucess, -1 on fail
362+
*/
363+
int
364+
vy_run_rebuild_index(struct vy_run *run, const char *dir,
365+
uint32_t space_id, uint32_t iid,
366+
const struct key_def *key_def,
367+
const struct key_def *user_key_def,
368+
struct tuple_format *space_format,
369+
struct tuple_format *upsert_format,
370+
const struct index_opts *opts);
371+
353372
enum vy_file_type {
354373
VY_FILE_INDEX,
355374
VY_FILE_RUN,

0 commit comments

Comments
 (0)