diff options
author | Blake Oler <blake.oler@mongodb.com> | 2021-05-03 20:14:00 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-05-04 14:41:44 +0000 |
commit | 2bec78480070f4585aa46f2ff2d5baab90dd3572 (patch) | |
tree | 7f89e1e977a42a38c92e88a7a0e066b3a8cfea73 | |
parent | 3d0d4c4229eb83ac5b2c03dce049c36b0cc736d3 (diff) | |
download | mongo-2bec78480070f4585aa46f2ff2d5baab90dd3572.tar.gz |
SERVER-56567 Add boolean field to reshardingFields to indicate whether an abort came from a user cancelation
3 files changed, 62 insertions, 18 deletions
diff --git a/src/mongo/db/s/resharding/resharding_coordinator_service.cpp b/src/mongo/db/s/resharding/resharding_coordinator_service.cpp index cab3b0be8f6..b9546aabbaa 100644 --- a/src/mongo/db/s/resharding/resharding_coordinator_service.cpp +++ b/src/mongo/db/s/resharding/resharding_coordinator_service.cpp @@ -313,6 +313,10 @@ BSONObj createReshardingFieldsUpdateForOriginalNss( if (auto abortReason = coordinatorDoc.getAbortReason()) { // If the abortReason exists, include it in the update. setBuilder.append("reshardingFields.abortReason", *abortReason); + + auto abortStatus = getStatusFromAbortReason(coordinatorDoc); + setBuilder.append("reshardingFields.userCanceled", + abortStatus == ErrorCodes::ReshardCollectionAborted); } } @@ -412,6 +416,10 @@ void writeToConfigCollectionsForTempNss(OperationContext* opCtx, if (auto abortReason = coordinatorDoc.getAbortReason()) { setBuilder.append("reshardingFields.abortReason", *abortReason); + + auto abortStatus = getStatusFromAbortReason(coordinatorDoc); + setBuilder.append("reshardingFields.userCanceled", + abortStatus == ErrorCodes::ReshardCollectionAborted); } } diff --git a/src/mongo/db/s/resharding/resharding_coordinator_test.cpp b/src/mongo/db/s/resharding/resharding_coordinator_test.cpp index c021a6c9471..645fa73e123 100644 --- a/src/mongo/db/s/resharding/resharding_coordinator_test.cpp +++ b/src/mongo/db/s/resharding/resharding_coordinator_test.cpp @@ -353,6 +353,12 @@ protected: ASSERT(onDiskReshardingFields.getAbortReason()); ASSERT_BSONOBJ_EQ(expectedAbortReason.get(), onDiskReshardingFields.getAbortReason().get()); + + auto userCanceled = getStatusFromAbortReason(expectedCoordinatorDoc) == + ErrorCodes::ReshardCollectionAborted; + ASSERT(onDiskReshardingFields.getUserCanceled() == userCanceled); + } else { + ASSERT(onDiskReshardingFields.getUserCanceled() == boost::none); } // Check the reshardingFields.recipientFields. @@ -406,6 +412,9 @@ protected: ASSERT(!onDiskReshardingFields.getRecipientFields()->getCloneTimestamp()); } + ASSERT(onDiskReshardingFields.getUserCanceled() == + expectedReshardingFields.getUserCanceled()); + if (onDiskReshardingFields.getState() == CoordinatorStateEnum::kError) { // Confirm 'reshardingFields.abortReason' exists on the temporary collection. ASSERT(onDiskReshardingFields.getAbortReason()); @@ -481,6 +490,9 @@ protected: AbortReason abortReasonStruct; abortReasonStruct.setAbortReason(abortReason); expectedReshardingFields.setAbortReasonStruct(std::move(abortReasonStruct)); + expectedReshardingFields.setUserCanceled( + getStatusFromAbortReason(expectedCoordinatorDoc) == + ErrorCodes::ReshardCollectionAborted); } auto expectedOriginalCollType = makeOriginalCollectionCatalogEntry( @@ -502,6 +514,17 @@ protected: expectedCoordinatorDoc, ChunkVersion(1, 1, OID::gen(), boost::none /* timestamp */), BSONObj()); + + // It's necessary to add the userCanceled field because the call into + // resharding::createTempReshardingCollectionType assumes that the collection entry is + // being created in a non-aborted state. + if (auto abortReason = expectedCoordinatorDoc.getAbortReason()) { + auto reshardingFields = expectedTempCollType->getReshardingFields(); + reshardingFields->setUserCanceled( + getStatusFromAbortReason(expectedCoordinatorDoc) == + ErrorCodes::ReshardCollectionAborted); + expectedTempCollType->setReshardingFields(std::move(reshardingFields)); + } } assertTemporaryCollectionCatalogEntryMatchesExpected(opCtx, expectedTempCollType); @@ -645,6 +668,28 @@ protected: opCtx, expectedOriginalCollType, expectedCoordinatorDoc); } + void transitionToErrorExpectSuccess(ErrorCodes::Error errorCode) { + auto coordinatorDoc = + insertStateAndCatalogEntries(CoordinatorStateEnum::kPreparingToDonate, _originalEpoch); + auto initialChunksIds = std::vector{OID::gen(), OID::gen()}; + + auto tempNssChunks = makeChunks(_tempNss, _tempEpoch, _newShardKey, initialChunksIds); + auto recipientChunk = tempNssChunks[1]; + insertChunkAndZoneEntries(tempNssChunks, makeZones(_tempNss, _newShardKey)); + + insertChunkAndZoneEntries( + makeChunks(_originalNss, OID::gen(), _oldShardKey, std::vector{OID::gen(), OID::gen()}), + makeZones(_originalNss, _oldShardKey)); + + // Persist the updates on disk + auto expectedCoordinatorDoc = coordinatorDoc; + expectedCoordinatorDoc.setState(CoordinatorStateEnum::kError); + auto abortReason = Status{errorCode, "reason to abort"}; + emplaceAbortReasonIfExists(expectedCoordinatorDoc, abortReason); + + writeStateTransitionUpdateExpectSuccess(operationContext(), expectedCoordinatorDoc); + } + void assertChunkVersionDidNotIncreaseAfterStateTransition( const ChunkType& chunk, const ChunkVersion& collectionVersion) { auto chunkAfterTransition = getChunkDoc(operationContext(), chunk.getMin()); @@ -814,25 +859,11 @@ TEST_F(ReshardingCoordinatorPersistenceTest, StateTranstionToDecisionPersistedSu } TEST_F(ReshardingCoordinatorPersistenceTest, StateTransitionToErrorSucceeds) { - auto coordinatorDoc = - insertStateAndCatalogEntries(CoordinatorStateEnum::kPreparingToDonate, _originalEpoch); - auto initialChunksIds = std::vector{OID::gen(), OID::gen()}; - - auto tempNssChunks = makeChunks(_tempNss, _tempEpoch, _newShardKey, initialChunksIds); - auto recipientChunk = tempNssChunks[1]; - insertChunkAndZoneEntries(tempNssChunks, makeZones(_tempNss, _newShardKey)); - - insertChunkAndZoneEntries( - makeChunks(_originalNss, OID::gen(), _oldShardKey, std::vector{OID::gen(), OID::gen()}), - makeZones(_originalNss, _oldShardKey)); - - // Persist the updates on disk - auto expectedCoordinatorDoc = coordinatorDoc; - expectedCoordinatorDoc.setState(CoordinatorStateEnum::kError); - auto abortReason = Status{ErrorCodes::InternalError, "reason to abort"}; - emplaceAbortReasonIfExists(expectedCoordinatorDoc, abortReason); + transitionToErrorExpectSuccess(ErrorCodes::InternalError); +} - writeStateTransitionUpdateExpectSuccess(operationContext(), expectedCoordinatorDoc); +TEST_F(ReshardingCoordinatorPersistenceTest, StateTransitionToErrorFromManualAbortSucceeds) { + transitionToErrorExpectSuccess(ErrorCodes::ReshardCollectionAborted); } TEST_F(ReshardingCoordinatorPersistenceTest, StateTransitionToDoneSucceeds) { diff --git a/src/mongo/s/resharding/type_collection_fields.idl b/src/mongo/s/resharding/type_collection_fields.idl index df6a347adb2..cc86cb52976 100644 --- a/src/mongo/s/resharding/type_collection_fields.idl +++ b/src/mongo/s/resharding/type_collection_fields.idl @@ -99,6 +99,11 @@ structs: state: type: CoordinatorState default: kUnused + userCanceled: + type: bool + optional: true + description: >- + If emplaced, indicates whether an abort originated from a user cancellation. donorFields: type: TypeCollectionDonorFields optional: true |