[PATCH 1/6] Add ERROR_INJECT_YIELD and ERROR_INJECT_SLEEP helpers
Vladimir Davydov
vdavydov.dev at gmail.com
Sun Jun 30 22:40:14 MSK 2019
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
More information about the Tarantool-patches
mailing list