diff --git a/src/box/alter.cc b/src/box/alter.cc index 15805b9bce1e4f8f611f61038b3a61b318d71358..b9d3c2d59762f9e9ffa425fefa523565b3199ab9 100644 --- a/src/box/alter.cc +++ b/src/box/alter.cc @@ -3041,7 +3041,7 @@ on_replace_dd_space_sequence(struct trigger * /* trigger */, void *event) txn_on_commit(txn, on_commit); if (stmt->new_tuple != NULL) { /* INSERT, UPDATE */ - struct index *pk = index_find(space, 0); + struct index *pk = index_find_xc(space, 0); index_def_check_sequence(pk->def, space_name(space)); if (seq->is_generated) { tnt_raise(ClientError, ER_ALTER_SPACE, diff --git a/src/box/vy_run.c b/src/box/vy_run.c index c12fb9c52b51fea461a1f5d3d737273afafde9d8..49caa3413ab1d19227e81bcdab2e3de673e10ce9 100644 --- a/src/box/vy_run.c +++ b/src/box/vy_run.c @@ -376,6 +376,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; @@ -429,6 +430,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); @@ -789,7 +792,10 @@ vy_page_read(struct vy_page *page, const struct vy_page_info *page_info, "Unexpected end of file"); goto error; } - ERROR_INJECT(ERRINJ_VY_READ_PAGE_TIMEOUT, {usleep(50000);}); + + struct errinj *inj = errinj(ERRINJ_VY_READ_PAGE_TIMEOUT, ERRINJ_DOUBLE); + if (inj != NULL && inj->dparam > 0) + usleep(inj->dparam * 1000000); /* decode xlog tx */ const char *data_pos = data; @@ -866,8 +872,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; } @@ -926,6 +934,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, @@ -934,6 +943,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 d31dd64512bd00cc50ce27653b87df2331cf2d28..85bb66a7bc623a46cbaa708e97ac6973802b5c06 100644 --- a/src/box/vy_run.h +++ b/src/box/vy_run.h @@ -127,15 +127,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 369b963f7887d215ac0232869789f3f4616c0338..912d9028c866a696da06df6b5749915808a0fa4f 100644 --- a/src/box/vy_scheduler.c +++ b/src/box/vy_scheduler.c @@ -1088,7 +1088,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/src/errinj.h b/src/errinj.h index 8be1a95eef9a7c4e09c2a8f430d1df3606f4141d..ab5988cdb1e8601d42d879741323c2cf326c8576 100644 --- a/src/errinj.h +++ b/src/errinj.h @@ -88,7 +88,7 @@ struct errinj { _(ERRINJ_VY_INDEX_DUMP, ERRINJ_INT, {.iparam = -1}) \ _(ERRINJ_VY_TASK_COMPLETE, ERRINJ_BOOL, {.bparam = false}) \ _(ERRINJ_VY_READ_PAGE, ERRINJ_BOOL, {.bparam = false}) \ - _(ERRINJ_VY_READ_PAGE_TIMEOUT, ERRINJ_BOOL, {.bparam = false}) \ + _(ERRINJ_VY_READ_PAGE_TIMEOUT, ERRINJ_DOUBLE, {.dparam = 0}) \ _(ERRINJ_VY_SQUASH_TIMEOUT, ERRINJ_DOUBLE, {.dparam = 0}) \ _(ERRINJ_VY_SCHED_TIMEOUT, ERRINJ_DOUBLE, {.dparam = 0}) \ _(ERRINJ_VY_GC, ERRINJ_BOOL, {.bparam = false}) \ diff --git a/test/box/errinj.result b/test/box/errinj.result index 0b1693d2e844e0d05685985a75b023fe35ded69d..92ae72357960ebfed9eaca9542624776cb890b0a 100644 --- a/test/box/errinj.result +++ b/test/box/errinj.result @@ -49,7 +49,7 @@ errinj.info() ERRINJ_RELAY_REPORT_INTERVAL: state: 0 ERRINJ_VY_READ_PAGE_TIMEOUT: - state: false + state: 0 ERRINJ_XLOG_META: state: false ERRINJ_WAL_WRITE_DISK: diff --git a/test/box/sequence.result b/test/box/sequence.result index a509207f78694526243ed23781ac5dcf7cdbf5ad..f0164b6f21867d52ef023883577480c3b4026c6b 100644 --- a/test/box/sequence.result +++ b/test/box/sequence.result @@ -711,6 +711,10 @@ sk:drop() pk:drop() --- ... +box.space._space_sequence:insert{s.id, sq.id, false} -- error +--- +- error: 'No index #0 is defined in space ''test''' +... s:create_index('pk', {sequence = {}}) -- error --- - error: 'Illegal parameters, options parameter ''sequence'' should be one of types: diff --git a/test/box/sequence.test.lua b/test/box/sequence.test.lua index 26147bb74e9805445aa0850c698da70bf828109d..af3432f9c2efce84f3be54f4c564e0e78d08c4a2 100644 --- a/test/box/sequence.test.lua +++ b/test/box/sequence.test.lua @@ -230,6 +230,7 @@ sk:alter{sequence = 'test'} -- error box.space._space_sequence:insert{s.id, sq.id, false} -- error sk:drop() pk:drop() +box.space._space_sequence:insert{s.id, sq.id, false} -- error s:create_index('pk', {sequence = {}}) -- error s:create_index('pk', {sequence = 'abc'}) -- error diff --git a/test/vinyl/errinj.result b/test/vinyl/errinj.result index db0f1d0d9bb1f1c799f56d4f606f68c15a49edff..91351086658e953b03bf5c718dfe7d4db718d234 100644 --- a/test/vinyl/errinj.result +++ b/test/vinyl/errinj.result @@ -217,7 +217,7 @@ s:select() - [9, 'test str9'] - [10, 'test str10'] ... -errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", true) +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0.05) --- - ok ... @@ -234,7 +234,7 @@ fiber.cancel(f1) fiber.sleep(0.1) --- ... -errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", false); +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0); --- - ok ... @@ -256,7 +256,7 @@ errinj.set("ERRINJ_VY_READ_PAGE", true) --- - ok ... -errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", true) +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0.05) --- - ok ... @@ -269,7 +269,7 @@ fiber.cancel(f1) fiber.sleep(0.1) --- ... -errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", false); +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0); --- - ok ... @@ -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} --- ... @@ -316,7 +334,7 @@ too_long_threshold = box.cfg.too_long_threshold box.cfg{too_long_threshold = 0.01} --- ... -errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", true) +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0.05) --- - ok ... @@ -328,7 +346,7 @@ s:get(10) ~= nil --- - true ... -errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", false); +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0); --- - ok ... diff --git a/test/vinyl/errinj.test.lua b/test/vinyl/errinj.test.lua index 592716730cd3bf1d6b0e5afee4c93cb8c51ab552..9724a69b82b28f61b42d5de95e45ee0ec3ef4627 100644 --- a/test/vinyl/errinj.test.lua +++ b/test/vinyl/errinj.test.lua @@ -82,26 +82,33 @@ s:select() errinj.set("ERRINJ_VY_READ_PAGE", false) s:select() -errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", true) +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0.05) function test_cancel_read () k = s:select() return #k end f1 = fiber.create(test_cancel_read) fiber.cancel(f1) -- task should be done fiber.sleep(0.1) -errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", false); +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0); s:select() -- error after timeout for canceled fiber errinj.set("ERRINJ_VY_READ_PAGE", true) -errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", true) +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0.05) f1 = fiber.create(test_cancel_read) fiber.cancel(f1) fiber.sleep(0.1) -errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", false); +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 @@ -111,10 +118,10 @@ for i = 1, 10 do s:insert{i, i * 2} end box.snapshot() too_long_threshold = box.cfg.too_long_threshold box.cfg{too_long_threshold = 0.01} -errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", true) +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0.05) s:get(10) ~= nil #s:select(5, {iterator = 'LE'}) == 5 -errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", false); +errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0); test_run:cmd("push filter 'lsn=[0-9]+' to 'lsn=<lsn>'") test_run:grep_log('default', 'get.* took too long') test_run:grep_log('default', 'select.* took too long')