summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2019-02-27 15:16:38 -0500
committerDavid Storch <david.storch@10gen.com>2019-03-06 12:00:36 -0500
commit03e8ccfaa221646f58e79c53b705f8ea71c1101d (patch)
tree94a4af5691df2a3d1b92f28f97c0d2c60f68f188
parenta4762a9723fd6955cc07d673911840d3527edc5a (diff)
downloadmongo-03e8ccfaa221646f58e79c53b705f8ea71c1101d.tar.gz
SERVER-38722 Make CollectionCloner tolerate QueryPlanKilled error on collection drop.
-rw-r--r--src/mongo/db/repl/collection_cloner.cpp3
-rw-r--r--src/mongo/db/repl/collection_cloner_test.cpp94
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.
{