diff options
author | Randolph Tan <randolph@10gen.com> | 2018-01-25 15:17:39 -0500 |
---|---|---|
committer | Randolph Tan <randolph@10gen.com> | 2018-02-12 15:01:07 -0500 |
commit | 2a511c4c8baa96320d089ec9f9b4ac00644bcecd (patch) | |
tree | 528b7f937493bfcd0d08e01e0020a8b806664491 | |
parent | 228a8e7d410ae01dc2ee8b90a83ddf08aa219bc9 (diff) | |
download | mongo-2a511c4c8baa96320d089ec9f9b4ac00644bcecd.tar.gz |
SERVER-32556 retryable write on local db hits an invariant
(cherry picked from commit d16ce76f69687e34f06eb6db298fa4445d8105dc)
-rw-r--r-- | jstests/sharding/retryable_writes.js | 64 | ||||
-rw-r--r-- | src/mongo/db/repl/oplog.cpp | 10 |
2 files changed, 69 insertions, 5 deletions
diff --git a/jstests/sharding/retryable_writes.js b/jstests/sharding/retryable_writes.js index f4f048f09ae..da0a936cbdb 100644 --- a/jstests/sharding/retryable_writes.js +++ b/jstests/sharding/retryable_writes.js @@ -399,7 +399,7 @@ assert.eq(1, collContents[1].y); } - function runMultiTests(mainConn, priConn) { + function runMultiTests(mainConn) { // Test the behavior of retryable writes with multi=true / limit=0 var lsid = {id: UUID()}; var testDb = mainConn.getDB('test_multi'); @@ -447,6 +447,63 @@ res.writeErrors[0].code); } + function runInvalidTests(mainConn) { + var lsid = {id: UUID()}; + var localDB = mainConn.getDB('local'); + + let cmd = { + insert: 'user', + documents: [{_id: 10}, {_id: 30}], + ordered: false, + lsid: lsid, + txnNumber: NumberLong(10), + }; + + let res = assert.commandWorked(localDB.runCommand(cmd)); + assert.eq(2, res.writeErrors.length); + + localDB.user.insert({_id: 10, x: 1}); + localDB.user.insert({_id: 30, z: 2}); + + cmd = { + update: 'user', + updates: [ + {q: {_id: 10}, u: {$inc: {x: 1}}}, // in place + {q: {_id: 20}, u: {$inc: {y: 1}}, upsert: true}, + {q: {_id: 30}, u: {z: 1}} // replacement + ], + ordered: false, + lsid: lsid, + txnNumber: NumberLong(11), + }; + + res = assert.commandWorked(localDB.runCommand(cmd)); + assert.eq(3, res.writeErrors.length); + + cmd = { + delete: 'user', + deletes: [{q: {x: 1}, limit: 1}, {q: {z: 2}, limit: 1}], + ordered: false, + lsid: lsid, + txnNumber: NumberLong(12), + }; + + res = assert.commandWorked(localDB.runCommand(cmd)); + assert.eq(2, res.writeErrors.length); + + cmd = { + findAndModify: 'user', + query: {_id: 60}, + update: {$inc: {x: 1}}, + new: true, + upsert: true, + lsid: {id: lsid}, + txnNumber: NumberLong(37), + }; + + assert.commandFailed(localDB.runCommand(cmd)); + } + // Tests for replica set var replTest = new ReplSetTest({nodes: 2}); replTest.startSet(); @@ -456,7 +513,8 @@ runTests(priConn, priConn); runFailpointTests(priConn, priConn); - runMultiTests(priConn, priConn); + runMultiTests(priConn); + runInvalidTests(priConn); replTest.stopSet(); @@ -465,7 +523,7 @@ runTests(st.s0, st.rs0.getPrimary()); runFailpointTests(st.s0, st.rs0.getPrimary()); - runMultiTests(st.s0, st.rs0.getPrimary()); + runMultiTests(st.s0); st.stop(); })(); diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index fad29c26e84..df2392d6dbf 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -418,7 +418,10 @@ OpTime logOp(OperationContext* opCtx, const OplogLink& oplogLink) { auto replCoord = ReplicationCoordinator::get(opCtx); if (replCoord->isOplogDisabledFor(opCtx, nss)) { - invariant(statementId == kUninitializedStmtId); + uassert(ErrorCodes::IllegalOperation, + str::stream() << "retryable writes is not supported for unreplicated ns: " + << nss.ns(), + statementId == kUninitializedStmtId); return {}; } @@ -462,7 +465,10 @@ std::vector<OpTime> logInsertOps(OperationContext* opCtx, auto replCoord = ReplicationCoordinator::get(opCtx); if (replCoord->isOplogDisabledFor(opCtx, nss)) { - invariant(begin->stmtId == kUninitializedStmtId); + uassert(ErrorCodes::IllegalOperation, + str::stream() << "retryable writes is not supported for unreplicated ns: " + << nss.ns(), + begin->stmtId == kUninitializedStmtId); return {}; } |