diff options
-rw-r--r-- | src/mongo/db/repl/collection_cloner.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/repl/collection_cloner_test.cpp | 94 |
2 files changed, 56 insertions, 41 deletions
diff --git a/src/mongo/db/repl/collection_cloner.cpp b/src/mongo/db/repl/collection_cloner.cpp index 15d411c0ed9..0cfb0eb46c0 100644 --- a/src/mongo/db/repl/collection_cloner.cpp +++ b/src/mongo/db/repl/collection_cloner.cpp @@ -774,7 +774,8 @@ void CollectionCloner::_handleARMResultsCallback( auto nextBatchStatus = _bufferNextBatchFromArm(lk); if (!nextBatchStatus.isOK()) { if (_options.uuid && (nextBatchStatus.code() == ErrorCodes::OperationFailed || - nextBatchStatus.code() == ErrorCodes::CursorNotFound)) { + nextBatchStatus.code() == ErrorCodes::CursorNotFound || + nextBatchStatus.code() == ErrorCodes::QueryPlanKilled)) { // With these errors, it's possible the collection was dropped while we were // cloning. If so, we'll execute the drop during oplog application, so it's OK to // just stop cloning. This is only safe if cloning by UUID; if we are cloning by diff --git a/src/mongo/db/repl/collection_cloner_test.cpp b/src/mongo/db/repl/collection_cloner_test.cpp index 7b06d95715b..23a15426583 100644 --- a/src/mongo/db/repl/collection_cloner_test.cpp +++ b/src/mongo/db/repl/collection_cloner_test.cpp @@ -1408,11 +1408,10 @@ protected: /** * Sets up a test for the CollectionCloner that simulates the collection being dropped while * copying the documents. - * The ARM returns CursorNotFound error to indicate a collection drop. Subsequently, the - * CollectionCloner should run a find command on the collection by UUID. This should be the next - * ready request on in the network interface. + * + * The mock network returns 'code' to indicate a collection drop. */ - void setUpVerifyCollectionWasDroppedTest() { + void setUpVerifyCollectionWasDroppedTest(ErrorCodes::Error code) { startupWithUUID(); { @@ -1437,8 +1436,7 @@ protected: // Return error response to getMore command. { executor::NetworkInterfaceMock::InNetworkGuard guard(getNet()); - processNetworkResponse(ErrorCodes::CursorNotFound, - "collection dropped while copying documents"); + processNetworkResponse(code, "collection dropped while copying documents"); } } @@ -1458,6 +1456,38 @@ protected: ASSERT_EQUALS(*options.uuid, unittest::assertGet(UUID::parse(firstElement))); return noi; } + + /** + * Start cloning. While copying collection, simulate a collection drop by having the mock + * network return code 'collectionDropErrCode'. + * + * The CollectionCloner should run a find command on the collection by UUID. Simulate successful + * find command with a drop-pending namespace in the response. The CollectionCloner should + * complete with a successful final status. + */ + void runCloningSuccessfulWithCollectionDropTest(ErrorCodes::Error collectionDropErrCode) { + setUpVerifyCollectionWasDroppedTest(collectionDropErrCode); + + // CollectionCloner should send a find command with the collection's UUID. + { + executor::NetworkInterfaceMock::InNetworkGuard guard(getNet()); + auto noi = getVerifyCollectionDroppedRequest(getNet()); + + // Return a drop-pending namespace in the find response instead of the original + // collection name passed to CollectionCloner at construction. + repl::OpTime dropOpTime(Timestamp(Seconds(100), 0), 1LL); + auto dpns = nss.makeDropPendingNamespace(dropOpTime); + scheduleNetworkResponse(noi, + createCursorResponse(0, dpns.ns(), BSONArray(), "firstBatch")); + finishProcessingNetworkResponse(); + } + + // CollectionCloner treats a in collection state to drop-pending during cloning as a + // successful clone operation. + collectionCloner->join(); + ASSERT_OK(getStatus()); + ASSERT_FALSE(collectionCloner->isActive()); + } }; TEST_F(CollectionClonerUUIDTest, FirstRemoteCommandWithUUID) { @@ -1560,49 +1590,33 @@ TEST_F(CollectionClonerUUIDTest, ThreeCloningCursorsWithUUIDUsesParallelCollecti testWithMaxNumCloningCursors(3, "parallelCollectionScan"); } -/** - * Start cloning. - * While copying collection, simulate a collection drop by having the ARM return a CursorNotFound - * error. - * The CollectionCloner should run a find command on the collection by UUID. - * Simulate successful find command with a drop-pending namespace in the response. - * The CollectionCloner should complete with a successful final status. - */ -TEST_F(CollectionClonerUUIDTest, CloningIsSuccessfulIfCollectionWasDroppedWhileCopyingDocuments) { - setUpVerifyCollectionWasDroppedTest(); +TEST_F(CollectionClonerUUIDTest, + CloningIsSuccessfulIfCollectionWasDroppedWithCursorNotFoundWhileCopyingDocuments) { + runCloningSuccessfulWithCollectionDropTest(ErrorCodes::CursorNotFound); +} - // CollectionCloner should send a find command with the collection's UUID. - { - executor::NetworkInterfaceMock::InNetworkGuard guard(getNet()); - auto noi = getVerifyCollectionDroppedRequest(getNet()); - // Return a drop-pending namespace in the find response instead of the original collection - // name passed to CollectionCloner at construction. - repl::OpTime dropOpTime(Timestamp(Seconds(100), 0), 1LL); - auto dpns = nss.makeDropPendingNamespace(dropOpTime); - scheduleNetworkResponse(noi, createCursorResponse(0, dpns.ns(), BSONArray(), "firstBatch")); - finishProcessingNetworkResponse(); - } +TEST_F(CollectionClonerUUIDTest, + CloningIsSuccessfulIfCollectionWasDroppedWithOperationFailedWhileCopyingDocuments) { + runCloningSuccessfulWithCollectionDropTest(ErrorCodes::OperationFailed); +} - // CollectionCloner treats a in collection state to drop-pending during cloning as a successful - // clone operation. - collectionCloner->join(); - ASSERT_OK(getStatus()); - ASSERT_FALSE(collectionCloner->isActive()); +TEST_F(CollectionClonerUUIDTest, + CloningIsSuccessfulIfCollectionWasDroppedWithQueryPlanKilledWhileCopyingDocuments) { + runCloningSuccessfulWithCollectionDropTest(ErrorCodes::QueryPlanKilled); } /** - * Start cloning. - * While copying collection, simulate a collection drop by having the ARM return a CursorNotFound - * error. - * The CollectionCloner should run a find command on the collection by UUID. - * Shut the CollectionCloner down. - * The CollectionCloner should return a CursorNotFound final status which is the last error from the - * ARM. + * Start cloning. While copying collection, simulate a collection drop by having the ARM return a + * CursorNotFound error. + * + * The CollectionCloner should run a find commnd on the collection by UUID. Shut the + * CollectionCloner down. The CollectionCloner should return a CursorNotFound final status which is + * the last error from the ARM. */ TEST_F(CollectionClonerUUIDTest, ShuttingDownCollectionClonerDuringCollectionDropVerificationReturnsCallbackCanceled) { - setUpVerifyCollectionWasDroppedTest(); + setUpVerifyCollectionWasDroppedTest(ErrorCodes::CursorNotFound); // CollectionCloner should send a find command with the collection's UUID. { |