diff options
Diffstat (limited to 'src/mongo/db/s')
-rw-r--r-- | src/mongo/db/s/collection_sharding_state.cpp | 22 | ||||
-rw-r--r-- | src/mongo/db/s/collection_sharding_state.h | 9 | ||||
-rw-r--r-- | src/mongo/db/s/collection_sharding_state_test.cpp | 11 | ||||
-rw-r--r-- | src/mongo/db/s/metadata_manager.cpp | 58 | ||||
-rw-r--r-- | src/mongo/db/s/metadata_manager.h | 11 | ||||
-rw-r--r-- | src/mongo/db/s/migration_chunk_cloner_source.h | 2 | ||||
-rw-r--r-- | src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/s/migration_chunk_cloner_source_legacy.h | 2 |
8 files changed, 40 insertions, 78 deletions
diff --git a/src/mongo/db/s/collection_sharding_state.cpp b/src/mongo/db/s/collection_sharding_state.cpp index b5a9217352f..4ad6a464009 100644 --- a/src/mongo/db/s/collection_sharding_state.cpp +++ b/src/mongo/db/s/collection_sharding_state.cpp @@ -267,17 +267,6 @@ boost::optional<KeyRange> CollectionShardingState::getNextOrphanRange(BSONObj co return _metadataManager->getNextOrphanRange(from); } -bool CollectionShardingState::isDocumentInMigratingChunk(OperationContext* opCtx, - const BSONObj& doc) { - dassert(opCtx->lockState()->isCollectionLockedForMode(_nss.ns(), MODE_IX)); - - if (_sourceMgr) { - return _sourceMgr->getCloner()->isDocumentInMigratingChunk(opCtx, doc); - } - - return false; -} - void CollectionShardingState::onInsertOp(OperationContext* opCtx, const BSONObj& insertedDoc) { dassert(opCtx->lockState()->isCollectionLockedForMode(_nss.ns(), MODE_IX)); @@ -330,11 +319,12 @@ void CollectionShardingState::onUpdateOp(OperationContext* opCtx, } } -CollectionShardingState::DeleteState::DeleteState(OperationContext* opCtx, - CollectionShardingState* css, - BSONObj const& doc) - : documentKey(css->_metadataManager->extractDocumentKey(doc).getOwned()), - isMigrating(css->_sourceMgr && css->isDocumentInMigratingChunk(opCtx, doc)) {} +auto CollectionShardingState::makeDeleteState(BSONObj const& doc) -> DeleteState { + BSONObj documentKey = getMetadata().extractDocumentKey(doc).getOwned(); + invariant(documentKey.hasField("_id"_sd)); + return {std::move(documentKey), + _sourceMgr && _sourceMgr->getCloner()->isDocumentInMigratingChunk(doc)}; +} void CollectionShardingState::onDeleteOp(OperationContext* opCtx, const CollectionShardingState::DeleteState& deleteState) { diff --git a/src/mongo/db/s/collection_sharding_state.h b/src/mongo/db/s/collection_sharding_state.h index 5d4393346e3..c94b64aeef3 100644 --- a/src/mongo/db/s/collection_sharding_state.h +++ b/src/mongo/db/s/collection_sharding_state.h @@ -71,12 +71,9 @@ public: ~CollectionShardingState(); /** - * Holds information used for tracking document removals during chunk migration. + * Details of documents being removed from a sharded collection. */ struct DeleteState { - DeleteState() = default; - DeleteState(OperationContext*, CollectionShardingState*, BSONObj const& doc); - // Contains the fields of the document that are in the collection's shard key, and "_id". BSONObj documentKey; @@ -86,6 +83,8 @@ public: bool isMigrating; }; + DeleteState makeDeleteState(BSONObj const& doc); + /** * Obtains the sharding state for the specified collection. If it does not exist, it will be * created and will remain active until the collection is dropped or unsharded. @@ -224,7 +223,6 @@ public: * * The global exclusive lock is expected to be held by the caller of any of these functions. */ - bool isDocumentInMigratingChunk(OperationContext* opCtx, const BSONObj& doc); void onInsertOp(OperationContext* opCtx, const BSONObj& insertedDoc); void onUpdateOp(OperationContext* opCtx, const BSONObj& query, @@ -327,7 +325,6 @@ private: int maxToDelete, CollectionRangeDeleter*) -> boost::optional<Date_t>; - friend DeleteState; }; } // namespace mongo diff --git a/src/mongo/db/s/collection_sharding_state_test.cpp b/src/mongo/db/s/collection_sharding_state_test.cpp index 3411becdf34..844727e72c4 100644 --- a/src/mongo/db/s/collection_sharding_state_test.cpp +++ b/src/mongo/db/s/collection_sharding_state_test.cpp @@ -196,7 +196,7 @@ TEST_F(CollShardingStateTest, MakeDeleteStateUnsharded) { // First, check that an order for deletion from an unsharded collection (where css has not been // "refreshed" with chunk metadata) extracts just the "_id" field: - auto deleteState = CollectionShardingState::DeleteState(operationContext(), css, doc); + auto deleteState = css->makeDeleteState(doc); ASSERT_BSONOBJ_EQ(deleteState.documentKey, BSON("_id" << "hello")); ASSERT_FALSE(deleteState.isMigrating); } @@ -212,7 +212,7 @@ TEST_F(CollShardingStateTest, MakeDeleteStateShardedWithoutIdInShardKey) { auto doc = BSON("key3" << "abc" << "key" << 100 << "_id" << "hello" << "key2" << true); // Verify the shard key is extracted, in correct order, followed by the "_id" field. - auto deleteState = CollectionShardingState::DeleteState(operationContext(), css, doc); + auto deleteState = css->makeDeleteState(doc); ASSERT_BSONOBJ_EQ( deleteState.documentKey, BSON("key" << 100 << "key3" << "abc" << "_id" << "hello")); ASSERT_FALSE(deleteState.isMigrating); @@ -230,7 +230,7 @@ TEST_F(CollShardingStateTest, MakeDeleteStateShardedWithIdInShardKey) { auto doc = BSON("key2" << true << "key3" << "abc" << "_id" << "hello" << "key" << 100); // Verify the shard key is extracted with "_id" in the right place. - auto deleteState = CollectionShardingState::DeleteState(operationContext(), css, doc); + auto deleteState = css->makeDeleteState(doc); ASSERT_BSONOBJ_EQ( deleteState.documentKey, BSON("key" << 100 << "_id" << "hello" << "key2" << true)); ASSERT_FALSE(deleteState.isMigrating); @@ -247,9 +247,8 @@ TEST_F(CollShardingStateTest, MakeDeleteStateShardedWithIdHashInShardKey) { auto doc = BSON("key2" << true << "_id" << "hello" << "key" << 100); // Verify the shard key is extracted with "_id" in the right place, not hashed. - auto deleteState = CollectionShardingState::DeleteState(operationContext(), css, doc); - ASSERT_BSONOBJ_EQ( - deleteState.documentKey, BSON("_id" << "hello")); + auto deleteState = css->makeDeleteState(doc); + ASSERT_BSONOBJ_EQ(deleteState.documentKey, BSON("_id" << "hello")); ASSERT_FALSE(deleteState.isMigrating); } } // unnamed namespace diff --git a/src/mongo/db/s/metadata_manager.cpp b/src/mongo/db/s/metadata_manager.cpp index 88450d4da96..d975a785e4e 100644 --- a/src/mongo/db/s/metadata_manager.cpp +++ b/src/mongo/db/s/metadata_manager.cpp @@ -35,6 +35,7 @@ #include "mongo/base/string_data.h" #include "mongo/bson/simple_bsonobj_comparator.h" #include "mongo/bson/util/builder.h" +#include "mongo/db/bson/dotted_path_support.h" #include "mongo/db/db_raii.h" #include "mongo/db/query/internal_plans.h" #include "mongo/db/range_arithmetic.h" @@ -277,6 +278,22 @@ ScopedCollectionMetadata::ScopedCollectionMetadata(std::shared_ptr<MetadataManag ++_metadata->_tracker.usageCounter; } +BSONObj ScopedCollectionMetadata::extractDocumentKey(BSONObj const& doc) const { + BSONObj key; + if (*this) { // is sharded + auto const& pattern = _metadata->_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"_sd]) { + return key.isEmpty() ? id.wrap() : BSONObjBuilder(std::move(key)).append(id).obj(); + } + return key; +} + ScopedCollectionMetadata::~ScopedCollectionMetadata() { _clear(); } @@ -571,45 +588,4 @@ boost::optional<KeyRange> MetadataManager::getNextOrphanRange(BSONObj const& fro return _metadata.back()->getNextOrphanRange(_receivingChunks, from); } -namespace { - -static BSONElement extractKeyElement(const BSONObj& doc, StringData pathStr) { - ElementPath path(pathStr, false, false); - BSONElementIterator elemIter(&path, doc); - if (!elemIter.more()) { - return {}; - } - BSONElement matchEl = elemIter.next().element(); - // We shouldn't have more than one element - we don't expand arrays - dassert(!elemIter.more()); - return matchEl; -} - -} // namespace - -BSONObj MetadataManager::extractDocumentKey(BSONObj const& doc) { - BSONObjBuilder keyBuilder; - bool gotId = false; - { - stdx::lock_guard<stdx::mutex> scopedLock(_managerLock); - if (!_metadata.empty()) { - BSONObjIterator patternIt(_metadata.back()->_cm->getShardKeyPattern().toBSON()); - while (patternIt.more()) { - BSONElement patternEl = patternIt.next(); - BSONElement matchEl = extractKeyElement(doc, patternEl.fieldNameStringData()); - if (matchEl.ok()) { - if (patternEl.fieldNameStringData() == StringData("_id")) { - gotId = true; - } - keyBuilder.appendAs(matchEl, patternEl.fieldName()); - } - } - } - } - if (!gotId && doc.hasField("_id")) { - keyBuilder.append(doc["_id"]); - } - return keyBuilder.obj(); -} - } // namespace mongo diff --git a/src/mongo/db/s/metadata_manager.h b/src/mongo/db/s/metadata_manager.h index 7a15e47d709..48cd08df125 100644 --- a/src/mongo/db/s/metadata_manager.h +++ b/src/mongo/db/s/metadata_manager.h @@ -140,11 +140,6 @@ public: boost::optional<KeyRange> getNextOrphanRange(BSONObj const& from); - /** - * Returns just the shard key fields, if collection is sharded, and the _id field, from `doc`. - */ - BSONObj extractDocumentKey(BSONObj const& doc); - private: // All of the following functions must be called while holding _managerLock. @@ -266,6 +261,12 @@ public: CollectionMetadata* getMetadata() const; /** + * Returns just the shard key fields, if collection is sharded, and the _id field, from `doc`. + * Does not alter any field values (e.g. by hashing); values are copied verbatim. + */ + BSONObj extractDocumentKey(BSONObj const& doc) const; + + /** * True if the ScopedCollectionMetadata stores a metadata (is not empty) and the collection is * sharded. */ diff --git a/src/mongo/db/s/migration_chunk_cloner_source.h b/src/mongo/db/s/migration_chunk_cloner_source.h index 50a31da4db6..750bcdcda80 100644 --- a/src/mongo/db/s/migration_chunk_cloner_source.h +++ b/src/mongo/db/s/migration_chunk_cloner_source.h @@ -109,7 +109,7 @@ public: * * NOTE: Must be called with at least IS lock held on the collection. */ - virtual bool isDocumentInMigratingChunk(OperationContext* opCtx, const BSONObj& doc) = 0; + virtual bool isDocumentInMigratingChunk(const BSONObj& doc) = 0; /** * Notifies this cloner that an insert happened to the collection, which it owns. It is up to diff --git a/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp b/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp index 2a60f3fbc8a..70a76e5e473 100644 --- a/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp +++ b/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp @@ -339,8 +339,7 @@ void MigrationChunkClonerSourceLegacy::cancelClone(OperationContext* opCtx) { } } -bool MigrationChunkClonerSourceLegacy::isDocumentInMigratingChunk(OperationContext* opCtx, - const BSONObj& doc) { +bool MigrationChunkClonerSourceLegacy::isDocumentInMigratingChunk(const BSONObj& doc) { return isInRange(doc, _args.getMinKey(), _args.getMaxKey(), _shardKeyPattern); } diff --git a/src/mongo/db/s/migration_chunk_cloner_source_legacy.h b/src/mongo/db/s/migration_chunk_cloner_source_legacy.h index 28eca3989c5..c072718475a 100644 --- a/src/mongo/db/s/migration_chunk_cloner_source_legacy.h +++ b/src/mongo/db/s/migration_chunk_cloner_source_legacy.h @@ -70,7 +70,7 @@ public: void cancelClone(OperationContext* opCtx) override; - bool isDocumentInMigratingChunk(OperationContext* opCtx, const BSONObj& doc) override; + bool isDocumentInMigratingChunk(const BSONObj& doc) override; void onInsertOp(OperationContext* opCtx, const BSONObj& insertedDoc) override; |