Skip to content

Commit

Permalink
SERVER-30894 Implement command for transferring session information d…
Browse files Browse the repository at this point in the history
…uring migration
  • Loading branch information
renctan committed Sep 26, 2017
1 parent 457ecaf commit 85d9721
Show file tree
Hide file tree
Showing 31 changed files with 810 additions and 139 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ selector:
- jstests/sharding/uuid_propagated_to_recipient_shard_on_recvChunkStart.js
- jstests/sharding/uuid_propagated_to_shards_on_setFCV_3_6.js
- jstests/sharding/close_cursor_on_chunk_migration_to_new_shards.js
- jstests/sharding/move_chunk_insert_with_write_retryability.js
- jstests/sharding/move_chunk_find_and_modify_with_write_retryability.js
- jstests/sharding/move_chunk_remove_with_write_retryability.js
- jstests/sharding/move_chunk_update_with_write_retryability.js
- jstests/sharding/write_transactions_during_migration.js
# New feature in v3.6 mongo shell.
- jstests/sharding/causal_consistency_shell_support.js
- jstests/sharding/keys_rotation_interval_sec.js
Expand Down
13 changes: 13 additions & 0 deletions jstests/auth/lib/commands_lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -4454,6 +4454,19 @@ var authCommandsLib = {
command: {refreshSessionsInternal: []},
testcases: [{runOnDb: adminDbName, roles: {__system: 1}}],
},
{
testname: "_getNextSessionMods",
command: {_getNextSessionMods: "a-b"},
skipSharded: true,
testcases: [
{
runOnDb: adminDbName,
roles: {__system: 1},
privileges: [{resource: {cluster: true}, actions: ["internal"]}],
expectFail: true
},
]
},
],

/************* SHARED TEST LOGIC ****************/
Expand Down
1 change: 1 addition & 0 deletions jstests/core/views/views_all_commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
_configsvrShardCollection: {skip: isAnInternalCommand},
_configsvrSetFeatureCompatibilityVersion: {skip: isAnInternalCommand},
_configsvrUpdateZoneKeyRange: {skip: isAnInternalCommand},
_getNextSessionMods: {skip: isAnInternalCommand},
_getUserCacheGeneration: {skip: isAnInternalCommand},
_hashBSONElement: {skip: isAnInternalCommand},
_isSelf: {skip: isAnInternalCommand},
Expand Down
119 changes: 119 additions & 0 deletions jstests/sharding/move_chunk_find_and_modify_with_write_retryability.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
load("jstests/sharding/move_chunk_with_session_helper.js");

(function() {

"use strict";

var checkFindAndModifyResult = function(expected, toCheck) {
assert.eq(expected.ok, toCheck.ok);
assert.eq(expected.value, toCheck.value);

// TODO: SERVER-30532: after adding upserted, just compare the entire lastErrorObject
var expectedLE = expected.lastErrorObject;
var toCheckLE = toCheck.lastErrorObject;

assert.neq(null, toCheckLE);
assert.eq(expected.updatedExisting, toCheck.updatedExisting);
assert.eq(expected.n, toCheck.n);
};

var lsid = UUID();
var tests = [
{
coll: 'findAndMod-upsert',
cmd: {
findAndModify: 'findAndMod-upsert',
query: {x: 60},
update: {$inc: {y: 1}},
new: true,
upsert: true,
lsid: {id: lsid},
txnNumber: NumberLong(37),
},
setup: function(coll) {},
checkRetryResult: function(result, retryResult) {
checkFindAndModifyResult(result, retryResult);
},
checkDocuments: function(coll) {
assert.eq(1, coll.findOne({x: 60}).y);
},
},
{
coll: 'findAndMod-update-preImage',
cmd: {
findAndModify: 'findAndMod-update-preImage',
query: {x: 60},
update: {$inc: {y: 1}},
new: false,
upsert: false,
lsid: {id: lsid},
txnNumber: NumberLong(38),
},
setup: function(coll) {
coll.insert({x: 60});
},
checkRetryResult: function(result, retryResult) {
checkFindAndModifyResult(result, retryResult);
},
checkDocuments: function(coll) {
assert.eq(1, coll.findOne({x: 60}).y);
},
},
{
coll: 'findAndMod-update-postImage',
cmd: {
findAndModify: 'findAndMod-update-postImage',
query: {x: 60},
update: {$inc: {y: 1}},
new: true,
upsert: false,
lsid: {id: lsid},
txnNumber: NumberLong(39),
},
setup: function(coll) {
coll.insert({x: 60});
},
checkRetryResult: function(result, retryResult) {
checkFindAndModifyResult(result, retryResult);
},
checkDocuments: function(coll) {
assert.eq(1, coll.findOne({x: 60}).y);
},
},
{
coll: 'findAndMod-delete',
cmd: {
findAndModify: 'findAndMod-delete',
query: {x: 10},
remove: true,
lsid: {id: lsid},
txnNumber: NumberLong(40),
},
setup: function(coll) {
var bulk = coll.initializeUnorderedBulkOp();
for (let i = 0; i < 10; i++) {
bulk.insert({x: 10});
}
assert.writeOK(bulk.execute());

},
checkRetryResult: function(result, retryResult) {
checkFindAndModifyResult(result, retryResult);
},
checkDocuments: function(coll) {
assert.eq(9, coll.find({x: 10}).itcount());
},
},
];

var st = new ShardingTest({shards: {rs0: {nodes: 2}, rs1: {nodes: 2}}});
assert.commandWorked(st.s.adminCommand({enableSharding: 'test'}));
st.ensurePrimaryShard('test', st.shard0.shardName);

tests.forEach(function(test) {
testMoveChunkWithSession(
st, test.coll, test.cmd, test.setup, test.checkRetryResult, test.checkDocuments);
});

st.stop();
})();
34 changes: 34 additions & 0 deletions jstests/sharding/move_chunk_insert_with_write_retryability.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
load("jstests/sharding/move_chunk_with_session_helper.js");

(function() {

"use strict";

var st = new ShardingTest({shards: {rs0: {nodes: 2}, rs1: {nodes: 2}}});
assert.commandWorked(st.s.adminCommand({enableSharding: 'test'}));
st.ensurePrimaryShard('test', st.shard0.shardName);

var coll = 'insert';
var cmd = {
insert: coll,
documents: [{x: 10}, {x: 30}],
ordered: false,
lsid: {id: UUID()},
txnNumber: NumberLong(34),
};
var setup = function() {};
var checkRetryResult = function(result, retryResult) {
assert.eq(result.ok, retryResult.ok);
assert.eq(result.n, retryResult.n);
assert.eq(result.writeErrors, retryResult.writeErrors);
assert.eq(result.writeConcernErrors, retryResult.writeConcernErrors);
};
var checkDocuments = function(coll) {
assert.eq(1, coll.find({x: 10}).itcount());
assert.eq(1, coll.find({x: 30}).itcount());
};

testMoveChunkWithSession(st, coll, cmd, setup, checkRetryResult, checkDocuments);

st.stop();
})();
41 changes: 41 additions & 0 deletions jstests/sharding/move_chunk_remove_with_write_retryability.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
load("jstests/sharding/move_chunk_with_session_helper.js");

(function() {

"use strict";

var st = new ShardingTest({shards: {rs0: {nodes: 2}, rs1: {nodes: 2}}});
assert.commandWorked(st.s.adminCommand({enableSharding: 'test'}));
st.ensurePrimaryShard('test', st.shard0.shardName);

var coll = 'delete';
var cmd = {
delete: coll,
deletes: [{q: {x: 10}, limit: 1}, {q: {x: 20}, limit: 1}],
ordered: false,
lsid: {id: UUID()},
txnNumber: NumberLong(36),
};
var setup = function(coll) {
var bulk = coll.initializeUnorderedBulkOp();
for (let i = 0; i < 10; i++) {
bulk.insert({x: 10});
bulk.insert({x: 20});
}
assert.writeOK(bulk.execute());
};
var checkRetryResult = function(result, retryResult) {
assert.eq(result.ok, retryResult.ok);
assert.eq(result.n, retryResult.n);
assert.eq(result.writeErrors, retryResult.writeErrors);
assert.eq(result.writeConcernErrors, retryResult.writeConcernErrors);
};
var checkDocuments = function(coll) {
assert.eq(9, coll.find({x: 10}).itcount());
assert.eq(9, coll.find({x: 20}).itcount());
};

testMoveChunkWithSession(st, coll, cmd, setup, checkRetryResult, checkDocuments);

st.stop();
})();
44 changes: 44 additions & 0 deletions jstests/sharding/move_chunk_update_with_write_retryability.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
load("jstests/sharding/move_chunk_with_session_helper.js");

(function() {

"use strict";

var st = new ShardingTest({shards: {rs0: {nodes: 2}, rs1: {nodes: 2}}});
assert.commandWorked(st.s.adminCommand({enableSharding: 'test'}));
st.ensurePrimaryShard('test', st.shard0.shardName);

var coll = 'update';
var cmd = {
update: 'update',
updates: [
{q: {x: 10}, u: {$inc: {a: 1}}}, // in place
{q: {x: 20}, u: {$inc: {b: 1}}, upsert: true},
{q: {x: 30}, u: {x: 30, z: 1}} // replacement
],
ordered: false,
lsid: {id: UUID()},
txnNumber: NumberLong(35),
};
var setup = function(coll) {
coll.insert({x: 10});
coll.insert({x: 30});
};
var checkRetryResult = function(result, retryResult) {
assert.eq(result.ok, retryResult.ok);
assert.eq(result.n, retryResult.n);
assert.eq(result.nModified, retryResult.nModified);
assert.eq(result.upserted, retryResult.upserted);
assert.eq(result.writeErrors, retryResult.writeErrors);
assert.eq(result.writeConcernErrors, retryResult.writeConcernErrors);
};
var checkDocuments = function(coll) {
assert.eq(1, coll.findOne({x: 10}).a);
assert.eq(1, coll.findOne({x: 20}).b);
assert.eq(1, coll.findOne({x: 30}).z);
};

testMoveChunkWithSession(st, coll, cmd, setup, checkRetryResult, checkDocuments);

st.stop();
})();
49 changes: 49 additions & 0 deletions jstests/sharding/move_chunk_with_session_helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
load("jstests/replsets/rslib.js");

/**
* High level test scenario:
* 1. Shard collection.
* 2. Perform writes.
* 3. Migrate only chunk to other shard.
* 4. Retry writes.
* 5. Step down primary and wait for new primary.
* 6. Retry writes.
* 7. Migrate only chunk back to original shard.
* 8. Retry writes.
*/
var testMoveChunkWithSession = function(
st, collName, cmdObj, setupFunc, checkRetryResultFunc, checkDocumentsFunc) {
var ns = 'test.' + collName;
var testDB = st.s.getDB('test');
var coll = testDB.getCollection(collName);

assert.commandWorked(st.s.adminCommand({shardCollection: ns, key: {x: 1}}));

setupFunc(coll);
var result = assert.commandWorked(testDB.runCommand(cmdObj));

assert.commandWorked(st.s.adminCommand({moveChunk: ns, find: {x: 0}, to: st.shard1.shardName}));

checkRetryResultFunc(result, assert.commandWorked(testDB.runCommand(cmdObj)));
checkDocumentsFunc(coll);

try {
st.rs1.getPrimary().adminCommand({replSetStepDown: 60, secondaryCatchUpPeriodSecs: 30});
} catch (excep) {
print('Expected exception due to step down: ' + tojson(excep));
}

st.rs1.awaitNodesAgreeOnPrimary();
awaitRSClientHosts(st.s, {host: st.rs1.getPrimary().host}, {ok: true, ismaster: true});

checkRetryResultFunc(result, assert.commandWorked(testDB.runCommand(cmdObj)));
checkDocumentsFunc(coll);

// Make sure that the other shard knows about the latest primary.
awaitRSClientHosts(
st.rs0.getPrimary(), {host: st.rs1.getPrimary().host}, {ok: true, ismaster: true});
assert.commandWorked(st.s.adminCommand({moveChunk: ns, find: {x: 0}, to: st.shard0.shardName}));

checkRetryResultFunc(result, assert.commandWorked(testDB.runCommand(cmdObj)));
checkDocumentsFunc(coll);
};
Loading

0 comments on commit 85d9721

Please sign in to comment.