diff options
author | Etienne Petrel <etienne.petrel@mongodb.com> | 2022-04-08 01:32:31 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-04-08 02:01:05 +0000 |
commit | 4508cd461c9ac97860d0a75ec3c1d1e929636e07 (patch) | |
tree | 8dba87511236295612adc3024233a2a010dc99e1 /src/third_party/wiredtiger | |
parent | e6cce2875f3efa0c9b1443cf66efab95d5325a8f (diff) | |
download | mongo-4508cd461c9ac97860d0a75ec3c1d1e929636e07.tar.gz |
Import wiredtiger: 2aa2673d45c3ef1666107a5e381202f92502201e from branch mongodb-master
ref: 03dfd53f7a..2aa2673d45
for: 6.0.0-rc0
WT-8990 Validate commit and durability timestamps at transaction commit
Diffstat (limited to 'src/third_party/wiredtiger')
-rw-r--r-- | src/third_party/wiredtiger/import.data | 2 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/docs/timestamp-misc.dox | 9 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/docs/transactions_api.dox | 12 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/include/extern.h | 6 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/session/session_api.c | 4 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/txn/txn.c | 4 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/txn/txn_timestamp.c | 132 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/format/format.h | 1 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/format/ops.c | 32 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/format/snap.c | 5 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/format/util.c | 21 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/format/wts.c | 2 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/suite/test_checkpoint_snapshot02.py | 4 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/suite/test_timestamp28.py | 59 |
14 files changed, 199 insertions, 94 deletions
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index 9de55d40aac..8fad1e19220 100644 --- a/src/third_party/wiredtiger/import.data +++ b/src/third_party/wiredtiger/import.data @@ -2,5 +2,5 @@ "vendor": "wiredtiger", "github": "wiredtiger/wiredtiger.git", "branch": "mongodb-master", - "commit": "03dfd53f7ac5eef24fe50241610e701bd8f67cda" + "commit": "2aa2673d45c3ef1666107a5e381202f92502201e" } diff --git a/src/third_party/wiredtiger/src/docs/timestamp-misc.dox b/src/third_party/wiredtiger/src/docs/timestamp-misc.dox index 5724a9fe814..537251a7773 100644 --- a/src/third_party/wiredtiger/src/docs/timestamp-misc.dox +++ b/src/third_party/wiredtiger/src/docs/timestamp-misc.dox @@ -61,15 +61,6 @@ will fail and drop core at the failing check. These are best-effort checks by WiredTiger, and there are cases where application misbehavior will not be detected. -@section timestamp_misc_reset_snapshot Resetting the snapshot - -Transactions that have not set \c read_timestamp can use -WT_SESSION::reset_snapshot with timestamped tables as with -non-timestamped tables, to get a new snapshot of the database to read -from. See @ref snapshot_reset. -Transactions that have set \c read_timestamp can also call -WT_SESSION::reset_snapshot, but it will have no effect. - @section timestamps_misc_in_memory In-memory configurations and timestamps Timestamps are supported for in-memory databases, but must be configured as in diff --git a/src/third_party/wiredtiger/src/docs/transactions_api.dox b/src/third_party/wiredtiger/src/docs/transactions_api.dox index e3083aaac59..de4054018da 100644 --- a/src/third_party/wiredtiger/src/docs/transactions_api.dox +++ b/src/third_party/wiredtiger/src/docs/transactions_api.dox @@ -136,14 +136,16 @@ well as any key and value that may have been set. @section snapshot_reset Resetting the session snapshot -Snapshot-isolation transactions can pin a large amount of data into the database +Snapshot-isolation transactions can pin large amounts of data into the database cache in order to be able to satisfy potential reads at the snapshot. WT_SESSION::reset_snapshot releases the current snapshot and gets a new (more recent) snapshot to avoid pinning content in the cache that is no longer needed. -Applications may see different search results compared to earlier after updating -the snapshot. It is an error to call WT_SESSION::reset_snapshot at any isolation -level other than snapshot, or if the current transaction has performed any write -operations. +It is an error to call WT_SESSION::reset_snapshot at any isolation level other +than snapshot, or if the current transaction has performed any write operations. + +\warning +Applications not using read timestamps for search may see different results +after the snapshot is updated. @snippet ex_all.c reset snapshot diff --git a/src/third_party/wiredtiger/src/include/extern.h b/src/third_party/wiredtiger/src/include/extern.h index 5b6c36bdb6e..7ebf7ba83e1 100644 --- a/src/third_party/wiredtiger/src/include/extern.h +++ b/src/third_party/wiredtiger/src/include/extern.h @@ -1588,7 +1588,7 @@ extern int __wt_txn_set_prepare_timestamp(WT_SESSION_IMPL *session, wt_timestamp WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); extern int __wt_txn_set_read_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t read_ts) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); -extern int __wt_txn_set_timestamp(WT_SESSION_IMPL *session, const char *cfg[]) +extern int __wt_txn_set_timestamp(WT_SESSION_IMPL *session, const char *cfg[], bool commit) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); extern int __wt_txn_set_timestamp_uint(WT_SESSION_IMPL *session, WT_TS_TXN_TYPE which, wt_timestamp_t ts) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); @@ -1600,6 +1600,10 @@ extern int __wt_txn_update_oldest(WT_SESSION_IMPL *session, uint32_t flags) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); extern int __wt_txn_update_pinned_timestamp(WT_SESSION_IMPL *session, bool force) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); +extern int __wt_txn_validate_commit_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t *commit_tsp) + WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); +extern int __wt_txn_validate_durable_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t durable_ts) + WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); extern int __wt_unexpected_object_type( WT_SESSION_IMPL *session, const char *uri, const char *expect) WT_GCC_FUNC_DECL_ATTRIBUTE((cold)) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); diff --git a/src/third_party/wiredtiger/src/session/session_api.c b/src/third_party/wiredtiger/src/session/session_api.c index c66963875ae..8adaee16387 100644 --- a/src/third_party/wiredtiger/src/session/session_api.c +++ b/src/third_party/wiredtiger/src/session/session_api.c @@ -1797,7 +1797,7 @@ __session_timestamp_transaction(WT_SESSION *wt_session, const char *config) cfg[1] = config; #endif - ret = __wt_txn_set_timestamp(session, cfg); + ret = __wt_txn_set_timestamp(session, cfg, false); err: API_END_RET(session, ret); } @@ -1851,7 +1851,7 @@ __session_reset_snapshot(WT_SESSION *wt_session) session = (WT_SESSION_IMPL *)wt_session; txn = session->txn; - /* Return error if the isolation mode is read committed. */ + /* Return error if the isolation mode is not snapshot. */ if (txn->isolation != WT_ISO_SNAPSHOT) WT_RET_MSG( session, ENOTSUP, "not supported in read-committed or read-uncommitted transactions"); diff --git a/src/third_party/wiredtiger/src/txn/txn.c b/src/third_party/wiredtiger/src/txn/txn.c index 730b08225e1..641d3ed0e5b 100644 --- a/src/third_party/wiredtiger/src/txn/txn.c +++ b/src/third_party/wiredtiger/src/txn/txn.c @@ -1491,7 +1491,7 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[]) F_CLR(txn, WT_TXN_TS_ROUND_PREPARED); /* Set the commit and the durable timestamps. */ - WT_ERR(__wt_txn_set_timestamp(session, cfg)); + WT_ERR(__wt_txn_set_timestamp(session, cfg, true)); if (prepare) { if (!F_ISSET(txn, WT_TXN_HAS_TS_COMMIT)) @@ -1786,7 +1786,7 @@ __wt_txn_prepare(WT_SESSION_IMPL *session, const char *cfg[]) WT_RET_MSG(session, EINVAL, "a prepared transaction cannot include a logged table"); /* Set the prepare timestamp. */ - WT_RET(__wt_txn_set_timestamp(session, cfg)); + WT_RET(__wt_txn_set_timestamp(session, cfg, false)); if (!F_ISSET(txn, WT_TXN_HAS_TS_PREPARE)) WT_RET_MSG(session, EINVAL, "prepare timestamp is not set"); diff --git a/src/third_party/wiredtiger/src/txn/txn_timestamp.c b/src/third_party/wiredtiger/src/txn/txn_timestamp.c index 5fe02c397cf..160f638a72c 100644 --- a/src/third_party/wiredtiger/src/txn/txn_timestamp.c +++ b/src/third_party/wiredtiger/src/txn/txn_timestamp.c @@ -520,28 +520,25 @@ __txn_assert_after_reads(WT_SESSION_IMPL *session, const char *op, wt_timestamp_ } /* - * __wt_txn_set_commit_timestamp -- + * __wt_txn_validate_commit_timestamp -- * Validate the commit timestamp of a transaction. */ int -__wt_txn_set_commit_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t commit_ts) +__wt_txn_validate_commit_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t *commit_tsp) { WT_TXN *txn; WT_TXN_GLOBAL *txn_global; - wt_timestamp_t oldest_ts, stable_ts; + wt_timestamp_t commit_ts, oldest_ts, stable_ts; char ts_string[2][WT_TS_INT_STRING_SIZE]; bool has_oldest_ts, has_stable_ts; txn = session->txn; txn_global = &S2C(session)->txn_global; + commit_ts = *commit_tsp; /* Added this redundant initialization to circumvent build failure. */ oldest_ts = stable_ts = WT_TS_NONE; - if (txn->isolation != WT_ISO_SNAPSHOT) - WT_RET_MSG(session, EINVAL, - "setting a commit_timestamp requires a transaction running at snapshot isolation"); - /* * Compare against the oldest and the stable timestamp. Return an error if the given timestamp * is less than oldest and/or stable timestamp. @@ -595,16 +592,40 @@ __wt_txn_set_commit_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t commit_ts "commit timestamp %s is less than the prepare timestamp %s for this transaction", __wt_timestamp_to_string(commit_ts, ts_string[0]), __wt_timestamp_to_string(txn->prepare_timestamp, ts_string[1])); - commit_ts = txn->prepare_timestamp; + + /* Update the caller's value. */ + *commit_tsp = txn->prepare_timestamp; } if (!F_ISSET(txn, WT_TXN_PREPARE)) WT_RET_MSG( session, EINVAL, "commit timestamp must not be set before transaction is prepared"); } - WT_ASSERT(session, - !F_ISSET(txn, WT_TXN_HAS_TS_DURABLE) || txn->durable_timestamp == txn->commit_timestamp); + return (0); +} + +/* + * __wt_txn_set_commit_timestamp -- + * Set the commit timestamp of a transaction. + */ +int +__wt_txn_set_commit_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t commit_ts) +{ + WT_TXN *txn; + + txn = session->txn; + + if (txn->isolation != WT_ISO_SNAPSHOT) + WT_RET_MSG(session, EINVAL, + "setting a commit_timestamp requires a transaction running at snapshot isolation"); + + /* + * In scenarios where the prepare timestamp is greater than the provided commit timestamp, the + * validate function returns the new commit timestamp based on the configuration. + */ + WT_RET(__wt_txn_validate_commit_timestamp(session, &commit_ts)); txn->commit_timestamp = commit_ts; + /* * First time copy the commit timestamp to the first commit timestamp. */ @@ -624,11 +645,11 @@ __wt_txn_set_commit_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t commit_ts } /* - * __wt_txn_set_durable_timestamp -- + * __wt_txn_validate_durable_timestamp -- * Validate the durable timestamp of a transaction. */ int -__wt_txn_set_durable_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t durable_ts) +__wt_txn_validate_durable_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t durable_ts) { WT_TXN *txn; WT_TXN_GLOBAL *txn_global; @@ -642,13 +663,6 @@ __wt_txn_set_durable_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t durable_ /* Added this redundant initialization to circumvent build failure. */ oldest_ts = stable_ts = 0; - if (!F_ISSET(txn, WT_TXN_PREPARE)) - WT_RET_MSG(session, EINVAL, - "durable timestamp should not be specified for non-prepared transaction"); - - if (!F_ISSET(txn, WT_TXN_HAS_TS_COMMIT)) - WT_RET_MSG(session, EINVAL, "commit timestamp is needed before the durable timestamp"); - /* * Compare against the oldest and the stable timestamp. Return an error if the given timestamp * is less than oldest and/or stable timestamp. @@ -677,6 +691,29 @@ __wt_txn_set_durable_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t durable_ __wt_timestamp_to_string(durable_ts, ts_string[0]), __wt_timestamp_to_string(txn->commit_timestamp, ts_string[1])); + return (0); +} + +/* + * __wt_txn_set_durable_timestamp -- + * Set the durable timestamp of a transaction. + */ +int +__wt_txn_set_durable_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t durable_ts) +{ + WT_TXN *txn; + + txn = session->txn; + + if (!F_ISSET(txn, WT_TXN_PREPARE)) + WT_RET_MSG(session, EINVAL, + "durable timestamp should not be specified for non-prepared transaction"); + + if (!F_ISSET(txn, WT_TXN_HAS_TS_COMMIT)) + WT_RET_MSG( + session, EINVAL, "a commit timestamp is required before setting a durable timestamp"); + + WT_RET(__wt_txn_validate_durable_timestamp(session, durable_ts)); txn->durable_timestamp = durable_ts; F_SET(txn, WT_TXN_HAS_TS_DURABLE); @@ -869,51 +906,58 @@ __wt_txn_set_read_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t read_ts) * Parse a request to set a timestamp in a transaction. */ int -__wt_txn_set_timestamp(WT_SESSION_IMPL *session, const char *cfg[]) +__wt_txn_set_timestamp(WT_SESSION_IMPL *session, const char *cfg[], bool commit) { WT_CONFIG cparser; WT_CONFIG_ITEM ckey, cval; WT_CONNECTION_IMPL *conn; WT_DECL_RET; + WT_TXN *txn; wt_timestamp_t commit_ts, durable_ts, prepare_ts, read_ts; bool set_ts; conn = S2C(session); - commit_ts = durable_ts = prepare_ts = read_ts = WT_TS_NONE; + txn = session->txn; set_ts = false; WT_RET(__wt_txn_context_check(session, true)); /* - * If the API received no configuration string, or we just have the base configuration, there's - * nothing to do. + * If no commit or durable timestamp is set here, set to any previously set values and validate + * them, the stable timestamp might have moved forward since they were successfully set. */ - if (cfg == NULL || cfg[0] == NULL || cfg[1] == NULL) - return (0); + commit_ts = durable_ts = prepare_ts = read_ts = WT_TS_NONE; + if (commit && F_ISSET(txn, WT_TXN_HAS_TS_COMMIT)) + commit_ts = txn->commit_timestamp; + if (commit && F_ISSET(txn, WT_TXN_HAS_TS_DURABLE)) + durable_ts = txn->durable_timestamp; /* - * We take a shortcut in parsing that works because we're only given a base configuration and a - * user configuration. + * If the API received no configuration string, or we just have the base configuration, there + * are no strings to parse. Additionally, take a shortcut in parsing that works because we're + * only given a base configuration and a user configuration. */ - WT_ASSERT(session, cfg[0] != NULL && cfg[1] != NULL && cfg[2] == NULL); - __wt_config_init(session, &cparser, cfg[1]); - while ((ret = __wt_config_next(&cparser, &ckey, &cval)) == 0) { - WT_ASSERT(session, ckey.str != NULL); - if (WT_STRING_MATCH("commit_timestamp", ckey.str, ckey.len)) { - WT_RET(__wt_txn_parse_timestamp(session, "commit", &commit_ts, &cval)); - set_ts = true; - } else if (WT_STRING_MATCH("durable_timestamp", ckey.str, ckey.len)) { - WT_RET(__wt_txn_parse_timestamp(session, "durable", &durable_ts, &cval)); - set_ts = true; - } else if (WT_STRING_MATCH("prepare_timestamp", ckey.str, ckey.len)) { - WT_RET(__wt_txn_parse_timestamp(session, "prepare", &prepare_ts, &cval)); - set_ts = true; - } else if (WT_STRING_MATCH("read_timestamp", ckey.str, ckey.len)) { - WT_RET(__wt_txn_parse_timestamp(session, "read", &read_ts, &cval)); - set_ts = true; + if (cfg != NULL && cfg[0] != NULL && cfg[1] != NULL) { + WT_ASSERT(session, cfg[2] == NULL); + __wt_config_init(session, &cparser, cfg[1]); + while ((ret = __wt_config_next(&cparser, &ckey, &cval)) == 0) { + WT_ASSERT(session, ckey.str != NULL); + if (WT_STRING_MATCH("commit_timestamp", ckey.str, ckey.len)) { + WT_RET(__wt_txn_parse_timestamp(session, "commit", &commit_ts, &cval)); + set_ts = true; + } else if (WT_STRING_MATCH("durable_timestamp", ckey.str, ckey.len)) { + WT_RET(__wt_txn_parse_timestamp(session, "durable", &durable_ts, &cval)); + set_ts = true; + } else if (WT_STRING_MATCH("prepare_timestamp", ckey.str, ckey.len)) { + WT_RET(__wt_txn_parse_timestamp(session, "prepare", &prepare_ts, &cval)); + set_ts = true; + } else if (WT_STRING_MATCH("read_timestamp", ckey.str, ckey.len)) { + WT_RET(__wt_txn_parse_timestamp(session, "read", &read_ts, &cval)); + set_ts = true; + } } + WT_RET_NOTFOUND_OK(ret); } - WT_RET_NOTFOUND_OK(ret); /* Look for a commit timestamp. */ if (commit_ts != WT_TS_NONE) diff --git a/src/third_party/wiredtiger/test/format/format.h b/src/third_party/wiredtiger/test/format/format.h index f53f519fd70..dd3f5d58018 100644 --- a/src/third_party/wiredtiger/test/format/format.h +++ b/src/third_party/wiredtiger/test/format/format.h @@ -374,6 +374,7 @@ void key_gen_teardown(WT_ITEM *); void key_init(TABLE *, void *); void lock_destroy(WT_SESSION *, RWLOCK *); void lock_init(WT_SESSION *, RWLOCK *); +uint64_t maximum_read_ts(void); void operations(u_int, bool); void path_setup(const char *); void set_alarm(u_int); diff --git a/src/third_party/wiredtiger/test/format/ops.c b/src/third_party/wiredtiger/test/format/ops.c index 62e29d2919b..df58005f131 100644 --- a/src/third_party/wiredtiger/test/format/ops.c +++ b/src/third_party/wiredtiger/test/format/ops.c @@ -401,7 +401,6 @@ operations(u_int ops_seconds, bool lastrun) static void begin_transaction_ts(TINFO *tinfo) { - TINFO **tlp; WT_DECL_RET; WT_SESSION *session; uint64_t ts; @@ -410,16 +409,13 @@ begin_transaction_ts(TINFO *tinfo) session = tinfo->session; /* - * Transaction reads are normally repeatable, but WiredTiger timestamps allow rewriting commits, - * that is, applications can specify at commit time the timestamp at which the commit happens. - * If that happens, our read might no longer be repeatable. Test in both modes: pick a read - * timestamp we know is repeatable (because it's at least as old as the oldest resolved commit - * timestamp in any thread), and pick a current timestamp, 50% of the time. + * Transaction timestamp reads are repeatable, but read timestamps must be before any possible + * commit timestamp. Without a read timestamp, reads are based on the transaction snapshot, + * which will include the latest values as of when the snapshot is taken. Test in both modes: + * 75% of the time, pick a read timestamp before any commit timestamp in any thread, 25% of + * the time don't set a timestamp at all. */ - ts = 0; - if (mmrand(&tinfo->rnd, 1, 2) == 1) - for (ts = UINT64_MAX, tlp = tinfo_list; *tlp != NULL; ++tlp) - ts = WT_MIN(ts, (*tlp)->commit_ts); + ts = mmrand(&tinfo->rnd, 1, 4) == 1 ? 0 : maximum_read_ts(); if (ts != 0) { wiredtiger_begin_transaction(session, NULL); @@ -442,22 +438,6 @@ begin_transaction_ts(TINFO *tinfo) wiredtiger_begin_transaction(session, NULL); - /* - * Otherwise, pick a current timestamp. - * - * Prepare returns an error if the prepare timestamp is less than any active read timestamp, - * single-thread transaction prepare and begin. - * - * Lock out the oldest timestamp update. - */ - lock_writelock(session, &g.ts_lock); - - ts = __wt_atomic_addv64(&g.timestamp, 1); - testutil_check(__wt_snprintf(buf, sizeof(buf), "read_timestamp=%" PRIx64, ts)); - testutil_check(session->timestamp_transaction(session, buf)); - - lock_writeunlock(session, &g.ts_lock); - snap_op_init(tinfo, ts, false); trace_op(tinfo, "begin snapshot read-ts=%" PRIu64 " (not repeatable)", ts); } diff --git a/src/third_party/wiredtiger/test/format/snap.c b/src/third_party/wiredtiger/test/format/snap.c index 2982f5bf4a1..94a7643c234 100644 --- a/src/third_party/wiredtiger/test/format/snap.c +++ b/src/third_party/wiredtiger/test/format/snap.c @@ -603,9 +603,12 @@ void snap_repeat_single(TINFO *tinfo) { SNAP_OPS *snap; + uint64_t ts; u_int v; int count; + ts = maximum_read_ts(); + /* * Start at a random spot in the list of operations and look for a read to retry. Stop when * we've walked the entire list or found one. @@ -616,7 +619,7 @@ snap_repeat_single(TINFO *tinfo) if (snap >= tinfo->snap_end) snap = tinfo->snap_list; - if (snap->repeatable) + if (snap->repeatable && snap->ts <= ts) break; } diff --git a/src/third_party/wiredtiger/test/format/util.c b/src/third_party/wiredtiger/test/format/util.c index 30f446da4e7..d0566e456a4 100644 --- a/src/third_party/wiredtiger/test/format/util.c +++ b/src/third_party/wiredtiger/test/format/util.c @@ -401,6 +401,27 @@ set_oldest_timestamp(void) } /* + * maximum_read_ts -- + * Return the largest safe read timestamp. + */ +uint64_t +maximum_read_ts(void) +{ + TINFO **tlp; + uint64_t ts; + + /* + * We can't use a read timestamp that's ahead of a commit timestamp. Find the maximum safe read + * timestamp. + */ + for (ts = g.timestamp, tlp = tinfo_list; *tlp != NULL; ++tlp) + ts = WT_MIN(ts, (*tlp)->commit_ts); + if (ts != 0) + --ts; + return (ts); +} + +/* * lock_init -- * Initialize abstract lock that can use either pthread of wt reader-writer locks. */ diff --git a/src/third_party/wiredtiger/test/format/wts.c b/src/third_party/wiredtiger/test/format/wts.c index 92f8f6bbf5a..dc91c759bf1 100644 --- a/src/third_party/wiredtiger/test/format/wts.c +++ b/src/third_party/wiredtiger/test/format/wts.c @@ -380,7 +380,7 @@ create_object(TABLE *table, void *arg) /* Assertions: assertions slow down the code for additional diagnostic checking. */ if (GV(ASSERT_READ_TIMESTAMP)) CONFIG_APPEND( - p, ",assert=(read_timestamp=%s)", g.transaction_timestamps_config ? "always" : "never"); + p, ",assert=(read_timestamp=%s)", g.transaction_timestamps_config ? "none" : "never"); if (GV(ASSERT_WRITE_TIMESTAMP)) CONFIG_APPEND(p, ",assert=(write_timestamp=on),write_timestamp_usage=%s", g.transaction_timestamps_config ? "always" : "never"); diff --git a/src/third_party/wiredtiger/test/suite/test_checkpoint_snapshot02.py b/src/third_party/wiredtiger/test/suite/test_checkpoint_snapshot02.py index c1f3f070944..89a7faddfc0 100644 --- a/src/third_party/wiredtiger/test/suite/test_checkpoint_snapshot02.py +++ b/src/third_party/wiredtiger/test/suite/test_checkpoint_snapshot02.py @@ -207,8 +207,8 @@ class test_checkpoint_snapshot02(wttest.WiredTigerTestCase): self.assertEqual(cursor1.insert(), 0) session1.timestamp_transaction('commit_timestamp=' + self.timestamp_str(30)) - # Set stable timestamp to 40 - self.conn.set_timestamp('stable_timestamp=' + self.timestamp_str(40)) + # Set stable timestamp to 25 + self.conn.set_timestamp('stable_timestamp=' + self.timestamp_str(25)) # Create a checkpoint thread done = threading.Event() diff --git a/src/third_party/wiredtiger/test/suite/test_timestamp28.py b/src/third_party/wiredtiger/test/suite/test_timestamp28.py new file mode 100644 index 00000000000..259499d7182 --- /dev/null +++ b/src/third_party/wiredtiger/test/suite/test_timestamp28.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# +# Public Domain 2014-present 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_timestamp28.py +# Timestamps: smoke test that commit is tested at both commit and set time. + +import wiredtiger, wttest +from wtdataset import SimpleDataSet + +# Timestamps: smoke test that commit is tested at both commit and set time. +class test_timestamp28(wttest.WiredTigerTestCase): + def test_timestamp28(self): + uri = 'table:timestamp28' + ds = SimpleDataSet(self, uri, 50, key_format='i', value_format='S') + ds.populate() + c = self.session.open_cursor(uri) + + self.conn.set_timestamp('stable_timestamp=' + self.timestamp_str(30)) + self.session.begin_transaction() + c[5] = 'xxx' + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, + lambda: self.session.commit_transaction( + 'commit_timestamp=' + self.timestamp_str(20)), '/must be after/') + + self.conn.set_timestamp('stable_timestamp=' + self.timestamp_str(40)) + self.session.begin_transaction() + c[5] = 'xxx' + self.session.timestamp_transaction('commit_timestamp=' + self.timestamp_str(50)) + self.conn.set_timestamp('stable_timestamp=' + self.timestamp_str(60)) + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, + lambda: self.session.commit_transaction(), '/must be after/') + +if __name__ == '__main__': + wttest.run() |