diff options
Diffstat (limited to 'src/third_party/wiredtiger/test')
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, ¬found); @@ -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") |