diff options
author | Siyuan Zhou <siyuan.zhou@mongodb.com> | 2018-10-12 18:38:16 -0400 |
---|---|---|
committer | Siyuan Zhou <siyuan.zhou@mongodb.com> | 2018-10-23 13:30:22 -0400 |
commit | f48fed6054f6e2bb0a7c15b15256feb1eb175509 (patch) | |
tree | 02c77fc221353c2f8d20db4dd8ef06a178822919 | |
parent | df048e23d9149a3607205ae0e69ef11e881c037c (diff) | |
download | mongo-f48fed6054f6e2bb0a7c15b15256feb1eb175509.tar.gz |
SERVER-37622 Disallow implicit abort on committed transactions.
-rw-r--r-- | buildscripts/resmokeconfig/suites/sharded_core_txns.yml | 2 | ||||
-rw-r--r-- | jstests/core/txns/errors_on_committed_transaction.js (renamed from jstests/core/txns/prepare_committed_transaction.js) | 31 | ||||
-rw-r--r-- | src/mongo/db/transaction_participant.cpp | 2 |
3 files changed, 29 insertions, 6 deletions
diff --git a/buildscripts/resmokeconfig/suites/sharded_core_txns.yml b/buildscripts/resmokeconfig/suites/sharded_core_txns.yml index 653dc3fa7c3..556d7d2310e 100644 --- a/buildscripts/resmokeconfig/suites/sharded_core_txns.yml +++ b/buildscripts/resmokeconfig/suites/sharded_core_txns.yml @@ -21,9 +21,9 @@ selector: - jstests/core/txns/disallow_operations_on_prepared_transaction.js - jstests/core/txns/empty_prepare.js - jstests/core/txns/ensure_active_txn_for_prepare_transaction.js + - jstests/core/txns/errors_on_committed_transaction.js - jstests/core/txns/no_new_transactions_when_prepared_transaction_in_progress.js - jstests/core/txns/no_writes_to_config_transactions_with_prepared_transaction.js - - jstests/core/txns/prepare_committed_transaction.js - jstests/core/txns/prepare_conflict.js - jstests/core/txns/prepare_nonexistent_transaction.js - jstests/core/txns/prepare_prepared_transaction.js diff --git a/jstests/core/txns/prepare_committed_transaction.js b/jstests/core/txns/errors_on_committed_transaction.js index 57b3c719075..dec27851ee9 100644 --- a/jstests/core/txns/prepare_committed_transaction.js +++ b/jstests/core/txns/errors_on_committed_transaction.js @@ -20,14 +20,18 @@ const doc = {x: 1}; - jsTestLog("Test that calling prepare on a committed transaction fails."); session.startTransaction(); assert.commandWorked(sessionColl.insert(doc)); session.commitTransaction(); + + const txnNumber = NumberLong(session.getTxnNumber_forTesting()); + + // Call prepare on committed transaction. + jsTestLog("Test that calling prepare on a committed transaction fails."); assert.commandFailedWithCode(sessionDB.adminCommand({ prepareTransaction: 1, coordinatorId: "dummy", - txnNumber: NumberLong(0), + txnNumber: txnNumber, autocommit: false }), ErrorCodes.TransactionCommitted); @@ -42,7 +46,7 @@ "providing autocommit to prepareTransaction."); assert.commandFailedWithCode( sessionDB.adminCommand( - {prepareTransaction: 1, coordinatorId: "dummy", txnNumber: NumberLong(0)}), + {prepareTransaction: 1, coordinatorId: "dummy", txnNumber: txnNumber}), ErrorCodes.InvalidOptions); jsTestLog("Test the error precedence when calling prepare on a committed transaction and " + @@ -50,11 +54,30 @@ assert.commandFailedWithCode(sessionDB.adminCommand({ prepareTransaction: 1, coordinatorId: "dummy", - txnNumber: NumberLong(0), + txnNumber: txnNumber, autocommit: false, startTransaction: true }), ErrorCodes.ConflictingOperationInProgress); + // Call commit on committed transaction without shell helper. + jsTestLog("Test that calling commit with invalid fields on a committed transaction fails."); + assert.commandFailedWithCode( + sessionDB.adminCommand( + {commitTransaction: 1, invalidField: 1, txnNumber: txnNumber, autocommit: false}), + 40415 /* IDL unknown field error */); + + // Call abort on committed transaction without shell helper. + jsTestLog("Test that calling abort on a committed transaction fails."); + assert.commandFailedWithCode( + sessionDB.adminCommand({abortTransaction: 1, txnNumber: txnNumber, autocommit: false}), + ErrorCodes.TransactionCommitted); + + jsTestLog("Test that calling abort with invalid fields on a committed transaction fails."); + assert.commandFailedWithCode( + sessionDB.adminCommand( + {abortTransaction: 1, invalidField: 1, txnNumber: txnNumber, autocommit: false}), + ErrorCodes.TransactionCommitted); + session.endSession(); }()); diff --git a/src/mongo/db/transaction_participant.cpp b/src/mongo/db/transaction_participant.cpp index 2d2bb82cec1..512c0ce7070 100644 --- a/src/mongo/db/transaction_participant.cpp +++ b/src/mongo/db/transaction_participant.cpp @@ -1081,7 +1081,7 @@ void TransactionParticipant::abortActiveTransaction(OperationContext* opCtx) { void TransactionParticipant::abortActiveUnpreparedOrStashPreparedTransaction( OperationContext* opCtx) try { stdx::unique_lock<stdx::mutex> lock(_mutex); - if (_txnState.isInSet(lock, TransactionState::kNone)) { + if (_txnState.isInSet(lock, TransactionState::kNone | TransactionState::kCommitted)) { // If there is no active transaction, do nothing. return; } |