diff options
author | Alex Gorrod <alexander.gorrod@mongodb.com> | 2017-10-10 16:29:49 +1100 |
---|---|---|
committer | Alex Gorrod <alexander.gorrod@mongodb.com> | 2017-10-10 16:37:55 +1100 |
commit | 39998ac6928c4e7f3acd2f7ee2fc5fb4df056c18 (patch) | |
tree | c075233cd32c6ec0205af77db475836c0fba60e9 /src/third_party/wiredtiger/test | |
parent | dd094ce1bc1fb424ccc6dd71939e5c7a30159e2e (diff) | |
download | mongo-39998ac6928c4e7f3acd2f7ee2fc5fb4df056c18.tar.gz |
Import wiredtiger: 0cd3d5bbd8a5c8779f1129c6754b4463403e788f from branch mongodb-3.6
ref: 6f561957cb..0cd3d5bbd8
for: 3.5.14
WT-3200 LSM bug: Failed lookup in bloom filter.
WT-3435 Lookaside eviction should be able to save unstable updates
WT-3453 Enhance lookaside table test coverage in Python suite
WT-3559 Detect when a checkpoint races with metadata changes
WT-3579 Enhance support for running wtperf workloads with workgen
WT-3582 Cache stuck full of internal pages
WT-3593 Add an API to enforce consistent use of timestamps (#3667)
WT-3599 reconciliation calculates block matching checksums too frequently.
WT-3600 timestamp API lets you set timestamps with invalid characters
WT-3612 Improve documentation of durability with backup cursors
WT-3613 test/format cache full with LSM
WT-3618 WT remove solaris from evergreen builds
WT-3620 POSIX thread attribute structures must be destroyed
WT-3621 Add test for full backups with concurrent table creation
WT-3622 Allow upper case hexadecimal timestamps
WT-3627 test_txn14.test_txn14.test_log_flush timeout
WT-3631 Convert timestamps to integers in Python tests before comparing
WT-3636 Account for page image sizes in cache consistently
WT-3638 format failure, update list without complete visible record
WT-3639 Test/format tried to drop named checkpoints during a hot backup
WT-3641 Track maximum timestamp used in each btree
WT-3642 Avoid lookaside reads for dead trees
Diffstat (limited to 'src/third_party/wiredtiger/test')
22 files changed, 800 insertions, 185 deletions
diff --git a/src/third_party/wiredtiger/test/fops/file.c b/src/third_party/wiredtiger/test/fops/file.c index 60320ae3a38..118845ab805 100644 --- a/src/third_party/wiredtiger/test/fops/file.c +++ b/src/third_party/wiredtiger/test/fops/file.c @@ -39,6 +39,8 @@ obj_bulk(void) testutil_check(conn->open_session(conn, NULL, NULL, &session)); + if (use_txn) + testutil_check(session->begin_transaction(session, NULL)); if ((ret = session->create(session, uri, config)) != 0) if (ret != EEXIST && ret != EBUSY) testutil_die(ret, "session.create"); @@ -51,6 +53,21 @@ obj_bulk(void) } else if (ret != ENOENT && ret != EBUSY && ret != EINVAL) testutil_die(ret, "session.open_cursor bulk"); } + + if (use_txn) { + /* + * As the operations are being performed concurrently, + * return value can be ENOENT, EBUSY or EINVAL will set + * error to transaction opened by session. In these + * cases the transaction has to be aborted. + */ + if (ret != ENOENT && ret != EBUSY && ret != EINVAL) + ret = session->commit_transaction(session, NULL); + else + ret = session->rollback_transaction(session, NULL); + if (ret == EINVAL) + testutil_die(ret, "session.commit bulk"); + } testutil_check(session->close(session, NULL)); } @@ -70,6 +87,8 @@ obj_bulk_unique(int force) new_uri, sizeof(new_uri), "%s.%u", uri, ++uid)); testutil_check(pthread_rwlock_unlock(&single)); + if (use_txn) + testutil_check(session->begin_transaction(session, NULL)); testutil_check(session->create(session, new_uri, config)); __wt_yield(); @@ -89,6 +108,10 @@ obj_bulk_unique(int force) if (ret != EBUSY) testutil_die(ret, "session.drop: %s", new_uri); + if (use_txn && + (ret = session->commit_transaction(session, NULL)) != 0 && + ret != EINVAL) + testutil_die(ret, "session.commit bulk unique"); testutil_check(session->close(session, NULL)); } @@ -101,12 +124,19 @@ obj_cursor(void) testutil_check(conn->open_session(conn, NULL, NULL, &session)); + if (use_txn) + testutil_check(session->begin_transaction(session, NULL)); if ((ret = session->open_cursor(session, uri, NULL, NULL, &cursor)) != 0) { if (ret != ENOENT && ret != EBUSY) testutil_die(ret, "session.open_cursor"); } else testutil_check(cursor->close(cursor)); + + if (use_txn && + (ret = session->commit_transaction(session, NULL)) != 0 && + ret != EINVAL) + testutil_die(ret, "session.commit cursor"); testutil_check(session->close(session, NULL)); } @@ -118,10 +148,16 @@ obj_create(void) testutil_check(conn->open_session(conn, NULL, NULL, &session)); + if (use_txn) + testutil_check(session->begin_transaction(session, NULL)); if ((ret = session->create(session, uri, config)) != 0) if (ret != EEXIST && ret != EBUSY) testutil_die(ret, "session.create"); + if (use_txn && + (ret = session->commit_transaction(session, NULL)) != 0 && + ret != EINVAL) + testutil_die(ret, "session.commit create"); testutil_check(session->close(session, NULL)); } @@ -140,13 +176,25 @@ obj_create_unique(int force) new_uri, sizeof(new_uri), "%s.%u", uri, ++uid)); testutil_check(pthread_rwlock_unlock(&single)); + if (use_txn) + testutil_check(session->begin_transaction(session, NULL)); testutil_check(session->create(session, new_uri, config)); + if (use_txn && + (ret = session->commit_transaction(session, NULL)) != 0 && + ret != EINVAL) + testutil_die(ret, "session.commit create unique"); __wt_yield(); + if (use_txn) + testutil_check(session->begin_transaction(session, NULL)); while ((ret = session->drop( session, new_uri, force ? "force" : NULL)) != 0) if (ret != EBUSY) testutil_die(ret, "session.drop: %s", new_uri); + if (use_txn && + (ret = session->commit_transaction(session, NULL)) != 0 && + ret != EINVAL) + testutil_die(ret, "session.commit create unique"); testutil_check(session->close(session, NULL)); } @@ -159,10 +207,26 @@ obj_drop(int force) testutil_check(conn->open_session(conn, NULL, NULL, &session)); + if (use_txn) + testutil_check(session->begin_transaction(session, NULL)); if ((ret = session->drop(session, uri, force ? "force" : NULL)) != 0) if (ret != ENOENT && ret != EBUSY) testutil_die(ret, "session.drop"); + if (use_txn) { + /* + * As the operations are being performed concurrently, + * return value can be ENOENT or EBUSY will set + * error to transaction opened by session. In these + * cases the transaction has to be aborted. + */ + if (ret != ENOENT && ret != EBUSY) + ret = session->commit_transaction(session, NULL); + else + ret = session->rollback_transaction(session, NULL); + if (ret == EINVAL) + testutil_die(ret, "session.commit drop"); + } testutil_check(session->close(session, NULL)); } diff --git a/src/third_party/wiredtiger/test/fops/t.c b/src/third_party/wiredtiger/test/fops/t.c index b6b80ba5db8..fcbbdcabd73 100644 --- a/src/third_party/wiredtiger/test/fops/t.c +++ b/src/third_party/wiredtiger/test/fops/t.c @@ -28,6 +28,7 @@ #include "thread.h" +bool use_txn; /* Operations with user txn */ WT_CONNECTION *conn; /* WiredTiger connection */ pthread_rwlock_t single; /* Single thread */ u_int nops; /* Operations */ @@ -77,8 +78,9 @@ main(int argc, char *argv[]) nops = 1000; nthreads = 10; runs = 1; + use_txn = false; config_open = working_dir = NULL; - while ((ch = __wt_getopt(progname, argc, argv, "C:h:l:n:r:t:")) != EOF) + while ((ch = __wt_getopt(progname, argc, argv, "C:h:l:n:r:t:x")) != EOF) switch (ch) { case 'C': /* wiredtiger_open config */ config_open = __wt_optarg; @@ -102,6 +104,9 @@ main(int argc, char *argv[]) case 't': nthreads = (u_int)atoi(__wt_optarg); break; + case 'x': + use_txn = true; + break; default: return (usage()); } @@ -245,7 +250,8 @@ usage(void) { fprintf(stderr, "usage: %s " - "[-C wiredtiger-config] [-l log] [-n ops] [-r runs] [-t threads]\n", + "[-C wiredtiger-config] [-l log] [-n ops] [-r runs] [-t threads] " + "[-x] \n", progname); fprintf(stderr, "%s", "\t-C specify wiredtiger_open configuration arguments\n" @@ -253,6 +259,7 @@ usage(void) "\t-l specify a log file\n" "\t-n set number of operations each thread does\n" "\t-r set number of runs\n" - "\t-t set number of threads\n"); + "\t-t set number of threads\n" + "\t-x operations within user transaction \n"); return (EXIT_FAILURE); } diff --git a/src/third_party/wiredtiger/test/fops/thread.h b/src/third_party/wiredtiger/test/fops/thread.h index f6b6bdffd63..0df36025be0 100644 --- a/src/third_party/wiredtiger/test/fops/thread.h +++ b/src/third_party/wiredtiger/test/fops/thread.h @@ -30,6 +30,7 @@ #include <signal.h> +extern bool use_txn; /* Operations with user txn */ extern WT_CONNECTION *conn; /* WiredTiger connection */ extern u_int nops; /* Operations per thread */ diff --git a/src/third_party/wiredtiger/test/format/format.h b/src/third_party/wiredtiger/test/format/format.h index 81b7fa27f79..f35e71f58aa 100644 --- a/src/third_party/wiredtiger/test/format/format.h +++ b/src/third_party/wiredtiger/test/format/format.h @@ -287,6 +287,7 @@ void bdb_update(const void *, size_t, const void *, size_t); WT_THREAD_RET alter(void *); WT_THREAD_RET backup(void *); +WT_THREAD_RET checkpoint(void *); WT_THREAD_RET compact(void *); void config_clear(void); void config_error(void); diff --git a/src/third_party/wiredtiger/test/format/ops.c b/src/third_party/wiredtiger/test/format/ops.c index f4770465628..4fed18d12b4 100644 --- a/src/third_party/wiredtiger/test/format/ops.c +++ b/src/third_party/wiredtiger/test/format/ops.c @@ -76,7 +76,8 @@ wts_ops(int lastrun) TINFO **tinfo_list, *tinfo, total; WT_CONNECTION *conn; WT_SESSION *session; - wt_thread_t alter_tid, backup_tid, compact_tid, lrt_tid, timestamp_tid; + wt_thread_t alter_tid, backup_tid, checkpoint_tid, compact_tid, lrt_tid; + wt_thread_t timestamp_tid; int64_t fourths, quit_fourths, thread_ops; uint32_t i; bool running; @@ -86,6 +87,7 @@ wts_ops(int lastrun) session = NULL; /* -Wconditional-uninitialized */ memset(&alter_tid, 0, sizeof(alter_tid)); memset(&backup_tid, 0, sizeof(backup_tid)); + memset(&checkpoint_tid, 0, sizeof(checkpoint_tid)); memset(&compact_tid, 0, sizeof(compact_tid)); memset(&lrt_tid, 0, sizeof(lrt_tid)); memset(×tamp_tid, 0, sizeof(timestamp_tid)); @@ -173,6 +175,9 @@ wts_ops(int lastrun) if (g.c_backups) testutil_check( __wt_thread_create(NULL, &backup_tid, backup, NULL)); + if (g.c_checkpoints) + testutil_check(__wt_thread_create( + NULL, &checkpoint_tid, checkpoint, NULL)); if (g.c_compact) testutil_check( __wt_thread_create(NULL, &compact_tid, compact, NULL)); @@ -247,6 +252,8 @@ wts_ops(int lastrun) testutil_check(__wt_thread_join(NULL, alter_tid)); if (g.c_backups) testutil_check(__wt_thread_join(NULL, backup_tid)); + if (g.c_checkpoints) + testutil_check(__wt_thread_join(NULL, checkpoint_tid)); if (g.c_compact) testutil_check(__wt_thread_join(NULL, compact_tid)); if (!SINGLETHREADED && g.c_long_running_txn) @@ -514,12 +521,11 @@ ops(void *arg) WT_DECL_RET; WT_ITEM *key, _key, *value, _value; WT_SESSION *session; - uint64_t ckpt_op, keyno, reset_op, session_op; + uint64_t keyno, reset_op, session_op; uint32_t rnd; u_int i, iso_config; int dir; - char *ckpt_config, ckpt_name[64]; - bool ckpt_available, intxn, positioned, readonly; + bool intxn, positioned, readonly; tinfo = arg; @@ -542,58 +548,61 @@ ops(void *arg) session = NULL; session_op = 0; - /* Set the first operation where we'll perform checkpoint operations. */ - ckpt_op = g.c_checkpoints ? mmrand(&tinfo->rnd, 100, 10000) : 0; - ckpt_available = false; - /* Set the first operation where we'll reset the session. */ reset_op = mmrand(&tinfo->rnd, 100, 10000); for (intxn = false; !tinfo->quit; ++tinfo->ops) { - /* - * We can't checkpoint or swap sessions/cursors while in a - * transaction, resolve any running transaction. - */ - if (intxn && - (tinfo->ops == ckpt_op || tinfo->ops == session_op)) { - commit_transaction(tinfo, session); - intxn = false; - } - - /* Open up a new session and cursors. */ - if (tinfo->ops == session_op || + /* Periodically open up a new session and cursors. */ + if (tinfo->ops > session_op || session == NULL || cursor == NULL) { + /* + * We can't swap sessions/cursors if in a transaction, + * resolve any running transaction. + */ + if (intxn) { + commit_transaction(tinfo, session); + intxn = false; + } + if (session != NULL) testutil_check(session->close(session, NULL)); - testutil_check( conn->open_session(conn, NULL, NULL, &session)); + /* Pick the next session/cursor close/open. */ + session_op += mmrand(&tinfo->rnd, 100, 5000); + /* * 10% of the time, perform some read-only operations * from a checkpoint. * - * Skip that if we are single-threaded and doing checks - * against a Berkeley DB database, because that won't - * work because the Berkeley DB database records won't - * match the checkpoint. Also skip if we are using - * LSM, because it doesn't support reads from - * checkpoints. + * Skip if single-threaded and doing checks against a + * Berkeley DB database, that won't work because the + * Berkeley DB database won't match the checkpoint. + * + * Skip if we are using data-sources or LSM, they don't + * support reading from checkpoints. */ - if (!SINGLETHREADED && !DATASOURCE("lsm") && - ckpt_available && mmrand(&tinfo->rnd, 1, 10) == 1) { + if (!SINGLETHREADED && !DATASOURCE("helium") && + !DATASOURCE("kvsbdb") && !DATASOURCE("lsm") && + mmrand(&tinfo->rnd, 1, 10) == 1) { /* * open_cursor can return EBUSY if concurrent * with a metadata operation, retry. */ while ((ret = session->open_cursor(session, - g.uri, NULL, ckpt_name, &cursor)) == EBUSY) + g.uri, NULL, + "checkpoint=WiredTigerCheckpoint", + &cursor)) == EBUSY) __wt_yield(); + /* + * If the checkpoint hasn't been created yet, + * ignore the error. + */ + if (ret == ENOENT) + continue; testutil_check(ret); - /* Pick the next session/cursor close/open. */ - session_op += 250; - /* Checkpoints are read-only. */ readonly = true; } else { @@ -608,75 +617,11 @@ ops(void *arg) __wt_yield(); testutil_check(ret); - /* Pick the next session/cursor close/open. */ - session_op += mmrand(&tinfo->rnd, 100, 5000); - /* Updates supported. */ readonly = false; } } - /* Checkpoint the database. */ - if (tinfo->ops == ckpt_op && g.c_checkpoints) { - /* - * Checkpoints are single-threaded inside WiredTiger, - * skip our checkpoint if another thread is already - * doing one. - */ - ret = pthread_rwlock_trywrlock(&g.checkpoint_lock); - if (ret == EBUSY) - goto skip_checkpoint; - testutil_check(ret); - - /* - * LSM and data-sources don't support named checkpoints - * and we can't drop a named checkpoint while there's a - * backup in progress, otherwise name the checkpoint 5% - * of the time. - */ - if (mmrand(&tinfo->rnd, 1, 20) != 1 || - DATASOURCE("helium") || - DATASOURCE("kvsbdb") || DATASOURCE("lsm") || - pthread_rwlock_trywrlock(&g.backup_lock) == EBUSY) - ckpt_config = NULL; - else { - testutil_check(__wt_snprintf( - ckpt_name, sizeof(ckpt_name), - "name=thread-%d", tinfo->id)); - ckpt_config = ckpt_name; - } - - ret = session->checkpoint(session, ckpt_config); - /* - * We may be trying to create a named checkpoint while - * we hold a cursor open to the previous checkpoint. - * Tolerate EBUSY. - */ - if (ret != 0 && ret != EBUSY) - testutil_die(ret, "%s", - ckpt_config == NULL ? "" : ckpt_config); - ret = 0; - - if (ckpt_config != NULL) - testutil_check( - pthread_rwlock_unlock(&g.backup_lock)); - testutil_check( - pthread_rwlock_unlock(&g.checkpoint_lock)); - - /* Rephrase the checkpoint name for cursor open. */ - if (ckpt_config == NULL) - strcpy(ckpt_name, - "checkpoint=WiredTigerCheckpoint"); - else - testutil_check(__wt_snprintf( - ckpt_name, sizeof(ckpt_name), - "checkpoint=thread-%d", tinfo->id)); - ckpt_available = true; - -skip_checkpoint: /* Pick the next checkpoint operation. */ - ckpt_op += mmrand(&tinfo->rnd, 5000, 20000); - } - /* * Reset the session every now and then, just to make sure that * operation gets tested. Note the test is not for equality, we diff --git a/src/third_party/wiredtiger/test/format/t.c b/src/third_party/wiredtiger/test/format/t.c index dc288ba4bc2..02ed0a2da60 100644 --- a/src/third_party/wiredtiger/test/format/t.c +++ b/src/third_party/wiredtiger/test/format/t.c @@ -169,7 +169,6 @@ main(int argc, char *argv[]) */ testutil_check(pthread_rwlock_init(&g.append_lock, NULL)); testutil_check(pthread_rwlock_init(&g.backup_lock, NULL)); - testutil_check(pthread_rwlock_init(&g.checkpoint_lock, NULL)); testutil_check(pthread_rwlock_init(&g.death_lock, NULL)); printf("%s: process %" PRIdMAX "\n", progname, (intmax_t)getpid()); @@ -267,7 +266,6 @@ main(int argc, char *argv[]) testutil_check(pthread_rwlock_destroy(&g.append_lock)); testutil_check(pthread_rwlock_destroy(&g.backup_lock)); - testutil_check(pthread_rwlock_destroy(&g.checkpoint_lock)); testutil_check(pthread_rwlock_destroy(&g.death_lock)); config_clear(); diff --git a/src/third_party/wiredtiger/test/format/util.c b/src/third_party/wiredtiger/test/format/util.c index 98af8e766f1..9ea44a29801 100644 --- a/src/third_party/wiredtiger/test/format/util.c +++ b/src/third_party/wiredtiger/test/format/util.c @@ -501,6 +501,86 @@ fclose_and_clear(FILE **fpp) } /* + * checkpoint -- + * Periodically take a checkpoint + */ +WT_THREAD_RET +checkpoint(void *arg) +{ + WT_CONNECTION *conn; + WT_DECL_RET; + WT_SESSION *session; + u_int secs; + const char *ckpt_config; + char config_buf[64]; + bool backup_locked; + + (void)arg; + conn = g.wts_conn; + testutil_check(conn->open_session(conn, NULL, NULL, &session)); + + for (secs = mmrand(NULL, 1, 10); !g.workers_finished;) { + if (secs > 0) { + __wt_sleep(1, 0); + --secs; + continue; + } + + /* + * LSM and data-sources don't support named checkpoints. Also, + * don't attempt named checkpoints during a hot backup. It's + * OK to create named checkpoints during a hot backup, but we + * can't delete them, so repeating an already existing named + * checkpoint will fail when we can't drop the previous one. + */ + ckpt_config = NULL; + backup_locked = false; + if (!DATASOURCE("helium") && !DATASOURCE("kvsbdb") && + !DATASOURCE("lsm")) + switch (mmrand(NULL, 1, 20)) { + case 1: + /* + * 5% create a named snapshot. Rotate between a + * few names to test multiple named snapshots in + * the system. + */ + ret = pthread_rwlock_trywrlock(&g.backup_lock); + if (ret == 0) { + backup_locked = true; + testutil_check(__wt_snprintf( + config_buf, sizeof(config_buf), + "name=mine.%" PRIu32, + mmrand(NULL, 1, 4))); + ckpt_config = config_buf; + } else if (ret != EBUSY) + testutil_check(ret); + break; + case 2: + /* + * 5% drop all named snapshots. + */ + ret = pthread_rwlock_trywrlock(&g.backup_lock); + if (ret == 0) { + backup_locked = true; + ckpt_config = "drop=(all)"; + } else if (ret != EBUSY) + testutil_check(ret); + break; + } + + testutil_check(session->checkpoint(session, ckpt_config)); + + if (backup_locked) + testutil_check(pthread_rwlock_unlock(&g.backup_lock)); + + secs = mmrand(NULL, 5, 40); + } + + testutil_check(session->close(session, NULL)); + return (WT_THREAD_RET_VALUE); +} + +/* * timestamp -- * Periodically update the oldest timestamp. */ diff --git a/src/third_party/wiredtiger/test/mciproject.yml b/src/third_party/wiredtiger/test/mciproject.yml index 72022fe46ec..4b67299d14c 100644 --- a/src/third_party/wiredtiger/test/mciproject.yml +++ b/src/third_party/wiredtiger/test/mciproject.yml @@ -167,20 +167,6 @@ buildvariants: - name: unit-test - name: fops -- name: solaris - display_name: Solaris - run_on: - - solaris - expansions: - make_command: PATH=/opt/mongodbtoolchain/bin:$PATH gmake - test_env_vars: LD_LIBRARY_PATH=`pwd`/.libs - smp_command: -j $(kstat cpu | sort -u | grep -c "^module") - configure_env_vars: PATH=/opt/mongodbtoolchain/bin:$PATH CFLAGS="-m64" - tasks: - - name: compile - - name: unit-test - - name: fops - - name: windows-64 display_name: Windows 64-bit run_on: diff --git a/src/third_party/wiredtiger/test/suite/test_assert01.py b/src/third_party/wiredtiger/test/suite/test_assert01.py new file mode 100644 index 00000000000..3a4f8e4127a --- /dev/null +++ b/src/third_party/wiredtiger/test/suite/test_assert01.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# +# Public Domain 2014-2017 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_assert01.py +# Timestamps: assert commit settings +# + +from suite_subprocess import suite_subprocess +import wiredtiger, wttest + +def timestamp_str(t): + return '%x' % t + +class test_assert01(wttest.WiredTigerTestCase, suite_subprocess): + base = 'assert01' + base_uri = 'file:' + base + uri_always = base_uri + '.always.wt' + uri_def = base_uri + '.def.wt' + uri_never = base_uri + '.never.wt' + uri_none = base_uri + '.none.wt' + cfg = 'key_format=S,value_format=S,' + cfg_always = 'assert=(commit_timestamp=always)' + cfg_def = '' + cfg_never = 'assert=(commit_timestamp=never)' + cfg_none = 'assert=(commit_timestamp=none)' + + count = 1 + # + # Commit a k/v pair making sure that it detects an error if needed, when + # used with and without a commit timestamp. + # + def insert_check(self, uri, use_ts): + c = self.session.open_cursor(uri) + key = 'key' + str(self.count) + val = 'value' + str(self.count) + + # Commit with a timestamp + self.session.begin_transaction() + self.session.timestamp_transaction( + 'commit_timestamp=' + timestamp_str(self.count)) + c[key] = val + # All settings other than never should commit successfully + if (use_ts != 'never'): + self.session.commit_transaction() + else: + msg = "/timestamp set on this transaction/" + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, + lambda:self.assertEquals(self.session.commit_transaction(), + 0), msg) + c.close() + self.count += 1 + + # Commit without a timestamp + key = 'key' + str(self.count) + val = 'value' + str(self.count) + c = self.session.open_cursor(uri) + self.session.begin_transaction() + c[key] = val + # All settings other than always should commit successfully + if (use_ts != 'always'): + self.session.commit_transaction() + else: + msg = "/none set on this transaction/" + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, + lambda:self.assertEquals(self.session.commit_transaction(), + 0), msg) + self.count += 1 + c.close() + + def test_commit_timestamp(self): + #if not wiredtiger.timestamp_build() or not wiredtiger.diagnostic_build(): + # self.skipTest('requires a timestamp and diagnostic build') + if not wiredtiger.timestamp_build(): + self.skipTest('requires a timestamp build') + + # Create a data item at a timestamp + self.session.create(self.uri_always, self.cfg + self.cfg_always) + self.session.create(self.uri_def, self.cfg + self.cfg_def) + self.session.create(self.uri_never, self.cfg + self.cfg_never) + self.session.create(self.uri_none, self.cfg + self.cfg_none) + + # Check inserting into each table + self.insert_check(self.uri_always, 'always') + self.insert_check(self.uri_def, 'none') + self.insert_check(self.uri_never, 'never') + self.insert_check(self.uri_none, 'none') + +if __name__ == '__main__': + wttest.run() diff --git a/src/third_party/wiredtiger/test/suite/test_assert02.py b/src/third_party/wiredtiger/test/suite/test_assert02.py new file mode 100644 index 00000000000..d264273c3a0 --- /dev/null +++ b/src/third_party/wiredtiger/test/suite/test_assert02.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python +# +# Public Domain 2014-2017 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_assert02.py +# Timestamps: assert read timestamp settings +# + +from suite_subprocess import suite_subprocess +import wiredtiger, wttest + +def timestamp_str(t): + return '%x' % t + +class test_assert02(wttest.WiredTigerTestCase, suite_subprocess): + def test_read_timestamp(self): + #if not wiredtiger.timestamp_build() or not wiredtiger.diagnostic_build(): + # self.skipTest('requires a timestamp and diagnostic build') + if not wiredtiger.timestamp_build(): + self.skipTest('requires a timestamp build') + + base = 'assert02.' + base_uri = 'file:' + base + uri_always = base_uri + '.always.wt' + uri_def = base_uri + '.def.wt' + uri_never = base_uri + '.never.wt' + uri_none = base_uri + '.none.wt' + + cfg = 'key_format=S,value_format=S' + cfg_always = cfg + ',assert=(read_timestamp=always)' + cfg_def = cfg + cfg_never = cfg + ',assert=(read_timestamp=never)' + cfg_none = cfg + ',assert=(read_timestamp=none)' + + # Create a data item at a timestamp + self.session.create(uri_always, cfg_always) + self.session.create(uri_def, cfg_def) + self.session.create(uri_never, cfg_never) + self.session.create(uri_none, cfg_none) + + # Insert a data item at timestamp 1. This should work for all. + c_always = self.session.open_cursor(uri_always) + c_def = self.session.open_cursor(uri_def) + c_never = self.session.open_cursor(uri_never) + c_none = self.session.open_cursor(uri_none) + self.session.begin_transaction() + self.session.timestamp_transaction( + 'commit_timestamp=' + timestamp_str(1)) + c_always['key1'] = 'value1' + c_def['key1'] = 'value1' + c_never['key1'] = 'value1' + c_none['key1'] = 'value1' + self.session.commit_transaction() + c_always.close() + c_def.close() + c_never.close() + c_none.close() + + # Now that we have a timestamped data, try reading with and without + # the timestamp. + c_always = self.session.open_cursor(uri_always) + c_def = self.session.open_cursor(uri_def) + c_never = self.session.open_cursor(uri_never) + c_none = self.session.open_cursor(uri_none) + + c_always.set_key('key1') + c_def.set_key('key1') + c_never.set_key('key1') + c_none.set_key('key1') + + self.session.begin_transaction('read_timestamp=' + timestamp_str(1)) + c_always.search() + c_def.search() + c_none.search() + self.assertEqual(c_always.get_value(), 'value1') + self.assertEqual(c_def.get_value(), 'value1') + self.assertEqual(c_none.get_value(), 'value1') + + msg = "/timestamp set on this transaction/" + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, + lambda:self.assertEquals(c_never.search(), 0), msg) + self.session.commit_transaction() + c_always.close() + c_def.close() + c_never.close() + c_none.close() + + # Read in a transaction without a timestamp. + c_always = self.session.open_cursor(uri_always) + c_def = self.session.open_cursor(uri_def) + c_never = self.session.open_cursor(uri_never) + c_none = self.session.open_cursor(uri_none) + + c_always.set_key('key1') + c_def.set_key('key1') + c_never.set_key('key1') + c_none.set_key('key1') + + self.session.begin_transaction() + c_never.search() + c_def.search() + c_none.search() + self.assertEqual(c_never.get_value(), 'value1') + self.assertEqual(c_def.get_value(), 'value1') + self.assertEqual(c_none.get_value(), 'value1') + + msg = "/none set on this transaction/" + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, + lambda:self.assertEquals(c_always.search(), 0), msg) + self.session.commit_transaction() + c_always.close() + c_def.close() + c_never.close() + c_none.close() + +if __name__ == '__main__': + wttest.run() diff --git a/src/third_party/wiredtiger/test/suite/test_assert03.py b/src/third_party/wiredtiger/test/suite/test_assert03.py new file mode 100644 index 00000000000..36d4936a82e --- /dev/null +++ b/src/third_party/wiredtiger/test/suite/test_assert03.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# +# Public Domain 2014-2017 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_assert03.py +# Test changing assert setting via alter. +# + +from suite_subprocess import suite_subprocess +import wiredtiger, wttest + +class test_assert03(wttest.WiredTigerTestCase, suite_subprocess): + conn_config = 'log=(enabled)' + base_uri = 'file:assert03.wt' + cfg = 'key_format=S,value_format=S' + always = 'assert=(commit_timestamp=always)' + never = 'assert=(commit_timestamp=never)' + none = 'assert=(commit_timestamp=none)' + + def test_assert03(self): + + #if not wiredtiger.timestamp_build() or not wiredtiger.diagnostic_build(): + # self.skipTest('requires a timestamp and diagnostic build') + if not wiredtiger.timestamp_build(): + self.skipTest('requires a timestamp build') + + # Create a data item at the default setting + self.session.create(self.base_uri, self.cfg) + c = self.session.open_cursor(self.base_uri) + self.session.begin_transaction() + c['key0'] = 'value0' + self.session.commit_transaction() + c.close() + + # Now rotate through the alter settings and verify the data. + # The always setting should fail. + self.session.alter(self.base_uri, self.always) + c = self.session.open_cursor(self.base_uri) + self.session.begin_transaction() + c['key1'] = 'value1' + msg = "/none set on this transaction/" + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, + lambda:self.assertEquals(self.session.commit_transaction(), 0), msg) + c.close() + + # The never and none settings should succeed. + self.session.alter(self.base_uri, self.never) + c = self.session.open_cursor(self.base_uri) + self.session.begin_transaction() + c['key2'] = 'value2' + self.session.commit_transaction() + c.close() + + self.session.alter(self.base_uri, self.none) + c = self.session.open_cursor(self.base_uri) + self.session.begin_transaction() + c['key3'] = 'value3' + self.session.commit_transaction() + c.close() + +if __name__ == '__main__': + wttest.run() diff --git a/src/third_party/wiredtiger/test/suite/test_backup07.py b/src/third_party/wiredtiger/test/suite/test_backup07.py new file mode 100644 index 00000000000..8332815b0ca --- /dev/null +++ b/src/third_party/wiredtiger/test/suite/test_backup07.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python +# +# Public Domain 2014-2017 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 +import os, shutil +from helper import compare_files +from suite_subprocess import suite_subprocess +from wtdataset import simple_key +from wtscenario import make_scenarios + +# test_backup07.py +# Test cursor backup with target URIs, logging and create during backup + +class test_backup07(wttest.WiredTigerTestCase, suite_subprocess): + dir='backup.dir' # Backup directory name + logmax="100K" + newuri="table:newtable" + + pfx = 'test_backup' + scenarios = make_scenarios([ + ('table', dict(uri='table:test',dsize=100,nops=100,nthreads=1)), + ]) + + # Create a large cache, otherwise this test runs quite slowly. + def conn_config(self): + return 'cache_size=1G,log=(archive=false,enabled,file_max=%s)' % \ + self.logmax + + # Run background inserts while running checkpoints and incremental backups + # repeatedly. + def test_backup07(self): + log2 = "WiredTigerLog.0000000002" + + self.session.create(self.uri, "key_format=S,value_format=S") + + # Insert small amounts of data at a time stopping just after we + # cross into log file 2. That way we can add more operations into + # log file 2 during the full backup. + loop = 0 + c = self.session.open_cursor(self.uri) + while not os.path.exists(log2): + for i in range(0, self.nops): + num = i + (loop * self.nops) + key = 'key' + str(num) + val = 'value' + str(num) + c[key] = val + loop += 1 + + # Test a potential bug in full backups and creates. + # We allow creates during backup because the file doesn't exist + # when the backup metadata is created on cursor open and the newly + # created file is not in the cursor list. However, if using logging + # and the create and inserts/updates appear in a log file copied, + # then currently there will be an error opening the backup directory. + + # Open up the backup cursor, create and add data to a new table + # and then copy the files. + os.mkdir(self.dir) + bkup_c = self.session.open_cursor('backup:', None, None) + + # Now create and populate the new table. Make sure the log records + # are on disk and will be copied to the backup. + self.session.create(self.newuri, "key_format=S,value_format=S") + c = self.session.open_cursor(self.newuri) + for i in range(0, self.nops): + key = 'key' + str(i) + val = 'value' + str(i) + c[key] = val + c.close() + self.session.log_flush('sync=on') + + # Now copy the files returned by the backup cursor. This will + # include the log file that has updates for the newly created table. + while True: + ret = bkup_c.next() + if ret != 0: + break + newfile = bkup_c.get_key() + sz = os.path.getsize(newfile) + self.pr('Copy from: ' + newfile + ' (' + str(sz) + ') to ' + self.dir) + shutil.copy(newfile, self.dir) + self.assertEqual(ret, wiredtiger.WT_NOTFOUND) + bkup_c.close() + + # After the full backup, open and recover the backup database. + # Make sure we properly recover even though the log file will have + # records for the newly created table file id. + backup_conn = self.wiredtiger_open(self.dir) + backup_conn.close() + +if __name__ == '__main__': + wttest.run() diff --git a/src/third_party/wiredtiger/test/suite/test_las.py b/src/third_party/wiredtiger/test/suite/test_las.py index d0bd1d108fa..52a0b2d7300 100644 --- a/src/third_party/wiredtiger/test/suite/test_las.py +++ b/src/third_party/wiredtiger/test/suite/test_las.py @@ -26,16 +26,53 @@ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. +from helper import copy_wiredtiger_home import wiredtiger, wttest from wtdataset import SimpleDataSet +def timestamp_str(t): + return '%x' % t + # test_las.py -# Smoke tests to ensure lookaside tables are working. +# Smoke tests to ensure lookaside tables are working. class test_las(wttest.WiredTigerTestCase): # Force a small cache. def conn_config(self): return 'cache_size=1GB' + def large_updates(self, session, uri, value, ds, nrows, timestamp=False): + # Insert a large number of records, we'll hang if the lookaside table + # isn't doing its thing. + cursor = session.open_cursor(uri) + for i in range(1, 1000000): + if timestamp == True: + session.begin_transaction() + cursor.set_key(ds.key(nrows + i)) + cursor.set_value(value) + self.assertEquals(cursor.update(), 0) + if timestamp == True: + session.commit_transaction('commit_timestamp=' + timestamp_str(i + 1)) + cursor.close() + + def durable_check(self, check_value, uri, ds, nrows): + # Checkpoint and backup so as to simulate recovery + self.session.checkpoint() + newdir = "BACKUP" + copy_wiredtiger_home('.', newdir, True) + + conn = self.setUpConnectionOpen(newdir) + session = self.setUpSessionOpen(conn) + cursor = session.open_cursor(uri, None) + # Skip the initial rows, which were not updated + for i in range(0, nrows+1): + self.assertEquals(cursor.next(), 0) + #print "Check value : " + str(check_value) + #print "value : " + str(cursor.get_value()) + self.assertTrue(check_value == cursor.get_value()) + cursor.close() + session.close() + conn.close() + @wttest.longtest('lookaside table smoke test') def test_las(self): # Create a small table. @@ -43,18 +80,49 @@ class test_las(wttest.WiredTigerTestCase): nrows = 100 ds = SimpleDataSet(self, uri, nrows, key_format="S") ds.populate() + bigvalue = "aaaaa" * 100 - # Take a snapshot. + # Initially load huge data + cursor = self.session.open_cursor(uri) + for i in range(1, 1000000): + cursor.set_key(ds.key(nrows + i)) + cursor.set_value(bigvalue) + self.assertEquals(cursor.insert(), 0) + cursor.close() + self.session.checkpoint() + + # Scenario: 1 + # Check to see LAS working with old snapshot + bigvalue1 = "bbbbb" * 100 self.session.snapshot("name=xxx") + # Update the values in different session after snapshot + self.large_updates(self.session, uri, bigvalue1, ds, nrows) + # Check to see the value after recovery + self.durable_check(bigvalue1, uri, ds, nrows) + self.session.snapshot("drop=(all)") - # Insert a large number of records, we'll hang if the lookaside table - # isn't doing its thing. - c = self.session.open_cursor(uri) - bigvalue = "abcde" * 100 - for i in range(1, 1000000): - c.set_key(ds.key(nrows + i)) - c.set_value(bigvalue) - self.assertEquals(c.insert(), 0) + # Scenario: 2 + # Check to see LAS working with old reader + bigvalue2 = "ccccc" * 100 + session2 = self.conn.open_session() + session2.begin_transaction('isolation=snapshot') + self.large_updates(self.session, uri, bigvalue2, ds, nrows) + # Check to see the value after recovery + self.durable_check(bigvalue2, uri, ds, nrows) + session2.rollback_transaction() + session2.close() + + # Scenario: 3 + # Check to see LAS working with old timestamp + bigvalue3 = "ddddd" * 100 + self.conn.set_timestamp('stable_timestamp=' + timestamp_str(1)) + self.large_updates(self.session, uri, bigvalue3, ds, nrows, timestamp=True) + # Check to see data can be see only till the stable_timestamp + self.durable_check(bigvalue2, uri, ds, nrows) + + self.conn.set_timestamp('stable_timestamp=' + timestamp_str(i + 1)) + # Check to see latest data can be seen + self.durable_check(bigvalue3, uri, ds, nrows) if __name__ == '__main__': wttest.run() diff --git a/src/third_party/wiredtiger/test/suite/test_timestamp01.py b/src/third_party/wiredtiger/test/suite/test_timestamp01.py index c7a5df66ae0..09a264e2afd 100644 --- a/src/third_party/wiredtiger/test/suite/test_timestamp01.py +++ b/src/third_party/wiredtiger/test/suite/test_timestamp01.py @@ -61,12 +61,40 @@ class test_timestamp01(wttest.WiredTigerTestCase, suite_subprocess): 'commit_timestamp=' + timestamp_str(1 << 5000)), '/too long/') - # One is okay, as is 2**64 - 1 + # Anything other than lower case hexadecimal characters is not permitted + self.session.begin_transaction() + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, + lambda: self.session.commit_transaction( + 'commit_timestamp=' + timestamp_str(-1)), + '/Failed to parse commit timestamp/') + + self.session.begin_transaction() + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, + lambda: self.session.commit_transaction( + 'commit_timestamp=' + 'a/78f'), + '/Failed to parse commit timestamp/') + + self.session.begin_transaction() + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, + lambda: self.session.commit_transaction( + 'commit_timestamp=' + 'a`78f'), + '/Failed to parse commit timestamp/') + + self.session.begin_transaction() + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, + lambda: self.session.commit_transaction( + 'commit_timestamp=' + 'a{78f'), + '/Failed to parse commit timestamp/') + + # One is okay, as is upper case hex and 2**64 - 1 self.session.begin_transaction() self.session.commit_transaction( 'commit_timestamp=' + timestamp_str(1)) self.session.begin_transaction() self.session.commit_transaction( + 'commit_timestamp=0A78F') + self.session.begin_transaction() + self.session.commit_transaction( 'commit_timestamp=' + timestamp_str(1 << 64 - 1)) if __name__ == '__main__': diff --git a/src/third_party/wiredtiger/test/suite/test_timestamp02.py b/src/third_party/wiredtiger/test/suite/test_timestamp02.py index 31bea22ec66..f928dbc184f 100644 --- a/src/third_party/wiredtiger/test/suite/test_timestamp02.py +++ b/src/third_party/wiredtiger/test/suite/test_timestamp02.py @@ -38,12 +38,6 @@ from wtscenario import make_scenarios def timestamp_str(t): return '%x' % t -def timestamp_ret_str(t): - s = timestamp_str(t) - if len(s) % 2 == 1: - s = '0' + s - return s - class test_timestamp02(wttest.WiredTigerTestCase, suite_subprocess): tablename = 'test_timestamp02' uri = 'table:' + tablename @@ -98,7 +92,7 @@ class test_timestamp02(wttest.WiredTigerTestCase, suite_subprocess): dict((k, 1) for k in orig_keys[:i+1])) # Everything up to and including timestamp 100 has been committed. - self.assertEqual(self.conn.query_timestamp(), timestamp_ret_str(100)) + 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)) @@ -111,11 +105,11 @@ class test_timestamp02(wttest.WiredTigerTestCase, suite_subprocess): self.session.commit_transaction('commit_timestamp=' + timestamp_str(k + 100)) # Everything up to and including timestamp 200 has been committed. - self.assertEqual(self.conn.query_timestamp(), timestamp_ret_str(200)) + self.assertTimestampsEqual(self.conn.query_timestamp(), timestamp_str(200)) # Test that we can manually move the commit timestamp back self.conn.set_timestamp('commit_timestamp=' + timestamp_str(150)) - self.assertEqual(self.conn.query_timestamp(), timestamp_ret_str(150)) + self.assertTimestampsEqual(self.conn.query_timestamp(), timestamp_str(150)) self.conn.set_timestamp('commit_timestamp=' + timestamp_str(200)) # Now the stable timestamp before we read. diff --git a/src/third_party/wiredtiger/test/suite/test_timestamp03.py b/src/third_party/wiredtiger/test/suite/test_timestamp03.py index 9caf597e6ed..1a2511ea6ee 100644 --- a/src/third_party/wiredtiger/test/suite/test_timestamp03.py +++ b/src/third_party/wiredtiger/test/suite/test_timestamp03.py @@ -39,12 +39,6 @@ from wtscenario import make_scenarios def timestamp_str(t): return '%x' % t -def timestamp_ret_str(t): - s = timestamp_str(t) - if len(s) % 2 == 1: - s = '0' + s - return s - class test_timestamp03(wttest.WiredTigerTestCase, suite_subprocess): table_ts_log = 'ts03_ts_logged' table_ts_nolog = 'ts03_ts_nologged' @@ -226,7 +220,7 @@ class test_timestamp03(wttest.WiredTigerTestCase, suite_subprocess): self.table_nots_nolog, dict((k, self.value) for k in orig_keys)) # Bump the oldest_timestamp, we're not going back... - self.assertEqual(self.conn.query_timestamp(), timestamp_ret_str(100)) + self.assertTimestampsEqual(self.conn.query_timestamp(), timestamp_str(100)) old_ts = timestamp_str(100) self.conn.set_timestamp('oldest_timestamp=' + old_ts) self.conn.set_timestamp('stable_timestamp=' + old_ts) diff --git a/src/third_party/wiredtiger/test/suite/test_timestamp04.py b/src/third_party/wiredtiger/test/suite/test_timestamp04.py index a52675daf8b..f7052448208 100644 --- a/src/third_party/wiredtiger/test/suite/test_timestamp04.py +++ b/src/third_party/wiredtiger/test/suite/test_timestamp04.py @@ -37,12 +37,6 @@ from wtscenario import make_scenarios def timestamp_str(t): return '%x' % t -def timestamp_ret_str(t): - s = timestamp_str(t) - if len(s) % 2 == 1: - s = '0' + s - return s - class test_timestamp04(wttest.WiredTigerTestCase, suite_subprocess): table_ts_log = 'table:ts04_ts_logged' table_ts_nolog = 'table:ts04_ts_nologged' @@ -61,6 +55,7 @@ class test_timestamp04(wttest.WiredTigerTestCase, suite_subprocess): ('col_var', dict(empty=0, cacheSize='cache_size=20MB', extra_config=',key_format=r')), ('lsm', dict(empty=0, cacheSize='cache_size=31MB', extra_config=',type=lsm')), ('row', dict(empty=0, cacheSize='cache_size=20MB', extra_config='',)), + ('row-smallcache', dict(empty=0, cacheSize='cache_size=2MB', extra_config='',)), ] scenarios = make_scenarios(conncfg, types) diff --git a/src/third_party/wiredtiger/test/suite/test_timestamp05.py b/src/third_party/wiredtiger/test/suite/test_timestamp05.py index d7131cb2004..f145184146c 100644 --- a/src/third_party/wiredtiger/test/suite/test_timestamp05.py +++ b/src/third_party/wiredtiger/test/suite/test_timestamp05.py @@ -39,12 +39,6 @@ from wtscenario import make_scenarios def timestamp_str(t): return '%x' % t -def timestamp_ret_str(t): - s = timestamp_str(t) - if len(s) % 2 == 1: - s = '0' + s - return s - class test_timestamp05(wttest.WiredTigerTestCase, suite_subprocess): uri = 'table:ts05' diff --git a/src/third_party/wiredtiger/test/suite/test_timestamp07.py b/src/third_party/wiredtiger/test/suite/test_timestamp07.py index 12b36bdc2f8..09547dba3a7 100644 --- a/src/third_party/wiredtiger/test/suite/test_timestamp07.py +++ b/src/third_party/wiredtiger/test/suite/test_timestamp07.py @@ -56,8 +56,8 @@ class test_timestamp07(wttest.WiredTigerTestCase, suite_subprocess): nkeys = [ ('100keys', dict(nkeys=100)), -# ('500keys', dict(nkeys=500)), -# ('1000keys', dict(nkeys=1000)), + ('500keys', dict(nkeys=500)), + ('1000keys', dict(nkeys=1000)), ] scenarios = make_scenarios(types, conncfg, nkeys) @@ -68,19 +68,20 @@ class test_timestamp07(wttest.WiredTigerTestCase, suite_subprocess): value3 = u'\u0001\u0002cdef\u0007\u0004' # Check that a cursor (optionally started in a new transaction), sees the - # expected values. - def check(self, session, txn_config, expected): + # expected value for a key + def check(self, session, txn_config, k, expected): if txn_config: session.begin_transaction(txn_config) c = session.open_cursor(self.uri + self.tablename, None) - actual = dict((k, v) for k, v in c if v != 0) - self.assertTrue(actual == expected) - # Search for the expected items as well as iterating - for k, v in expected.iteritems(): - self.assertEqual(c[k], v, "for key " + str(k)) + if not expected: + c.set_key(k) + self.assertEqual(c.search(), wiredtiger.WT_NOTFOUND) + else: + self.assertEqual(c[k], expected) c.close() if txn_config: session.commit_transaction() + # # Take a backup of the database and verify that the value we want to # check exists in the tables the expected number of times. @@ -168,12 +169,14 @@ class test_timestamp07(wttest.WiredTigerTestCase, suite_subprocess): # Now check that we see the expected state when reading at each # timestamp. - for i, t in enumerate(orig_keys): - self.check(self.session, 'read_timestamp=' + timestamp_str(t), - dict((k, self.value) for k in orig_keys[:i+1])) + for k in orig_keys: + self.check(self.session, 'read_timestamp=' + timestamp_str(k), + k, self.value) + self.check(self.session, 'read_timestamp=' + timestamp_str(k), + k + 1, None) # Bump the oldest timestamp, we're not going back... - self.assertEqual(self.conn.query_timestamp(), timestamp_str(self.nkeys)) + self.assertTimestampsEqual(self.conn.query_timestamp(), timestamp_str(self.nkeys)) self.oldts = timestamp_str(self.nkeys) self.conn.set_timestamp('oldest_timestamp=' + self.oldts) self.conn.set_timestamp('stable_timestamp=' + self.oldts) @@ -201,12 +204,8 @@ class test_timestamp07(wttest.WiredTigerTestCase, suite_subprocess): # Take a checkpoint using the given configuration. Then verify # whether value2 appears in a copy of that data or not. - valcnt2 = valcnt3 = self.nkeys - valcnt = 0 - # If logging is disabled then value2 should not appear in logged table. - if self.using_log == False: - valcnt3 = 0 - self.ckpt_backup(self.value2, valcnt, valcnt2, valcnt3) + self.ckpt_backup(self.value2, 0, self.nkeys, self.nkeys if self.using_log else 0) + # Update the stable timestamp to the latest, but not the oldest # timestamp and make sure we can see the data. Once the stable # timestamp is moved we should see all keys with value2. @@ -245,9 +244,7 @@ class test_timestamp07(wttest.WiredTigerTestCase, suite_subprocess): # of that data or not. Both tables that are logged should see # all the data regardless of timestamps. The table that is not # logged should not see any of it. - valcnt = 0 - valcnt2 = valcnt3 = self.nkeys - self.backup_check(self.value3, valcnt, valcnt2, valcnt3) + self.backup_check(self.value3, 0, self.nkeys, self.nkeys) if __name__ == '__main__': wttest.run() diff --git a/src/third_party/wiredtiger/test/suite/test_timestamp09.py b/src/third_party/wiredtiger/test/suite/test_timestamp09.py index 41a6909cbef..b79521329e7 100644 --- a/src/third_party/wiredtiger/test/suite/test_timestamp09.py +++ b/src/third_party/wiredtiger/test/suite/test_timestamp09.py @@ -114,8 +114,7 @@ class test_timestamp09(wttest.WiredTigerTestCase, suite_subprocess): # Oldest timestamp is 3 at the moment, trying to set it to an earlier # timestamp is a no-op. self.conn.set_timestamp('oldest_timestamp=' + timestamp_str(1)) - self.assertEqual(int(self.conn.query_timestamp('get=oldest')), - int(timestamp_str(3))) + self.assertTimestampsEqual(self.conn.query_timestamp('get=oldest'), timestamp_str(3)) self.conn.set_timestamp('oldest_timestamp=' + timestamp_str(3) + ',stable_timestamp=' + timestamp_str(3)) @@ -123,8 +122,7 @@ class test_timestamp09(wttest.WiredTigerTestCase, suite_subprocess): # Stable timestamp is 5 at the moment, trying to set it to an earlier # timestamp is a no-op. self.conn.set_timestamp('stable_timestamp=' + timestamp_str(4)) - self.assertEqual(int(self.conn.query_timestamp('get=stable')), - int(timestamp_str(5))) + self.assertTimestampsEqual(self.conn.query_timestamp('get=stable'), timestamp_str(5)) self.conn.set_timestamp('oldest_timestamp=' + timestamp_str(5)) self.assertRaisesWithMessage(wiredtiger.WiredTigerError, diff --git a/src/third_party/wiredtiger/test/suite/test_txn14.py b/src/third_party/wiredtiger/test/suite/test_txn14.py index 7579bbc8e54..2245f49ae85 100644 --- a/src/third_party/wiredtiger/test/suite/test_txn14.py +++ b/src/third_party/wiredtiger/test/suite/test_txn14.py @@ -93,10 +93,11 @@ class test_txn14(wttest.WiredTigerTestCase, suite_subprocess): c.close() self.session.log_flush(cfgarg) if self.sync == 'background': - # If doing a background flush, wait a few seconds. I have - # seen an individual log file's fsync take more than a second - # on some systems. So give it time to flush perhaps a few files. - self.session.transaction_sync('timeout_ms=4000') + # If doing a background flush, wait 10 seconds. I have seen an + # individual log file's fsync take more than a second on some + # systems, and we've seen timeouts at lower levels on systems + # with slow I/O. So give it time to flush perhaps a few files. + self.session.transaction_sync('timeout_ms=10000') self.simulate_crash_restart(".", "RESTART") c = self.session.open_cursor(self.t1, None, None) i = 0 diff --git a/src/third_party/wiredtiger/test/suite/wttest.py b/src/third_party/wiredtiger/test/suite/wttest.py index 1c95eb355ae..c654370718c 100644 --- a/src/third_party/wiredtiger/test/suite/wttest.py +++ b/src/third_party/wiredtiger/test/suite/wttest.py @@ -490,6 +490,12 @@ class WiredTigerTestCase(unittest.TestCase): with self.expectedStderr(message): self.assertRaises(exceptionType, expr) + def assertTimestampsEqual(self, ts1, ts2): + """ + TestCase.assertEqual() for timestamps + """ + self.assertEqual(int(ts1, 16), int(ts2, 16)) + def exceptionToStderr(self, expr): """ Used by assertRaisesHavingMessage to convert an expression |