diff options
author | Misha Tyulenev <misha.tyulenev@mongodb.com> | 2020-07-08 22:28:55 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-08-13 00:17:26 +0000 |
commit | ae4c35cab8616eb1690150e352d417016ba25851 (patch) | |
tree | e99291b987878194697739bb989506f6786d3657 | |
parent | d6fcdbf2abf93e083898179b3d9254a4adb37fb4 (diff) | |
download | mongo-ae4c35cab8616eb1690150e352d417016ba25851.tar.gz |
SERVER-49091 fail with MovePrimaryInProgress on create drop collMod renameCollection commands
(cherry picked from commit d6f3aebf450e53dd41ca31947cc0cc9ccf30e1bc)
-rw-r--r-- | jstests/sharding/move_primary_with_writes.js | 84 | ||||
-rw-r--r-- | src/mongo/db/catalog/database_impl.cpp | 22 |
2 files changed, 91 insertions, 15 deletions
diff --git a/jstests/sharding/move_primary_with_writes.js b/jstests/sharding/move_primary_with_writes.js index 8c58f37da86..11d9e8f6150 100644 --- a/jstests/sharding/move_primary_with_writes.js +++ b/jstests/sharding/move_primary_with_writes.js @@ -29,6 +29,7 @@ function createCollections() { assert.commandWorked(st.s.adminCommand({movePrimary: dbName, to: st.shard0.shardName})); assert.commandWorked(db.createCollection('unshardedFoo')); + assert.commandWorked(db.createView('viewOnFoo', 'unshardedFoo', [{$match: {}}])); assert.commandWorked(db.createCollection('shardedBar')); for (let i = 0; i < 3; i++) { @@ -46,14 +47,33 @@ function createCollections() { function buildCommands(collName) { const commands = [ - {insert: collName, documents: [{a: 10}]}, - {update: collName, updates: [{q: {a: 1}, u: {$set: {a: 11}}}]}, - {findAndModify: collName, query: {a: 2}, update: {$set: {a: 11}}}, - {delete: collName, deletes: [{q: {a: 0}, limit: 1}]} + {command: {insert: collName, documents: [{a: 10}]}, alwaysFail: false}, + { + command: {update: collName, updates: [{q: {a: 1}, u: {$set: {a: 11}}}]}, + alwaysFail: false + }, + { + command: {findAndModify: collName, query: {_id: 2}, update: {$set: {a: 11}}}, + alwaysFail: false + }, + {command: {delete: collName, deletes: [{q: {_id: 0}, limit: 1}]}, alwaysFail: false}, + {command: {create: "testCollection"}, alwaysFail: true}, + { + command: {collMod: "viewOnFoo", viewOn: "unshardedFoo", pipeline: [{$match: {_id: 1}}]}, + alwaysFail: true + }, ]; return commands; } +function buildDDLCommands() { + const commands = [{ + command: {renameCollection: "testdb.unshardedFoo", to: "testdb.testCollection"}, + alwaysFail: true + }]; + return commands; +} + function testMovePrimary(failpoint, fromShard, toShard, db, shouldFail, sharded) { let codeToRunInParallelShell = '{ db.getSiblingDB("admin").runCommand({movePrimary: "' + dbName + '", to: "' + toShard.name + '"}); }'; @@ -75,13 +95,46 @@ function testMovePrimary(failpoint, fromShard, toShard, db, shouldFail, sharded) collName = "unshardedFoo"; } - buildCommands(collName).forEach(command => { + buildCommands(collName).forEach(commandObj => { + if (shouldFail) { + jsTestLog("running command: " + tojson(commandObj.command) + + ",\nshoudFail: " + shouldFail); + assert.commandFailedWithCode(db.runCommand(commandObj.command), + ErrorCodes.MovePrimaryInProgress); + } else if (!commandObj.alwaysFail) { + jsTestLog("running command: " + tojson(commandObj.command) + + ",\nshoudFail: " + shouldFail); + assert.commandWorked(db.runCommand(commandObj.command)); + } + }); + + assert.commandWorked(fromShard.adminCommand({configureFailPoint: failpoint, mode: 'off'})); + + awaitShell(); +} + +function testMovePrimaryDDL(failpoint, fromShard, toShard, db, shouldFail) { + let codeToRunInParallelShell = '{ db.getSiblingDB("admin").runCommand({movePrimary: "' + + dbName + '", to: "' + toShard.name + '"}); }'; + + assert.commandWorked(fromShard.adminCommand({configureFailPoint: failpoint, mode: 'alwaysOn'})); + + let awaitShell = startParallelShell(codeToRunInParallelShell, st.s.port); + + jsTestLog("Waiting for failpoint " + failpoint); + waitForFailpoint("Hit " + failpoint, 1); + clearRawMongoProgramOutput(); + + buildDDLCommands().forEach(commandObj => { if (shouldFail) { - jsTestLog("running command: " + tojson(command) + ",\nshoudFail: " + shouldFail); - assert.commandFailedWithCode(db.runCommand(command), ErrorCodes.MovePrimaryInProgress); - } else { - jsTestLog("running command: " + tojson(command) + ",\nshoudFail: " + shouldFail); - assert.commandWorked(db.runCommand(command)); + jsTestLog("running command: " + tojson(commandObj.command) + + ",\nshoudFail: " + shouldFail); + assert.commandFailedWithCode(db.runCommand(commandObj.command), + ErrorCodes.MovePrimaryInProgress); + } else if (!commandObj.alwaysFail) { + jsTestLog("running command: " + tojson(commandObj.command) + + ",\nshoudFail: " + shouldFail); + assert.commandWorked(db.runCommand(commandObj.command)); } }); @@ -94,21 +147,22 @@ createCollections(); let fromShard = st.getPrimaryShard(dbName); let toShard = st.getOther(fromShard); -testMovePrimary('hangInCloneStage', fromShard, toShard, fromShard.getDB(dbName), true, false); +testMovePrimary('hangInCloneStage', fromShard, toShard, st.s.getDB(dbName), true, false); verifyDocuments(toShard.getDB(dbName), 3); verifyDocuments(fromShard.getDB(dbName), 0); createCollections(); fromShard = st.getPrimaryShard(dbName); toShard = st.getOther(fromShard); -testMovePrimary('hangInCloneStage', fromShard, toShard, fromShard.getDB(dbName), false, true); + +testMovePrimary('hangInCloneStage', fromShard, toShard, st.s.getDB(dbName), false, true); +verifyDocuments(toShard.getDB(dbName), 3); +verifyDocuments(fromShard.getDB(dbName), 0); createCollections(); fromShard = st.getPrimaryShard(dbName); toShard = st.getOther(fromShard); -testMovePrimary('hangInCloneStage', fromShard, toShard, st.s.getDB(dbName), true, false); -verifyDocuments(toShard.getDB(dbName), 3); -verifyDocuments(fromShard.getDB(dbName), 0); +testMovePrimaryDDL('hangInCloneStage', fromShard, toShard, st.s.getDB("admin"), true); createCollections(); fromShard = st.getPrimaryShard(dbName); diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp index b813dc56a1c..5505f5e3843 100644 --- a/src/mongo/db/catalog/database_impl.cpp +++ b/src/mongo/db/catalog/database_impl.cpp @@ -63,6 +63,7 @@ #include "mongo/db/repl/drop_pending_collection_reaper.h" #include "mongo/db/repl/oplog.h" #include "mongo/db/repl/replication_coordinator.h" +#include "mongo/db/s/database_sharding_state.h" #include "mongo/db/s/operation_sharding_state.h" #include "mongo/db/server_options.h" #include "mongo/db/service_context.h" @@ -107,6 +108,25 @@ Status validateDBNameForWindows(StringData dbname) { PseudoRandom uniqueCollectionNamespacePseudoRandom(Date_t::now().asInt64()); Mutex uniqueCollectionNamespaceMutex = MONGO_MAKE_LATCH("DatabaseUniqueCollectionNamespaceMutex"); + +void assertMovePrimaryInProgress(OperationContext* opCtx, NamespaceString const& nss) { + Lock::DBLock dblock(opCtx, nss.db(), MODE_IS); + auto dss = DatabaseShardingState::get(opCtx, nss.db().toString()); + if (!dss) { + return; + } + + auto dssLock = DatabaseShardingState::DSSLock::lockShared(opCtx, dss); + auto mpsm = dss->getMovePrimarySourceManager(dssLock); + + if (mpsm) { + LOGV2(4909100, "assertMovePrimaryInProgress", "movePrimaryNss"_attr = nss.toString()); + + uasserted(ErrorCodes::MovePrimaryInProgress, + "movePrimary is in progress for namespace " + nss.toString()); + } +} + } // namespace Status DatabaseImpl::validateDBName(StringData dbname) { @@ -559,6 +579,7 @@ Status DatabaseImpl::renameCollection(OperationContext* opCtx, << toNss); } } + assertMovePrimaryInProgress(opCtx, fromNss); LOGV2(20319, "renameCollection: renaming collection {collToRename_uuid} from {fromNss} to {toNss}", @@ -639,6 +660,7 @@ void DatabaseImpl::_checkCanCreateCollection(OperationContext* opCtx, << " FCV 4.2 Limit: " << NamespaceString::MaxNSCollectionLenFCV42, nss.size() <= NamespaceString::MaxNSCollectionLenFCV42); } + assertMovePrimaryInProgress(opCtx, nss); } Status DatabaseImpl::createView(OperationContext* opCtx, |