summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandolph Tan <randolph@10gen.com>2018-01-25 15:17:39 -0500
committerRandolph Tan <randolph@10gen.com>2018-02-12 15:01:07 -0500
commit2a511c4c8baa96320d089ec9f9b4ac00644bcecd (patch)
tree528b7f937493bfcd0d08e01e0020a8b806664491
parent228a8e7d410ae01dc2ee8b90a83ddf08aa219bc9 (diff)
downloadmongo-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.js64
-rw-r--r--src/mongo/db/repl/oplog.cpp10
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 {};
}