diff options
-rw-r--r-- | src/mongo/db/catalog/drop_database.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/catalog/drop_database_test.cpp | 24 |
2 files changed, 38 insertions, 0 deletions
diff --git a/src/mongo/db/catalog/drop_database.cpp b/src/mongo/db/catalog/drop_database.cpp index 1df925e5b49..ff526a9feda 100644 --- a/src/mongo/db/catalog/drop_database.cpp +++ b/src/mongo/db/catalog/drop_database.cpp @@ -224,6 +224,20 @@ Status dropDatabase(OperationContext* opCtx, const std::string& dbName) { return writeConflictRetry(opCtx, "dropDatabase_database", dbName, [&] { Lock::GlobalWrite lk(opCtx); + + bool userInitiatedWritesAndNotPrimary = + opCtx->writesAreReplicated() && !replCoord->canAcceptWritesForDatabase(opCtx, dbName); + + if (userInitiatedWritesAndNotPrimary) { + return Status(ErrorCodes::NotMaster, + str::stream() << "Could not drop database " << dbName + << " because we transitioned from PRIMARY to " + << replCoord->getMemberState().toString() + << " while waiting for " + << numCollectionsToDrop + << " pending collection drop(s)."); + } + AutoGetDb autoDB(opCtx, dbName, MODE_X); if (auto db = autoDB.getDb()) { return _finishDropDatabase(opCtx, dbName, db); diff --git a/src/mongo/db/catalog/drop_database_test.cpp b/src/mongo/db/catalog/drop_database_test.cpp index 1e384c3a031..7ba02585bcd 100644 --- a/src/mongo/db/catalog/drop_database_test.cpp +++ b/src/mongo/db/catalog/drop_database_test.cpp @@ -426,4 +426,28 @@ TEST_F(DropDatabaseTest, ASSERT_FALSE(AutoGetDb(_opCtx.get(), _nss.db(), MODE_X).getDb()); } +TEST_F(DropDatabaseTest, + DropDatabaseReturnsNotMasterIfNotPrimaryAfterCollectionsDropsAreReplicated) { + // Transition from PRIMARY to SECONDARY while awaiting replication of collection drops. + _replCoord->setAwaitReplicationReturnValueFunction([this](const repl::OpTime&) { + ASSERT_OK(_replCoord->setFollowerMode(repl::MemberState::RS_SECONDARY)); + ASSERT_TRUE(_opCtx->writesAreReplicated()); + ASSERT_FALSE(_replCoord->canAcceptWritesForDatabase(_opCtx.get(), _nss.db())); + return repl::ReplicationCoordinator::StatusAndDuration(Status::OK(), Milliseconds(0)); + }); + + _createCollection(_opCtx.get(), _nss); + + ASSERT_TRUE(AutoGetDb(_opCtx.get(), _nss.db(), MODE_X).getDb()); + + auto status = dropDatabase(_opCtx.get(), _nss.db().toString()); + ASSERT_EQUALS(ErrorCodes::NotMaster, status); + ASSERT_EQUALS(status.reason(), + str::stream() << "Could not drop database " << _nss.db() + << " because we transitioned from PRIMARY to SECONDARY" + << " while waiting for 1 pending collection drop(s)."); + + ASSERT_TRUE(AutoGetDb(_opCtx.get(), _nss.db(), MODE_X).getDb()); +} + } // namespace |