summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/test/format/ops.c
diff options
context:
space:
mode:
authorLuke Chen <luke.chen@mongodb.com>2018-12-27 13:48:37 +1100
committerLuke Chen <luke.chen@mongodb.com>2018-12-27 13:48:37 +1100
commit9ff8d7452ddf7370fc9047ebe9517fd7558914e6 (patch)
tree582219e9112051f579005f48781c0f6f9fb29ea8 /src/third_party/wiredtiger/test/format/ops.c
parent62c7e599ba211209eb93ae8f652d17fc8f6c251f (diff)
downloadmongo-9ff8d7452ddf7370fc9047ebe9517fd7558914e6.tar.gz
Import wiredtiger: e6c1b9724ed6ed2879a36d7e140f4fa9daceb261 from branch mongodb-4.2
ref: d5793d4dd5..e6c1b9724e for: 4.1.7 WT-4366 Fix how test/format handles prepare conflict errors WT-4426 Change WT data format to include timestamps in leaf page key/value cells WT-4475 clang detected memory leak while executing csuite tests WT-4499 Fix prepared transactions for cursor key order check failure WT-4506 Bypass some csuite tests for valgrind
Diffstat (limited to 'src/third_party/wiredtiger/test/format/ops.c')
-rw-r--r--src/third_party/wiredtiger/test/format/ops.c97
1 files changed, 73 insertions, 24 deletions
diff --git a/src/third_party/wiredtiger/test/format/ops.c b/src/third_party/wiredtiger/test/format/ops.c
index f92f438a4f1..d5ed0320761 100644
--- a/src/third_party/wiredtiger/test/format/ops.c
+++ b/src/third_party/wiredtiger/test/format/ops.c
@@ -276,6 +276,44 @@ wts_ops(int lastrun)
free(tinfo_list);
}
+typedef enum { NEXT, PREV, SEARCH, SEARCH_NEAR } read_operation;
+
+/*
+ * read_op --
+ * Perform a read operation, waiting out prepare conflicts.
+ */
+static inline int
+read_op(WT_CURSOR *cursor, read_operation op, int *exactp)
+{
+ WT_DECL_RET;
+
+ /*
+ * Read operations wait out prepare-conflicts. (As part of the snapshot
+ * isolation checks, we repeat reads that succeeded before, they should
+ * be repeatable.)
+ */
+ switch (op) {
+ case NEXT:
+ while ((ret = cursor->next(cursor)) == WT_PREPARE_CONFLICT)
+ __wt_yield();
+ break;
+ case PREV:
+ while ((ret = cursor->prev(cursor)) == WT_PREPARE_CONFLICT)
+ __wt_yield();
+ break;
+ case SEARCH:
+ while ((ret = cursor->search(cursor)) == WT_PREPARE_CONFLICT)
+ __wt_yield();
+ break;
+ case SEARCH_NEAR:
+ while ((ret =
+ cursor->search_near(cursor, exactp)) == WT_PREPARE_CONFLICT)
+ __wt_yield();
+ break;
+ }
+ return (ret);
+}
+
typedef enum { INSERT, MODIFY, READ, REMOVE, TRUNCATE, UPDATE } thread_op;
typedef struct {
thread_op op; /* Operation */
@@ -401,7 +439,7 @@ snap_check(WT_CURSOR *cursor,
}
}
- switch (ret = cursor->search(cursor)) {
+ switch (ret = read_op(cursor, SEARCH, NULL)) {
case 0:
if (g.type == FIX) {
testutil_check(
@@ -634,12 +672,22 @@ prepare_transaction(TINFO *tinfo, WT_SESSION *session)
*/
#define OP_FAILED(notfound_ok) do { \
positioned = false; \
- if (intxn && (ret == WT_CACHE_FULL || \
- ret == WT_PREPARE_CONFLICT || ret == WT_ROLLBACK)) \
+ if (intxn && (ret == WT_CACHE_FULL || ret == WT_ROLLBACK)) \
goto rollback; \
testutil_assert((notfound_ok && ret == WT_NOTFOUND) || \
- ret == WT_CACHE_FULL || \
- ret == WT_PREPARE_CONFLICT || ret == WT_ROLLBACK); \
+ ret == WT_CACHE_FULL || ret == WT_ROLLBACK); \
+} while (0)
+
+/*
+ * Rollback updates returning prepare-conflict, they're unlikely to succeed
+ * unless the prepare aborts. Reads wait out the error, so it's unexpected.
+ */
+#define READ_OP_FAILED(notfound_ok) \
+ OP_FAILED(notfound_ok)
+#define WRITE_OP_FAILED(notfound_ok) do { \
+ if (ret == WT_PREPARE_CONFLICT) \
+ ret = WT_ROLLBACK; \
+ OP_FAILED(notfound_ok); \
} while (0)
/*
@@ -826,7 +874,7 @@ ops(void *arg)
positioned = true;
SNAP_TRACK(READ, tinfo);
} else
- OP_FAILED(true);
+ READ_OP_FAILED(true);
}
/* Optionally reserve a row. */
@@ -845,7 +893,7 @@ ops(void *arg)
__wt_yield(); /* Let other threads proceed. */
} else
- OP_FAILED(true);
+ WRITE_OP_FAILED(true);
}
/* Perform the operation. */
@@ -875,7 +923,7 @@ ops(void *arg)
++tinfo->insert;
SNAP_TRACK(INSERT, tinfo);
} else
- OP_FAILED(false);
+ WRITE_OP_FAILED(false);
break;
case MODIFY:
/*
@@ -899,7 +947,7 @@ ops(void *arg)
positioned = true;
SNAP_TRACK(MODIFY, tinfo);
} else
- OP_FAILED(true);
+ WRITE_OP_FAILED(true);
break;
case READ:
++tinfo->search;
@@ -908,7 +956,7 @@ ops(void *arg)
positioned = true;
SNAP_TRACK(READ, tinfo);
} else
- OP_FAILED(true);
+ READ_OP_FAILED(true);
break;
case REMOVE:
remove_instead_of_truncate:
@@ -929,7 +977,7 @@ remove_instead_of_truncate:
*/
SNAP_TRACK(REMOVE, tinfo);
} else
- OP_FAILED(true);
+ WRITE_OP_FAILED(true);
break;
case TRUNCATE:
/*
@@ -958,7 +1006,8 @@ remove_instead_of_truncate:
* vice-versa).
*/
greater_than = mmrand(&tinfo->rnd, 0, 1) == 1;
- range = mmrand(&tinfo->rnd, 1, (u_int)g.rows / 20);
+ range = g.rows < 20 ?
+ 1 : mmrand(&tinfo->rnd, 1, (u_int)g.rows / 20);
tinfo->last = tinfo->keyno;
if (greater_than) {
if (g.c_reverse) {
@@ -992,14 +1041,15 @@ remove_instead_of_truncate:
ret = col_truncate(tinfo, cursor);
break;
}
- positioned = false;
(void)__wt_atomic_subv64(&g.truncate_cnt, 1);
+ /* Truncate never leaves the cursor positioned. */
+ positioned = false;
if (ret == 0) {
++tinfo->truncate;
SNAP_TRACK(TRUNCATE, tinfo);
} else
- OP_FAILED(false);
+ WRITE_OP_FAILED(false);
break;
case UPDATE:
update_instead_of_chosen_op:
@@ -1017,7 +1067,7 @@ update_instead_of_chosen_op:
positioned = true;
SNAP_TRACK(UPDATE, tinfo);
} else
- OP_FAILED(false);
+ WRITE_OP_FAILED(false);
break;
}
@@ -1033,7 +1083,7 @@ update_instead_of_chosen_op:
if ((ret = nextprev(tinfo, cursor, next)) == 0)
continue;
- OP_FAILED(true);
+ READ_OP_FAILED(true);
break;
}
}
@@ -1066,9 +1116,8 @@ update_instead_of_chosen_op:
*/
if (g.c_prepare && mmrand(&tinfo->rnd, 1, 10) == 1) {
ret = prepare_transaction(tinfo, session);
- testutil_assert(ret == 0 || ret == WT_PREPARE_CONFLICT);
- if (ret == WT_PREPARE_CONFLICT)
- goto rollback;
+ if (ret != 0)
+ WRITE_OP_FAILED(false);
__wt_yield(); /* Let other threads proceed. */
}
@@ -1193,11 +1242,11 @@ read_row_worker(
}
if (sn) {
- ret = cursor->search_near(cursor, &exact);
+ ret = read_op(cursor, SEARCH_NEAR, &exact);
if (ret == 0 && exact != 0)
ret = WT_NOTFOUND;
} else
- ret = cursor->search(cursor);
+ ret = read_op(cursor, SEARCH, NULL);
switch (ret) {
case 0:
if (g.type == FIX) {
@@ -1288,7 +1337,7 @@ nextprev(TINFO *tinfo, WT_CURSOR *cursor, bool next)
keyno = 0;
which = next ? "WT_CURSOR.next" : "WT_CURSOR.prev";
- switch (ret = (next ? cursor->next(cursor) : cursor->prev(cursor))) {
+ switch (ret = read_op(cursor, next ? NEXT : PREV, NULL)) {
case 0:
switch (g.type) {
case FIX:
@@ -2019,7 +2068,7 @@ row_remove(TINFO *tinfo, WT_CURSOR *cursor, bool positioned)
}
/* We use the cursor in overwrite mode, check for existence. */
- if ((ret = cursor->search(cursor)) == 0)
+ if ((ret = read_op(cursor, SEARCH, NULL)) == 0)
ret = cursor->remove(cursor);
if (ret != 0 && ret != WT_NOTFOUND)
@@ -2053,7 +2102,7 @@ col_remove(TINFO *tinfo, WT_CURSOR *cursor, bool positioned)
cursor->set_key(cursor, tinfo->keyno);
/* We use the cursor in overwrite mode, check for existence. */
- if ((ret = cursor->search(cursor)) == 0)
+ if ((ret = read_op(cursor, SEARCH, NULL)) == 0)
ret = cursor->remove(cursor);
if (ret != 0 && ret != WT_NOTFOUND)