diff options
Diffstat (limited to 'jstests/sharding')
-rw-r--r-- | jstests/sharding/reshard_collection_joins_existing_operation.js | 115 | ||||
-rw-r--r-- | jstests/sharding/resharding_on_existing_key_is_noop.js | 39 |
2 files changed, 154 insertions, 0 deletions
diff --git a/jstests/sharding/reshard_collection_joins_existing_operation.js b/jstests/sharding/reshard_collection_joins_existing_operation.js new file mode 100644 index 00000000000..0ee7dce2b64 --- /dev/null +++ b/jstests/sharding/reshard_collection_joins_existing_operation.js @@ -0,0 +1,115 @@ +/** + * Tests that if a _configsvrReshardCollection command is issued and then the same command gets + * issued again, the second command issued joins with the instance of resharding already in + * progress. + * + * Use _configsvrReshardCollection instead of reshardCollection to exercise the behavior of the + * config server in the absence of the distributed lock taken by _shardsvrReshardCollection on the + * primary shard for the database. + * + * @tags: [ + * requires_fcv_49, + * uses_atclustertime, + * ] + */ +(function() { +"use strict"; + +load("jstests/libs/discover_topology.js"); +load("jstests/libs/parallelTester.js"); +load("jstests/sharding/libs/resharding_test_fixture.js"); + +// Generates a new thread to run _configsvrReshardCollection. +const makeConfigsvrReshardCollectionThread = (mongosConnString, configsvrReshardCollectionCmd) => { + return new Thread((mongosConnString, configsvrReshardCollectionCmd) => { + load("jstests/libs/discover_topology.js"); + const mongos = new Mongo(mongosConnString); + const topology = DiscoverTopology.findConnectedNodes(mongos); + const configsvr = new Mongo(topology.configsvr.nodes[0]); + assert.commandWorked(configsvr.adminCommand(configsvrReshardCollectionCmd)); + }, mongosConnString, configsvrReshardCollectionCmd); +}; + +const constructTempReshardingNs = (dbName, collName) => { + const sourceCollectionUUID = getUUIDFromListCollections(dbName, collName); + const sourceCollectionUUIDString = extractUUIDFromObject(sourceCollectionUUID); + return `${dbName}.system.resharding.${sourceCollectionUUIDString}`; +}; + +// Callers must ensure the temporary collection has actually been created by the time this is +// called. +const getTempUUID = (tempNs) => { + const tempCollection = mongos.getCollection(tempNs); + return getUUIDFromConfigCollections(mongos, tempCollection.getFullName()); +}; + +const st = new ShardingTest({ + mongos: 1, + config: 1, + shards: 2, + rs: {nodes: 2}, +}); + +const sourceCollection = st.s.getCollection("reshardingDb.coll"); + +CreateShardedCollectionUtil.shardCollectionWithChunks(sourceCollection, {oldKey: 1}, [ + {min: {oldKey: MinKey}, max: {oldKey: MaxKey}, shard: st.shard0.shardName}, +]); + +const reshardKey = { + newKey: 1 +}; +const configsvrReshardCollectionCmd = { + _configsvrReshardCollection: sourceCollection.getFullName(), + key: reshardKey, + writeConcern: {w: "majority"} +}; + +// Before starting the actual resharding, get the source collection's UUID to construct the +// namespace for the temporary collection that will be created. +const sourceDBName = sourceCollection.getDB(); +const sourceCollName = sourceCollection.getName(); +const tempNs = constructTempReshardingNs(sourceDBName, sourceCollName); + +const mongos = sourceCollection.getMongo(); +const topology = DiscoverTopology.findConnectedNodes(mongos); +const configsvr = new Mongo(topology.configsvr.nodes[0]); + +const reshardCollectionThread1 = + makeConfigsvrReshardCollectionThread(topology.mongos.nodes[0], configsvrReshardCollectionCmd); +const pauseBeforeCloningFP = + configureFailPoint(configsvr, "reshardingPauseCoordinatorBeforeCloning"); + +// Issue the first _configsvrReshardCollection command and pause after the temporary collection is +// created but before its config.collections entry is replaced. +reshardCollectionThread1.start(); +pauseBeforeCloningFP.wait(); + +// The UUID of the temporary resharding collection should become the UUID of the original collection +// once resharding has completed. +const expectedUUIDAfterReshardingCompletes = getTempUUID(tempNs); + +const reshardCollectionJoinedFP = + configureFailPoint(configsvr, "reshardCollectionJoinedExistingOperation"); +const reshardCollectionThread2 = + makeConfigsvrReshardCollectionThread(topology.mongos.nodes[0], configsvrReshardCollectionCmd); + +// Hitting the reshardCollectionJoinedFP is additional confirmation that the second +// _configsvrReshardCollection command (identical to the first) gets joined with the instance +// created/running for the first command issued. +reshardCollectionThread2.start(); +reshardCollectionJoinedFP.wait(); + +reshardCollectionJoinedFP.off(); +pauseBeforeCloningFP.off(); + +reshardCollectionThread2.join(); +reshardCollectionThread1.join(); + +// Confirm the UUID for the namespace that was resharded is the same as the temporary collection's +// UUID before the second reshardCollection command was issued. +const finalSourceCollectionUUID = getUUIDFromListCollections(sourceDBName, sourceCollName); +assert.eq(expectedUUIDAfterReshardingCompletes, finalSourceCollectionUUID); + +st.stop(); +})(); diff --git a/jstests/sharding/resharding_on_existing_key_is_noop.js b/jstests/sharding/resharding_on_existing_key_is_noop.js new file mode 100644 index 00000000000..dcc3f68178e --- /dev/null +++ b/jstests/sharding/resharding_on_existing_key_is_noop.js @@ -0,0 +1,39 @@ +/** + * Tests that trying to perform reshardCollection with a resharding key that matches the + * collection's existing shard key is a noop (which can be done by confirming the collection's UUID + * remains unchanged after the operation). + * + * @tags: [uses_atclustertime, requires_fcv_49,] + */ +(function() { +"use strict"; + +load("jstests/libs/uuid_util.js"); +load("jstests/sharding/libs/create_sharded_collection_util.js"); + +const st = new ShardingTest({ + mongos: 1, + config: 1, + shards: 2, + rs: {nodes: 2}, +}); + +const sourceCollection = st.s.getCollection("reshardingDb.coll"); + +CreateShardedCollectionUtil.shardCollectionWithChunks(sourceCollection, {key: 1}, [ + {min: {key: MinKey}, max: {key: 0}, shard: st.shard0.shardName}, + {min: {key: 0}, max: {key: MaxKey}, shard: st.shard1.shardName}, +]); + +const ns = sourceCollection.getFullName(); +const mongos = sourceCollection.getMongo(); +const sourceDB = sourceCollection.getDB(); + +// The UUID should remain the same if the resharding key matches the existing shard key. +const preReshardCollectionUUID = getUUIDFromListCollections(sourceDB, sourceCollection.getName()); +assert.commandWorked(mongos.adminCommand({reshardCollection: ns, key: {key: 1}})); +const postReshardCollectionUUID = getUUIDFromListCollections(sourceDB, sourceCollection.getName()); +assert.eq(preReshardCollectionUUID, postReshardCollectionUUID); + +st.stop(); +})(); |