diff --git a/src/box/vy_run.c b/src/box/vy_run.c index 08d0761bf1b8b6923a86bf938778a46351264d9f..a41e9a057ea6298147c9b430caa101382e63fbb8 100644 --- a/src/box/vy_run.c +++ b/src/box/vy_run.c @@ -371,6 +371,7 @@ vy_slice_new(int64_t id, struct vy_run *run, slice->id = id; slice->run = run; vy_run_ref(run); + run->slice_count++; if (begin != NULL) tuple_ref(begin); slice->begin = begin; @@ -424,6 +425,8 @@ void vy_slice_delete(struct vy_slice *slice) { assert(slice->pin_count == 0); + assert(slice->run->slice_count > 0); + slice->run->slice_count--; vy_run_unref(slice->run); if (slice->begin != NULL) tuple_unref(slice->begin); @@ -910,8 +913,10 @@ static int vy_page_read_cb_free(struct cbus_call_msg *base) { struct vy_page_read_task *task = (struct vy_page_read_task *)base; + struct vy_run_env *env = task->run->env; vy_page_delete(task->page); - mempool_free(&task->run->env->read_task_pool, task); + vy_run_unref(task->run); + mempool_free(&env->read_task_pool, task); return 0; } @@ -970,6 +975,7 @@ vy_run_iterator_load_page(struct vy_run_iterator *itr, uint32_t page_no, task->run = slice->run; task->page_info = *page_info; task->page = page; + vy_run_ref(task->run); /* Post task to the reader thread. */ rc = cbus_call(&reader->reader_pipe, &reader->tx_pipe, @@ -978,6 +984,7 @@ vy_run_iterator_load_page(struct vy_run_iterator *itr, uint32_t page_no, if (!task->base.complete) return -1; /* timed out or cancelled */ + vy_run_unref(task->run); mempool_free(&env->read_task_pool, task); if (rc != 0) { diff --git a/src/box/vy_run.h b/src/box/vy_run.h index 6973ee2d30f0cd1fd45e3790676204a36ff4a5e2..b3e3d1c6ff4d112f2a1d28005b4df690c3ed575c 100644 --- a/src/box/vy_run.h +++ b/src/box/vy_run.h @@ -130,15 +130,18 @@ struct vy_run { /** * Run reference counter, the run is deleted once it hits 0. * A new run is created with the reference counter set to 1. - * A run is referenced by each slice created for it. + * A run is referenced by each slice created for it and each + * pending read or write task. */ int refs; + /** Number of slices created for this run. */ + int slice_count; /** * Counter used on completion of a compaction task to check if * all slices of the run have been compacted and so the run is * not used any more and should be deleted. */ - int64_t compacted_slice_count; + int compacted_slice_count; /** * Link in the list of runs that became unused * after compaction. diff --git a/src/box/vy_scheduler.c b/src/box/vy_scheduler.c index b6225ace6ad207bbfb12012c6c15ac926f69a360..4954afe75d4898b9cbb654050fabe1f1badc8bac 100644 --- a/src/box/vy_scheduler.c +++ b/src/box/vy_scheduler.c @@ -1102,7 +1102,7 @@ vy_task_compact_complete(struct vy_scheduler *scheduler, struct vy_task *task) } for (slice = first_slice; ; slice = rlist_next_entry(slice, in_range)) { run = slice->run; - if (run->compacted_slice_count == run->refs) + if (run->compacted_slice_count == run->slice_count) rlist_add_entry(&unused_runs, run, in_unused); slice->run->compacted_slice_count = 0; if (slice == last_slice) diff --git a/test/vinyl/errinj.result b/test/vinyl/errinj.result index e7c9bc71ce9e0b7afa7f311701b53301bf08d3bf..91351086658e953b03bf5c718dfe7d4db718d234 100644 --- a/test/vinyl/errinj.result +++ b/test/vinyl/errinj.result @@ -290,9 +290,27 @@ s:select() - [9, 'test str9'] - [10, 'test str10'] ... +-- index is dropped while a read task is in progress +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0.05) +--- +- ok +... +f1 = fiber.create(test_cancel_read) +--- +... +fiber.cancel(f1) +--- +... s:drop() --- ... +fiber.sleep(0.1) +--- +... +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0); +--- +- ok +... box.cfg{vinyl_cache = vinyl_cache} --- ... diff --git a/test/vinyl/errinj.test.lua b/test/vinyl/errinj.test.lua index 7655a57cc4154894237bd5208bb1da5592bb227c..9724a69b82b28f61b42d5de95e45ee0ec3ef4627 100644 --- a/test/vinyl/errinj.test.lua +++ b/test/vinyl/errinj.test.lua @@ -101,7 +101,14 @@ errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0); errinj.set("ERRINJ_VY_READ_PAGE", false); s:select() +-- index is dropped while a read task is in progress +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0.05) +f1 = fiber.create(test_cancel_read) +fiber.cancel(f1) s:drop() +fiber.sleep(0.1) +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0); + box.cfg{vinyl_cache = vinyl_cache} -- gh-2871: check that long reads are logged