diff options
author | Daniel Gottlieb <daniel.gottlieb@mongodb.com> | 2021-03-31 17:02:12 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-03-31 21:45:49 +0000 |
commit | 9f857d7249b9dc5a8aa8032a2c55e533fc1e980a (patch) | |
tree | 1e25e84508d71ed494e4ea84c171e75bd9e17791 /src/mongo/db/s | |
parent | bed9b4820e4421d63ff5457cd854671cf51bf4f6 (diff) | |
download | mongo-9f857d7249b9dc5a8aa8032a2c55e533fc1e980a.tar.gz |
SERVER-54486: Clear resharding filtering metadata on primary stepUp.
Diffstat (limited to 'src/mongo/db/s')
7 files changed, 169 insertions, 3 deletions
diff --git a/src/mongo/db/s/collection_metadata.cpp b/src/mongo/db/s/collection_metadata.cpp index 86744c1594f..518f5405085 100644 --- a/src/mongo/db/s/collection_metadata.cpp +++ b/src/mongo/db/s/collection_metadata.cpp @@ -184,6 +184,12 @@ void CollectionMetadata::toBSONBasic(BSONObjBuilder& bb) const { } } +BSONObj CollectionMetadata::toBSON() const { + BSONObjBuilder builder; + toBSONBasic(builder); + return builder.obj(); +} + std::string CollectionMetadata::toStringBasic() const { if (isSharded()) { return str::stream() << "collection version: " << _cm->getVersion().toString() diff --git a/src/mongo/db/s/collection_metadata.h b/src/mongo/db/s/collection_metadata.h index 13fe79d78e0..a742b77726f 100644 --- a/src/mongo/db/s/collection_metadata.h +++ b/src/mongo/db/s/collection_metadata.h @@ -170,11 +170,17 @@ public: */ void toBSONBasic(BSONObjBuilder& bb) const; + BSONObj toBSON() const; + /** * String output of the collection and shard versions. */ std::string toStringBasic() const; + std::string toString() const { + return toStringBasic(); + } + // // Methods used for orphan filtering and general introspection of the chunks owned by the shard // diff --git a/src/mongo/db/s/resharding/resharding_donor_recipient_common.cpp b/src/mongo/db/s/resharding/resharding_donor_recipient_common.cpp index df03a16bddb..8c95024d108 100644 --- a/src/mongo/db/s/resharding/resharding_donor_recipient_common.cpp +++ b/src/mongo/db/s/resharding/resharding_donor_recipient_common.cpp @@ -32,14 +32,17 @@ #include "mongo/platform/basic.h" #include "mongo/db/s/resharding/resharding_donor_recipient_common.h" -#include "mongo/db/storage/duplicate_key_error_info.h" #include <fmt/format.h> +#include "mongo/db/persistent_task_store.h" +#include "mongo/db/s/shard_filtering_metadata_refresh.h" #include "mongo/db/s/sharding_state.h" +#include "mongo/db/storage/duplicate_key_error_info.h" #include "mongo/logv2/log.h" #include "mongo/s/catalog/sharding_catalog_client.h" #include "mongo/s/grid.h" +#include "mongo/stdx/unordered_set.h" namespace mongo { namespace resharding { @@ -376,6 +379,49 @@ void processReshardingFieldsForCollection(OperationContext* opCtx, } } +void clearFilteringMetadata(OperationContext* opCtx, bool scheduleAsyncRefresh) { + stdx::unordered_set<NamespaceString> namespacesToRefresh; + for (const NamespaceString homeToReshardingDocs : + {NamespaceString::kDonorReshardingOperationsNamespace, + NamespaceString::kRecipientReshardingOperationsNamespace}) { + PersistentTaskStore<CommonReshardingMetadata> store(homeToReshardingDocs); + + store.forEach(opCtx, Query(), [&](CommonReshardingMetadata reshardingDoc) -> bool { + namespacesToRefresh.insert(reshardingDoc.getSourceNss()); + namespacesToRefresh.insert(reshardingDoc.getTempReshardingNss()); + + return true; + }); + } + + for (const auto& nss : namespacesToRefresh) { + AutoGetCollection autoColl(opCtx, nss, MODE_IX); + CollectionShardingRuntime::get(opCtx, nss)->clearFilteringMetadata(opCtx); + + if (!scheduleAsyncRefresh) { + continue; + } + + ExecutorFuture<void>(Grid::get(opCtx)->getExecutorPool()->getFixedExecutor()) + .then([svcCtx = opCtx->getServiceContext(), nss] { + ThreadClient tc("TriggerReshardingRecovery", svcCtx); + { + stdx::lock_guard<Client> lk(*tc.get()); + tc->setSystemOperationKillableByStepdown(lk); + } + + auto opCtx = tc->makeOperationContext(); + onShardVersionMismatch(opCtx.get(), nss, boost::none /* shardVersionReceived */); + }) + .onError([](const Status& status) { + LOGV2_WARNING(5498101, + "Error on deferred shardVersion recovery execution", + "error"_attr = redact(status)); + }) + .getAsync([](auto) {}); + } +} + } // namespace resharding } // namespace mongo diff --git a/src/mongo/db/s/resharding/resharding_donor_recipient_common.h b/src/mongo/db/s/resharding/resharding_donor_recipient_common.h index bf016473582..0a103ef3619 100644 --- a/src/mongo/db/s/resharding/resharding_donor_recipient_common.h +++ b/src/mongo/db/s/resharding/resharding_donor_recipient_common.h @@ -76,6 +76,8 @@ void processReshardingFieldsForCollection(OperationContext* opCtx, const CollectionMetadata& metadata, const ReshardingFields& reshardingFields); +void clearFilteringMetadata(OperationContext* opCtx, bool scheduleAsyncRefresh); + } // namespace resharding } // namespace mongo diff --git a/src/mongo/db/s/resharding/resharding_donor_recipient_common_test.cpp b/src/mongo/db/s/resharding/resharding_donor_recipient_common_test.cpp index 6bfdd45bbe8..9768b725524 100644 --- a/src/mongo/db/s/resharding/resharding_donor_recipient_common_test.cpp +++ b/src/mongo/db/s/resharding/resharding_donor_recipient_common_test.cpp @@ -31,12 +31,15 @@ #include "mongo/db/s/resharding/resharding_donor_recipient_common_test.h" +#include "mongo/db/catalog/drop_database.h" #include "mongo/db/catalog_raii.h" #include "mongo/db/db_raii.h" #include "mongo/db/dbdirectclient.h" +#include "mongo/db/persistent_task_store.h" #include "mongo/db/repl/wait_for_majority_service.h" #include "mongo/db/s/collection_sharding_runtime.h" #include "mongo/db/s/operation_sharding_state.h" +#include "mongo/db/s/resharding/donor_document_gen.h" #include "mongo/db/s/resharding/resharding_donor_recipient_common.h" #include "mongo/db/s/shard_server_test_fixture.h" #include "mongo/unittest/death_test.h" @@ -213,6 +216,81 @@ TEST_F(ReshardingDonorRecipientCommonTest, ProcessReshardingFieldsWithoutDonorOr 5274201); } +TEST_F(ReshardingDonorRecipientCommonTest, ClearReshardingFilteringMetaData) { + OperationContext* opCtx = operationContext(); + + const bool scheduleAsyncRefresh = false; + auto doSetupFunc = [&] { + // Clear out the resharding donor/recipient metadata collections. + for (auto const& nss : {NamespaceString::kDonorReshardingOperationsNamespace, + NamespaceString::kRecipientReshardingOperationsNamespace}) { + dropDatabase(opCtx, nss.db().toString()).ignore(); + } + + // Assert the prestate has no filtering metadata. + for (auto const& nss : {kOriginalNss, kTemporaryReshardingNss}) { + AutoGetCollection autoColl(opCtx, nss, LockMode::MODE_IS); + auto csr = CollectionShardingRuntime::get(opCtx, nss); + ASSERT(csr->getCurrentMetadataIfKnown() == boost::none); + } + + // Add filtering metadata for the collection being resharded. + { + AutoGetCollection autoColl(opCtx, kOriginalNss, LockMode::MODE_IS); + auto csr = CollectionShardingRuntime::get(opCtx, kOriginalNss); + csr->setFilteringMetadata(opCtx, + makeShardedMetadataForOriginalCollection(opCtx, kThisShard)); + ASSERT(csr->getCurrentMetadataIfKnown()); + } + + // Add filtering metadata for the temporary resharding namespace. + { + AutoGetCollection autoColl(opCtx, kTemporaryReshardingNss, LockMode::MODE_IS); + auto csr = CollectionShardingRuntime::get(opCtx, kTemporaryReshardingNss); + csr->setFilteringMetadata( + opCtx, makeShardedMetadataForTemporaryReshardingCollection(opCtx, kThisShard)); + ASSERT(csr->getCurrentMetadataIfKnown()); + } + + // Prior to adding a resharding document, assert that attempting to clear filtering does + // nothing. + resharding::clearFilteringMetadata(opCtx, scheduleAsyncRefresh); + + for (auto const& nss : {kOriginalNss, kTemporaryReshardingNss}) { + AutoGetCollection autoColl(opCtx, nss, LockMode::MODE_IS); + auto csr = CollectionShardingRuntime::get(opCtx, nss); + ASSERT(csr->getCurrentMetadataIfKnown()); + } + }; + + doSetupFunc(); + // Add a resharding donor document that targets the namespaces involved in resharding. + ReshardingDonorDocument donorDoc = makeDonorStateDoc(); + ReshardingDonorService::DonorStateMachine::insertStateDocument(opCtx, donorDoc); + + // Clear the filtering metadata (without scheduling a refresh) and assert the metadata is gone. + resharding::clearFilteringMetadata(opCtx, scheduleAsyncRefresh); + + for (auto const& nss : {kOriginalNss, kTemporaryReshardingNss}) { + AutoGetCollection autoColl(opCtx, nss, LockMode::MODE_IS); + auto csr = CollectionShardingRuntime::get(opCtx, nss); + ASSERT(csr->getCurrentMetadataIfKnown() == boost::none); + } + + doSetupFunc(); + // Add a resharding recipient document that targets the namespaces involved in resharding. + ReshardingRecipientDocument recipDoc = makeRecipientStateDoc(); + ReshardingRecipientService::RecipientStateMachine::insertStateDocument(opCtx, recipDoc); + + // Clear the filtering metadata (without scheduling a refresh) and assert the metadata is gone. + resharding::clearFilteringMetadata(opCtx, scheduleAsyncRefresh); + + for (auto const& nss : {kOriginalNss, kTemporaryReshardingNss}) { + AutoGetCollection autoColl(opCtx, nss, LockMode::MODE_IS); + auto csr = CollectionShardingRuntime::get(opCtx, nss); + ASSERT(csr->getCurrentMetadataIfKnown() == boost::none); + } +} } // namespace } // namespace mongo diff --git a/src/mongo/db/s/resharding/resharding_donor_recipient_common_test.h b/src/mongo/db/s/resharding/resharding_donor_recipient_common_test.h index b707a975444..f2f4ee7001f 100644 --- a/src/mongo/db/s/resharding/resharding_donor_recipient_common_test.h +++ b/src/mongo/db/s/resharding/resharding_donor_recipient_common_test.h @@ -126,6 +126,36 @@ protected: return CollectionMetadata(std::move(cm), kThisShard); } + ReshardingDonorDocument makeDonorStateDoc() { + DonorShardContext donorCtx; + donorCtx.setState(DonorStateEnum::kPreparingToDonate); + + ReshardingDonorDocument doc(std::move(donorCtx), {kThisShard, kOtherShard}); + + NamespaceString sourceNss = kOriginalNss; + auto sourceUUID = UUID::gen(); + auto commonMetadata = CommonReshardingMetadata( + UUID::gen(), sourceNss, sourceUUID, kTemporaryReshardingNss, kReshardingKeyPattern); + + doc.setCommonReshardingMetadata(std::move(commonMetadata)); + return doc; + } + + ReshardingRecipientDocument makeRecipientStateDoc() { + RecipientShardContext recipCtx; + recipCtx.setState(RecipientStateEnum::kCloning); + + ReshardingRecipientDocument doc(std::move(recipCtx), {kThisShard, kOtherShard}, 1000); + + NamespaceString sourceNss = kOriginalNss; + auto sourceUUID = UUID::gen(); + auto commonMetadata = CommonReshardingMetadata( + UUID::gen(), sourceNss, sourceUUID, kTemporaryReshardingNss, kReshardingKeyPattern); + + doc.setCommonReshardingMetadata(std::move(commonMetadata)); + return doc; + } + ReshardingFields createCommonReshardingFields(const UUID& reshardingUUID, CoordinatorStateEnum state) { auto fields = ReshardingFields(reshardingUUID); diff --git a/src/mongo/db/s/resharding_util.cpp b/src/mongo/db/s/resharding_util.cpp index 10bb3fcc583..b96711fd30b 100644 --- a/src/mongo/db/s/resharding_util.cpp +++ b/src/mongo/db/s/resharding_util.cpp @@ -177,7 +177,6 @@ void validateReshardedChunks(const std::vector<mongo::BSONObj>& chunks, Grid::get(opCtx)->shardRegistry()->getShard(opCtx, chunk.getRecipientShardId())); validChunks.push_back(chunk); } - checkForHolesAndOverlapsInChunks(validChunks, keyPattern); } @@ -527,5 +526,4 @@ NamespaceString getLocalConflictStashNamespace(UUID existingUUID, ShardId donorS "localReshardingConflictStash.{}.{}"_format(existingUUID.toString(), donorShardId.toString())}; } - } // namespace mongo |