diff options
Diffstat (limited to 'src/mongo/db/s')
-rw-r--r-- | src/mongo/db/s/collection_metadata.cpp | 110 | ||||
-rw-r--r-- | src/mongo/db/s/collection_metadata.h | 110 | ||||
-rw-r--r-- | src/mongo/db/s/collection_metadata_filtering_test.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/s/collection_sharding_state.cpp | 27 | ||||
-rw-r--r-- | src/mongo/db/s/collection_sharding_state.h | 26 | ||||
-rw-r--r-- | src/mongo/db/s/get_shard_version_command.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/s/op_observer_sharding_impl.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/s/shard_server_op_observer.cpp | 4 |
8 files changed, 134 insertions, 152 deletions
diff --git a/src/mongo/db/s/collection_metadata.cpp b/src/mongo/db/s/collection_metadata.cpp index 108395683d8..19c7b60a759 100644 --- a/src/mongo/db/s/collection_metadata.cpp +++ b/src/mongo/db/s/collection_metadata.cpp @@ -47,46 +47,6 @@ namespace mongo { CollectionMetadata::CollectionMetadata(std::shared_ptr<ChunkManager> cm, const ShardId& thisShardId) : _cm(std::move(cm)), _thisShardId(thisShardId) {} -BSONObj CollectionMetadata::extractDocumentKey(const BSONObj& doc) const { - BSONObj key; - - if (isSharded()) { - auto const& pattern = _cm->getShardKeyPattern(); - key = dotted_path_support::extractElementsBasedOnTemplate(doc, pattern.toBSON()); - if (pattern.hasId()) { - return key; - } - // else, try to append an _id field from the document. - } - - if (auto id = doc["_id"]) { - return key.isEmpty() ? id.wrap() : BSONObjBuilder(std::move(key)).append(id).obj(); - } - - // For legacy documents that lack an _id, use the document itself as its key. - return doc; -} - -void CollectionMetadata::toBSONBasic(BSONObjBuilder& bb) const { - if (isSharded()) { - _cm->getVersion().appendLegacyWithField(&bb, "collVersion"); - getShardVersion().appendLegacyWithField(&bb, "shardVersion"); - bb.append("keyPattern", _cm->getShardKeyPattern().toBSON()); - } else { - ChunkVersion::UNSHARDED().appendLegacyWithField(&bb, "collVersion"); - ChunkVersion::UNSHARDED().appendLegacyWithField(&bb, "shardVersion"); - } -} - -std::string CollectionMetadata::toStringBasic() const { - if (isSharded()) { - return str::stream() << "collection version: " << _cm->getVersion().toString() - << ", shard version: " << getShardVersion().toString(); - } else { - return "collection version: <unsharded>"; - } -} - RangeMap CollectionMetadata::getChunks() const { invariant(isSharded()); @@ -153,8 +113,62 @@ Status CollectionMetadata::checkChunkIsValid(const ChunkType& chunk) const { return Status::OK(); } +BSONObj CollectionMetadata::extractDocumentKey(BSONObj const& doc) const { + BSONObj key; + + if (isSharded()) { + auto const& pattern = getChunkManager()->getShardKeyPattern(); + key = dotted_path_support::extractElementsBasedOnTemplate(doc, pattern.toBSON()); + if (pattern.hasId()) { + return key; + } + // else, try to append an _id field from the document. + } + + if (auto id = doc["_id"]) { + return key.isEmpty() ? id.wrap() : BSONObjBuilder(std::move(key)).append(id).obj(); + } + + // For legacy documents that lack an _id, use the document itself as its key. + return doc; +} + +void CollectionMetadata::toBSONBasic(BSONObjBuilder& bb) const { + if (isSharded()) { + _cm->getVersion().appendLegacyWithField(&bb, "collVersion"); + getShardVersion().appendLegacyWithField(&bb, "shardVersion"); + bb.append("keyPattern", _cm->getShardKeyPattern().toBSON()); + } else { + ChunkVersion::UNSHARDED().appendLegacyWithField(&bb, "collVersion"); + ChunkVersion::UNSHARDED().appendLegacyWithField(&bb, "shardVersion"); + } +} + +void CollectionMetadata::toBSONChunks(BSONArrayBuilder& bb) const { + if (!isSharded()) + return; + + for (const auto& chunk : _cm->chunks()) { + if (chunk.getShardId() == _thisShardId) { + BSONArrayBuilder chunkBB(bb.subarrayStart()); + chunkBB.append(chunk.getMin()); + chunkBB.append(chunk.getMax()); + chunkBB.done(); + } + } +} + +std::string CollectionMetadata::toStringBasic() const { + if (isSharded()) { + return str::stream() << "collection version: " << _cm->getVersion().toString() + << ", shard version: " << getShardVersion().toString(); + } else { + return "collection version: <unsharded>"; + } +} + boost::optional<ChunkRange> CollectionMetadata::getNextOrphanRange( - const RangeMap& receivingChunks, const BSONObj& origLookupKey) const { + RangeMap const& receivingChunks, BSONObj const& origLookupKey) const { invariant(isSharded()); const BSONObj maxKey = getMaxKey(); @@ -222,18 +236,4 @@ boost::optional<ChunkRange> CollectionMetadata::getNextOrphanRange( return boost::none; } -void CollectionMetadata::toBSONChunks(BSONArrayBuilder* builder) const { - if (!isSharded()) - return; - - for (const auto& chunk : _cm->chunks()) { - if (chunk.getShardId() == _thisShardId) { - BSONArrayBuilder chunkBB(builder->subarrayStart()); - chunkBB.append(chunk.getMin()); - chunkBB.append(chunk.getMax()); - chunkBB.done(); - } - } -} - } // namespace mongo diff --git a/src/mongo/db/s/collection_metadata.h b/src/mongo/db/s/collection_metadata.h index f123af36e26..ae72682ca49 100644 --- a/src/mongo/db/s/collection_metadata.h +++ b/src/mongo/db/s/collection_metadata.h @@ -64,7 +64,8 @@ public: CollectionMetadata(std::shared_ptr<ChunkManager> cm, const ShardId& thisShardId); /** - * Returns whether this metadata object represents a sharded or unsharded collection. + * Returns whether this metadata object represents a sharded collection which requires + * filtering. */ bool isSharded() const { return bool(_cm); @@ -85,47 +86,6 @@ public: } /** - * Obtains the shard id with which this collection metadata is configured. - */ - const ShardId& shardId() const { - invariant(isSharded()); - return _thisShardId; - } - - /** - * Returns true if 'key' contains exactly the same fields as the shard key pattern. - */ - bool isValidKey(const BSONObj& key) const { - invariant(isSharded()); - return _cm->getShardKeyPattern().isShardKey(key); - } - - const BSONObj& getKeyPattern() const { - invariant(isSharded()); - return _cm->getShardKeyPattern().toBSON(); - } - - const std::vector<std::unique_ptr<FieldRef>>& getKeyPatternFields() const { - invariant(isSharded()); - return _cm->getShardKeyPattern().getKeyPatternFields(); - } - - BSONObj getMinKey() const { - invariant(isSharded()); - return _cm->getShardKeyPattern().getKeyPattern().globalMin(); - } - - BSONObj getMaxKey() const { - invariant(isSharded()); - return _cm->getShardKeyPattern().getKeyPattern().globalMax(); - } - - bool uuidMatches(UUID uuid) const { - invariant(isSharded()); - return _cm->uuidMatches(uuid); - } - - /** * Returns just the shard key fields, if the collection is sharded, and the _id field, from * `doc`. Does not alter any field values (e.g. by hashing); values are copied verbatim. */ @@ -137,17 +97,29 @@ public: void toBSONBasic(BSONObjBuilder& bb) const; /** + * BSON output of the chunks metadata into a BSONArray + */ + void toBSONChunks(BSONArrayBuilder& bb) const; + + /** * String output of the collection and shard versions. */ std::string toStringBasic() const; - // - // Methods used for orphan filtering and general introspection of the chunks owned by the shard - // + /** + * Obtains the shard id with which this collection metadata is configured. + */ + const ShardId& shardId() const { + invariant(isSharded()); + return _thisShardId; + } - ChunkManager* getChunkManager() const { + /** + * Returns true if 'key' contains exactly the same fields as the shard key pattern. + */ + bool isValidKey(const BSONObj& key) const { invariant(isSharded()); - return _cm.get(); + return _cm->getShardKeyPattern().isShardKey(key); } /** @@ -180,7 +152,7 @@ public: /** * Returns true if the argument range overlaps any chunk. */ - bool rangeOverlapsChunk(const ChunkRange& range) const { + bool rangeOverlapsChunk(ChunkRange const& range) const { invariant(isSharded()); return _cm->rangeOverlapsShard(range, _thisShardId); } @@ -203,25 +175,49 @@ public: * * @return orphanRange the output range. Note that the NS is not set. */ - boost::optional<ChunkRange> getNextOrphanRange(const RangeMap& receiveMap, - const BSONObj& lookupKey) const; + boost::optional<ChunkRange> getNextOrphanRange(RangeMap const& receiveMap, + BSONObj const& lookupKey) const; /** * Returns all the chunks which are contained on this shard. */ RangeMap getChunks() const; - /** - * BSON output of the chunks metadata into a BSONArray - */ - void toBSONChunks(BSONArrayBuilder* builder) const; + const BSONObj& getKeyPattern() const { + invariant(isSharded()); + return _cm->getShardKeyPattern().toBSON(); + } + + const std::vector<std::unique_ptr<FieldRef>>& getKeyPatternFields() const { + invariant(isSharded()); + return _cm->getShardKeyPattern().getKeyPatternFields(); + } + + BSONObj getMinKey() const { + invariant(isSharded()); + return _cm->getShardKeyPattern().getKeyPattern().globalMin(); + } + + BSONObj getMaxKey() const { + invariant(isSharded()); + return _cm->getShardKeyPattern().getKeyPattern().globalMax(); + } + + std::shared_ptr<ChunkManager> getChunkManager() const { + invariant(isSharded()); + return _cm; + } + + bool uuidMatches(UUID uuid) const { + invariant(isSharded()); + return _cm->uuidMatches(uuid); + } private: - // The full routing table for the collection or nullptr if the collection is not sharded + // The full routing table for the collection. std::shared_ptr<ChunkManager> _cm; - // The identity of this shard, for the purpose of answering "key belongs to me" queries. If the - // collection is not sharded (_cm is nullptr), then this value will be empty. + // The identity of this shard, for the purpose of answering "key belongs to me" queries. ShardId _thisShardId; }; diff --git a/src/mongo/db/s/collection_metadata_filtering_test.cpp b/src/mongo/db/s/collection_metadata_filtering_test.cpp index 00c19583b17..46db156c36a 100644 --- a/src/mongo/db/s/collection_metadata_filtering_test.cpp +++ b/src/mongo/db/s/collection_metadata_filtering_test.cpp @@ -141,7 +141,7 @@ TEST_F(CollectionMetadataFilteringTest, FilterDocumentsInTheFuture) { AutoGetCollection autoColl(operationContext(), kNss, MODE_IS); auto* const css = CollectionShardingState::get(operationContext(), kNss); - testFn(css->getOrphansFilter(operationContext())); + testFn(css->getMetadataForOperation(operationContext())); } { @@ -172,7 +172,7 @@ TEST_F(CollectionMetadataFilteringTest, FilterDocumentsInThePast) { AutoGetCollection autoColl(operationContext(), kNss, MODE_IS); auto* const css = CollectionShardingState::get(operationContext(), kNss); - testFn(css->getOrphansFilter(operationContext())); + testFn(css->getMetadataForOperation(operationContext())); } { @@ -211,7 +211,7 @@ TEST_F(CollectionMetadataFilteringTest, FilterDocumentsTooFarInThePastThrowsStal AutoGetCollection autoColl(operationContext(), kNss, MODE_IS); auto* const css = CollectionShardingState::get(operationContext(), kNss); - testFn(css->getOrphansFilter(operationContext())); + testFn(css->getMetadataForOperation(operationContext())); } { diff --git a/src/mongo/db/s/collection_sharding_state.cpp b/src/mongo/db/s/collection_sharding_state.cpp index 8a3e0304146..f65f262a029 100644 --- a/src/mongo/db/s/collection_sharding_state.cpp +++ b/src/mongo/db/s/collection_sharding_state.cpp @@ -111,8 +111,7 @@ private: const auto kUnshardedCollection = std::make_shared<UnshardedCollection>(); -boost::optional<ChunkVersion> getOperationReceivedVersion(OperationContext* opCtx, - const NamespaceString& nss) { +ChunkVersion getOperationReceivedVersion(OperationContext* opCtx, const NamespaceString& nss) { auto& oss = OperationShardingState::get(opCtx); // If there is a version attached to the OperationContext, use it as the received version, @@ -126,12 +125,12 @@ boost::optional<ChunkVersion> getOperationReceivedVersion(OperationContext* opCt // in a single call, the lack of version for a namespace on the collection must be treated // as UNSHARDED return connectionShardVersion.value_or(ChunkVersion::UNSHARDED()); + } else { + // There is no shard version information on either 'opCtx' or 'client'. This means that the + // operation represented by 'opCtx' is unversioned, and the shard version is always OK for + // unversioned operations. + return ChunkVersion::IGNORED(); } - - // There is no shard version information on either 'opCtx' or 'client'. This means that the - // operation represented by 'opCtx' is unversioned, and the shard version is always OK for - // unversioned operations - return boost::none; } } // namespace @@ -152,10 +151,12 @@ void CollectionShardingState::report(OperationContext* opCtx, BSONObjBuilder* bu collectionsMap->report(opCtx, builder); } -ScopedCollectionMetadata CollectionShardingState::getOrphansFilter(OperationContext* opCtx) { +ScopedCollectionMetadata CollectionShardingState::getMetadataForOperation(OperationContext* opCtx) { const auto receivedShardVersion = getOperationReceivedVersion(opCtx, _nss); - if (!receivedShardVersion) + + if (ChunkVersion::isIgnoredVersion(receivedShardVersion)) { return {kUnshardedCollection}; + } const auto atClusterTime = repl::ReadConcernArgs::get(opCtx).getArgsAtClusterTime(); auto optMetadata = _getMetadata(atClusterTime); @@ -192,12 +193,8 @@ boost::optional<ChunkVersion> CollectionShardingState::getCurrentShardVersionIfK } void CollectionShardingState::checkShardVersionOrThrow(OperationContext* opCtx) { - const auto optReceivedShardVersion = getOperationReceivedVersion(opCtx, _nss); - - if (!optReceivedShardVersion) - return; + const auto receivedShardVersion = getOperationReceivedVersion(opCtx, _nss); - const auto& receivedShardVersion = *optReceivedShardVersion; if (ChunkVersion::isIgnoredVersion(receivedShardVersion)) { return; } @@ -206,7 +203,7 @@ void CollectionShardingState::checkShardVersionOrThrow(OperationContext* opCtx) invariant(repl::ReadConcernArgs::get(opCtx).getLevel() != repl::ReadConcernLevel::kAvailableReadConcern); - const auto metadata = getCurrentMetadata(); + const auto metadata = getMetadataForOperation(opCtx); const auto wantedShardVersion = metadata->isSharded() ? metadata->getShardVersion() : ChunkVersion::UNSHARDED(); diff --git a/src/mongo/db/s/collection_sharding_state.h b/src/mongo/db/s/collection_sharding_state.h index cbd7f9d563f..e964dbced12 100644 --- a/src/mongo/db/s/collection_sharding_state.h +++ b/src/mongo/db/s/collection_sharding_state.h @@ -73,26 +73,16 @@ public: static void report(OperationContext* opCtx, BSONObjBuilder* builder); /** - * Returns the orphan chunk filtering metadata that the current operation should be using for - * the collection. + * Returns the chunk filtering metadata that the current operation should be using for that + * collection or otherwise throws if it has not been loaded yet. If the operation does not + * require a specific shard version, returns an UNSHARDED metadata. The returned object is safe + * to access outside of collection lock. * - * If the operation context contains an 'atClusterTime', the returned filtering metadata will be - * tied to a specific point in time. Otherwise, it will reference the latest time available. If - * the operation is not associated with a shard version (refer to - * OperationShardingState::isOperationVersioned for more info on that), returns an UNSHARDED - * metadata object. - * - * The intended users of this method are callers which need to perform orphan filtering. Use - * 'getCurrentMetadata' for all other cases, where just sharding-related properties of the - * collection are necessary (e.g., isSharded or the shard key). - * - * The returned object is safe to access even after the collection lock has been dropped. - */ - ScopedCollectionMetadata getOrphansFilter(OperationContext* opCtx); - - /** - * See the comments for 'getOrphansFilter' above for more information on this method. + * If the operation context contains an 'atClusterTime' property, the returned filtering + * metadata will be tied to a specific point in time. Otherwise it will reference the latest + * time available. */ + ScopedCollectionMetadata getMetadataForOperation(OperationContext* opCtx); ScopedCollectionMetadata getCurrentMetadata(); /** diff --git a/src/mongo/db/s/get_shard_version_command.cpp b/src/mongo/db/s/get_shard_version_command.cpp index b986ffecb82..a51ce749549 100644 --- a/src/mongo/db/s/get_shard_version_command.cpp +++ b/src/mongo/db/s/get_shard_version_command.cpp @@ -133,7 +133,7 @@ public: metadata->toBSONBasic(metadataBuilder); BSONArrayBuilder chunksArr(metadataBuilder.subarrayStart("chunks")); - metadata->toBSONChunks(&chunksArr); + metadata->toBSONChunks(chunksArr); chunksArr.doneFast(); BSONArrayBuilder pendingArr(metadataBuilder.subarrayStart("pending")); diff --git a/src/mongo/db/s/op_observer_sharding_impl.cpp b/src/mongo/db/s/op_observer_sharding_impl.cpp index 70b090881de..0f6aaba48c4 100644 --- a/src/mongo/db/s/op_observer_sharding_impl.cpp +++ b/src/mongo/db/s/op_observer_sharding_impl.cpp @@ -63,7 +63,6 @@ namespace mongo { namespace { - const auto getIsMigrating = OperationContext::declareDecoration<bool>(); } diff --git a/src/mongo/db/s/shard_server_op_observer.cpp b/src/mongo/db/s/shard_server_op_observer.cpp index 5733763902c..3078fd59396 100644 --- a/src/mongo/db/s/shard_server_op_observer.cpp +++ b/src/mongo/db/s/shard_server_op_observer.cpp @@ -207,7 +207,7 @@ void ShardServerOpObserver::onInserts(OperationContext* opCtx, std::vector<InsertStatement>::const_iterator end, bool fromMigrate) { auto* const css = CollectionShardingState::get(opCtx, nss); - const auto metadata = css->getCurrentMetadata(); + const auto metadata = css->getMetadataForOperation(opCtx); for (auto it = begin; it != end; ++it) { const auto& insertedDoc = it->doc; @@ -233,7 +233,7 @@ void ShardServerOpObserver::onInserts(OperationContext* opCtx, void ShardServerOpObserver::onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) { auto* const css = CollectionShardingState::get(opCtx, args.nss); - const auto metadata = css->getCurrentMetadata(); + const auto metadata = css->getMetadataForOperation(opCtx); if (args.nss == NamespaceString::kShardConfigCollectionsNamespace) { // Notification of routing table changes are only needed on secondaries |