summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/wiredtiger/test')
-rw-r--r--src/third_party/wiredtiger/test/csuite/rwlock/main.c4
-rw-r--r--src/third_party/wiredtiger/test/format/config.c8
-rw-r--r--src/third_party/wiredtiger/test/format/ops.c411
-rw-r--r--src/third_party/wiredtiger/test/suite/test_cursor14.py60
-rw-r--r--src/third_party/wiredtiger/test/suite/test_prepare04.py122
-rw-r--r--src/third_party/wiredtiger/test/suite/test_timestamp04.py22
-rw-r--r--src/third_party/wiredtiger/test/suite/test_timestamp10.py4
7 files changed, 358 insertions, 273 deletions
diff --git a/src/third_party/wiredtiger/test/csuite/rwlock/main.c b/src/third_party/wiredtiger/test/csuite/rwlock/main.c
index e1d00344ee2..f69628dca40 100644
--- a/src/third_party/wiredtiger/test/csuite/rwlock/main.c
+++ b/src/third_party/wiredtiger/test/csuite/rwlock/main.c
@@ -171,8 +171,8 @@ thread_dump(void *arg) {
sleep(1);
printf("\n"
"rwlock { current %" PRIu8 ", next %" PRIu8
- ", reader %" PRIu8 ", readers_active %" PRIu16
- ", readers_queued %" PRIu16 " }\n",
+ ", reader %" PRIu8 ", readers_active %" PRIu32
+ ", readers_queued %" PRIu8 " }\n",
rwlock.u.s.current,
rwlock.u.s.next,
rwlock.u.s.reader,
diff --git a/src/third_party/wiredtiger/test/format/config.c b/src/third_party/wiredtiger/test/format/config.c
index 8d85d331c89..d46b0868887 100644
--- a/src/third_party/wiredtiger/test/format/config.c
+++ b/src/third_party/wiredtiger/test/format/config.c
@@ -191,9 +191,13 @@ config_setup(void)
/*
* Turn off truncate for LSM runs (some configurations with truncate
* always results in a timeout).
+ *
+ * WiredTiger doesn't currently support truncate and prepare at the
+ * same time, see WT-3922. For now, pick one on each run.
*/
- if (!config_is_perm("truncate") && DATASOURCE("lsm"))
- config_single("truncate=off", 0);
+ if (!config_is_perm("truncate"))
+ if (DATASOURCE("lsm") || mmrand(NULL, 0, 1) == 1)
+ config_single("truncate=off", 0);
/* Give Helium configuration a final review. */
if (DATASOURCE("helium"))
diff --git a/src/third_party/wiredtiger/test/format/ops.c b/src/third_party/wiredtiger/test/format/ops.c
index 4c54972516e..2466fe4d64d 100644
--- a/src/third_party/wiredtiger/test/format/ops.c
+++ b/src/third_party/wiredtiger/test/format/ops.c
@@ -403,10 +403,8 @@ snap_check(WT_CURSOR *cursor,
break;
case WT_NOTFOUND:
break;
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
default:
- testutil_die(ret, "WT_CURSOR.search");
+ return (ret);
}
/* Check for simple matches. */
@@ -644,6 +642,19 @@ prepare_transaction(TINFO *tinfo, WT_SESSION *session)
}
/*
+ * OP_FAILED --
+ * General error handling.
+ */
+#define OP_FAILED(notfound_ok) do { \
+ positioned = false; \
+ if (intxn && (ret == WT_CACHE_FULL || ret == WT_ROLLBACK)) \
+ goto deadlock; \
+ testutil_assert((notfound_ok && ret == WT_NOTFOUND) || \
+ ret == WT_CACHE_FULL || \
+ ret == WT_PREPARE_CONFLICT || ret == WT_ROLLBACK); \
+} while (0)
+
+/*
* ops --
* Per-thread operations.
*/
@@ -825,11 +836,8 @@ ops(void *arg)
if (ret == 0) {
positioned = true;
SNAP_TRACK(READ, tinfo);
- } else {
- if (ret == WT_ROLLBACK && intxn)
- goto deadlock;
- testutil_assert(ret == WT_NOTFOUND);
- }
+ } else
+ OP_FAILED(true);
}
/* Optionally reserve a row. */
@@ -847,12 +855,8 @@ ops(void *arg)
positioned = true;
__wt_yield(); /* Let other threads proceed. */
- } else {
- positioned = false;
- if (ret == WT_ROLLBACK && intxn)
- goto deadlock;
- testutil_assert(ret == WT_NOTFOUND);
- }
+ } else
+ OP_FAILED(true);
}
/* Perform the operation. */
@@ -881,11 +885,8 @@ ops(void *arg)
if (ret == 0) {
++tinfo->insert;
SNAP_TRACK(INSERT, tinfo);
- } else {
- if (ret == WT_ROLLBACK && intxn)
- goto deadlock;
- testutil_assert(ret == WT_ROLLBACK);
- }
+ } else
+ OP_FAILED(false);
break;
case MODIFY:
/*
@@ -907,13 +908,8 @@ ops(void *arg)
if (ret == 0) {
positioned = true;
SNAP_TRACK(MODIFY, tinfo);
- } else {
- positioned = false;
- if (ret == WT_ROLLBACK && intxn)
- goto deadlock;
- testutil_assert(
- ret == WT_NOTFOUND || ret == WT_ROLLBACK);
- }
+ } else
+ OP_FAILED(true);
break;
case READ:
++tinfo->search;
@@ -921,12 +917,8 @@ ops(void *arg)
if (ret == 0) {
positioned = true;
SNAP_TRACK(READ, tinfo);
- } else {
- positioned = false;
- if (ret == WT_ROLLBACK && intxn)
- goto deadlock;
- testutil_assert(ret == WT_NOTFOUND);
- }
+ } else
+ OP_FAILED(true);
break;
case REMOVE:
remove_instead_of_truncate:
@@ -946,12 +938,8 @@ remove_instead_of_truncate:
* previous state, but not necessarily set.
*/
SNAP_TRACK(REMOVE, tinfo);
- } else {
- positioned = false;
- if (ret == WT_ROLLBACK && intxn)
- goto deadlock;
- testutil_assert(ret == WT_NOTFOUND);
- }
+ } else
+ OP_FAILED(true);
break;
case TRUNCATE:
/*
@@ -1020,11 +1008,8 @@ remove_instead_of_truncate:
if (ret == 0) {
++tinfo->truncate;
SNAP_TRACK(TRUNCATE, tinfo);
- } else {
- testutil_assert(ret == WT_ROLLBACK);
- if (intxn)
- goto deadlock;
- }
+ } else
+ OP_FAILED(false);
break;
case UPDATE:
update_instead_of_chosen_op:
@@ -1041,12 +1026,8 @@ update_instead_of_chosen_op:
if (ret == 0) {
positioned = true;
SNAP_TRACK(UPDATE, tinfo);
- } else {
- positioned = false;
- if (ret == WT_ROLLBACK && intxn)
- goto deadlock;
- testutil_assert(ret == WT_ROLLBACK);
- }
+ } else
+ OP_FAILED(false);
break;
}
@@ -1061,9 +1042,8 @@ update_instead_of_chosen_op:
for (i = 0; i < j; ++i) {
if ((ret = nextprev(tinfo, cursor, next)) == 0)
continue;
- if (ret == WT_ROLLBACK && intxn)
- goto deadlock;
- testutil_assert(ret == WT_NOTFOUND);
+
+ OP_FAILED(true);
break;
}
}
@@ -1090,9 +1070,11 @@ update_instead_of_chosen_op:
goto deadlock;
}
- /* Prepare the transaction 10% of the time. */
- /* XXX: CONFIGURE PREPARE OFF FOR NOW */
- if (mmrand(&tinfo->rnd, 1, 10) == 0) {
+ /*
+ * Prepare the transaction 10% of the time.
+ * Currently doesn't work with truncation, see WT-3922.
+ */
+ if (g.c_truncate == 0 && mmrand(&tinfo->rnd, 1, 10) == 1) {
ret = prepare_transaction(tinfo, session);
testutil_assert(ret == 0 || ret == WT_PREPARE_CONFLICT);
if (ret == WT_PREPARE_CONFLICT)
@@ -1138,7 +1120,7 @@ deadlock: ++tinfo->deadlock;
/*
* wts_read_scan --
- * Read and verify all elements in a file.
+ * Read and verify a subset of the elements in a file.
*/
void
wts_read_scan(void)
@@ -1182,6 +1164,7 @@ wts_read_scan(void)
case 0:
case WT_NOTFOUND:
case WT_ROLLBACK:
+ case WT_PREPARE_CONFLICT:
break;
default:
testutil_die(
@@ -1209,11 +1192,6 @@ read_row_worker(
session = cursor->session;
- /* Log the operation */
- if (g.logging == LOG_OPS)
- (void)g.wt_api->msg_printf(g.wt_api,
- session, "%-10s%" PRIu64, "read", keyno);
-
/* Retrieve the key/value pair by key. */
switch (g.type) {
case FIX:
@@ -1254,12 +1232,15 @@ read_row_worker(
value->size = 1;
}
break;
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
default:
- testutil_die(ret, "read_row: read row %" PRIu64, keyno);
+ return (ret);
}
+ /* Log the operation */
+ if (g.logging == LOG_OPS)
+ (void)g.wt_api->msg_printf(g.wt_api,
+ session, "%-10s%" PRIu64, "read", keyno);
+
#ifdef HAVE_BERKELEY_DB
if (!SINGLETHREADED)
return (ret);
@@ -1394,24 +1375,39 @@ nextprev(TINFO *tinfo, WT_CURSOR *cursor, bool next)
break;
case WT_NOTFOUND:
break;
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
default:
- testutil_die(ret, "%s", which);
+ return (ret);
}
+ if (g.logging == LOG_OPS)
+ switch (g.type) {
+ case FIX:
+ (void)g.wt_api->msg_printf(g.wt_api,
+ cursor->session, "%-10s%" PRIu64 " {0x%02x}",
+ which, keyno, ((char *)value.data)[0]);
+ break;
+ case ROW:
+ (void)g.wt_api->msg_printf(g.wt_api,
+ cursor->session, "%-10s{%.*s}, {%.*s}",
+ which, (int)key.size, (char *)key.data,
+ (int)value.size, (char *)value.data);
+ break;
+ case VAR:
+ (void)g.wt_api->msg_printf(g.wt_api,
+ cursor->session, "%-10s%" PRIu64 " {%.*s}",
+ which, keyno, (int)value.size, (char *)value.data);
+ break;
+ }
+
#ifdef HAVE_BERKELEY_DB
if (!SINGLETHREADED)
return (ret);
{
WT_ITEM bdb_key, bdb_value;
- WT_SESSION *session;
int notfound;
char *p;
- session = cursor->session;
-
/* Retrieve the BDB key/value. */
bdb_np(next, &bdb_key.data, &bdb_key.size,
&bdb_value.data, &bdb_value.size, &notfound);
@@ -1444,26 +1440,6 @@ mismatch: if (g.type == ROW) {
print_item(" wt-value", &value);
testutil_die(0, NULL);
}
-
- if (g.logging == LOG_OPS)
- switch (g.type) {
- case FIX:
- (void)g.wt_api->msg_printf(g.wt_api,
- session, "%-10s%" PRIu64 " {0x%02x}", which,
- keyno, ((char *)value.data)[0]);
- break;
- case ROW:
- (void)g.wt_api->msg_printf(
- g.wt_api, session, "%-10s{%.*s}, {%.*s}", which,
- (int)key.size, (char *)key.data,
- (int)value.size, (char *)value.data);
- break;
- case VAR:
- (void)g.wt_api->msg_printf(g.wt_api, session,
- "%-10s%" PRIu64 " {%.*s}", which,
- keyno, (int)value.size, (char *)value.data);
- break;
- }
}
#endif
return (ret);
@@ -1483,24 +1459,14 @@ row_reserve(TINFO *tinfo, WT_CURSOR *cursor, bool positioned)
cursor->set_key(cursor, tinfo->key);
}
+ if ((ret = cursor->reserve(cursor)) != 0)
+ return (ret);
+
if (g.logging == LOG_OPS)
(void)g.wt_api->msg_printf(g.wt_api, cursor->session,
"%-10s{%.*s}", "reserve",
(int)tinfo->key->size, tinfo->key->data);
- switch (ret = cursor->reserve(cursor)) {
- case 0:
- break;
- case WT_CACHE_FULL:
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
- case WT_NOTFOUND:
- return (WT_NOTFOUND);
- default:
- testutil_die(ret,
- "row_reserve: reserve row %" PRIu64 " by key",
- tinfo->keyno);
- }
return (0);
}
@@ -1516,21 +1482,13 @@ col_reserve(TINFO *tinfo, WT_CURSOR *cursor, bool positioned)
if (!positioned)
cursor->set_key(cursor, tinfo->keyno);
+ if ((ret = cursor->reserve(cursor)) != 0)
+ return (ret);
+
if (g.logging == LOG_OPS)
(void)g.wt_api->msg_printf(g.wt_api, cursor->session,
"%-10s%" PRIu64, "reserve", tinfo->keyno);
- switch (ret = cursor->reserve(cursor)) {
- case 0:
- break;
- case WT_CACHE_FULL:
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
- case WT_NOTFOUND:
- return (WT_NOTFOUND);
- default:
- testutil_die(ret, "col_reserve: %" PRIu64, tinfo->keyno);
- }
return (0);
}
@@ -1577,19 +1535,10 @@ row_modify(TINFO *tinfo, WT_CURSOR *cursor, bool positioned)
}
modify_build(tinfo, entries, &nentries);
- switch (ret = cursor->modify(cursor, entries, nentries)) {
- case 0:
- testutil_check(cursor->get_value(cursor, tinfo->value));
- break;
- case WT_CACHE_FULL:
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
- case WT_NOTFOUND:
- return (WT_NOTFOUND);
- default:
- testutil_die(ret,
- "row_modify: modify row %" PRIu64 " by key", tinfo->keyno);
- }
+ if ((ret = cursor->modify(cursor, entries, nentries)) != 0)
+ return (ret);
+
+ testutil_check(cursor->get_value(cursor, tinfo->value));
if (g.logging == LOG_OPS)
(void)g.wt_api->msg_printf(g.wt_api, cursor->session,
@@ -1624,25 +1573,16 @@ col_modify(TINFO *tinfo, WT_CURSOR *cursor, bool positioned)
cursor->set_key(cursor, tinfo->keyno);
modify_build(tinfo, entries, &nentries);
- switch (ret = cursor->modify(cursor, entries, nentries)) {
- case 0:
- testutil_check(cursor->get_value(cursor, tinfo->value));
- break;
- case WT_CACHE_FULL:
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
- case WT_NOTFOUND:
- return (WT_NOTFOUND);
- default:
- testutil_die(ret,
- "col_modify: modify row %" PRIu64, tinfo->keyno);
- }
+ if ((ret = cursor->modify(cursor, entries, nentries)) != 0)
+ return (ret);
+
+ testutil_check(cursor->get_value(cursor, tinfo->value));
if (g.logging == LOG_OPS)
(void)g.wt_api->msg_printf(g.wt_api, cursor->session,
- "%-10s{%.*s}, {%.*s}",
+ "%-10s%" PRIu64 ", {%.*s}",
"modify",
- (int)tinfo->key->size, tinfo->key->data,
+ tinfo->keyno,
(int)tinfo->value->size, tinfo->value->data);
#ifdef HAVE_BERKELEY_DB
@@ -1698,24 +1638,15 @@ row_truncate(TINFO *tinfo, WT_CURSOR *cursor)
testutil_check(c2->close(c2));
}
+ if (ret != 0)
+ return (ret);
+
if (g.logging == LOG_OPS)
(void)g.wt_api->msg_printf(g.wt_api, session,
"%-10s%" PRIu64 ", %" PRIu64,
"truncate",
tinfo->keyno, tinfo->last);
- switch (ret) {
- case 0:
- break;
- case WT_CACHE_FULL:
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
- default:
- testutil_die(ret,
- "row_truncate: row %" PRIu64 "-%" PRIu64,
- tinfo->keyno, tinfo->last);
- }
-
#ifdef HAVE_BERKELEY_DB
if (SINGLETHREADED)
bdb_truncate(tinfo->keyno, tinfo->last);
@@ -1724,49 +1655,6 @@ row_truncate(TINFO *tinfo, WT_CURSOR *cursor)
}
/*
- * row_update --
- * Update a row in a row-store file.
- */
-static int
-row_update(TINFO *tinfo, WT_CURSOR *cursor, bool positioned)
-{
- WT_DECL_RET;
-
- if (!positioned) {
- key_gen(tinfo->key, tinfo->keyno);
- cursor->set_key(cursor, tinfo->key);
- }
- val_gen(&tinfo->rnd, tinfo->value, tinfo->keyno);
- cursor->set_value(cursor, tinfo->value);
-
- if (g.logging == LOG_OPS)
- (void)g.wt_api->msg_printf(g.wt_api, cursor->session,
- "%-10s{%.*s}, {%.*s}",
- "put",
- (int)tinfo->key->size, tinfo->key->data,
- (int)tinfo->value->size, tinfo->value->data);
-
- switch (ret = cursor->update(cursor)) {
- case 0:
- break;
- case WT_CACHE_FULL:
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
- default:
- testutil_die(ret,
- "row_update: update row %" PRIu64 " by key", tinfo->keyno);
- }
-
-#ifdef HAVE_BERKELEY_DB
- if (SINGLETHREADED)
- bdb_update(
- tinfo->key->data, tinfo->key->size,
- tinfo->value->data, tinfo->value->size);
-#endif
- return (0);
-}
-
-/*
* col_truncate --
* Truncate rows in a column-store file.
*/
@@ -1802,6 +1690,8 @@ col_truncate(TINFO *tinfo, WT_CURSOR *cursor)
ret = session->truncate(session, NULL, cursor, c2, NULL);
testutil_check(c2->close(c2));
}
+ if (ret != 0)
+ return (ret);
if (g.logging == LOG_OPS)
(void)g.wt_api->msg_printf(g.wt_api, session,
@@ -1809,21 +1699,44 @@ col_truncate(TINFO *tinfo, WT_CURSOR *cursor)
"truncate",
tinfo->keyno, tinfo->last);
- switch (ret) {
- case 0:
- break;
- case WT_CACHE_FULL:
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
- default:
- testutil_die(ret,
- "col_truncate: row %" PRIu64 "-%" PRIu64,
- tinfo->keyno, tinfo->last);
+#ifdef HAVE_BERKELEY_DB
+ if (SINGLETHREADED)
+ bdb_truncate(tinfo->keyno, tinfo->last);
+#endif
+ return (0);
+}
+
+/*
+ * row_update --
+ * Update a row in a row-store file.
+ */
+static int
+row_update(TINFO *tinfo, WT_CURSOR *cursor, bool positioned)
+{
+ WT_DECL_RET;
+
+ if (!positioned) {
+ key_gen(tinfo->key, tinfo->keyno);
+ cursor->set_key(cursor, tinfo->key);
}
+ val_gen(&tinfo->rnd, tinfo->value, tinfo->keyno);
+ cursor->set_value(cursor, tinfo->value);
+
+ if ((ret = cursor->update(cursor)) != 0)
+ return (ret);
+
+ if (g.logging == LOG_OPS)
+ (void)g.wt_api->msg_printf(g.wt_api, cursor->session,
+ "%-10s{%.*s}, {%.*s}",
+ "put",
+ (int)tinfo->key->size, tinfo->key->data,
+ (int)tinfo->value->size, tinfo->value->data);
#ifdef HAVE_BERKELEY_DB
if (SINGLETHREADED)
- bdb_truncate(tinfo->keyno, tinfo->last);
+ bdb_update(
+ tinfo->key->data, tinfo->key->size,
+ tinfo->value->data, tinfo->value->size);
#endif
return (0);
}
@@ -1845,6 +1758,9 @@ col_update(TINFO *tinfo, WT_CURSOR *cursor, bool positioned)
else
cursor->set_value(cursor, tinfo->value);
+ if ((ret = cursor->update(cursor)) != 0)
+ return (ret);
+
if (g.logging == LOG_OPS) {
if (g.type == FIX)
(void)g.wt_api->msg_printf(g.wt_api, cursor->session,
@@ -1859,16 +1775,6 @@ col_update(TINFO *tinfo, WT_CURSOR *cursor, bool positioned)
(char *)tinfo->value->data);
}
- switch (ret = cursor->update(cursor)) {
- case 0:
- break;
- case WT_CACHE_FULL:
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
- default:
- testutil_die(ret, "col_update: %" PRIu64, tinfo->keyno);
- }
-
#ifdef HAVE_BERKELEY_DB
if (SINGLETHREADED) {
key_gen(tinfo->key, tinfo->keyno);
@@ -1999,6 +1905,9 @@ row_insert(TINFO *tinfo, WT_CURSOR *cursor, bool positioned)
val_gen(&tinfo->rnd, tinfo->value, tinfo->keyno);
cursor->set_value(cursor, tinfo->value);
+ if ((ret = cursor->insert(cursor)) != 0)
+ return (ret);
+
/* Log the operation */
if (g.logging == LOG_OPS)
(void)g.wt_api->msg_printf(g.wt_api, cursor->session,
@@ -2007,17 +1916,6 @@ row_insert(TINFO *tinfo, WT_CURSOR *cursor, bool positioned)
(int)tinfo->key->size, tinfo->key->data,
(int)tinfo->value->size, tinfo->value->data);
- switch (ret = cursor->insert(cursor)) {
- case 0:
- break;
- case WT_CACHE_FULL:
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
- default:
- testutil_die(ret,
- "row_insert: insert row %" PRIu64 " by key", tinfo->keyno);
- }
-
#ifdef HAVE_BERKELEY_DB
if (SINGLETHREADED)
bdb_update(
@@ -2041,15 +1939,10 @@ col_insert(TINFO *tinfo, WT_CURSOR *cursor)
cursor->set_value(cursor, *(uint8_t *)tinfo->value->data);
else
cursor->set_value(cursor, tinfo->value);
- switch (ret = cursor->insert(cursor)) {
- case 0:
- break;
- case WT_CACHE_FULL:
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
- default:
- testutil_die(ret, "cursor.insert");
- }
+
+ if ((ret = cursor->insert(cursor)) != 0)
+ return (ret);
+
testutil_check(cursor->get_key(cursor, &tinfo->keyno));
table_append(tinfo->keyno); /* Extend the object. */
@@ -2093,23 +1986,16 @@ row_remove(TINFO *tinfo, WT_CURSOR *cursor, bool positioned)
cursor->set_key(cursor, tinfo->key);
}
- if (g.logging == LOG_OPS)
- (void)g.wt_api->msg_printf(g.wt_api,
- cursor->session, "%-10s%" PRIu64, "remove", tinfo->keyno);
-
/* We use the cursor in overwrite mode, check for existence. */
if ((ret = cursor->search(cursor)) == 0)
ret = cursor->remove(cursor);
- switch (ret) {
- case 0:
- case WT_NOTFOUND:
- break;
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
- default:
- testutil_die(ret,
- "row_remove: remove %" PRIu64 " by key", tinfo->keyno);
- }
+
+ if (ret != 0 && ret != WT_NOTFOUND)
+ return (ret);
+
+ if (g.logging == LOG_OPS)
+ (void)g.wt_api->msg_printf(g.wt_api,
+ cursor->session, "%-10s%" PRIu64, "remove", tinfo->keyno);
#ifdef HAVE_BERKELEY_DB
if (SINGLETHREADED) {
@@ -2134,23 +2020,16 @@ col_remove(TINFO *tinfo, WT_CURSOR *cursor, bool positioned)
if (!positioned)
cursor->set_key(cursor, tinfo->keyno);
- if (g.logging == LOG_OPS)
- (void)g.wt_api->msg_printf(g.wt_api,
- cursor->session, "%-10s%" PRIu64, "remove", tinfo->keyno);
-
/* We use the cursor in overwrite mode, check for existence. */
if ((ret = cursor->search(cursor)) == 0)
ret = cursor->remove(cursor);
- switch (ret) {
- case 0:
- case WT_NOTFOUND:
- break;
- case WT_ROLLBACK:
- return (WT_ROLLBACK);
- default:
- testutil_die(ret,
- "col_remove: remove %" PRIu64 " by key", tinfo->keyno);
- }
+
+ if (ret != 0 && ret != WT_NOTFOUND)
+ return (ret);
+
+ if (g.logging == LOG_OPS)
+ (void)g.wt_api->msg_printf(g.wt_api,
+ cursor->session, "%-10s%" PRIu64, "remove", tinfo->keyno);
#ifdef HAVE_BERKELEY_DB
if (SINGLETHREADED) {
diff --git a/src/third_party/wiredtiger/test/suite/test_cursor14.py b/src/third_party/wiredtiger/test/suite/test_cursor14.py
new file mode 100644
index 00000000000..25bd0cec00a
--- /dev/null
+++ b/src/third_party/wiredtiger/test/suite/test_cursor14.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2018 MongoDB, Inc.
+# Public Domain 2008-2014 WiredTiger, Inc.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+import wiredtiger, wttest
+from wtdataset import SimpleDataSet, ComplexDataSet, ComplexLSMDataSet
+from wtscenario import make_scenarios
+
+# test_cursor14.py
+# Test that more than 64K cursors can be opened on a data source
+class test_cursor14(wttest.WiredTigerTestCase):
+ scenarios = make_scenarios([
+ ('file-r', dict(type='file:', keyfmt='r', dataset=SimpleDataSet)),
+ ('file-S', dict(type='file:', keyfmt='S', dataset=SimpleDataSet)),
+ ('lsm-S', dict(type='lsm:', keyfmt='S', dataset=SimpleDataSet)),
+ ('table-r', dict(type='table:', keyfmt='r', dataset=SimpleDataSet)),
+ ('table-S', dict(type='table:', keyfmt='S', dataset=SimpleDataSet)),
+ ('table-r-complex', dict(type='table:', keyfmt='r',
+ dataset=ComplexDataSet)),
+ ('table-S-complex', dict(type='table:', keyfmt='S',
+ dataset=ComplexDataSet)),
+ ('table-S-complex-lsm', dict(type='table:', keyfmt='S',
+ dataset=ComplexLSMDataSet)),
+ ])
+
+ def test_cursor14(self):
+ uri = self.type + 'cursor14'
+
+ ds = self.dataset(self, uri, 100, key_format=self.keyfmt)
+ ds.populate()
+
+ for i in xrange(66000):
+ cursor = self.session.open_cursor(uri, None, None)
+
+if __name__ == '__main__':
+ wttest.run()
diff --git a/src/third_party/wiredtiger/test/suite/test_prepare04.py b/src/third_party/wiredtiger/test/suite/test_prepare04.py
new file mode 100644
index 00000000000..af5dd12b1e5
--- /dev/null
+++ b/src/third_party/wiredtiger/test/suite/test_prepare04.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2018 MongoDB, Inc.
+# Public Domain 2008-2014 WiredTiger, Inc.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# test_prepare04.py
+# Prepare: prepare conflict with update and read operations
+#
+
+import random
+from suite_subprocess import suite_subprocess
+import wiredtiger, wttest
+from wtscenario import make_scenarios
+
+def timestamp_str(t):
+ return '%x' % t
+
+class test_prepare04(wttest.WiredTigerTestCase, suite_subprocess):
+ tablename = 'test_prepare_cursor'
+ uri = 'table:' + tablename
+ before_ts = timestamp_str(150)
+ prepare_ts = timestamp_str(200)
+ after_ts = timestamp_str(250)
+
+ types = [
+ ('col', dict(extra_config=',log=(enabled=false),key_format=r')),
+ ('lsm', dict(extra_config=',log=(enabled=false),type=lsm')),
+ ('row', dict(extra_config=',log=(enabled=false)')),
+ ]
+
+ # Various begin_transaction config
+ txncfg = [
+ ('before_ts', dict(txn_config='isolation=snapshot,read_timestamp=' + before_ts, after_ts=False)),
+ ('after_ts', dict(txn_config='isolation=snapshot,read_timestamp=' + after_ts, after_ts=True)),
+ ('no_ts', dict(txn_config='isolation=snapshot', after_ts=True)),
+ ]
+
+ preparecfg = [
+ ('ignore_false', dict(ignore_config=',ignore_prepare=false', ignore=False)),
+ ('ignore_true', dict(ignore_config=',ignore_prepare=true', ignore=True)),
+ ]
+ conn_config = 'log=(enabled)'
+
+ scenarios = make_scenarios(types, txncfg, preparecfg)
+
+ def test_prepare_conflict(self):
+ if not wiredtiger.timestamp_build():
+ self.skipTest('requires a timestamp build')
+
+ self.session.create(self.uri,
+ 'key_format=i,value_format=i' + self.extra_config)
+ c = self.session.open_cursor(self.uri)
+
+ # Insert keys 1..100 each with timestamp=key, in some order
+ orig_keys = range(1, 101)
+ keys = orig_keys[:]
+ random.shuffle(keys)
+
+ k = 1
+ self.session.begin_transaction()
+ c[k] = 1
+ self.session.commit_transaction('commit_timestamp=' + timestamp_str(100))
+
+ # Everything up to and including timestamp 100 has been committed.
+ self.assertTimestampsEqual(self.conn.query_timestamp(), timestamp_str(100))
+
+ # Bump the oldest timestamp, we're not going back...
+ self.conn.set_timestamp('oldest_timestamp=' + timestamp_str(100))
+
+ # make prepared updates.
+ k = 1
+ self.session.begin_transaction('isolation=snapshot')
+ c.set_key(1)
+ c.set_value(2)
+ c.update()
+ self.session.prepare_transaction('prepare_timestamp=' + self.prepare_ts)
+ conflictmsg = '/conflict between concurrent operations/'
+ preparemsg = '/conflict with a prepared update/'
+
+ #'''
+ # Verify data visibility from a different session/transaction.
+ s_other = self.conn.open_session()
+ c_other = s_other.open_cursor(self.uri, None)
+ s_other.begin_transaction(self.txn_config + self.ignore_config)
+ c_other.set_key(1)
+ if self.ignore == False and self.after_ts == True:
+ self.assertRaises(wiredtiger.WiredTigerError, lambda:c_other.search())
+ else:
+ c_other.search()
+ self.assertTrue(c_other.get_value() == 1)
+ c_other.set_value(3)
+ self.assertRaises(wiredtiger.WiredTigerError, lambda:c_other.update())
+ s_other.commit_transaction()
+ #'''
+
+ self.session.commit_transaction('commit_timestamp=' + timestamp_str(300))
+
+if __name__ == '__main__':
+ wttest.run()
diff --git a/src/third_party/wiredtiger/test/suite/test_timestamp04.py b/src/third_party/wiredtiger/test/suite/test_timestamp04.py
index 48ec7fac9a6..83ed4e904a6 100644
--- a/src/third_party/wiredtiger/test/suite/test_timestamp04.py
+++ b/src/third_party/wiredtiger/test/suite/test_timestamp04.py
@@ -32,6 +32,7 @@
from suite_subprocess import suite_subprocess
import wiredtiger, wttest
+from wiredtiger import stat
from wtscenario import make_scenarios
def timestamp_str(t):
@@ -98,7 +99,7 @@ class test_timestamp04(wttest.WiredTigerTestCase, suite_subprocess):
def ConnectionOpen(self, cacheSize):
self.home = '.'
- conn_params = 'create,' + \
+ conn_params = 'create,statistics=(fast),' + \
cacheSize + ',error_prefix="%s" %s' % (self.shortid(), self.conn_config)
try:
self.conn = wiredtiger.wiredtiger_open(self.home, conn_params)
@@ -164,6 +165,12 @@ class test_timestamp04(wttest.WiredTigerTestCase, suite_subprocess):
stable_ts = timestamp_str(key_range / 2)
self.conn.set_timestamp('stable_timestamp=' + stable_ts)
self.conn.rollback_to_stable()
+ stat_cursor = self.session.open_cursor('statistics:', None, None)
+ calls = stat_cursor[stat.conn.txn_rollback_to_stable][2]
+ upd_aborted = stat_cursor[stat.conn.txn_rollback_upd_aborted][2]
+ stat_cursor.close()
+ self.assertEqual(calls, 1)
+ self.assertTrue(upd_aborted >= key_range/2)
# Check that we see the inserted value (i.e. 1) for all the keys in
# non-timestamp tables.
@@ -224,9 +231,20 @@ class test_timestamp04(wttest.WiredTigerTestCase, suite_subprocess):
# Scenario: 4
# Advance the stable_timestamp by a quarter range and rollback.
# Three-fourths of the later timestamps will be rolled back.
- stable_ts = timestamp_str(key_range + key_range / 4)
+ rolled_range = key_range + key_range / 4
+ stable_ts = timestamp_str(rolled_range)
self.conn.set_timestamp('stable_timestamp=' + stable_ts)
self.conn.rollback_to_stable()
+ stat_cursor = self.session.open_cursor('statistics:', None, None)
+ calls = stat_cursor[stat.conn.txn_rollback_to_stable][2]
+ upd_aborted = stat_cursor[stat.conn.txn_rollback_upd_aborted][2]
+ stat_cursor.close()
+ self.assertEqual(calls, 2)
+ #
+ # We rolled back half on the earlier call and now three-quarters on
+ # this call, which is one and one quarter of all keys rolled back.
+ #
+ self.assertTrue(upd_aborted >= rolled_range)
# Check that we see the updated value (i.e. 2) for all the keys in
# non-timestamped tables.
diff --git a/src/third_party/wiredtiger/test/suite/test_timestamp10.py b/src/third_party/wiredtiger/test/suite/test_timestamp10.py
index a798f5ff355..02b22e6afbe 100644
--- a/src/third_party/wiredtiger/test/suite/test_timestamp10.py
+++ b/src/third_party/wiredtiger/test/suite/test_timestamp10.py
@@ -27,7 +27,7 @@
# OTHER DEALINGS IN THE SOFTWARE.
#
# test_timestamp10.py
-# Timestamps: Saving and querying the checkpoint recovery timestamp
+# Timestamps: Saving and querying the last checkpoint and recovery timestamps
#
import fnmatch, os, shutil
@@ -101,6 +101,8 @@ class test_timestamp10(wttest.WiredTigerTestCase, suite_subprocess):
',stable_timestamp=' + timestamp_str(ts))
# This forces a different checkpoint timestamp for each table.
self.session.checkpoint()
+ q = self.conn.query_timestamp('get=last_checkpoint')
+ self.assertTimestampsEqual(q, timestamp_str(ts))
# Copy to a new database and then recover.
self.copy_dir(".", "RESTART")