diff options
author | Luke Chen <luke.chen@mongodb.com> | 2021-08-16 14:53:13 +1000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-08-16 05:21:34 +0000 |
commit | 5a20195efb81fa18645498eac5a0865372b8a663 (patch) | |
tree | e99c759b8176a49418f003e327a916bd401a2b91 /src/third_party | |
parent | bf1abfe3e0d0eada19512d69dfe8e9e9183b946c (diff) | |
download | mongo-5a20195efb81fa18645498eac5a0865372b8a663.tar.gz |
Import wiredtiger: 8099896388aa3476a53d36698018fc69e4240ab5 from branch mongodb-master
ref: 8c0e76f74a..8099896388
for: 5.1.0
WT-7945 Move rollback handling to the operation layer in the cppsuite.
Diffstat (limited to 'src/third_party')
5 files changed, 126 insertions, 96 deletions
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index 1b85c3af1dd..e48dcc7aa78 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": "8c0e76f74ab9d29709548b2c3c3c96583cd8af59" + "commit": "8099896388aa3476a53d36698018fc69e4240ab5" } diff --git a/src/third_party/wiredtiger/test/cppsuite/test_harness/workload/database_operation.cxx b/src/third_party/wiredtiger/test/cppsuite/test_harness/workload/database_operation.cxx index e18125446fe..ebd73acf286 100644 --- a/src/third_party/wiredtiger/test/cppsuite/test_harness/workload/database_operation.cxx +++ b/src/third_party/wiredtiger/test/cppsuite/test_harness/workload/database_operation.cxx @@ -52,8 +52,9 @@ populate_worker(thread_context *tc) for (uint64_t i = 0; i < tc->key_count; ++i) { /* Start a txn. */ tc->transaction.begin(); - if (!tc->insert(cursor, coll.id, i)) { - /* We failed to insert, and our transaction was rolled back retry. */ + if (tc->insert(cursor, coll.id, i)) { + /* We failed to insert, rollback our transaction and retry. */ + tc->transaction.rollback(); --i; continue; } @@ -162,24 +163,31 @@ database_operation::insert_operation(thread_context *tc) auto &cc = ccv[counter]; while (tc->transaction.active() && tc->running()) { /* Insert a key value pair. */ - if (!tc->insert(cc.cursor, cc.coll.id, start_key + added_count)) { - committed = false; - break; + bool rollback_required = tc->insert(cc.cursor, cc.coll.id, start_key + added_count); + if (!rollback_required) { + added_count++; + if (tc->transaction.can_commit()) { + rollback_required = tc->transaction.commit(); + if (!rollback_required) + /* + * We need to inform the database model that we've added these keys as some + * other thread may rely on the key_count data. Only do so if we + * successfully committed. + */ + cc.coll.increase_key_count(added_count); + } } - added_count++; - tc->transaction.try_commit(); + + if (rollback_required) { + added_count = 0; + tc->transaction.rollback(); + } + /* Sleep the duration defined by the op_rate. */ tc->sleep(); } /* Reset our cursor to avoid pinning content. */ testutil_check(cc.cursor->reset(cc.cursor.get())); - - /* - * We need to inform the database model that we've added these keys as some other thread may - * rely on the key_count data. Only do so if we successfully committed. - */ - if (committed) - cc.coll.increase_key_count(added_count); counter++; if (counter == collections_per_thread) counter = 0; @@ -208,9 +216,17 @@ database_operation::read_operation(thread_context *tc) tc->transaction.begin(); while (tc->transaction.active() && tc->running()) { - if (tc->next(cursor) == WT_ROLLBACK) - /* We got an error, our transaction has been rolled back. */ - break; + auto ret = cursor->next(cursor.get()); + if (ret != 0) { + if (ret == WT_NOTFOUND) { + cursor->reset(cursor.get()); + } else if (ret == WT_ROLLBACK) { + tc->transaction.rollback(); + tc->sleep(); + continue; + } else + testutil_die(ret, "Unexpected error returned from cursor->next()"); + } tc->transaction.add_op(); tc->transaction.try_rollback(); tc->sleep(); @@ -263,21 +279,21 @@ database_operation::update_operation(thread_context *tc) /* Choose a random key to update. */ uint64_t key_id = random_generator::instance().generate_integer<uint64_t>(0, coll.get_key_count() - 1); - bool successful_update = tc->update(cursor, coll.id, tc->key_to_string(key_id)); + bool rollback_required = tc->update(cursor, coll.id, tc->key_to_string(key_id)); /* Reset our cursor to avoid pinning content. */ testutil_check(cursor->reset(cursor.get())); - /* We received a rollback in update. */ - if (!successful_update) - continue; - /* Commit the current transaction if we're able to. */ - tc->transaction.try_commit(); + if (!rollback_required && tc->transaction.can_commit()) + rollback_required = tc->transaction.commit(); + + if (rollback_required) + tc->transaction.rollback(); } - /* Make sure the last operation is committed now the work is finished. */ + /* Make sure the last operation is rolled back now the work is finished. */ if (tc->transaction.active()) - tc->transaction.commit(); + tc->transaction.rollback(); } } // namespace test_harness diff --git a/src/third_party/wiredtiger/test/cppsuite/test_harness/workload/thread_context.cxx b/src/third_party/wiredtiger/test/cppsuite/test_harness/workload/thread_context.cxx index 321cc45b61b..aadf992133e 100644 --- a/src/third_party/wiredtiger/test/cppsuite/test_harness/workload/thread_context.cxx +++ b/src/third_party/wiredtiger/test/cppsuite/test_harness/workload/thread_context.cxx @@ -71,6 +71,7 @@ transaction_context::begin(const std::string &config) random_generator::instance().generate_integer<int64_t>(_min_op_count, _max_op_count); _op_count = 0; _in_txn = true; + _needs_rollback = false; } void @@ -80,21 +81,22 @@ transaction_context::try_begin(const std::string &config) begin(config); } -void +/* It's possible to receive rollback in commit which is handled internally. */ +bool transaction_context::commit(const std::string &config) { + WT_DECL_RET; testutil_assert(_in_txn); - testutil_check( - _session->commit_transaction(_session, config.empty() ? nullptr : config.c_str())); - _op_count = 0; - _in_txn = false; -} - -void -transaction_context::try_commit(const std::string &config) -{ - if (can_commit_rollback()) - commit(config); + if ((ret = _session->commit_transaction(_session, config.empty() ? nullptr : config.c_str())) != + 0) { + logger::log_msg(LOG_WARN, + "Failed to commit transaction in commit, received error code: " + std::to_string(ret)); + _needs_rollback = true; + } else { + _op_count = 0; + _in_txn = false; + } + return (_needs_rollback); } void @@ -103,6 +105,7 @@ transaction_context::rollback(const std::string &config) testutil_assert(_in_txn); testutil_check( _session->rollback_transaction(_session, config.empty() ? nullptr : config.c_str())); + _needs_rollback = false; _op_count = 0; _in_txn = false; } @@ -110,7 +113,7 @@ transaction_context::rollback(const std::string &config) void transaction_context::try_rollback(const std::string &config) { - if (can_commit_rollback()) + if (can_rollback()) rollback(config); } @@ -124,8 +127,20 @@ transaction_context::set_commit_timestamp(wt_timestamp_t ts) testutil_check(_session->timestamp_transaction(_session, config.c_str())); } +void +transaction_context::set_needs_rollback(bool rollback) +{ + _needs_rollback = rollback; +} + bool -transaction_context::can_commit_rollback() +transaction_context::can_commit() +{ + return (!_needs_rollback && can_rollback()); +} + +bool +transaction_context::can_rollback() { return (_in_txn && _op_count >= _target_op_count); } @@ -184,8 +199,8 @@ thread_context::update(scoped_cursor &cursor, uint64_t collection_id, const std: ret = cursor->update(cursor.get()); if (ret != 0) { if (ret == WT_ROLLBACK) { - transaction.rollback(); - return (false); + transaction.set_needs_rollback(true); + return (true); } else testutil_die(ret, "unhandled error while trying to update a key"); } @@ -193,14 +208,14 @@ thread_context::update(scoped_cursor &cursor, uint64_t collection_id, const std: tracking_operation::INSERT, collection_id, key.c_str(), value.c_str(), ts, op_track_cursor); if (ret != 0) { if (ret == WT_ROLLBACK) { - transaction.rollback(); - return (false); + transaction.set_needs_rollback(true); + return (true); } else testutil_die( ret, "unhandled error while trying to save an update to the tracking table"); } transaction.add_op(); - return (true); + return (false); } bool @@ -226,8 +241,8 @@ thread_context::insert(scoped_cursor &cursor, uint64_t collection_id, uint64_t k ret = cursor->insert(cursor.get()); if (ret != 0) { if (ret == WT_ROLLBACK) { - transaction.rollback(); - return (false); + transaction.set_needs_rollback(true); + return (true); } else testutil_die(ret, "unhandled error while trying to insert a key"); } @@ -235,38 +250,14 @@ thread_context::insert(scoped_cursor &cursor, uint64_t collection_id, uint64_t k tracking_operation::INSERT, collection_id, key.c_str(), value.c_str(), ts, op_track_cursor); if (ret != 0) { if (ret == WT_ROLLBACK) { - transaction.rollback(); - return (false); + transaction.set_needs_rollback(true); + return (true); } else testutil_die( ret, "unhandled error while trying to save an insert to the tracking table"); } transaction.add_op(); - return (true); -} - -int -thread_context::next(scoped_cursor &cursor) -{ - WT_DECL_RET; - - ret = cursor->next(cursor.get()); - - if (ret == WT_NOTFOUND) { - testutil_check(cursor->reset(cursor.get())); - return (ret); - } - - if (ret == WT_ROLLBACK) { - transaction.rollback(); - testutil_check(cursor->reset(cursor.get())); - return (ret); - } - - if (ret != 0) - testutil_die(ret, "cursor->next() failed with an unexpected error."); - - return (0); + return (false); } void diff --git a/src/third_party/wiredtiger/test/cppsuite/test_harness/workload/thread_context.h b/src/third_party/wiredtiger/test/cppsuite/test_harness/workload/thread_context.h index 5255740f59c..7bb6ac66cb6 100644 --- a/src/third_party/wiredtiger/test/cppsuite/test_harness/workload/thread_context.h +++ b/src/third_party/wiredtiger/test/cppsuite/test_harness/workload/thread_context.h @@ -71,17 +71,28 @@ class transaction_context { void begin(const std::string &config = ""); /* Begin a transaction if we are not currently in one. */ void try_begin(const std::string &config = ""); - void commit(const std::string &config = ""); - /* Attempt to commit the transaction given the requirements are met. */ - void try_commit(const std::string &config = ""); + /* + * Commit a transaction and return true if a rollback is required. + */ + bool commit(const std::string &config = ""); + /* Rollback a transaction, failure will abort the test. */ void rollback(const std::string &config = ""); /* Attempt to rollback the transaction given the requirements are met. */ void try_rollback(const std::string &config = ""); /* Set a commit timestamp. */ void set_commit_timestamp(wt_timestamp_t ts); - - private: - bool can_commit_rollback(); + /* Set that the transaction needs to be rolled back. */ + void set_needs_rollback(bool rollback); + /* + * Returns true if a transaction can be committed as determined by the op count and the state of + * the transaction. + */ + bool can_commit(); + /* + * Returns true if a transaction can be rolled back as determined by the op count and the state + * of the transaction. + */ + bool can_rollback(); private: /* @@ -99,6 +110,7 @@ class transaction_context { int64_t _max_op_count = INT64_MAX; int64_t _target_op_count = 0; bool _in_txn = false; + bool _needs_rollback = false; WT_SESSION *_session = nullptr; timestamp_manager *_timestamp_manager = nullptr; @@ -124,25 +136,17 @@ class thread_context { /* * Generic update function, takes a collection_id and key, will generate the value. * - * Returns true if it successfully updates the key, false if it receives rollback from the API. + * Returns true if a rollback is required. */ bool update(scoped_cursor &cursor, uint64_t collection_id, const std::string &key); /* * Generic insert function, takes a collection_id and key_id, will generate the value. * - * Returns true if it successfully inserts the key, false if it receives rollback from the API. + * Returns true if a rollback is required. */ bool insert(scoped_cursor &cursor, uint64_t collection_id, uint64_t key_id); - /* - * Generic next function. - * - * Handles rollback and not found internally, but will return the error code to the caller so - * the caller can distinguish between them. - */ - int next(scoped_cursor &cursor); - void sleep(); bool running() const; diff --git a/src/third_party/wiredtiger/test/cppsuite/tests/hs_cleanup.cxx b/src/third_party/wiredtiger/test/cppsuite/tests/hs_cleanup.cxx index 4dd073cc115..03de6947a86 100644 --- a/src/third_party/wiredtiger/test/cppsuite/tests/hs_cleanup.cxx +++ b/src/third_party/wiredtiger/test/cppsuite/tests/hs_cleanup.cxx @@ -62,8 +62,24 @@ class hs_cleanup : public test { while (tc->running()) { tc->sleep(); - if (tc->next(cursor) != 0) - continue; + auto ret = cursor->next(cursor.get()); + if (ret != 0) { + if (ret == WT_NOTFOUND) { + cursor->reset(cursor.get()); + continue; + } + if (ret == WT_ROLLBACK) { + /* + * As a result of the logic in this test its possible that the previous next + * call can happen outside the context of a transaction. Assert that we are in + * one if we got a rollback. + */ + testutil_check(tc->transaction.can_rollback()); + tc->transaction.rollback(); + continue; + } + testutil_die(ret, "Unexpected error returned from cursor->next()"); + } testutil_check(cursor->get_key(cursor.get(), &key_tmp)); @@ -75,14 +91,17 @@ class hs_cleanup : public test { * API doesn't guarantee our buffer will still be valid once it is called, as such we * copy the buffer and then pass it into the API. */ - if (!tc->update(cursor, coll.id, key_value_t(key_tmp))) - continue; + bool rollback_required = tc->update(cursor, coll.id, key_value_t(key_tmp)); /* Commit our transaction. */ - tc->transaction.try_commit(); + if (!rollback_required && tc->transaction.can_commit()) + rollback_required = tc->transaction.commit(); + + if (rollback_required) + tc->transaction.rollback(); } /* Ensure our last transaction is resolved. */ if (tc->transaction.active()) - tc->transaction.commit(); + tc->transaction.rollback(); } }; |