diff options
author | Tess Avitabile <tess.avitabile@mongodb.com> | 2019-05-15 12:36:54 -0400 |
---|---|---|
committer | Tess Avitabile <tess.avitabile@mongodb.com> | 2019-05-16 09:46:43 -0400 |
commit | 06c7e27f2e7a668d81baf02d89f422cdda205fce (patch) | |
tree | 81ed0df5ecd0193fe7a2dc1846980cdfd2863fc9 /src/mongo/db/transaction_validation.cpp | |
parent | 953c6116138800e0fbed79e7654eda1690d56f71 (diff) | |
download | mongo-06c7e27f2e7a668d81baf02d89f422cdda205fce.tar.gz |
SERVER-41050 Ban txnNumbers outside of transactions and retryable writes
Diffstat (limited to 'src/mongo/db/transaction_validation.cpp')
-rw-r--r-- | src/mongo/db/transaction_validation.cpp | 45 |
1 files changed, 13 insertions, 32 deletions
diff --git a/src/mongo/db/transaction_validation.cpp b/src/mongo/db/transaction_validation.cpp index dfd13ba85c4..65fddae3b39 100644 --- a/src/mongo/db/transaction_validation.cpp +++ b/src/mongo/db/transaction_validation.cpp @@ -31,47 +31,26 @@ #include "mongo/db/transaction_validation.h" +#include <fmt/format.h> + #include "mongo/db/commands.h" #include "mongo/db/logical_session_id.h" #include "mongo/db/write_concern_options.h" namespace mongo { +using namespace fmt::literals; + namespace { -// The command names for which to check out a session. These are commands that support retryable -// writes, readConcern snapshot, or multi-statement transactions. We additionally check out the -// session for commands that can take a lock and then run another whitelisted command in -// DBDirectClient. Otherwise, the nested command would try to check out a session under a lock, -// which is not allowed. -const StringMap<int> sessionCheckOutList = {{"abortTransaction", 1}, - {"aggregate", 1}, - {"applyOps", 1}, - {"commitTransaction", 1}, - {"count", 1}, - {"delete", 1}, - {"distinct", 1}, - {"doTxn", 1}, - {"explain", 1}, - {"filemd5", 1}, - {"find", 1}, - {"findandmodify", 1}, - {"findAndModify", 1}, - {"geoNear", 1}, - {"geoSearch", 1}, - {"getMore", 1}, - {"group", 1}, - {"insert", 1}, - {"killCursors", 1}, - {"prepareTransaction", 1}, - {"refreshLogicalSessionCacheNow", 1}, - {"update", 1}}; +const StringMap<int> retryableWriteCommands = { + {"delete", 1}, {"findandmodify", 1}, {"findAndModify", 1}, {"insert", 1}, {"update", 1}}; // Commands that can be sent with session info but should not check out a session. const StringMap<int> skipSessionCheckoutList = {{"coordinateCommitTransaction", 1}}; -bool commandCanCheckOutSession(StringData cmdName) { - return sessionCheckOutList.find(cmdName) != sessionCheckOutList.cend(); +bool isRetryableWriteCommand(StringData cmdName) { + return retryableWriteCommands.find(cmdName) != retryableWriteCommands.cend(); } } // namespace @@ -95,10 +74,12 @@ void validateSessionOptions(const OperationSessionInfoFromClient& sessionOptions uassertStatusOK(CommandHelpers::canUseTransactions(dbname, cmdName)); } - if (sessionOptions.getTxnNumber()) { + if (!sessionOptions.getAutocommit() && sessionOptions.getTxnNumber()) { uassert(50768, - str::stream() << "It is illegal to provide a txnNumber for command " << cmdName, - commandCanCheckOutSession(cmdName) || shouldCommandSkipSessionCheckout(cmdName)); + "txnNumber may only be provided for multi-document transactions and retryable " + "write commands. autocommit:false was not provided, and {} is not a retryable " + "write command."_format(cmdName), + isRetryableWriteCommand(cmdName)); } if (sessionOptions.getStartTransaction()) { |