From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-lj1-f172.google.com (mail-lj1-f172.google.com [209.85.208.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 1261646970E for ; Tue, 4 Feb 2020 17:32:25 +0300 (MSK) Received: by mail-lj1-f172.google.com with SMTP id n18so18813718ljo.7 for ; Tue, 04 Feb 2020 06:32:25 -0800 (PST) From: Cyrill Gorcunov Date: Tue, 4 Feb 2020 17:31:46 +0300 Message-Id: <20200204143147.20791-4-gorcunov@gmail.com> In-Reply-To: <20200204143147.20791-1-gorcunov@gmail.com> References: <20200204143147.20791-1-gorcunov@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [PATCH v3 3/4] errinj: add ERRINJ_FIBER_MADVISE and ERRINJ_FIBER_MPROTECT List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: tml We will need them to test fiber's stack memory manipulations. Co-developed-by: Alexander Turenko Signed-off-by: Cyrill Gorcunov --- src/lib/core/errinj.h | 2 + src/lib/core/fiber.c | 20 +- test/box/errinj.result | 2616 +++++++++++++++++++++------------------- 3 files changed, 1380 insertions(+), 1258 deletions(-) diff --git a/src/lib/core/errinj.h b/src/lib/core/errinj.h index 672da2119..ed0cba903 100644 --- a/src/lib/core/errinj.h +++ b/src/lib/core/errinj.h @@ -135,6 +135,8 @@ struct errinj { _(ERRINJ_COIO_SENDFILE_CHUNK, ERRINJ_INT, {.iparam = -1}) \ _(ERRINJ_SWIM_FD_ONLY, ERRINJ_BOOL, {.bparam = false}) \ _(ERRINJ_DYN_MODULE_COUNT, ERRINJ_INT, {.iparam = 0}) \ + _(ERRINJ_FIBER_MADVISE, ERRINJ_BOOL, {.bparam = false}) \ + _(ERRINJ_FIBER_MPROTECT, ERRINJ_INT, {.iparam = -1}) ENUM0(errinj_id, ERRINJ_LIST); extern struct errinj errinjs[]; diff --git a/src/lib/core/fiber.c b/src/lib/core/fiber.c index d6ff481a5..36f1b1209 100644 --- a/src/lib/core/fiber.c +++ b/src/lib/core/fiber.c @@ -41,6 +41,7 @@ #include "assoc.h" #include "memory.h" #include "trigger.h" +#include "errinj.h" #if ENABLE_FIBER_TOP #include /* __rdtscp() */ @@ -176,7 +177,14 @@ static int (*fiber_invoke)(fiber_func f, va_list ap); static inline int fiber_madvise(void *addr, size_t len, int advice) { - if (madvise(addr, len, advice) != 0) { + int rc = 0; + + ERROR_INJECT(ERRINJ_FIBER_MADVISE, { + errno = ENOMEM; + rc = -1; + }); + + if (rc != 0 || madvise(addr, len, advice) != 0) { diag_set(SystemError, "fiber madvise %p:%zu:%d failed", addr, len, advice); return -1; @@ -187,7 +195,15 @@ fiber_madvise(void *addr, size_t len, int advice) static inline int fiber_mprotect(void *addr, size_t len, int prot) { - if (mprotect(addr, len, prot) != 0) { + int rc = 0; + + struct errinj *inj = errinj(ERRINJ_FIBER_MPROTECT, ERRINJ_INT); + if (inj != NULL && inj->iparam == prot) { + errno = ENOMEM; + rc = -1; + } + + if (rc != 0 || mprotect(addr, len, prot) != 0) { diag_set(SystemError, "fiber mprotect %p:%zu:%d failed", addr, len, prot); return -1; diff --git a/test/box/errinj.result b/test/box/errinj.result index babe36b1b..c58e1d2e8 100644 --- a/test/box/errinj.result +++ b/test/box/errinj.result @@ -1,1783 +1,1887 @@ +-- test-run result file version 2 -- Test that recovery had been completed without errors test_run = require('test_run').new() ---- -... + | --- + | ... test_run:cmd("restart server default") + | box.error.last() == nil ---- -- true -... + | --- + | - true + | ... + errinj = box.error.injection ---- -... + | --- + | ... net_box = require('net.box') ---- -... + | --- + | ... + space = box.schema.space.create('tweedledum') ---- -... + | --- + | ... index = space:create_index('primary', { type = 'hash' }) ---- -... + | --- + | ... + errinj.info() ---- -- ERRINJ_VY_RUN_WRITE_STMT_TIMEOUT: - state: 0 - ERRINJ_WAL_WRITE: - state: false - ERRINJ_RELAY_BREAK_LSN: - state: -1 - ERRINJ_HTTPC_EXECUTE: - state: false - ERRINJ_VYRUN_DATA_READ: - state: false - ERRINJ_SWIM_FD_ONLY: - state: false - ERRINJ_SQL_NAME_NORMALIZATION: - state: false - ERRINJ_VY_SCHED_TIMEOUT: - state: 0 - ERRINJ_COIO_SENDFILE_CHUNK: - state: -1 - ERRINJ_HTTP_RESPONSE_ADD_WAIT: - state: false - ERRINJ_WAL_WRITE_PARTIAL: - state: -1 - ERRINJ_VY_GC: - state: false - ERRINJ_WAL_DELAY: - state: false - ERRINJ_INDEX_ALLOC: - state: false - ERRINJ_WAL_WRITE_EOF: - state: false - ERRINJ_WAL_SYNC: - state: false - ERRINJ_BUILD_INDEX: - state: -1 - ERRINJ_BUILD_INDEX_DELAY: - state: false - ERRINJ_VY_RUN_FILE_RENAME: - state: false - ERRINJ_VY_COMPACTION_DELAY: - state: false - ERRINJ_VY_DUMP_DELAY: - state: false - ERRINJ_VY_DELAY_PK_LOOKUP: - state: false - ERRINJ_VY_TASK_COMPLETE: - state: false - ERRINJ_PORT_DUMP: - state: false - ERRINJ_WAL_BREAK_LSN: - state: -1 - ERRINJ_WAL_IO: - state: false - ERRINJ_WAL_FALLOCATE: - state: 0 - ERRINJ_DYN_MODULE_COUNT: - state: 0 - ERRINJ_VY_INDEX_FILE_RENAME: - state: false - ERRINJ_TUPLE_FORMAT_COUNT: - state: -1 - ERRINJ_TUPLE_ALLOC: - state: false - ERRINJ_VY_RUN_WRITE_DELAY: - state: false - ERRINJ_VY_READ_PAGE: - state: false - ERRINJ_RELAY_REPORT_INTERVAL: - state: 0 - ERRINJ_VY_LOG_FILE_RENAME: - state: false - ERRINJ_VY_READ_PAGE_TIMEOUT: - state: 0 - ERRINJ_XLOG_META: - state: false - ERRINJ_SIO_READ_MAX: - state: -1 - ERRINJ_SNAP_COMMIT_DELAY: - state: false - ERRINJ_WAL_WRITE_DISK: - state: false - ERRINJ_SNAP_WRITE_DELAY: - state: false - ERRINJ_LOG_ROTATE: - state: false - ERRINJ_VY_RUN_WRITE: - state: false - ERRINJ_CHECK_FORMAT_DELAY: - state: false - ERRINJ_VY_LOG_FLUSH_DELAY: - state: false - ERRINJ_RELAY_FINAL_JOIN: - state: false - ERRINJ_REPLICA_JOIN_DELAY: - state: false - ERRINJ_RELAY_FINAL_SLEEP: - state: false - ERRINJ_VY_RUN_DISCARD: - state: false - ERRINJ_WAL_ROTATE: - state: false - ERRINJ_RELAY_EXIT_DELAY: - state: 0 - ERRINJ_VY_POINT_ITER_WAIT: - state: false - ERRINJ_MEMTX_DELAY_GC: - state: false - ERRINJ_IPROTO_TX_DELAY: - state: false - ERRINJ_XLOG_READ: - state: -1 - ERRINJ_TUPLE_FIELD: - state: false - ERRINJ_XLOG_GARBAGE: - state: false - ERRINJ_VY_INDEX_DUMP: - state: -1 - ERRINJ_VY_READ_PAGE_DELAY: - state: false - ERRINJ_TESTING: - state: false - ERRINJ_RELAY_SEND_DELAY: - state: false - ERRINJ_VY_SQUASH_TIMEOUT: - state: 0 - ERRINJ_VY_LOG_FLUSH: - state: false - ERRINJ_RELAY_TIMEOUT: - state: 0 -... + | --- + | - ERRINJ_VY_RUN_WRITE_STMT_TIMEOUT: + | state: 0 + | ERRINJ_WAL_BREAK_LSN: + | state: -1 + | ERRINJ_VYRUN_DATA_READ: + | state: false + | ERRINJ_VY_SCHED_TIMEOUT: + | state: 0 + | ERRINJ_HTTP_RESPONSE_ADD_WAIT: + | state: false + | ERRINJ_WAL_WRITE_EOF: + | state: false + | ERRINJ_BUILD_INDEX_DELAY: + | state: false + | ERRINJ_VY_DELAY_PK_LOOKUP: + | state: false + | ERRINJ_VY_POINT_ITER_WAIT: + | state: false + | ERRINJ_WAL_IO: + | state: false + | ERRINJ_VY_INDEX_FILE_RENAME: + | state: false + | ERRINJ_TUPLE_FORMAT_COUNT: + | state: -1 + | ERRINJ_TUPLE_ALLOC: + | state: false + | ERRINJ_VY_RUN_FILE_RENAME: + | state: false + | ERRINJ_VY_READ_PAGE: + | state: false + | ERRINJ_RELAY_REPORT_INTERVAL: + | state: 0 + | ERRINJ_RELAY_BREAK_LSN: + | state: -1 + | ERRINJ_XLOG_META: + | state: false + | ERRINJ_SNAP_COMMIT_DELAY: + | state: false + | ERRINJ_VY_RUN_WRITE: + | state: false + | ERRINJ_BUILD_INDEX: + | state: -1 + | ERRINJ_RELAY_FINAL_JOIN: + | state: false + | ERRINJ_REPLICA_JOIN_DELAY: + | state: false + | ERRINJ_LOG_ROTATE: + | state: false + | ERRINJ_MEMTX_DELAY_GC: + | state: false + | ERRINJ_XLOG_GARBAGE: + | state: false + | ERRINJ_VY_READ_PAGE_DELAY: + | state: false + | ERRINJ_SWIM_FD_ONLY: + | state: false + | ERRINJ_WAL_WRITE: + | state: false + | ERRINJ_HTTPC_EXECUTE: + | state: false + | ERRINJ_SQL_NAME_NORMALIZATION: + | state: false + | ERRINJ_WAL_WRITE_PARTIAL: + | state: -1 + | ERRINJ_VY_GC: + | state: false + | ERRINJ_WAL_DELAY: + | state: false + | ERRINJ_XLOG_READ: + | state: -1 + | ERRINJ_WAL_SYNC: + | state: false + | ERRINJ_VY_TASK_COMPLETE: + | state: false + | ERRINJ_PORT_DUMP: + | state: false + | ERRINJ_COIO_SENDFILE_CHUNK: + | state: -1 + | ERRINJ_DYN_MODULE_COUNT: + | state: 0 + | ERRINJ_SIO_READ_MAX: + | state: -1 + | ERRINJ_FIBER_MPROTECT: + | state: -1 + | ERRINJ_FIBER_MADVISE: + | state: false + | ERRINJ_RELAY_TIMEOUT: + | state: 0 + | ERRINJ_VY_DUMP_DELAY: + | state: false + | ERRINJ_VY_SQUASH_TIMEOUT: + | state: 0 + | ERRINJ_VY_LOG_FLUSH_DELAY: + | state: false + | ERRINJ_RELAY_SEND_DELAY: + | state: false + | ERRINJ_VY_COMPACTION_DELAY: + | state: false + | ERRINJ_VY_LOG_FILE_RENAME: + | state: false + | ERRINJ_VY_RUN_DISCARD: + | state: false + | ERRINJ_WAL_ROTATE: + | state: false + | ERRINJ_VY_READ_PAGE_TIMEOUT: + | state: 0 + | ERRINJ_VY_INDEX_DUMP: + | state: -1 + | ERRINJ_TUPLE_FIELD: + | state: false + | ERRINJ_SNAP_WRITE_DELAY: + | state: false + | ERRINJ_IPROTO_TX_DELAY: + | state: false + | ERRINJ_RELAY_EXIT_DELAY: + | state: 0 + | ERRINJ_RELAY_FINAL_SLEEP: + | state: false + | ERRINJ_WAL_WRITE_DISK: + | state: false + | ERRINJ_CHECK_FORMAT_DELAY: + | state: false + | ERRINJ_TESTING: + | state: false + | ERRINJ_VY_RUN_WRITE_DELAY: + | state: false + | ERRINJ_WAL_FALLOCATE: + | state: 0 + | ERRINJ_VY_LOG_FLUSH: + | state: false + | ERRINJ_INDEX_ALLOC: + | state: false + | ... errinj.set("some-injection", true) ---- -- 'error: can''t find error injection ''some-injection''' -... + | --- + | - 'error: can''t find error injection ''some-injection''' + | ... errinj.set("some-injection") -- check error ---- -- 'error: can''t find error injection ''some-injection''' -... + | --- + | - 'error: can''t find error injection ''some-injection''' + | ... space:select{222444} ---- -- [] -... + | --- + | - [] + | ... errinj.set("ERRINJ_TESTING", true) ---- -- ok -... + | --- + | - ok + | ... space:select{222444} ---- -- error: Error injection 'ERRINJ_TESTING' -... + | --- + | - error: Error injection 'ERRINJ_TESTING' + | ... errinj.set("ERRINJ_TESTING", false) ---- -- ok -... + | --- + | - ok + | ... + -- Check how well we handle a failed log write errinj.set("ERRINJ_WAL_IO", true) ---- -- ok -... + | --- + | - ok + | ... space:insert{1} ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... space:get{1} ---- -... + | --- + | ... errinj.set("ERRINJ_WAL_IO", false) ---- -- ok -... + | --- + | - ok + | ... space:insert{1} ---- -- [1] -... + | --- + | - [1] + | ... errinj.set("ERRINJ_WAL_IO", true) ---- -- ok -... + | --- + | - ok + | ... space:update(1, {{'=', 2, 2}}) ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... space:get{1} ---- -- [1] -... + | --- + | - [1] + | ... space:get{2} ---- -... + | --- + | ... errinj.set("ERRINJ_WAL_IO", false) ---- -- ok -... + | --- + | - ok + | ... space:update(1, {{'=', 2, 2}}) ---- -- [1, 2] -... + | --- + | - [1, 2] + | ... space:truncate() ---- -... + | --- + | ... + -- Check that WAL vclock isn't promoted on failed write. lsn1 = box.info.vclock[box.info.id] ---- -... + | --- + | ... errinj.set("ERRINJ_WAL_WRITE_PARTIAL", 0) ---- -- ok -... + | --- + | - ok + | ... space:insert{1} ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... errinj.set("ERRINJ_WAL_WRITE_PARTIAL", -1) ---- -- ok -... + | --- + | - ok + | ... space:insert{1} ---- -- [1] -... + | --- + | - [1] + | ... -- Check vclock was promoted only one time box.info.vclock[box.info.id] == lsn1 + 1 ---- -- true -... + | --- + | - true + | ... errinj.set("ERRINJ_WAL_WRITE_PARTIAL", 0) ---- -- ok -... + | --- + | - ok + | ... space:update(1, {{'=', 2, 2}}) ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... space:get{1} ---- -- [1] -... + | --- + | - [1] + | ... errinj.set("ERRINJ_WAL_WRITE_PARTIAL", -1) ---- -- ok -... + | --- + | - ok + | ... space:update(1, {{'=', 2, 2}}) ---- -- [1, 2] -... + | --- + | - [1, 2] + | ... -- Check vclock was promoted only two times box.info.vclock[box.info.id] == lsn1 + 2 ---- -- true -... + | --- + | - true + | ... space:truncate() ---- -... + | --- + | ... + -- Check a failed log rotation errinj.set("ERRINJ_WAL_ROTATE", true) ---- -- ok -... + | --- + | - ok + | ... space:insert{1} ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... space:get{1} ---- -... + | --- + | ... errinj.set("ERRINJ_WAL_ROTATE", false) ---- -- ok -... + | --- + | - ok + | ... space:insert{1} ---- -- [1] -... + | --- + | - [1] + | ... errinj.set("ERRINJ_WAL_ROTATE", true) ---- -- ok -... + | --- + | - ok + | ... space:update(1, {{'=', 2, 2}}) ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... space:get{1} ---- -- [1] -... + | --- + | - [1] + | ... space:get{2} ---- -... + | --- + | ... errinj.set("ERRINJ_WAL_ROTATE", false) ---- -- ok -... + | --- + | - ok + | ... space:update(1, {{'=', 2, 2}}) ---- -- [1, 2] -... + | --- + | - [1, 2] + | ... space:get{1} ---- -- [1, 2] -... + | --- + | - [1, 2] + | ... space:get{2} ---- -... + | --- + | ... space:truncate() ---- -... + | --- + | ... + space:drop() ---- -... + | --- + | ... + -- Check how well we handle a failed log write in DDL s_disabled = box.schema.space.create('disabled') ---- -... + | --- + | ... s_withindex = box.schema.space.create('withindex') ---- -... + | --- + | ... index1 = s_withindex:create_index('primary', { type = 'hash' }) ---- -... + | --- + | ... s_withdata = box.schema.space.create('withdata') ---- -... + | --- + | ... index2 = s_withdata:create_index('primary', { type = 'tree' }) ---- -... + | --- + | ... s_withdata:insert{1, 2, 3, 4, 5} ---- -- [1, 2, 3, 4, 5] -... + | --- + | - [1, 2, 3, 4, 5] + | ... s_withdata:insert{4, 5, 6, 7, 8} ---- -- [4, 5, 6, 7, 8] -... + | --- + | - [4, 5, 6, 7, 8] + | ... index3 = s_withdata:create_index('secondary', { type = 'hash', parts = {2, 'unsigned', 3, 'unsigned' }}) ---- -... + | --- + | ... errinj.set("ERRINJ_WAL_IO", true) ---- -- ok -... + | --- + | - ok + | ... test = box.schema.space.create('test') ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... s_disabled:create_index('primary', { type = 'hash' }) ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... s_disabled.enabled ---- -- false -... + | --- + | - false + | ... s_disabled:insert{0} ---- -- error: 'No index #0 is defined in space ''disabled''' -... + | --- + | - error: 'No index #0 is defined in space ''disabled''' + | ... s_withindex:create_index('secondary', { type = 'tree', parts = { 2, 'unsigned'} }) ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... s_withindex.index.secondary ---- -- null -... + | --- + | - null + | ... s_withdata.index.secondary:drop() ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... s_withdata.index.secondary.unique ---- -- true -... + | --- + | - true + | ... s_withdata:drop() ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... box.space['withdata'].enabled ---- -- true -... + | --- + | - true + | ... index4 = s_withdata:create_index('another', { type = 'tree', parts = { 5, 'unsigned' }, unique = false}) ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... s_withdata.index.another ---- -- null -... + | --- + | - null + | ... errinj.set("ERRINJ_WAL_IO", false) ---- -- ok -... + | --- + | - ok + | ... test = box.schema.space.create('test') ---- -... + | --- + | ... index5 = s_disabled:create_index('primary', { type = 'hash' }) ---- -... + | --- + | ... s_disabled.enabled ---- -- true -... + | --- + | - true + | ... s_disabled:insert{0} ---- -- [0] -... + | --- + | - [0] + | ... index6 = s_withindex:create_index('secondary', { type = 'tree', parts = { 2, 'unsigned'} }) ---- -... + | --- + | ... s_withindex.index.secondary.unique ---- -- true -... + | --- + | - true + | ... s_withdata.index.secondary:drop() ---- -... + | --- + | ... s_withdata.index.secondary ---- -- null -... + | --- + | - null + | ... s_withdata:drop() ---- -... + | --- + | ... box.space['withdata'] ---- -- null -... + | --- + | - null + | ... index7 = s_withdata:create_index('another', { type = 'tree', parts = { 5, 'unsigned' }, unique = false}) ---- -- error: Space 'withdata' does not exist -... + | --- + | - error: Space 'withdata' does not exist + | ... s_withdata.index.another ---- -- null -... + | --- + | - null + | ... test:drop() ---- -... + | --- + | ... s_disabled:drop() ---- -... + | --- + | ... s_withindex:drop() ---- -... + | --- + | ... + -- Check transaction rollback when out of memory env = require('test_run') ---- -... + | --- + | ... test_run = env.new() ---- -... + | --- + | ... + s = box.schema.space.create('s') ---- -... + | --- + | ... _ = s:create_index('pk') ---- -... + | --- + | ... errinj.set("ERRINJ_TUPLE_ALLOC", true) ---- -- ok -... + | --- + | - ok + | ... s:auto_increment{} ---- -- error: Failed to allocate 16 bytes in slab allocator for memtx_tuple -... + | --- + | - error: Failed to allocate 16 bytes in slab allocator for memtx_tuple + | ... s:select{} ---- -- [] -... + | --- + | - [] + | ... s:auto_increment{} ---- -- error: Failed to allocate 16 bytes in slab allocator for memtx_tuple -... + | --- + | - error: Failed to allocate 16 bytes in slab allocator for memtx_tuple + | ... s:select{} ---- -- [] -... + | --- + | - [] + | ... s:auto_increment{} ---- -- error: Failed to allocate 16 bytes in slab allocator for memtx_tuple -... + | --- + | - error: Failed to allocate 16 bytes in slab allocator for memtx_tuple + | ... s:select{} ---- -- [] -... + | --- + | - [] + | ... test_run:cmd("setopt delimiter ';'") ---- -- true -... + | --- + | - true + | ... box.begin() s:insert{1} box.commit(); ---- -- error: Failed to allocate 16 bytes in slab allocator for memtx_tuple -... + | --- + | - error: Failed to allocate 16 bytes in slab allocator for memtx_tuple + | ... box.rollback(); ---- -... + | --- + | ... s:select{}; ---- -- [] -... + | --- + | - [] + | ... box.begin() s:insert{1} s:insert{2} box.commit(); ---- -- error: Failed to allocate 16 bytes in slab allocator for memtx_tuple -... + | --- + | - error: Failed to allocate 16 bytes in slab allocator for memtx_tuple + | ... s:select{}; ---- -- [] -... + | --- + | - [] + | ... box.rollback(); ---- -... + | --- + | ... box.begin() pcall(s.insert, s, {1}) s:insert{2} box.commit(); ---- -- error: Failed to allocate 16 bytes in slab allocator for memtx_tuple -... + | --- + | - error: Failed to allocate 16 bytes in slab allocator for memtx_tuple + | ... s:select{}; ---- -- [] -... + | --- + | - [] + | ... box.rollback(); ---- -... + | --- + | ... errinj.set("ERRINJ_TUPLE_ALLOC", false); ---- -- ok -... + | --- + | - ok + | ... box.begin() s:insert{1} errinj.set("ERRINJ_TUPLE_ALLOC", true) s:insert{2} box.commit(); ---- -- error: Failed to allocate 16 bytes in slab allocator for memtx_tuple -... + | --- + | - error: Failed to allocate 16 bytes in slab allocator for memtx_tuple + | ... errinj.set("ERRINJ_TUPLE_ALLOC", false); ---- -- ok -... + | --- + | - ok + | ... box.rollback(); ---- -... + | --- + | ... s:select{}; ---- -- [] -... + | --- + | - [] + | ... box.begin() s:insert{1} errinj.set("ERRINJ_TUPLE_ALLOC", true) pcall(s.insert, s, {2}) box.commit(); ---- -... + | --- + | ... s:select{}; ---- -- - [1] -... + | --- + | - - [1] + | ... box.rollback(); ---- -... + | --- + | ... + test_run:cmd("setopt delimiter ''"); ---- -- true -... + | --- + | - true + | ... errinj.set("ERRINJ_TUPLE_ALLOC", false) ---- -- ok -... + | --- + | - ok + | ... + s:drop() ---- -... + | --- + | ... s = box.schema.space.create('test') ---- -... + | --- + | ... _ = s:create_index('test', {parts = {1, 'unsigned', 3, 'unsigned', 5, 'unsigned'}}) ---- -... + | --- + | ... s:insert{1, 2, 3, 4, 5, 6} ---- -- [1, 2, 3, 4, 5, 6] -... + | --- + | - [1, 2, 3, 4, 5, 6] + | ... t = s:select{}[1] ---- -... + | --- + | ... errinj.set("ERRINJ_TUPLE_FIELD", true) ---- -- ok -... + | --- + | - ok + | ... tostring(t[1]) .. tostring(t[2]) ..tostring(t[3]) .. tostring(t[4]) .. tostring(t[5]) .. tostring(t[6]) ---- -- 1nil3nil5nil -... + | --- + | - 1nil3nil5nil + | ... errinj.set("ERRINJ_TUPLE_FIELD", false) ---- -- ok -... + | --- + | - ok + | ... tostring(t[1]) .. tostring(t[2]) ..tostring(t[3]) .. tostring(t[4]) .. tostring(t[5]) .. tostring(t[6]) ---- -- '123456' -... + | --- + | - '123456' + | ... + s:drop() ---- -... + | --- + | ... s = box.schema.space.create('test') ---- -... + | --- + | ... _ = s:create_index('test', {parts = {2, 'unsigned', 4, 'unsigned', 6, 'unsigned'}}) ---- -... + | --- + | ... s:insert{1, 2, 3, 4, 5, 6} ---- -- [1, 2, 3, 4, 5, 6] -... + | --- + | - [1, 2, 3, 4, 5, 6] + | ... t = s:select{}[1] ---- -... + | --- + | ... errinj.set("ERRINJ_TUPLE_FIELD", true) ---- -- ok -... + | --- + | - ok + | ... tostring(t[1]) .. tostring(t[2]) ..tostring(t[3]) .. tostring(t[4]) .. tostring(t[5]) .. tostring(t[6]) ---- -- 12nil4nil6 -... + | --- + | - 12nil4nil6 + | ... errinj.set("ERRINJ_TUPLE_FIELD", false) ---- -- ok -... + | --- + | - ok + | ... tostring(t[1]) .. tostring(t[2]) ..tostring(t[3]) .. tostring(t[4]) .. tostring(t[5]) .. tostring(t[6]) ---- -- '123456' -... + | --- + | - '123456' + | ... + -- Cleanup s:drop() ---- -... + | --- + | ... + -- -- gh-2046: don't store offsets for sequential multi-parts keys -- s = box.schema.space.create('test') ---- -... + | --- + | ... _ = s:create_index('seq2', { parts = { 1, 'unsigned', 2, 'unsigned' }}) ---- -... + | --- + | ... _ = s:create_index('seq3', { parts = { 1, 'unsigned', 2, 'unsigned', 3, 'unsigned' }}) ---- -... + | --- + | ... _ = s:create_index('seq5', { parts = { 1, 'unsigned', 2, 'unsigned', 3, 'unsigned', 4, 'scalar', 5, 'number' }}) ---- -... + | --- + | ... _ = s:create_index('rnd1', { parts = { 3, 'unsigned' }}) ---- -... + | --- + | ... + errinj.set("ERRINJ_TUPLE_FIELD", true) ---- -- ok -... + | --- + | - ok + | ... tuple = s:insert({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) ---- -... + | --- + | ... tuple ---- -- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -... + | --- + | - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + | ... tuple[1] -- not-null, always accessible ---- -- 1 -... + | --- + | - 1 + | ... tuple[2] -- null, doesn't have offset ---- -- null -... + | --- + | - null + | ... tuple[3] -- not null, has offset ---- -- 3 -... + | --- + | - 3 + | ... tuple[4] -- null, doesn't have offset ---- -- null -... + | --- + | - null + | ... tuple[5] -- null, doesn't have offset ---- -- null -... + | --- + | - null + | ... s.index.seq2:select({1}) ---- -- - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -... + | --- + | - - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + | ... s.index.seq2:select({1, 2}) ---- -- - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -... + | --- + | - - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + | ... s.index.seq3:select({1}) ---- -- - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -... + | --- + | - - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + | ... s.index.seq3:select({1, 2, 3}) ---- -- - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -... + | --- + | - - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + | ... s.index.seq5:select({1}) ---- -- - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -... + | --- + | - - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + | ... s.index.seq5:select({1, 2, 3, 4, 5}) ---- -- - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -... + | --- + | - - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + | ... s.index.rnd1:select({3}) ---- -- - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -... + | --- + | - - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + | ... errinj.set("ERRINJ_TUPLE_FIELD", false) ---- -- ok -... + | --- + | - ok + | ... s:drop() ---- -... + | --- + | ... + space = box.schema.space.create('test') ---- -... + | --- + | ... _ = space:create_index('pk') ---- -... + | --- + | ... errinj.set("ERRINJ_WAL_WRITE", true) ---- -- ok -... + | --- + | - ok + | ... space:insert{1} ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... errinj.set("ERRINJ_WAL_WRITE", false) ---- -- ok -... + | --- + | - ok + | ... + errinj.set("ERRINJ_WAL_WRITE_DISK", true) ---- -- ok -... + | --- + | - ok + | ... _ = space:insert{1, require'digest'.urandom(192 * 1024)} ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... errinj.set("ERRINJ_WAL_WRITE_DISK", false) ---- -- ok -... + | --- + | - ok + | ... + _ = space:insert{1} ---- -... + | --- + | ... errinj.set("ERRINJ_WAL_WRITE", true) ---- -- ok -... + | --- + | - ok + | ... box.snapshot() ---- -- error: Error injection 'xlog write injection' -... + | --- + | - error: Error injection 'xlog write injection' + | ... errinj.set("ERRINJ_WAL_WRITE", false) ---- -- ok -... + | --- + | - ok + | ... space:drop() ---- -... + | --- + | ... + --test space:bsize() in case of memory error utils = dofile('utils.lua') ---- -... + | --- + | ... s = box.schema.space.create('space_bsize') ---- -... + | --- + | ... idx = s:create_index('primary') ---- -... + | --- + | ... + for i = 1, 13 do s:insert{ i, string.rep('x', i) } end ---- -... + | --- + | ... + s:bsize() ---- -- 130 -... + | --- + | - 130 + | ... utils.space_bsize(s) ---- -- 130 -... + | --- + | - 130 + | ... + errinj.set("ERRINJ_TUPLE_ALLOC", true) ---- -- ok -... + | --- + | - ok + | ... + s:replace{1, "test"} ---- -- error: Failed to allocate 21 bytes in slab allocator for memtx_tuple -... + | --- + | - error: Failed to allocate 21 bytes in slab allocator for memtx_tuple + | ... s:bsize() ---- -- 130 -... + | --- + | - 130 + | ... utils.space_bsize(s) ---- -- 130 -... + | --- + | - 130 + | ... + s:update({1}, {{'=', 3, '!'}}) ---- -- error: Failed to allocate 20 bytes in slab allocator for memtx_tuple -... + | --- + | - error: Failed to allocate 20 bytes in slab allocator for memtx_tuple + | ... s:bsize() ---- -- 130 -... + | --- + | - 130 + | ... utils.space_bsize(s) ---- -- 130 -... + | --- + | - 130 + | ... + errinj.set("ERRINJ_TUPLE_ALLOC", false) ---- -- ok -... + | --- + | - ok + | ... + s:drop() ---- -... + | --- + | ... + space = box.schema.space.create('test') ---- -... + | --- + | ... index1 = space:create_index('primary') ---- -... + | --- + | ... fiber = require'fiber' ---- -... + | --- + | ... ch = fiber.channel(1) ---- -... + | --- + | ... + test_run:cmd('setopt delimiter ";"') ---- -- true -... + | --- + | - true + | ... function test() errinj.set('ERRINJ_WAL_WRITE_DISK', true) pcall(box.space.test.replace, box.space.test, {1, 1}) errinj.set('ERRINJ_WAL_WRITE_DISK', false) ch:put(true) end ; ---- -... + | --- + | ... + function run() fiber.create(test) box.snapshot() end ; ---- -... + | --- + | ... + test_run:cmd('setopt delimiter ""'); ---- -- true -... + | --- + | - true + | ... + -- Port_dump can fail. + box.schema.user.grant('guest', 'read', 'space', '_space') ---- -... + | --- + | ... + cn = net_box.connect(box.cfg.listen) ---- -... + | --- + | ... cn:ping() ---- -- true -... + | --- + | - true + | ... errinj.set('ERRINJ_PORT_DUMP', true) ---- -- ok -... + | --- + | - ok + | ... ok, ret = pcall(cn.space._space.select, cn.space._space) ---- -... + | --- + | ... assert(not ok) ---- -- true -... + | --- + | - true + | ... assert(string.match(tostring(ret), 'Failed to allocate')) ---- -- Failed to allocate -... + | --- + | - Failed to allocate + | ... errinj.set('ERRINJ_PORT_DUMP', false) ---- -- ok -... + | --- + | - ok + | ... cn:close() ---- -... + | --- + | ... box.schema.user.revoke('guest', 'read', 'space', '_space') ---- -... + | --- + | ... + run() ---- -- error: Can't start a checkpoint while in cascading rollback -... + | --- + | - error: Can't start a checkpoint while in cascading rollback + | ... ch:get() ---- -- true -... + | --- + | - true + | ... + box.space.test:select() ---- -- [] -... + | --- + | - [] + | ... test_run:cmd('restart server default') + | box.space.test:select() ---- -- [] -... + | --- + | - [] + | ... box.space.test:drop() ---- -... + | --- + | ... + errinj = box.error.injection ---- -... + | --- + | ... net_box = require('net.box') ---- -... + | --- + | ... fiber = require'fiber' ---- -... + | --- + | ... + s = box.schema.space.create('test') ---- -... + | --- + | ... _ = s:create_index('pk') ---- -... + | --- + | ... + ch = fiber.channel(2) ---- -... + | --- + | ... + test_run:cmd("setopt delimiter ';'") ---- -- true -... + | --- + | - true + | ... function test(tuple) ch:put({pcall(s.replace, s, tuple)}) end; ---- -... + | --- + | ... test_run:cmd("setopt delimiter ''"); ---- -- true -... + | --- + | - true + | ... + errinj.set("ERRINJ_WAL_WRITE", true) ---- -- ok -... + | --- + | - ok + | ... _ = {fiber.create(test, {1, 2, 3}), fiber.create(test, {3, 4, 5})} ---- -... + | --- + | ... + {ch:get(), ch:get()} ---- -- - - false - - Failed to write to disk - - - false - - Failed to write to disk -... + | --- + | - - - false + | - Failed to write to disk + | - - false + | - Failed to write to disk + | ... errinj.set("ERRINJ_WAL_WRITE", false) ---- -- ok -... + | --- + | - ok + | ... s:drop() ---- -... + | --- + | ... + -- rebuild some secondary indexes if the primary was changed s = box.schema.space.create('test') ---- -... + | --- + | ... i1 = s:create_index('i1', {parts = {1, 'unsigned'}}) ---- -... + | --- + | ... --i2 = s:create_index('i2', {parts = {5, 'unsigned'}, unique = false}) --i3 = s:create_index('i3', {parts = {6, 'unsigned'}, unique = false}) i2 = i1 i3 = i1 ---- -... + | --- + | ... + _ = s:insert{1, 4, 3, 4, 10, 10} ---- -... + | --- + | ... _ = s:insert{2, 3, 1, 2, 10, 10} ---- -... + | --- + | ... _ = s:insert{3, 2, 2, 1, 10, 10} ---- -... + | --- + | ... _ = s:insert{4, 1, 4, 3, 10, 10} ---- -... + | --- + | ... + i1:select{} ---- -- - [1, 4, 3, 4, 10, 10] - - [2, 3, 1, 2, 10, 10] - - [3, 2, 2, 1, 10, 10] - - [4, 1, 4, 3, 10, 10] -... + | --- + | - - [1, 4, 3, 4, 10, 10] + | - [2, 3, 1, 2, 10, 10] + | - [3, 2, 2, 1, 10, 10] + | - [4, 1, 4, 3, 10, 10] + | ... i2:select{} ---- -- - [1, 4, 3, 4, 10, 10] - - [2, 3, 1, 2, 10, 10] - - [3, 2, 2, 1, 10, 10] - - [4, 1, 4, 3, 10, 10] -... + | --- + | - - [1, 4, 3, 4, 10, 10] + | - [2, 3, 1, 2, 10, 10] + | - [3, 2, 2, 1, 10, 10] + | - [4, 1, 4, 3, 10, 10] + | ... i3:select{} ---- -- - [1, 4, 3, 4, 10, 10] - - [2, 3, 1, 2, 10, 10] - - [3, 2, 2, 1, 10, 10] - - [4, 1, 4, 3, 10, 10] -... + | --- + | - - [1, 4, 3, 4, 10, 10] + | - [2, 3, 1, 2, 10, 10] + | - [3, 2, 2, 1, 10, 10] + | - [4, 1, 4, 3, 10, 10] + | ... + i1:alter({parts={2, 'unsigned'}}) ---- -... + | --- + | ... + _ = collectgarbage('collect') ---- -... + | --- + | ... i1:select{} ---- -- - [4, 1, 4, 3, 10, 10] - - [3, 2, 2, 1, 10, 10] - - [2, 3, 1, 2, 10, 10] - - [1, 4, 3, 4, 10, 10] -... + | --- + | - - [4, 1, 4, 3, 10, 10] + | - [3, 2, 2, 1, 10, 10] + | - [2, 3, 1, 2, 10, 10] + | - [1, 4, 3, 4, 10, 10] + | ... i2:select{} ---- -- - [4, 1, 4, 3, 10, 10] - - [3, 2, 2, 1, 10, 10] - - [2, 3, 1, 2, 10, 10] - - [1, 4, 3, 4, 10, 10] -... + | --- + | - - [4, 1, 4, 3, 10, 10] + | - [3, 2, 2, 1, 10, 10] + | - [2, 3, 1, 2, 10, 10] + | - [1, 4, 3, 4, 10, 10] + | ... i3:select{} ---- -- - [4, 1, 4, 3, 10, 10] - - [3, 2, 2, 1, 10, 10] - - [2, 3, 1, 2, 10, 10] - - [1, 4, 3, 4, 10, 10] -... + | --- + | - - [4, 1, 4, 3, 10, 10] + | - [3, 2, 2, 1, 10, 10] + | - [2, 3, 1, 2, 10, 10] + | - [1, 4, 3, 4, 10, 10] + | ... + box.error.injection.set('ERRINJ_BUILD_INDEX', i2.id) ---- -- ok -... + | --- + | - ok + | ... + i1:alter{parts = {3, "unsigned"}} ---- -- error: Error injection 'build index' -... + | --- + | - error: Error injection 'build index' + | ... + _ = collectgarbage('collect') ---- -... + | --- + | ... i1:select{} ---- -- - [4, 1, 4, 3, 10, 10] - - [3, 2, 2, 1, 10, 10] - - [2, 3, 1, 2, 10, 10] - - [1, 4, 3, 4, 10, 10] -... + | --- + | - - [4, 1, 4, 3, 10, 10] + | - [3, 2, 2, 1, 10, 10] + | - [2, 3, 1, 2, 10, 10] + | - [1, 4, 3, 4, 10, 10] + | ... i2:select{} ---- -- - [4, 1, 4, 3, 10, 10] - - [3, 2, 2, 1, 10, 10] - - [2, 3, 1, 2, 10, 10] - - [1, 4, 3, 4, 10, 10] -... + | --- + | - - [4, 1, 4, 3, 10, 10] + | - [3, 2, 2, 1, 10, 10] + | - [2, 3, 1, 2, 10, 10] + | - [1, 4, 3, 4, 10, 10] + | ... i3:select{} ---- -- - [4, 1, 4, 3, 10, 10] - - [3, 2, 2, 1, 10, 10] - - [2, 3, 1, 2, 10, 10] - - [1, 4, 3, 4, 10, 10] -... + | --- + | - - [4, 1, 4, 3, 10, 10] + | - [3, 2, 2, 1, 10, 10] + | - [2, 3, 1, 2, 10, 10] + | - [1, 4, 3, 4, 10, 10] + | ... + box.error.injection.set('ERRINJ_BUILD_INDEX', i3.id) ---- -- ok -... + | --- + | - ok + | ... + i1:alter{parts = {4, "unsigned"}} ---- -- error: Error injection 'build index' -... + | --- + | - error: Error injection 'build index' + | ... + _ = collectgarbage('collect') ---- -... + | --- + | ... i1:select{} ---- -- - [4, 1, 4, 3, 10, 10] - - [3, 2, 2, 1, 10, 10] - - [2, 3, 1, 2, 10, 10] - - [1, 4, 3, 4, 10, 10] -... + | --- + | - - [4, 1, 4, 3, 10, 10] + | - [3, 2, 2, 1, 10, 10] + | - [2, 3, 1, 2, 10, 10] + | - [1, 4, 3, 4, 10, 10] + | ... i2:select{} ---- -- - [4, 1, 4, 3, 10, 10] - - [3, 2, 2, 1, 10, 10] - - [2, 3, 1, 2, 10, 10] - - [1, 4, 3, 4, 10, 10] -... + | --- + | - - [4, 1, 4, 3, 10, 10] + | - [3, 2, 2, 1, 10, 10] + | - [2, 3, 1, 2, 10, 10] + | - [1, 4, 3, 4, 10, 10] + | ... i3:select{} ---- -- - [4, 1, 4, 3, 10, 10] - - [3, 2, 2, 1, 10, 10] - - [2, 3, 1, 2, 10, 10] - - [1, 4, 3, 4, 10, 10] -... + | --- + | - - [4, 1, 4, 3, 10, 10] + | - [3, 2, 2, 1, 10, 10] + | - [2, 3, 1, 2, 10, 10] + | - [1, 4, 3, 4, 10, 10] + | ... + box.error.injection.set('ERRINJ_BUILD_INDEX', -1) ---- -- ok -... + | --- + | - ok + | ... + s:drop() ---- -... + | --- + | ... + -- -- Do not rebuild index if the only change is a key part type -- compatible change. -- s = box.schema.space.create('test') ---- -... + | --- + | ... pk = s:create_index('pk') ---- -... + | --- + | ... sk = s:create_index('sk', {parts = {2, 'unsigned'}}) ---- -... + | --- + | ... s:replace{1, 1} ---- -- [1, 1] -... + | --- + | - [1, 1] + | ... box.error.injection.set('ERRINJ_BUILD_INDEX', sk.id) ---- -- ok -... + | --- + | - ok + | ... sk:alter({parts = {2, 'number'}}) ---- -... + | --- + | ... box.error.injection.set('ERRINJ_BUILD_INDEX', -1) ---- -- ok -... + | --- + | - ok + | ... s:drop() ---- -... + | --- + | ... + -- -- gh-3255: iproto can crash and discard responses, if a network -- is saturated, and DML yields too long on commit. -- + s = box.schema.space.create('test') ---- -... + | --- + | ... _ = s:create_index('pk') ---- -... + | --- + | ... box.schema.user.grant('guest', 'read,write,alter', 'space', 'test') ---- -... + | --- + | ... c = net_box.connect(box.cfg.listen) ---- -... + | --- + | ... + ch = fiber.channel(200) ---- -... + | --- + | ... errinj.set("ERRINJ_IPROTO_TX_DELAY", true) ---- -- ok -... + | --- + | - ok + | ... for i = 1, 100 do fiber.create(function() for j = 1, 10 do c.space.test:replace{1} end ch:put(true) end) end ---- -... + | --- + | ... for i = 1, 100 do fiber.create(function() for j = 1, 10 do c.space.test:select() end ch:put(true) end) end ---- -... + | --- + | ... for i = 1, 200 do ch:get() end ---- -... + | --- + | ... errinj.set("ERRINJ_IPROTO_TX_DELAY", false) ---- -- ok -... + | --- + | - ok + | ... + s:drop() ---- -... + | --- + | ... + -- -- gh-3325: do not cancel already sent requests, when a schema -- change is detected. -- + box.schema.user.grant('guest', 'execute', 'universe') ---- -... + | --- + | ... + s = box.schema.create_space('test') ---- -... + | --- + | ... pk = s:create_index('pk') ---- -... + | --- + | ... + box.schema.user.grant('guest', 'read,write,alter', 'space', 'test') ---- -... + | --- + | ... box.schema.user.grant('guest', 'create', 'space') ---- -... + | --- + | ... box.schema.user.grant('guest', 'write', 'space', '_index') ---- -... + | --- + | ... s:replace{1, 1} ---- -- [1, 1] -... + | --- + | - [1, 1] + | ... cn = net_box.connect(box.cfg.listen) ---- -... + | --- + | ... errinj.set("ERRINJ_WAL_DELAY", true) ---- -- ok -... + | --- + | - ok + | ... ok = nil ---- -... + | --- + | ... err = nil ---- -... + | --- + | ... test_run:cmd('setopt delimiter ";"') ---- -- true -... + | --- + | - true + | ... f = fiber.create(function() local str = 'box.space.test:create_index("sk", {parts = {{2, "integer"}}})' ok, err = pcall(cn.eval, cn, str) end) test_run:cmd('setopt delimiter ""'); ---- -... + | --- + | ... cn.space.test:get{1} ---- -- [1, 1] -... + | --- + | - [1, 1] + | ... errinj.set("ERRINJ_WAL_DELAY", false) ---- -- ok -... + | --- + | - ok + | ... while ok == nil do fiber.sleep(0.01) end ---- -... + | --- + | ... ok, err ---- -- true -- null -... + | --- + | - true + | - null + | ... cn:close() ---- -... + | --- + | ... s:drop() ---- -... + | --- + | ... box.schema.user.revoke('guest', 'execute', 'universe') ---- -... + | --- + | ... box.schema.user.revoke('guest', 'create', 'space') ---- -... + | --- + | ... box.schema.user.revoke('guest', 'write', 'space', '_index') ---- -... + | --- + | ... -- -- If message memory pool is used up, stop the connection, until -- the pool has free memory. -- started = 0 ---- -... + | --- + | ... finished = 0 ---- -... + | --- + | ... continue = false ---- -... + | --- + | ... test_run:cmd('setopt delimiter ";"') ---- -- true -... + | --- + | - true + | ... function long_poll_f() started = started + 1 f = fiber.self() while not continue do fiber.sleep(0.01) end finished = finished + 1 end; ---- -... + | --- + | ... + box.schema.func.create('long_poll_f'); ---- -... + | --- + | ... box.schema.user.grant('guest', 'execute', 'function', 'long_poll_f'); ---- -... + | --- + | ... + test_run:cmd('setopt delimiter ""'); ---- -- true -... + | --- + | - true + | ... cn = net_box.connect(box.cfg.listen) ---- -... + | --- + | ... function long_poll() cn:call('long_poll_f') end ---- -... + | --- + | ... _ = fiber.create(long_poll) ---- -... + | --- + | ... while started ~= 1 do fiber.sleep(0.01) end ---- -... + | --- + | ... -- Simulate OOM for new requests. errinj.set("ERRINJ_TESTING", true) ---- -- ok -... + | --- + | - ok + | ... -- This request tries to allocate memory for request data and -- fails. This stops the connection until an existing -- request is finished. log = require('log') ---- -... + | --- + | ... -- Fill the log with garbage to not accidentally read log messages -- produced by a previous test. log.info(string.rep('a', 1000)) ---- -... + | --- + | ... _ = fiber.create(long_poll) ---- -... + | --- + | ... while not test_run:grep_log('default', 'can not allocate memory for a new message', 1000) do fiber.sleep(0.01) end ---- -... + | --- + | ... test_run:grep_log('default', 'stopping input on connection', 1000) ~= nil ---- -- true -... + | --- + | - true + | ... started == 1 ---- -- true -... + | --- + | - true + | ... continue = true ---- -... + | --- + | ... errinj.set("ERRINJ_TESTING", false) ---- -- ok -... + | --- + | - ok + | ... -- Ensure that when memory is available again, the pending -- request is executed. while finished ~= 2 do fiber.sleep(0.01) end ---- -... + | --- + | ... cn:close() ---- -... + | --- + | ... + box.schema.user.revoke('guest', 'execute', 'function', 'long_poll_f') ---- -... + | --- + | ... box.schema.func.drop('long_poll_f') ---- -... + | --- + | ... -- -- gh-3289: drop/truncate leaves the space in inconsistent -- state if WAL write fails. -- s = box.schema.space.create('test') ---- -... + | --- + | ... _ = s:create_index('pk') ---- -... + | --- + | ... for i = 1, 10 do s:replace{i} end ---- -... + | --- + | ... errinj.set('ERRINJ_WAL_IO', true) ---- -- ok -... + | --- + | - ok + | ... s:drop() ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... s:truncate() ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... s:drop() ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... s:truncate() ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... errinj.set('ERRINJ_WAL_IO', false) ---- -- ok -... + | --- + | - ok + | ... for i = 1, 10 do s:replace{i + 10} end ---- -... + | --- + | ... s:select() ---- -- - [1] - - [2] - - [3] - - [4] - - [5] - - [6] - - [7] - - [8] - - [9] - - [10] - - [11] - - [12] - - [13] - - [14] - - [15] - - [16] - - [17] - - [18] - - [19] - - [20] -... + | --- + | - - [1] + | - [2] + | - [3] + | - [4] + | - [5] + | - [6] + | - [7] + | - [8] + | - [9] + | - [10] + | - [11] + | - [12] + | - [13] + | - [14] + | - [15] + | - [16] + | - [17] + | - [18] + | - [19] + | - [20] + | ... s:drop() ---- -... + | --- + | ... + -- -- gh-3432: check that deletion of temporary tuples is not delayed -- if snapshot is in progress. -- test_run:cmd("create server test with script='box/lua/cfg_memory.lua'") ---- -- true -... + | --- + | - true + | ... test_run:cmd(string.format("start server test with args='%d'", 100 * 1024 * 1024)) ---- -- true -... + | --- + | - true + | ... test_run:cmd("switch test") ---- -- true -... + | --- + | - true + | ... + fiber = require('fiber') ---- -... + | --- + | ... + -- Create a persistent space. _ = box.schema.space.create('test') ---- -... + | --- + | ... _ = box.space.test:create_index('pk') ---- -... + | --- + | ... for i = 1, 100 do box.space.test:insert{i} end ---- -... + | --- + | ... + -- Create a temporary space. count = 500 ---- -... + | --- + | ... pad = string.rep('x', 100 * 1024) ---- -... + | --- + | ... _ = box.schema.space.create('tmp', {temporary = true}) ---- -... + | --- + | ... _ = box.space.tmp:create_index('pk') ---- -... + | --- + | ... for i = 1, count do box.space.tmp:insert{i, pad} end ---- -... + | --- + | ... + -- Start background snapshot. c = fiber.channel(1) ---- -... + | --- + | ... box.error.injection.set('ERRINJ_SNAP_WRITE_DELAY', true) ---- -- ok -... + | --- + | - ok + | ... _ = fiber.create(function() box.snapshot() c:put(true) end) ---- -... + | --- + | ... + -- Overwrite data stored in the temporary space while snapshot -- is in progress to make sure that tuples stored in it are freed -- immediately. for i = 1, count do box.space.tmp:delete{i} end ---- -... + | --- + | ... _ = collectgarbage('collect') ---- -... + | --- + | ... for i = 1, count do box.space.tmp:insert{i, pad} end ---- -... + | --- + | ... + box.error.injection.set('ERRINJ_SNAP_WRITE_DELAY', false) ---- -- ok -... + | --- + | - ok + | ... c:get() ---- -- true -... + | --- + | - true + | ... + box.space.tmp:drop() ---- -... + | --- + | ... box.space.test:drop() ---- -... + | --- + | ... + test_run:cmd("switch default") ---- -- true -... + | --- + | - true + | ... test_run:cmd("stop server test") ---- -- true -... + | --- + | - true + | ... test_run:cmd("cleanup server test") ---- -- true -... + | --- + | - true + | ... + -- -- gh-3406: check that incomplete files got cleaned up after restart. -- fio = require('fio') ---- -... + | --- + | ... fiber = require('fiber') ---- -... + | --- + | ... + -- Check that snap.inprogress files are removed. _ = box.schema.space.create('test') ---- -... + | --- + | ... _ = box.space.test:create_index('primary') ---- -... + | --- + | ... for i = 1, 10 do box.space.test:insert{i} end ---- -... + | --- + | ... + errinj.set('ERRINJ_SNAP_WRITE_DELAY', true) ---- -- ok -... + | --- + | - ok + | ... _ = fiber.create(function() box.snapshot() end) ---- -... + | --- + | ... path = fio.pathjoin(box.cfg.memtx_dir, '*.snap.inprogress') ---- -... + | --- + | ... while #fio.glob(path) == 0 do fiber.sleep(0.001) end ---- -... + | --- + | ... #fio.glob(path) > 0 ---- -- true -... + | --- + | - true + | ... + test_run:cmd('restart server default') + | + fio = require('fio') ---- -... + | --- + | ... fiber = require('fiber') ---- -... + | --- + | ... errinj = box.error.injection ---- -... + | --- + | ... + #fio.glob(fio.pathjoin(box.cfg.memtx_dir, "*.snap.inprogress")) == 0 ---- -- true -... + | --- + | - true + | ... box.space.test:drop() ---- -... + | --- + | ... + -- Check that run.inprogress, index.inprogress, and vylog.inprogress -- files are removed. _ = box.schema.space.create('test', {engine = 'vinyl'}) ---- -... + | --- + | ... _ = box.space.test:create_index('primary') ---- -... + | --- + | ... + errinj.set('ERRINJ_VY_LOG_FILE_RENAME', true) ---- -- ok -... + | --- + | - ok + | ... box.snapshot() ---- -- error: Error injection 'vinyl log file rename' -... + | --- + | - error: Error injection 'vinyl log file rename' + | ... errinj.set('ERRINJ_VY_LOG_FILE_RENAME', false) ---- -- ok -... + | --- + | - ok + | ... + errinj.set('ERRINJ_VY_GC', true) ---- -- ok -... + | --- + | - ok + | ... errinj.set('ERRINJ_VY_SCHED_TIMEOUT', 0.001) ---- -- ok -... + | --- + | - ok + | ... + errinj.set('ERRINJ_VY_RUN_FILE_RENAME', true) ---- -- ok -... + | --- + | - ok + | ... box.space.test:insert{1} ---- -- [1] -... + | --- + | - [1] + | ... box.snapshot() -- error ---- -- error: Error injection 'vinyl run file rename' -... + | --- + | - error: Error injection 'vinyl run file rename' + | ... errinj.set('ERRINJ_VY_RUN_FILE_RENAME', false) ---- -- ok -... + | --- + | - ok + | ... + -- Wait for the scheduler to unthrottle. repeat fiber.sleep(0.001) until pcall(box.snapshot) ---- -... + | --- + | ... + errinj.set('ERRINJ_VY_INDEX_FILE_RENAME', true) ---- -- ok -... + | --- + | - ok + | ... box.space.test:insert{2} ---- -- [2] -... + | --- + | - [2] + | ... box.snapshot() -- error ---- -- error: Error injection 'vinyl index file rename' -... + | --- + | - error: Error injection 'vinyl index file rename' + | ... errinj.set('ERRINJ_VY_INDEX_FILE_RENAME', false) ---- -- ok -... + | --- + | - ok + | ... + errinj.set('ERRINJ_VY_SCHED_TIMEOUT', 0) ---- -- ok -... + | --- + | - ok + | ... errinj.set('ERRINJ_VY_GC', false) ---- -- ok -... + | --- + | - ok + | ... + test_run:cmd('restart server default') + | + fio = require('fio') ---- -... + | --- + | ... #fio.glob(fio.pathjoin(box.cfg.vinyl_dir, '*.vylog.inprogress')) == 0 ---- -- true -... + | --- + | - true + | ... #fio.glob(fio.pathjoin(box.cfg.vinyl_dir, box.space.test.id, 0, '*.run.inprogress')) == 0 ---- -- true -... + | --- + | - true + | ... #fio.glob(fio.pathjoin(box.cfg.vinyl_dir, box.space.test.id, 0, '*.index.inprogress')) == 0 ---- -- true -... + | --- + | - true + | ... + box.space.test:drop() ---- -... + | --- + | ... + -- gh-4276 - check grant privilege rollback _ = box.schema.user.create('testg') ---- -... + | --- + | ... _ = box.schema.space.create('testg'):create_index('pk') ---- -... + | --- + | ... + box.error.injection.set('ERRINJ_WAL_IO', true) ---- -- ok -... + | --- + | - ok + | ... -- the grant operation above fails and test hasn't any space test permissions box.schema.user.grant('testg', 'read,write', 'space', 'testg') ---- -- error: Failed to write to disk -... + | --- + | - error: Failed to write to disk + | ... -- switch user and check they couldn't select box.session.su('testg') ---- -... + | --- + | ... box.space.testg:select() ---- -- error: Read access to space 'testg' is denied for user 'testg' -... + | --- + | - error: Read access to space 'testg' is denied for user 'testg' + | ... box.session.su('admin') ---- -... + | --- + | ... box.error.injection.set('ERRINJ_WAL_IO', false) ---- -- ok -... + | --- + | - ok + | ... box.schema.user.drop('testg') ---- -... + | --- + | ... box.space.testg:drop() ---- -... + | --- + | ... + -- -- Errinj:get(). -- box.error.injection.get('bad name') ---- -- 'error: can''t find error injection ''bad name''' -... + | --- + | - 'error: can''t find error injection ''bad name''' + | ... box.error.injection.set('ERRINJ_WAL_IO', true) ---- -- ok -... + | --- + | - ok + | ... box.error.injection.get('ERRINJ_WAL_IO') ---- -- true -... + | --- + | - true + | ... box.error.injection.set('ERRINJ_WAL_IO', false) ---- -- ok -... + | --- + | - ok + | ... box.error.injection.get('ERRINJ_WAL_IO') ---- -- false -... + | --- + | - false + | ... box.error.injection.set('ERRINJ_TUPLE_FORMAT_COUNT', 20) ---- -- ok -... + | --- + | - ok + | ... box.error.injection.get('ERRINJ_TUPLE_FORMAT_COUNT') ---- -- 20 -... + | --- + | - 20 + | ... box.error.injection.set('ERRINJ_TUPLE_FORMAT_COUNT', -1) ---- -- ok -... + | --- + | - ok + | ... box.error.injection.get('ERRINJ_TUPLE_FORMAT_COUNT') ---- -- -1 -... + | --- + | - -1 + | ... box.error.injection.set('ERRINJ_RELAY_TIMEOUT', 0.5) ---- -- ok -... + | --- + | - ok + | ... box.error.injection.get('ERRINJ_RELAY_TIMEOUT') ---- -- 0.5 -... + | --- + | - 0.5 + | ... box.error.injection.set('ERRINJ_RELAY_TIMEOUT', 0) ---- -- ok -... + | --- + | - ok + | ... box.error.injection.get('ERRINJ_RELAY_TIMEOUT') ---- -- 0 -... + | --- + | - 0 + | ... -- 2.20.1