mirror of https://github.com/mongodb/mongo
181 lines
8.0 KiB
JavaScript
181 lines
8.0 KiB
JavaScript
import {FixtureHelpers} from "jstests/libs/fixture_helpers.js";
|
|
import {ShardingTest} from "jstests/libs/shardingtest.js";
|
|
|
|
function collectionExists(shard, dbName, collName) {
|
|
return Array.contains(shard.getDB(dbName).getCollectionNames(), collName);
|
|
}
|
|
|
|
let st = new ShardingTest({mongos: 1, shards: 2});
|
|
|
|
let mongos = st.s0;
|
|
let shard0 = st.shard0;
|
|
let shard1 = st.shard1;
|
|
let config = st.config;
|
|
|
|
const dbName = "test_db";
|
|
const coll1Name = "test_coll_1";
|
|
const coll2Name = "test_coll_2";
|
|
const coll3Name = "test_coll_3";
|
|
const coll4Name = "test_coll_4";
|
|
const coll1NS = dbName + "." + coll1Name;
|
|
const coll2NS = dbName + "." + coll2Name;
|
|
const coll3NS = dbName + "." + coll3Name;
|
|
const coll4NS = dbName + "." + coll4Name;
|
|
|
|
assert.commandWorked(mongos.adminCommand({enableSharding: dbName, primaryShard: shard0.shardName}));
|
|
assert.commandWorked(mongos.getCollection(coll1NS).insert({name: "Tom"}));
|
|
assert.commandWorked(mongos.getCollection(coll1NS).insert({name: "Dick"}));
|
|
assert.commandWorked(mongos.getCollection(coll2NS).insert({name: "Harry"}));
|
|
|
|
assert.commandWorked(mongos.getDB(dbName).runCommand({createUnsplittableCollection: coll3Name}));
|
|
assert.commandWorked(mongos.getCollection(coll3NS).insert({name: "Peter"}));
|
|
|
|
assert.commandWorked(
|
|
mongos.getDB(dbName).runCommand({createUnsplittableCollection: coll4Name, dataShard: shard1.shardName}),
|
|
);
|
|
assert.commandWorked(mongos.getCollection(coll4NS).insert({name: "Jack"}));
|
|
|
|
assert.commandWorked(st.s.adminCommand({shardCollection: coll2NS, key: {_id: 1}}));
|
|
|
|
jsTest.log("Test preconditions");
|
|
{
|
|
// Fail with internal databases.
|
|
assert.commandFailed(mongos.adminCommand({movePrimary: "config", to: shard1.shardName}));
|
|
assert.commandFailed(mongos.adminCommand({movePrimary: "admin", to: shard1.shardName}));
|
|
assert.commandFailed(mongos.adminCommand({movePrimary: "local", to: shard1.shardName}));
|
|
|
|
// Fail with invalid database names.
|
|
assert.commandFailed(mongos.adminCommand({movePrimary: "", to: shard1.shardName}));
|
|
assert.commandFailed(mongos.adminCommand({movePrimary: "a.b", to: shard1.shardName}));
|
|
|
|
// Fail against a non-admin database.
|
|
assert.commandFailedWithCode(
|
|
mongos.getDB("test").runCommand({movePrimary: dbName, to: shard1.shardName}),
|
|
ErrorCodes.Unauthorized,
|
|
);
|
|
|
|
// Fail if the destination shard is invalid or does not exist.
|
|
assert.commandFailed(mongos.adminCommand({movePrimary: dbName}));
|
|
assert.commandFailed(mongos.adminCommand({movePrimary: dbName, to: ""}));
|
|
assert.commandFailed(mongos.adminCommand({movePrimary: dbName, to: "Unknown"}));
|
|
|
|
// Succeed if the destination shard is already the primary for the given database.
|
|
assert.commandWorked(mongos.adminCommand({movePrimary: dbName, to: shard0.shardName}));
|
|
}
|
|
|
|
jsTest.log("Test that orphaned documents on recipient causes the operation to fail");
|
|
{
|
|
// Insert an orphaned document on shard1.
|
|
assert.commandWorked(shard1.getCollection(coll1NS).insertOne({name: "Emma"}));
|
|
|
|
// The documents are on both the shards.
|
|
assert.eq(2, shard0.getCollection(coll1NS).find().itcount());
|
|
assert.eq(1, shard1.getCollection(coll1NS).find().itcount());
|
|
|
|
// If the collection is being cloned by the movePrimary operation, this will fail with
|
|
// NamespaceExists. Otherwise, when the collection is being cloned, it will fail with
|
|
// InvalidOptions due to the UUIDS not matching.
|
|
let expectedErrorCode = ErrorCodes.NamespaceExists;
|
|
assert.commandFailedWithCode(mongos.adminCommand({movePrimary: dbName, to: shard1.shardName}), expectedErrorCode);
|
|
|
|
// The documents are on both the shards.
|
|
assert.eq(2, shard0.getCollection(coll1NS).find().itcount());
|
|
assert.eq(1, shard1.getCollection(coll1NS).find().itcount());
|
|
|
|
// Remove the orphaned document on shard1 leaving an empty collection.
|
|
assert.commandWorked(shard1.getCollection(coll1NS).remove({name: "Emma"}));
|
|
assert.eq(0, shard1.getCollection(coll1NS).find().itcount());
|
|
|
|
assert.commandFailedWithCode(mongos.adminCommand({movePrimary: dbName, to: shard1.shardName}), expectedErrorCode);
|
|
|
|
// Drop the orphaned collection on shard1.
|
|
shard1.getCollection(coll1NS).drop();
|
|
}
|
|
|
|
jsTest.log("Test that unsharded, untracked collections are moved");
|
|
{
|
|
{
|
|
// Unsharded (maybe tracked) collection (1)'s documents are on shard 0.
|
|
assert.eq(2, shard0.getCollection(coll1NS).find().itcount());
|
|
assert.eq(0, shard1.getCollection(coll1NS).find().itcount());
|
|
// Sharded collection (2)'s documents are on shard 0.
|
|
assert.eq(1, shard0.getCollection(coll2NS).find().itcount());
|
|
assert.eq(0, shard1.getCollection(coll2NS).find().itcount());
|
|
// Unsharded, tracked collection (3)'s documents are on shard 0.
|
|
|
|
assert.eq(1, shard0.getCollection(coll3NS).find().itcount());
|
|
assert.eq(0, shard1.getCollection(coll3NS).find().itcount());
|
|
|
|
// Unsharded, tracked collection (4)'s documents are on shard 1.
|
|
|
|
assert.eq(1, shard1.getCollection(coll4NS).find().itcount());
|
|
assert.eq(0, shard0.getCollection(coll4NS).find().itcount());
|
|
}
|
|
|
|
assert.commandWorked(mongos.adminCommand({movePrimary: dbName, to: shard1.shardName}));
|
|
|
|
{
|
|
// Unsharded collection (1) may or may not be tracked. If it is tracked, it's documents will
|
|
// still be on shard 0, otherwise, they will have moved to shard 1.
|
|
if (FixtureHelpers.isTracked(mongos.getCollection(coll1NS))) {
|
|
assert.eq(2, shard0.getCollection(coll1NS).find().itcount());
|
|
assert.eq(0, shard1.getCollection(coll1NS).find().itcount());
|
|
} else {
|
|
assert.eq(0, shard0.getCollection(coll1NS).find().itcount());
|
|
assert.eq(2, shard1.getCollection(coll1NS).find().itcount());
|
|
}
|
|
// Sharded collection (2)'s documents are on shard 0
|
|
assert.eq(1, shard0.getCollection(coll2NS).find().itcount());
|
|
assert.eq(0, shard1.getCollection(coll2NS).find().itcount());
|
|
// Unsharded, tracked collection (3)'s documents are on shard 0
|
|
|
|
assert.eq(1, shard0.getCollection(coll3NS).find().itcount());
|
|
assert.eq(0, shard1.getCollection(coll3NS).find().itcount());
|
|
|
|
// Unsharded, tracked collection (4)'s documents are on shard 1
|
|
|
|
assert.eq(0, shard0.getCollection(coll4NS).find().itcount());
|
|
assert.eq(1, shard1.getCollection(coll4NS).find().itcount());
|
|
}
|
|
|
|
assert.commandWorked(mongos.adminCommand({movePrimary: dbName, to: shard0.shardName}));
|
|
|
|
{
|
|
// Unsharded collection (1)'s documents are on shard 0.
|
|
assert.eq(2, shard0.getCollection(coll1NS).find().itcount());
|
|
assert.eq(0, shard1.getCollection(coll1NS).find().itcount());
|
|
// Sharded collection (2)'s documents are on shard 0
|
|
assert.eq(1, shard0.getCollection(coll2NS).find().itcount());
|
|
assert.eq(0, shard1.getCollection(coll2NS).find().itcount());
|
|
// Unsharded, tracked collection (3)'s documents are on shard 0
|
|
|
|
assert.eq(1, shard0.getCollection(coll3NS).find().itcount());
|
|
assert.eq(0, shard1.getCollection(coll3NS).find().itcount());
|
|
|
|
// Unsharded, tracked collection (4)'s documents are on shard 1
|
|
|
|
assert.eq(0, shard0.getCollection(coll4NS).find().itcount());
|
|
assert.eq(1, shard1.getCollection(coll4NS).find().itcount());
|
|
}
|
|
}
|
|
|
|
jsTest.log("Test that metadata has changed");
|
|
{
|
|
// The current primary shard is shard1.
|
|
const previousMetadata = config.databases.findOne({_id: dbName});
|
|
assert.eq(shard0.shardName, previousMetadata.primary);
|
|
|
|
assert.commandWorked(mongos.adminCommand({movePrimary: dbName, to: shard1.shardName}));
|
|
|
|
// The new primary shard is shard0.
|
|
const nextMetadata = config.databases.findOne({_id: dbName});
|
|
assert.eq(shard1.shardName, nextMetadata.primary);
|
|
|
|
// UUID has not changed, but timestamp and lastMod have been bumped.
|
|
assert.eq(previousMetadata.version.uuid, nextMetadata.version.uuid);
|
|
assert.eq(-1, timestampCmp(previousMetadata.version.timestamp, nextMetadata.version.timestamp));
|
|
assert.eq(previousMetadata.version.lastMod + 1, nextMetadata.version.lastMod);
|
|
}
|
|
|
|
st.stop();
|