From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Vladimir Davydov Subject: [PATCH 1/6] Add ERROR_INJECT_YIELD and ERROR_INJECT_SLEEP helpers Date: Sun, 30 Jun 2019 22:40:14 +0300 Message-Id: In-Reply-To: References: In-Reply-To: References: To: kostja@tarantool.org Cc: tarantool-patches@freelists.org List-ID: ERROR_INJECT_YIELD yields the current fiber execution by calling fiber_sleep(0) while the given error injection is set. ERROR_INJECT_SLEEP suspends the current thread execution by calling usleep(1000) while the given error injection is set. --- src/box/memtx_engine.c | 16 ++-------- src/box/memtx_space.c | 79 ++++++++++++++++++-------------------------------- src/box/relay.cc | 6 ++-- src/box/vinyl.c | 23 ++------------- src/box/vy_log.c | 6 +--- src/box/vy_run.c | 6 +--- src/box/vy_scheduler.c | 22 ++++---------- src/box/wal.c | 4 +-- src/curl.c | 7 +---- src/lib/core/errinj.h | 8 +++++ 10 files changed, 53 insertions(+), 124 deletions(-) diff --git a/src/box/memtx_engine.c b/src/box/memtx_engine.c index f371d147..c60f831c 100644 --- a/src/box/memtx_engine.c +++ b/src/box/memtx_engine.c @@ -774,14 +774,7 @@ memtx_engine_commit_checkpoint(struct engine *engine, snprintf(to, sizeof(to), "%s", xdir_format_filename(dir, lsn, NONE)); const char *from = xdir_format_filename(dir, lsn, INPROGRESS); -#ifndef NDEBUG - struct errinj *delay = errinj(ERRINJ_SNAP_COMMIT_DELAY, - ERRINJ_BOOL); - if (delay != NULL && delay->bparam) { - while (delay->bparam) - fiber_sleep(0.001); - } -#endif + ERROR_INJECT_YIELD(ERRINJ_SNAP_COMMIT_DELAY); int rc = coio_rename(from, to); if (rc != 0) panic("can't rename .snap.inprogress"); @@ -990,12 +983,7 @@ memtx_engine_gc_f(va_list va) struct memtx_engine *memtx = va_arg(va, struct memtx_engine *); while (!fiber_is_cancelled()) { bool stop; - struct errinj *delay = errinj(ERRINJ_MEMTX_DELAY_GC, - ERRINJ_BOOL); - if (delay != NULL && delay->bparam) { - while (delay->bparam) - fiber_sleep(0.001); - } + ERROR_INJECT_YIELD(ERRINJ_MEMTX_DELAY_GC); memtx_engine_run_gc(memtx, &stop); if (stop) { fiber_yield_timeout(TIMEOUT_INFINITY); diff --git a/src/box/memtx_space.c b/src/box/memtx_space.c index 77a8f7d5..f0e1cfd2 100644 --- a/src/box/memtx_space.c +++ b/src/box/memtx_space.c @@ -910,33 +910,21 @@ memtx_space_check_format(struct space *space, struct tuple_format *format) rc = tuple_validate(format, tuple); if (rc != 0) break; + + state.cursor = tuple; + tuple_ref(state.cursor); + if (++count % MEMTX_DDL_YIELD_LOOPS == 0 && - memtx->state == MEMTX_OK) { - state.cursor = tuple; - tuple_ref(state.cursor); + memtx->state == MEMTX_OK) fiber_sleep(0); - tuple_unref(state.cursor); - if (state.rc != 0) { - rc = -1; - diag_move(&state.diag, diag_get()); - break; - } - } + ERROR_INJECT_YIELD(ERRINJ_CHECK_FORMAT_DELAY); - struct errinj *inj = errinj(ERRINJ_CHECK_FORMAT_DELAY, ERRINJ_BOOL); - if (inj != NULL && inj->bparam && count == 1) { - state.cursor = tuple; - tuple_ref(state.cursor); - do { - fiber_sleep(0); - } while (inj->bparam); - tuple_unref(state.cursor); - if (state.rc != 0) { - rc = -1; - diag_move(&state.diag, diag_get()); - break; - } + tuple_unref(state.cursor); + if (state.rc != 0) { + rc = -1; + diag_move(&state.diag, diag_get()); + break; } } iterator_delete(it); @@ -1086,39 +1074,30 @@ memtx_space_build_index(struct space *src_space, struct index *new_index, */ if (new_index->def->iid == 0) tuple_ref(tuple); + /* + * Remember the latest inserted tuple to + * avoid processing yet to be added tuples + * in on_replace triggers. + */ + state.cursor = tuple; + tuple_ref(state.cursor); if (++count % MEMTX_DDL_YIELD_LOOPS == 0 && - memtx->state == MEMTX_OK) { - /* - * Remember the latest inserted tuple to - * avoid processing yet to be added tuples - * in on_replace triggers. - */ - state.cursor = tuple; - tuple_ref(state.cursor); + memtx->state == MEMTX_OK) fiber_sleep(0); - tuple_unref(state.cursor); - /* - * The on_replace trigger may have failed - * during the yield. - */ - if (state.rc != 0) { - rc = -1; - diag_move(&state.diag, diag_get()); - break; - } - } /* * Sleep after at least one tuple is inserted to test * on_replace triggers for index build. */ - struct errinj *inj = errinj(ERRINJ_BUILD_INDEX_DELAY, ERRINJ_BOOL); - if (inj != NULL && inj->bparam && count == 1) { - state.cursor = tuple; - tuple_ref(state.cursor); - do { - fiber_sleep(0); - } while (inj->bparam); - tuple_unref(state.cursor); + ERROR_INJECT_YIELD(ERRINJ_BUILD_INDEX_DELAY); + tuple_unref(state.cursor); + /* + * The on_replace trigger may have failed + * during the yield. + */ + if (state.rc != 0) { + rc = -1; + diag_move(&state.diag, diag_get()); + break; } } iterator_delete(it); diff --git a/src/box/relay.cc b/src/box/relay.cc index 906bf8ef..e9f5bdca 100644 --- a/src/box/relay.cc +++ b/src/box/relay.cc @@ -684,16 +684,14 @@ relay_subscribe(struct replica *replica, int fd, uint64_t sync, static void relay_send(struct relay *relay, struct xrow_header *packet) { - struct errinj *inj = errinj(ERRINJ_RELAY_SEND_DELAY, ERRINJ_BOOL); - while (inj != NULL && inj->bparam) - fiber_sleep(0.01); + ERROR_INJECT_YIELD(ERRINJ_RELAY_SEND_DELAY); packet->sync = relay->sync; relay->last_row_time = ev_monotonic_now(loop()); coio_write_xrow(&relay->io, packet); fiber_gc(); - inj = errinj(ERRINJ_RELAY_TIMEOUT, ERRINJ_DOUBLE); + struct errinj *inj = errinj(ERRINJ_RELAY_TIMEOUT, ERRINJ_DOUBLE); if (inj != NULL && inj->dparam > 0) fiber_sleep(inj->dparam); } diff --git a/src/box/vinyl.c b/src/box/vinyl.c index 814325da..128b1199 100644 --- a/src/box/vinyl.c +++ b/src/box/vinyl.c @@ -1156,12 +1156,7 @@ vinyl_space_check_format(struct space *space, struct tuple_format *format) */ if (++loops % VY_YIELD_LOOPS == 0) fiber_sleep(0); - struct errinj *inj = errinj(ERRINJ_CHECK_FORMAT_DELAY, ERRINJ_BOOL); - if (inj != NULL && inj->bparam && loops == 1) { - do { - fiber_sleep(0); - } while (inj->bparam); - } + ERROR_INJECT_YIELD(ERRINJ_CHECK_FORMAT_DELAY); if (ctx.is_failed) { diag_move(&ctx.diag, diag_get()); rc = -1; @@ -3882,14 +3877,7 @@ next: *ret = NULL; return 0; } -#ifndef NDEBUG - struct errinj *delay = errinj(ERRINJ_VY_DELAY_PK_LOOKUP, - ERRINJ_BOOL); - if (delay && delay->bparam) { - while (delay->bparam) - fiber_sleep(0.01); - } -#endif + ERROR_INJECT_YIELD(ERRINJ_VY_DELAY_PK_LOOKUP); /* Get the full tuple from the primary index. */ if (vy_get_by_secondary_tuple(it->lsm, it->tx, vy_tx_read_view(it->tx), @@ -4422,12 +4410,7 @@ vinyl_space_build_index(struct space *src_space, struct index *new_index, * Sleep after one tuple is inserted to test * on_replace triggers for index build. */ - inj = errinj(ERRINJ_BUILD_INDEX_DELAY, ERRINJ_BOOL); - if (inj != NULL && inj->bparam && loops == 1) { - do { - fiber_sleep(0); - } while (inj->bparam); - } + ERROR_INJECT_YIELD(ERRINJ_BUILD_INDEX_DELAY); } vy_read_iterator_close(&itr); diff --git a/src/box/vy_log.c b/src/box/vy_log.c index bf50f552..cb291f3c 100644 --- a/src/box/vy_log.c +++ b/src/box/vy_log.c @@ -807,11 +807,7 @@ vy_log_tx_flush(struct vy_log_tx *tx) diag_set(ClientError, ER_INJECTION, "vinyl log flush"); return -1; }); - struct errinj *delay = errinj(ERRINJ_VY_LOG_FLUSH_DELAY, ERRINJ_BOOL); - if (delay != NULL && delay->bparam) { - while (delay->bparam) - fiber_sleep(0.001); - } + ERROR_INJECT_YIELD(ERRINJ_VY_LOG_FLUSH_DELAY); int tx_size = 0; struct vy_log_record *record; diff --git a/src/box/vy_run.c b/src/box/vy_run.c index dfd71f1f..c6c17aee 100644 --- a/src/box/vy_run.c +++ b/src/box/vy_run.c @@ -916,11 +916,7 @@ vy_page_read(struct vy_page *page, const struct vy_page_info *page_info, if (inj != NULL && inj->dparam > 0) usleep(inj->dparam * 1000000); - inj = errinj(ERRINJ_VY_READ_PAGE_DELAY, ERRINJ_BOOL); - if (inj != NULL) { - while (inj->bparam) - usleep(10000); - } + ERROR_INJECT_SLEEP(ERRINJ_VY_READ_PAGE_DELAY); /* decode xlog tx */ const char *data_pos = data; diff --git a/src/box/vy_scheduler.c b/src/box/vy_scheduler.c index 0df55818..f3bded20 100644 --- a/src/box/vy_scheduler.c +++ b/src/box/vy_scheduler.c @@ -1040,12 +1040,7 @@ vy_task_write_run(struct vy_task *task, bool no_compression) ERROR_INJECT(ERRINJ_VY_RUN_WRITE, {diag_set(ClientError, ER_INJECTION, "vinyl dump"); return -1;}); - - struct errinj *inj = errinj(ERRINJ_VY_RUN_WRITE_DELAY, ERRINJ_BOOL); - if (inj != NULL && inj->bparam) { - while (inj->bparam) - usleep(10000); - } + ERROR_INJECT_SLEEP(ERRINJ_VY_RUN_WRITE_DELAY); struct vy_run_writer writer; if (vy_run_writer_create(&writer, task->new_run, lsm->env->path, @@ -1061,7 +1056,8 @@ vy_task_write_run(struct vy_task *task, bool no_compression) int loops = 0; struct vy_entry entry = vy_entry_none(); while ((rc = wi->iface->next(wi, &entry)) == 0 && entry.stmt != NULL) { - inj = errinj(ERRINJ_VY_RUN_WRITE_STMT_TIMEOUT, ERRINJ_DOUBLE); + struct errinj *inj = errinj(ERRINJ_VY_RUN_WRITE_STMT_TIMEOUT, + ERRINJ_DOUBLE); if (inj != NULL && inj->dparam > 0) usleep(inj->dparam * 1000000); @@ -1095,11 +1091,7 @@ fail: static int vy_task_dump_execute(struct vy_task *task) { - struct errinj *errinj = errinj(ERRINJ_VY_DUMP_DELAY, ERRINJ_BOOL); - if (errinj != NULL && errinj->bparam) { - while (errinj->bparam) - fiber_sleep(0.01); - } + ERROR_INJECT_SLEEP(ERRINJ_VY_DUMP_DELAY); /* * Don't compress L1 runs as they are most frequently read * and smallest runs at the same time and so we would gain @@ -1441,11 +1433,7 @@ err: static int vy_task_compaction_execute(struct vy_task *task) { - struct errinj *errinj = errinj(ERRINJ_VY_COMPACTION_DELAY, ERRINJ_BOOL); - if (errinj != NULL && errinj->bparam) { - while (errinj->bparam) - fiber_sleep(0.01); - } + ERROR_INJECT_SLEEP(ERRINJ_VY_COMPACTION_DELAY); return vy_task_write_run(task, false); } diff --git a/src/box/wal.c b/src/box/wal.c index 6f5d0a58..58a58e5b 100644 --- a/src/box/wal.c +++ b/src/box/wal.c @@ -936,9 +936,7 @@ wal_write_to_disk(struct cmsg *msg) struct vclock vclock_diff; vclock_create(&vclock_diff); - struct errinj *inj = errinj(ERRINJ_WAL_DELAY, ERRINJ_BOOL); - while (inj != NULL && inj->bparam) - usleep(10); + ERROR_INJECT_SLEEP(ERRINJ_WAL_DELAY); if (writer->in_rollback.route != NULL) { /* We're rolling back a failed write. */ diff --git a/src/curl.c b/src/curl.c index 3b48f907..a41c65e4 100644 --- a/src/curl.c +++ b/src/curl.c @@ -297,12 +297,7 @@ curl_execute(struct curl_request *curl_request, struct curl_env *env, mcode = curl_multi_add_handle(env->multi, curl_request->easy); if (mcode != CURLM_OK) goto curl_merror; -#ifndef NDEBUG - struct errinj *errinj = errinj(ERRINJ_HTTP_RESPONSE_ADD_WAIT, - ERRINJ_BOOL); - while (errinj != NULL && errinj->bparam) - fiber_sleep(0.001); -#endif + ERROR_INJECT_YIELD(ERRINJ_HTTP_RESPONSE_ADD_WAIT); /* Don't wait on a cond if request has already failed or finished. */ if (curl_request->code == CURLE_OK && curl_request->in_progress) { ++env->stat.active_requests; diff --git a/src/lib/core/errinj.h b/src/lib/core/errinj.h index 78783651..a55f583c 100644 --- a/src/lib/core/errinj.h +++ b/src/lib/core/errinj.h @@ -153,6 +153,7 @@ errinj_foreach(errinj_cb cb, void *cb_ctx); #ifdef NDEBUG # define ERROR_INJECT(ID, CODE) +# define ERROR_INJECT_WHILE(ID, CODE) # define errinj(ID, TYPE) ((struct errinj *) NULL) #else # /* Returns the error injection by id */ @@ -167,9 +168,16 @@ errinj_foreach(errinj_cb cb, void *cb_ctx); if (errinj(ID, ERRINJ_BOOL)->bparam) \ CODE; \ } while (0) +# define ERROR_INJECT_WHILE(ID, CODE) \ + do { \ + while (errinj(ID, ERRINJ_BOOL)->bparam) \ + CODE; \ + } while (0) #endif #define ERROR_INJECT_RETURN(ID) ERROR_INJECT(ID, return -1) +#define ERROR_INJECT_SLEEP(ID) ERROR_INJECT_WHILE(ID, usleep(1000)) +#define ERROR_INJECT_YIELD(ID) ERROR_INJECT_WHILE(ID, fiber_sleep(0)) #if defined(__cplusplus) } /* extern "C" */ -- 2.11.0