Skip to content

Commit

Permalink
SERVER-32556 retryable write on local db hits an invariant
Browse files Browse the repository at this point in the history
  • Loading branch information
renctan committed Jan 29, 2018
1 parent 494dbd0 commit d16ce76
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 5 deletions.
64 changes: 61 additions & 3 deletions jstests/sharding/retryable_writes.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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.commandWorkedIgnoringWriteErrors(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.commandWorkedIgnoringWriteErrors(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.commandWorkedIgnoringWriteErrors(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();
Expand All @@ -456,7 +513,8 @@

runTests(priConn, priConn);
runFailpointTests(priConn, priConn);
runMultiTests(priConn, priConn);
runMultiTests(priConn);
runInvalidTests(priConn);

replTest.stopSet();

Expand All @@ -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();
})();
10 changes: 8 additions & 2 deletions src/mongo/db/repl/oplog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,10 @@ OpTime logOp(OperationContext* opCtx,
// For commands, the test below is on the command ns and therefore does not check for
// specific namespaces such as system.profile. This is the caller's responsibility.
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 {};
}

Expand Down Expand Up @@ -464,7 +467,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 {};
}

Expand Down

0 comments on commit d16ce76

Please sign in to comment.