diff options
Diffstat (limited to 'src')
20 files changed, 177 insertions, 141 deletions
diff --git a/src/mongo/db/s/catalog_cache_loader_mock.cpp b/src/mongo/db/s/catalog_cache_loader_mock.cpp index 4dc0f775fab..7b3a3b03c2d 100644 --- a/src/mongo/db/s/catalog_cache_loader_mock.cpp +++ b/src/mongo/db/s/catalog_cache_loader_mock.cpp @@ -105,12 +105,13 @@ std::shared_ptr<Notification<void>> CatalogCacheLoaderMock::getChunksSince( uassertStatusOK(_swCollectionReturnValue); uassertStatusOK(_swChunksReturnValue); - return CollectionAndChangedChunks{ + return CollectionAndChangedChunks( + _swCollectionReturnValue.getValue().getUUID(), _swCollectionReturnValue.getValue().getEpoch(), _swCollectionReturnValue.getValue().getKeyPattern().toBSON(), _swCollectionReturnValue.getValue().getDefaultCollation(), _swCollectionReturnValue.getValue().getUnique(), - _swChunksReturnValue.getValue()}; + _swChunksReturnValue.getValue()); } catch (const DBException& ex) { return ex.toStatus(); } diff --git a/src/mongo/db/s/collection_metadata.h b/src/mongo/db/s/collection_metadata.h index ae301d90212..dbec901f2e0 100644 --- a/src/mongo/db/s/collection_metadata.h +++ b/src/mongo/db/s/collection_metadata.h @@ -172,6 +172,10 @@ public: return _cm; } + bool uuidMatches(UUID uuid) const { + return _cm->uuidMatches(uuid); + } + private: struct Tracker { uint32_t usageCounter{0}; diff --git a/src/mongo/db/s/collection_metadata_test.cpp b/src/mongo/db/s/collection_metadata_test.cpp index cf5bea78a00..13b4d540de2 100644 --- a/src/mongo/db/s/collection_metadata_test.cpp +++ b/src/mongo/db/s/collection_metadata_test.cpp @@ -70,7 +70,8 @@ std::unique_ptr<CollectionMetadata> makeCollectionMetadataImpl( kNss, ChunkRange{nextMinKey, shardKeyPattern.globalMax()}, version, kOtherShard); } - auto cm = ChunkManager::makeNew(kNss, shardKeyPattern, nullptr, false, epoch, allChunks); + UUID uuid(UUID::gen()); + auto cm = ChunkManager::makeNew(kNss, uuid, shardKeyPattern, nullptr, false, epoch, allChunks); return stdx::make_unique<CollectionMetadata>(cm, kThisShard); } diff --git a/src/mongo/db/s/collection_range_deleter_test.cpp b/src/mongo/db/s/collection_range_deleter_test.cpp index 1763301fbb4..30135befdbc 100644 --- a/src/mongo/db/s/collection_range_deleter_test.cpp +++ b/src/mongo/db/s/collection_range_deleter_test.cpp @@ -110,6 +110,7 @@ void CollectionRangeDeleterTest::setUp() { const KeyPattern skPattern(kKeyPattern); auto cm = ChunkManager::makeNew( kNss, + UUID::gen(), kKeyPattern, nullptr, false, diff --git a/src/mongo/db/s/collection_sharding_state.cpp b/src/mongo/db/s/collection_sharding_state.cpp index 0c4e6a1b70d..25f2727ff55 100644 --- a/src/mongo/db/s/collection_sharding_state.cpp +++ b/src/mongo/db/s/collection_sharding_state.cpp @@ -418,7 +418,7 @@ void CollectionShardingState::_onConfigRefreshCompleteInvalidateCachedMetadataAn // Extract which collection entry is being updated std::string refreshCollection; fassertStatusOK( - 40477, bsonExtractStringField(query, ShardCollectionType::uuid.name(), &refreshCollection)); + 40477, bsonExtractStringField(query, ShardCollectionType::ns.name(), &refreshCollection)); // Parse the '$set' update, which will contain the 'lastRefreshedCollectionVersion' if it is // present. @@ -443,7 +443,7 @@ void CollectionShardingState::_onConfigDeleteInvalidateCachedMetadataAndNotify( // Extract which collection entry is being deleted from the _id field. std::string deletedCollection; fassertStatusOK( - 40479, bsonExtractStringField(query, ShardCollectionType::uuid.name(), &deletedCollection)); + 40479, bsonExtractStringField(query, ShardCollectionType::ns.name(), &deletedCollection)); opCtx->recoveryUnit()->registerChange( new CollectionVersionLogOpHandler(opCtx, NamespaceString(deletedCollection))); diff --git a/src/mongo/db/s/collection_sharding_state_test.cpp b/src/mongo/db/s/collection_sharding_state_test.cpp index 9ac9f4a9702..f9fcbc69420 100644 --- a/src/mongo/db/s/collection_sharding_state_test.cpp +++ b/src/mongo/db/s/collection_sharding_state_test.cpp @@ -180,7 +180,7 @@ auto makeAMetadata(BSONObj const& keyPattern) -> std::unique_ptr<CollectionMetad auto range = ChunkRange(BSON("key" << MINKEY), BSON("key" << MAXKEY)); auto chunk = ChunkType(testNss, std::move(range), ChunkVersion(1, 0, epoch), ShardId("other")); auto cm = ChunkManager::makeNew( - testNss, KeyPattern(keyPattern), nullptr, false, epoch, {std::move(chunk)}); + testNss, UUID::gen(), KeyPattern(keyPattern), nullptr, false, epoch, {std::move(chunk)}); return stdx::make_unique<CollectionMetadata>(std::move(cm), ShardId("this")); } diff --git a/src/mongo/db/s/metadata_manager_test.cpp b/src/mongo/db/s/metadata_manager_test.cpp index 16cb8a5e122..50f2aed8274 100644 --- a/src/mongo/db/s/metadata_manager_test.cpp +++ b/src/mongo/db/s/metadata_manager_test.cpp @@ -92,6 +92,7 @@ protected: auto cm = ChunkManager::makeNew( kNss, + UUID::gen(), kShardKeyPattern, nullptr, false, diff --git a/src/mongo/db/s/shard_metadata_util.cpp b/src/mongo/db/s/shard_metadata_util.cpp index 9e076435a4c..533d955d575 100644 --- a/src/mongo/db/s/shard_metadata_util.cpp +++ b/src/mongo/db/s/shard_metadata_util.cpp @@ -91,7 +91,7 @@ Status setPersistedRefreshFlags(OperationContext* opCtx, const NamespaceString& // Set 'refreshing' to true. BSONObj update = BSON(ShardCollectionType::refreshing() << true); return updateShardCollectionsEntry( - opCtx, BSON(ShardCollectionType::uuid() << nss.ns()), update, false /*upsert*/); + opCtx, BSON(ShardCollectionType::ns() << nss.ns()), update, false /*upsert*/); } Status unsetPersistedRefreshFlags(OperationContext* opCtx, @@ -103,10 +103,8 @@ Status unsetPersistedRefreshFlags(OperationContext* opCtx, updateBuilder.appendTimestamp(ShardCollectionType::lastRefreshedCollectionVersion(), refreshedVersion.toLong()); - return updateShardCollectionsEntry(opCtx, - BSON(ShardCollectionType::uuid() << nss.ns()), - updateBuilder.obj(), - false /*upsert*/); + return updateShardCollectionsEntry( + opCtx, BSON(ShardCollectionType::ns() << nss.ns()), updateBuilder.obj(), false /*upsert*/); } StatusWith<RefreshState> getPersistedRefreshFlags(OperationContext* opCtx, @@ -142,7 +140,7 @@ StatusWith<RefreshState> getPersistedRefreshFlags(OperationContext* opCtx, StatusWith<ShardCollectionType> readShardCollectionsEntry(OperationContext* opCtx, const NamespaceString& nss) { - Query fullQuery(BSON(ShardCollectionType::uuid() << nss.ns())); + Query fullQuery(BSON(ShardCollectionType::ns() << nss.ns())); try { DBDirectClient client(opCtx); @@ -335,7 +333,7 @@ Status dropChunksAndDeleteCollectionsEntry(OperationContext* opCtx, const Namesp NamespaceString{NamespaceString::kShardConfigCollectionsCollectionName}); deleteOp.setDeletes({[&] { write_ops::DeleteOpEntry entry; - entry.setQ(BSON(ShardCollectionType::uuid << nss.ns())); + entry.setQ(BSON(ShardCollectionType::ns << nss.ns())); entry.setMulti(true); return entry; }()}); diff --git a/src/mongo/db/s/shard_metadata_util_test.cpp b/src/mongo/db/s/shard_metadata_util_test.cpp index fa30bda71af..31564329893 100644 --- a/src/mongo/db/s/shard_metadata_util_test.cpp +++ b/src/mongo/db/s/shard_metadata_util_test.cpp @@ -55,24 +55,23 @@ const NamespaceString kChunkMetadataNss = NamespaceString("config.chunks.test.fo const ShardId kShardId = ShardId("shard0"); const bool kUnique = false; -class ShardMetadataUtilTest : public ShardServerTestFixture { -protected: +struct ShardMetadataUtilTest : public ShardServerTestFixture { /** * Inserts a collections collection entry for 'kNss'. */ ShardCollectionType setUpCollection() { BSONObjBuilder builder; - builder.append(ShardCollectionType::uuid(), kNss.ns()); builder.append(ShardCollectionType::ns(), kNss.ns()); - builder.append(ShardCollectionType::epoch(), _maxCollVersion.epoch()); - builder.append(ShardCollectionType::keyPattern(), _keyPattern.toBSON()); - builder.append(ShardCollectionType::defaultCollation(), _defaultCollation); + uuid.appendToBuilder(&builder, ShardCollectionType::uuid()); + builder.append(ShardCollectionType::epoch(), maxCollVersion.epoch()); + builder.append(ShardCollectionType::keyPattern(), keyPattern.toBSON()); + builder.append(ShardCollectionType::defaultCollation(), defaultCollation); builder.append(ShardCollectionType::unique(), kUnique); ShardCollectionType shardCollectionType = assertGet(ShardCollectionType::fromBSON(builder.obj())); ASSERT_OK(updateShardCollectionsEntry(operationContext(), - BSON(ShardCollectionType::uuid(kNss.ns())), + BSON(ShardCollectionType::ns(kNss.ns())), shardCollectionType.toBSON(), true /*upsert*/)); return shardCollectionType; @@ -84,7 +83,7 @@ protected: void setUpChunks(const NamespaceString& nss, const std::vector<ChunkType> chunks) { NamespaceString chunkMetadataNss(ChunkType::ShardNSPrefix + nss.ns()); - ASSERT_OK(updateShardChunks(operationContext(), kNss, chunks, _maxCollVersion.epoch())); + ASSERT_OK(updateShardChunks(operationContext(), kNss, chunks, maxCollVersion.epoch())); } /** @@ -96,15 +95,15 @@ protected: BSONObj maxs[] = {BSON("a" << 10), BSON("a" << 50), BSON("a" << 100), BSON("a" << MAXKEY)}; for (int i = 0; i < 4; ++i) { - _maxCollVersion.incMajor(); + maxCollVersion.incMajor(); BSONObj shardChunk = BSON(ChunkType::minShardID(mins[i]) << ChunkType::max(maxs[i]) << ChunkType::shard(kShardId.toString()) - << ChunkType::lastmod(Date_t::fromMillisSinceEpoch(_maxCollVersion.toLong()))); + << ChunkType::lastmod(Date_t::fromMillisSinceEpoch(maxCollVersion.toLong()))); chunks.push_back( - assertGet(ChunkType::fromShardBSON(shardChunk, _maxCollVersion.epoch()))); + assertGet(ChunkType::fromShardBSON(shardChunk, maxCollVersion.epoch()))); } return chunks; @@ -162,23 +161,11 @@ protected: } } - const ChunkVersion& getCollectionVersion() const { - return _maxCollVersion; - } - - const BSONObj& getKeyPattern() const { - return _keyPattern.toBSON(); - } - - const BSONObj& getDefaultCollation() const { - return _defaultCollation; - } - -private: - ChunkVersion _maxCollVersion{0, 0, OID::gen()}; - const KeyPattern _keyPattern{BSON("a" << 1)}; - const BSONObj _defaultCollation{BSON("locale" - << "fr_CA")}; + ChunkVersion maxCollVersion{0, 0, OID::gen()}; + const KeyPattern keyPattern{BSON("a" << 1)}; + const BSONObj defaultCollation{BSON("locale" + << "fr_CA")}; + const UUID uuid = UUID::gen(); }; TEST_F(ShardMetadataUtilTest, UpdateAndReadCollectionsEntry) { @@ -186,7 +173,8 @@ TEST_F(ShardMetadataUtilTest, UpdateAndReadCollectionsEntry) { ShardCollectionType readShardCollectionType = assertGet(readShardCollectionsEntry(operationContext(), kNss)); - ASSERT_EQUALS(updateShardCollectionType.getUUID(), readShardCollectionType.getUUID()); + ASSERT_TRUE(readShardCollectionType.getUUID()); + ASSERT_EQUALS(*updateShardCollectionType.getUUID(), *readShardCollectionType.getUUID()); ASSERT_EQUALS(updateShardCollectionType.getNss(), readShardCollectionType.getNss()); ASSERT_EQUALS(updateShardCollectionType.getEpoch(), readShardCollectionType.getEpoch()); ASSERT_BSONOBJ_EQ(updateShardCollectionType.getKeyPattern().toBSON(), @@ -211,11 +199,11 @@ TEST_F(ShardMetadataUtilTest, PersistedRefreshSignalStartAndFinish) { ShardCollectionType shardCollectionsEntry = assertGet(readShardCollectionsEntry(operationContext(), kNss)); - ASSERT_EQUALS(shardCollectionsEntry.getUUID(), kNss); - ASSERT_EQUALS(shardCollectionsEntry.getNss(), kNss); - ASSERT_EQUALS(shardCollectionsEntry.getEpoch(), getCollectionVersion().epoch()); - ASSERT_BSONOBJ_EQ(shardCollectionsEntry.getKeyPattern().toBSON(), getKeyPattern()); - ASSERT_BSONOBJ_EQ(shardCollectionsEntry.getDefaultCollation(), getDefaultCollation()); + ASSERT_EQUALS(*shardCollectionsEntry.getUUID(), uuid); + ASSERT_EQUALS(shardCollectionsEntry.getNss(), kNss.ns()); + ASSERT_EQUALS(shardCollectionsEntry.getEpoch(), maxCollVersion.epoch()); + ASSERT_BSONOBJ_EQ(shardCollectionsEntry.getKeyPattern().toBSON(), keyPattern.toBSON()); + ASSERT_BSONOBJ_EQ(shardCollectionsEntry.getDefaultCollation(), defaultCollation); ASSERT_EQUALS(shardCollectionsEntry.getUnique(), kUnique); ASSERT_EQUALS(shardCollectionsEntry.getRefreshing(), true); ASSERT(!shardCollectionsEntry.hasLastRefreshedCollectionVersion()); @@ -225,35 +213,34 @@ TEST_F(ShardMetadataUtilTest, PersistedRefreshSignalStartAndFinish) { RefreshState state = assertGet(getPersistedRefreshFlags(operationContext(), kNss)); - ASSERT_EQUALS(state.epoch, getCollectionVersion().epoch()); + ASSERT_EQUALS(state.epoch, maxCollVersion.epoch()); ASSERT_EQUALS(state.refreshing, true); - ASSERT_EQUALS(state.lastRefreshedCollectionVersion, - ChunkVersion(0, 0, getCollectionVersion().epoch())); + ASSERT_EQUALS(state.lastRefreshedCollectionVersion, ChunkVersion(0, 0, maxCollVersion.epoch())); // Signal refresh finish - ASSERT_OK(unsetPersistedRefreshFlags(operationContext(), kNss, getCollectionVersion())); + ASSERT_OK(unsetPersistedRefreshFlags(operationContext(), kNss, maxCollVersion)); state = assertGet(getPersistedRefreshFlags(operationContext(), kNss)); - ASSERT_EQUALS(state.epoch, getCollectionVersion().epoch()); + ASSERT_EQUALS(state.epoch, maxCollVersion.epoch()); ASSERT_EQUALS(state.refreshing, false); - ASSERT_EQUALS(state.lastRefreshedCollectionVersion, getCollectionVersion()); + ASSERT_EQUALS(state.lastRefreshedCollectionVersion, maxCollVersion); } TEST_F(ShardMetadataUtilTest, WriteAndReadChunks) { std::vector<ChunkType> chunks = makeFourChunks(); - ASSERT_OK(updateShardChunks(operationContext(), kNss, chunks, getCollectionVersion().epoch())); + ASSERT_OK(updateShardChunks(operationContext(), kNss, chunks, maxCollVersion.epoch())); checkChunks(kChunkMetadataNss, chunks); // read all the chunks QueryAndSort allChunkDiff = - createShardChunkDiffQuery(ChunkVersion(0, 0, getCollectionVersion().epoch())); + createShardChunkDiffQuery(ChunkVersion(0, 0, maxCollVersion.epoch())); std::vector<ChunkType> readChunks = assertGet(readShardChunks(operationContext(), kNss, allChunkDiff.query, allChunkDiff.sort, boost::none, - getCollectionVersion().epoch())); + maxCollVersion.epoch())); for (auto chunkIt = chunks.begin(), readChunkIt = readChunks.begin(); chunkIt != chunks.end() && readChunkIt != readChunks.end(); ++chunkIt, ++readChunkIt) { @@ -261,13 +248,13 @@ TEST_F(ShardMetadataUtilTest, WriteAndReadChunks) { } // read only the highest version chunk - QueryAndSort oneChunkDiff = createShardChunkDiffQuery(getCollectionVersion()); + QueryAndSort oneChunkDiff = createShardChunkDiffQuery(maxCollVersion); readChunks = assertGet(readShardChunks(operationContext(), kNss, oneChunkDiff.query, oneChunkDiff.sort, boost::none, - getCollectionVersion().epoch())); + maxCollVersion.epoch())); ASSERT_TRUE(readChunks.size() == 1); ASSERT_BSONOBJ_EQ(chunks.back().toShardBSON(), readChunks.front().toShardBSON()); @@ -277,7 +264,7 @@ TEST_F(ShardMetadataUtilTest, UpdateWithWriteNewChunks) { // Load some chunk metadata. std::vector<ChunkType> chunks = makeFourChunks(); - ASSERT_OK(updateShardChunks(operationContext(), kNss, chunks, getCollectionVersion().epoch())); + ASSERT_OK(updateShardChunks(operationContext(), kNss, chunks, maxCollVersion.epoch())); checkChunks(kChunkMetadataNss, chunks); // Load some changes and make sure it's applied correctly. @@ -286,7 +273,7 @@ TEST_F(ShardMetadataUtilTest, UpdateWithWriteNewChunks) { std::vector<ChunkType> newChunks; ChunkType lastChunk = chunks.back(); chunks.pop_back(); - ChunkVersion collVersion = getCollectionVersion(); + ChunkVersion collVersion = maxCollVersion; collVersion.incMinor(); // chunk only split BSONObjBuilder splitChunkOneBuilder; @@ -302,6 +289,7 @@ TEST_F(ShardMetadataUtilTest, UpdateWithWriteNewChunks) { newChunks.push_back(splitChunkOne); collVersion.incMajor(); // chunk split and moved + BSONObjBuilder splitChunkTwoMovedBuilder; { BSONObjBuilder subMin(splitChunkTwoMovedBuilder.subobjStart(ChunkType::minShardID())); diff --git a/src/mongo/db/s/shard_server_catalog_cache_loader.cpp b/src/mongo/db/s/shard_server_catalog_cache_loader.cpp index 683e5d0317b..70d1a50968c 100644 --- a/src/mongo/db/s/shard_server_catalog_cache_loader.cpp +++ b/src/mongo/db/s/shard_server_catalog_cache_loader.cpp @@ -83,13 +83,13 @@ Status persistCollectionAndChangedChunks(OperationContext* opCtx, const CollectionAndChangedChunks& collAndChunks) { // Update the collections collection entry for 'nss' in case there are any new updates. ShardCollectionType update = ShardCollectionType(nss, - nss, + collAndChunks.uuid, collAndChunks.epoch, collAndChunks.shardKeyPattern, collAndChunks.defaultCollation, collAndChunks.shardKeyIsUnique); Status status = updateShardCollectionsEntry( - opCtx, BSON(ShardCollectionType::uuid() << nss.ns()), update.toBSON(), true /*upsert*/); + opCtx, BSON(ShardCollectionType::ns() << nss.ns()), update.toBSON(), true /*upsert*/); if (!status.isOK()) { return status; } @@ -189,7 +189,8 @@ CollectionAndChangedChunks getPersistedMetadataSinceVersion(OperationContext* op auto changedChunks = uassertStatusOK( readShardChunks(opCtx, nss, diff.query, diff.sort, boost::none, startingVersion.epoch())); - return CollectionAndChangedChunks{shardCollectionEntry.getEpoch(), + return CollectionAndChangedChunks{shardCollectionEntry.getUUID(), + shardCollectionEntry.getEpoch(), shardCollectionEntry.getKeyPattern().toBSON(), shardCollectionEntry.getDefaultCollation(), shardCollectionEntry.getUnique(), diff --git a/src/mongo/s/catalog/type_shard_collection.cpp b/src/mongo/s/catalog/type_shard_collection.cpp index 186b35fbb44..3a98a15f7ba 100644 --- a/src/mongo/s/catalog/type_shard_collection.cpp +++ b/src/mongo/s/catalog/type_shard_collection.cpp @@ -42,8 +42,8 @@ namespace mongo { const std::string ShardCollectionType::ConfigNS = NamespaceString::kShardConfigCollectionsCollectionName.toString(); -const BSONField<std::string> ShardCollectionType::uuid("_id"); -const BSONField<std::string> ShardCollectionType::ns("ns"); +const BSONField<std::string> ShardCollectionType::ns("_id"); +const BSONField<UUID> ShardCollectionType::uuid("uuid"); const BSONField<OID> ShardCollectionType::epoch("epoch"); const BSONField<BSONObj> ShardCollectionType::keyPattern("key"); const BSONField<BSONObj> ShardCollectionType::defaultCollation("defaultCollation"); @@ -52,28 +52,20 @@ const BSONField<bool> ShardCollectionType::refreshing("refreshing"); const BSONField<Date_t> ShardCollectionType::lastRefreshedCollectionVersion( "lastRefreshedCollectionVersion"); -ShardCollectionType::ShardCollectionType(const NamespaceString& uuid, - const NamespaceString& nss, - const OID& epoch, +ShardCollectionType::ShardCollectionType(NamespaceString nss, + boost::optional<UUID> uuid, + OID epoch, const KeyPattern& keyPattern, const BSONObj& defaultCollation, - const bool& unique) - : _uuid(uuid), - _nss(nss), - _epoch(epoch), + bool unique) + : _nss(std::move(nss)), + _uuid(uuid), + _epoch(std::move(epoch)), _keyPattern(keyPattern.toBSON()), _defaultCollation(defaultCollation.getOwned()), _unique(unique) {} StatusWith<ShardCollectionType> ShardCollectionType::fromBSON(const BSONObj& source) { - NamespaceString uuid; - { - std::string ns; - Status status = bsonExtractStringField(source, ShardCollectionType::uuid.name(), &ns); - if (!status.isOK()) - return status; - uuid = NamespaceString{ns}; - } NamespaceString nss; { @@ -85,6 +77,23 @@ StatusWith<ShardCollectionType> ShardCollectionType::fromBSON(const BSONObj& sou nss = NamespaceString{ns}; } + boost::optional<UUID> uuid; + { + BSONElement uuidElem; + Status status = bsonExtractTypedField( + source, ShardCollectionType::uuid.name(), BSONType::BinData, &uuidElem); + if (status.isOK()) { + auto uuidWith = UUID::parse(uuidElem); + if (!uuidWith.isOK()) + return uuidWith.getStatus(); + uuid = uuidWith.getValue(); + } else if (status == ErrorCodes::NoSuchKey) { + // The field is not set, which is okay. + } else { + return status; + } + } + OID epoch; { BSONElement oidElem; @@ -134,7 +143,8 @@ StatusWith<ShardCollectionType> ShardCollectionType::fromBSON(const BSONObj& sou } } - ShardCollectionType shardCollectionType(uuid, nss, epoch, pattern, collation, unique); + ShardCollectionType shardCollectionType( + std::move(nss), uuid, std::move(epoch), pattern, collation, unique); // Below are optional fields. @@ -170,8 +180,10 @@ StatusWith<ShardCollectionType> ShardCollectionType::fromBSON(const BSONObj& sou BSONObj ShardCollectionType::toBSON() const { BSONObjBuilder builder; - builder.append(uuid.name(), _uuid.ns()); builder.append(ns.name(), _nss.ns()); + if (_uuid) { + _uuid->appendToBuilder(&builder, uuid.name()); + } builder.append(epoch.name(), _epoch); builder.append(keyPattern.name(), _keyPattern.toBSON()); @@ -196,19 +208,18 @@ std::string ShardCollectionType::toString() const { return toBSON().toString(); } -void ShardCollectionType::setUUID(const NamespaceString& uuid) { - invariant(uuid.isValid()); +void ShardCollectionType::setUUID(UUID uuid) { _uuid = uuid; } -void ShardCollectionType::setNss(const NamespaceString& nss) { +void ShardCollectionType::setNss(NamespaceString nss) { invariant(nss.isValid()); - _nss = nss; + _nss = std::move(nss); } -void ShardCollectionType::setEpoch(const OID& epoch) { +void ShardCollectionType::setEpoch(OID epoch) { invariant(epoch.isSet()); - _epoch = epoch; + _epoch = std::move(epoch); } void ShardCollectionType::setKeyPattern(const KeyPattern& keyPattern) { diff --git a/src/mongo/s/catalog/type_shard_collection.h b/src/mongo/s/catalog/type_shard_collection.h index aa17812e980..8129943ade0 100644 --- a/src/mongo/s/catalog/type_shard_collection.h +++ b/src/mongo/s/catalog/type_shard_collection.h @@ -35,6 +35,7 @@ #include "mongo/db/keypattern.h" #include "mongo/db/namespace_string.h" #include "mongo/s/chunk_version.h" +#include "mongo/util/uuid.h" namespace mongo { @@ -50,8 +51,8 @@ class StatusWith; * * Expected shard server config.collections collection format: * { - * "_id" : "foo.bar", // will become UUID when available - * "ns" : "foo.bar", + * "_id" : "foo.bar", + * "uuid" : UUID, // optional in 3.6 * "epoch" : ObjectId("58b6fd76132358839e409e47"), // will remove when UUID becomes available * "key" : { * "_id" : 1 @@ -60,8 +61,8 @@ class StatusWith; * "locale" : "fr_CA" * }, * "unique" : false, - * "refreshing" : true, - * "lastRefreshedCollectionVersion" : Timestamp(1, 0) + * "refreshing" : true, // optional + * "lastRefreshedCollectionVersion" : Timestamp(1, 0) // optional * } * */ @@ -70,8 +71,8 @@ public: // Name of the collections collection on the shard server. static const std::string ConfigNS; - static const BSONField<std::string> uuid; - static const BSONField<std::string> ns; + static const BSONField<std::string> ns; // "_id" + static const BSONField<UUID> uuid; static const BSONField<OID> epoch; static const BSONField<BSONObj> keyPattern; static const BSONField<BSONObj> defaultCollation; @@ -79,12 +80,12 @@ public: static const BSONField<bool> refreshing; static const BSONField<Date_t> lastRefreshedCollectionVersion; - explicit ShardCollectionType(const NamespaceString& uuid, - const NamespaceString& nss, - const OID& epoch, - const KeyPattern& keyPattern, - const BSONObj& defaultCollation, - const bool& unique); + ShardCollectionType(NamespaceString nss, + boost::optional<UUID> uuid, + OID epoch, + const KeyPattern& keyPattern, + const BSONObj& defaultCollation, + bool unique); /** * Constructs a new ShardCollectionType object from BSON. Also does validation of the contents. @@ -101,20 +102,20 @@ public: */ std::string toString() const; - const NamespaceString& getUUID() const { - return _uuid; - } - void setUUID(const NamespaceString& uuid); - const NamespaceString& getNss() const { return _nss; } - void setNss(const NamespaceString& nss); + void setNss(NamespaceString nss); + + const boost::optional<UUID> getUUID() const { + return _uuid; + } + void setUUID(UUID uuid); const OID& getEpoch() const { return _epoch; } - void setEpoch(const OID& epoch); + void setEpoch(OID epoch); const KeyPattern& getKeyPattern() const { return _keyPattern; @@ -152,12 +153,12 @@ public: } private: - // Will become the UUID when available. Currently a duplicate of '_nss'. - NamespaceString _uuid; - // The full namespace (with the database prefix). NamespaceString _nss; + // The UUID of the collection, if known. + boost::optional<UUID> _uuid; + // Uniquely identifies this instance of the collection, in case of drop/create. OID _epoch; diff --git a/src/mongo/s/catalog/type_shard_collection_test.cpp b/src/mongo/s/catalog/type_shard_collection_test.cpp index 51a8b6758ca..5d31d5940ad 100644 --- a/src/mongo/s/catalog/type_shard_collection_test.cpp +++ b/src/mongo/s/catalog/type_shard_collection_test.cpp @@ -48,11 +48,12 @@ const BSONObj kDefaultCollation = BSON("locale" TEST(ShardCollectionType, ToFromBSON) { const OID epoch = OID::gen(); + const UUID uuid = UUID::gen(); const ChunkVersion lastRefreshedCollectionVersion(2, 0, epoch); BSONObjBuilder builder; - builder.append(ShardCollectionType::uuid.name(), kNss.ns()); builder.append(ShardCollectionType::ns.name(), kNss.ns()); + uuid.appendToBuilder(&builder, ShardCollectionType::uuid.name()); builder.append(ShardCollectionType::epoch(), epoch); builder.append(ShardCollectionType::keyPattern.name(), kKeyPattern); builder.append(ShardCollectionType::defaultCollation(), kDefaultCollation); @@ -64,8 +65,9 @@ TEST(ShardCollectionType, ToFromBSON) { ShardCollectionType shardCollectionType = assertGet(ShardCollectionType::fromBSON(obj)); - ASSERT_EQUALS(shardCollectionType.getUUID(), kNss); ASSERT_EQUALS(shardCollectionType.getNss(), kNss); + ASSERT(shardCollectionType.getUUID()); + ASSERT_EQUALS(*shardCollectionType.getUUID(), uuid); ASSERT_EQUALS(shardCollectionType.getEpoch(), epoch); ASSERT_BSONOBJ_EQ(shardCollectionType.getKeyPattern().toBSON(), kKeyPattern); ASSERT_BSONOBJ_EQ(shardCollectionType.getDefaultCollation(), kDefaultCollation); @@ -81,7 +83,6 @@ TEST(ShardCollectionType, ToFromShardBSONWithoutOptionals) { const OID epoch = OID::gen(); BSONObjBuilder builder; - builder.append(ShardCollectionType::uuid.name(), kNss.ns()); builder.append(ShardCollectionType::ns.name(), kNss.ns()); builder.append(ShardCollectionType::epoch(), epoch); builder.append(ShardCollectionType::keyPattern.name(), kKeyPattern); @@ -91,12 +92,13 @@ TEST(ShardCollectionType, ToFromShardBSONWithoutOptionals) { ShardCollectionType shardCollectionType = assertGet(ShardCollectionType::fromBSON(obj)); - ASSERT_EQUALS(shardCollectionType.getUUID(), kNss); ASSERT_EQUALS(shardCollectionType.getNss(), kNss); ASSERT_EQUALS(shardCollectionType.getEpoch(), epoch); ASSERT_BSONOBJ_EQ(shardCollectionType.getKeyPattern().toBSON(), kKeyPattern); ASSERT_BSONOBJ_EQ(shardCollectionType.getDefaultCollation(), kDefaultCollation); ASSERT_EQUALS(shardCollectionType.getUnique(), true); + ASSERT_FALSE(shardCollectionType.hasRefreshing()); + ASSERT_FALSE(shardCollectionType.hasLastRefreshedCollectionVersion()); ASSERT_BSONOBJ_EQ(obj, shardCollectionType.toBSON()); } @@ -106,38 +108,45 @@ TEST(ShardCollectionType, FromEmptyBSON) { ASSERT_FALSE(status.isOK()); } -TEST(ShardCollectionType, FromBSONNoUUIDFails) { - BSONObj obj = - BSON(ShardCollectionType::ns(kNss.ns()) << ShardCollectionType::keyPattern(kKeyPattern)); - - StatusWith<ShardCollectionType> status = ShardCollectionType::fromBSON(obj); - ASSERT_EQUALS(status.getStatus().code(), ErrorCodes::NoSuchKey); - ASSERT_STRING_CONTAINS(status.getStatus().reason(), ShardCollectionType::uuid()); +TEST(ShardCollectionType, FromBSONNoUUIDIsOK) { + BSONObjBuilder builder; + builder.append(ShardCollectionType::ns.name(), kNss.ns()); + builder.append(ShardCollectionType::epoch(), OID::gen()); + builder.append(ShardCollectionType::keyPattern(), kKeyPattern); + builder.append(ShardCollectionType::unique(), true); + StatusWith<ShardCollectionType> status = ShardCollectionType::fromBSON(builder.obj()); + ASSERT_OK(status.getStatus()); + ASSERT_FALSE(status.getValue().getUUID()); } TEST(ShardCollectionType, FromBSONNoNSFails) { - BSONObj obj = - BSON(ShardCollectionType::uuid(kNss.ns()) << ShardCollectionType::keyPattern(kKeyPattern)); - - StatusWith<ShardCollectionType> status = ShardCollectionType::fromBSON(obj); + BSONObjBuilder builder; + UUID::gen().appendToBuilder(&builder, ShardCollectionType::uuid.name()); + builder.append(ShardCollectionType::epoch(), OID::gen()); + builder.append(ShardCollectionType::keyPattern(), kKeyPattern); + builder.append(ShardCollectionType::unique(), true); + StatusWith<ShardCollectionType> status = ShardCollectionType::fromBSON(builder.obj()); ASSERT_EQUALS(status.getStatus().code(), ErrorCodes::NoSuchKey); ASSERT_STRING_CONTAINS(status.getStatus().reason(), ShardCollectionType::ns()); } TEST(ShardCollectionType, FromBSONNoEpochFails) { - BSONObj obj = BSON(ShardCollectionType::uuid(kNss.ns()) << ShardCollectionType::ns(kNss.ns())); - - StatusWith<ShardCollectionType> status = ShardCollectionType::fromBSON(obj); + BSONObjBuilder builder; + builder.append(ShardCollectionType::ns.name(), kNss.ns()); + UUID::gen().appendToBuilder(&builder, ShardCollectionType::uuid.name()); + builder.append(ShardCollectionType::keyPattern(), kKeyPattern); + builder.append(ShardCollectionType::unique(), true); + StatusWith<ShardCollectionType> status = ShardCollectionType::fromBSON(builder.obj()); ASSERT_EQUALS(status.getStatus().code(), ErrorCodes::NoSuchKey); ASSERT_STRING_CONTAINS(status.getStatus().reason(), ShardCollectionType::epoch()); } TEST(ShardCollectionType, FromBSONNoShardKeyFails) { BSONObjBuilder builder; - builder.append(ShardCollectionType::uuid.name(), kNss.ns()); builder.append(ShardCollectionType::ns.name(), kNss.ns()); + UUID::gen().appendToBuilder(&builder, ShardCollectionType::uuid.name()); builder.append(ShardCollectionType::epoch(), OID::gen()); - + builder.append(ShardCollectionType::unique(), true); StatusWith<ShardCollectionType> status = ShardCollectionType::fromBSON(builder.obj()); ASSERT_EQUALS(status.getStatus().code(), ErrorCodes::NoSuchKey); ASSERT_STRING_CONTAINS(status.getStatus().reason(), ShardCollectionType::keyPattern()); @@ -145,12 +154,11 @@ TEST(ShardCollectionType, FromBSONNoShardKeyFails) { TEST(ShardCollectionType, FromBSONNoUniqueFails) { BSONObjBuilder builder; - builder.append(ShardCollectionType::uuid.name(), kNss.ns()); builder.append(ShardCollectionType::ns.name(), kNss.ns()); + UUID::gen().appendToBuilder(&builder, ShardCollectionType::uuid.name()); builder.append(ShardCollectionType::epoch(), OID::gen()); builder.append(ShardCollectionType::keyPattern.name(), kKeyPattern); builder.append(ShardCollectionType::defaultCollation(), kDefaultCollation); - StatusWith<ShardCollectionType> status = ShardCollectionType::fromBSON(builder.obj()); ASSERT_EQUALS(status.getStatus().code(), ErrorCodes::NoSuchKey); ASSERT_STRING_CONTAINS(status.getStatus().reason(), ShardCollectionType::unique()); @@ -158,8 +166,8 @@ TEST(ShardCollectionType, FromBSONNoUniqueFails) { TEST(ShardCollectionType, FromBSONNoDefaultCollationIsOK) { BSONObjBuilder builder; - builder.append(ShardCollectionType::uuid.name(), kNss.ns()); builder.append(ShardCollectionType::ns.name(), kNss.ns()); + UUID::gen().appendToBuilder(&builder, ShardCollectionType::uuid.name()); builder.append(ShardCollectionType::epoch(), OID::gen()); builder.append(ShardCollectionType::keyPattern.name(), kKeyPattern); builder.append(ShardCollectionType::unique(), true); diff --git a/src/mongo/s/catalog_cache.cpp b/src/mongo/s/catalog_cache.cpp index 5681d0afa05..2ca85400c86 100644 --- a/src/mongo/s/catalog_cache.cpp +++ b/src/mongo/s/catalog_cache.cpp @@ -95,6 +95,7 @@ std::shared_ptr<ChunkManager> refreshCollectionRoutingInfo( return nullptr; }(); return ChunkManager::makeNew(nss, + collectionAndChunks.uuid, KeyPattern(collectionAndChunks.shardKeyPattern), std::move(defaultCollator), collectionAndChunks.shardKeyIsUnique, diff --git a/src/mongo/s/catalog_cache_loader.cpp b/src/mongo/s/catalog_cache_loader.cpp index ba81c0fe771..faa433d4d1c 100644 --- a/src/mongo/s/catalog_cache_loader.cpp +++ b/src/mongo/s/catalog_cache_loader.cpp @@ -41,12 +41,14 @@ const auto catalogCacheLoaderDecoration = CatalogCacheLoader::CollectionAndChangedChunks::CollectionAndChangedChunks() = default; CatalogCacheLoader::CollectionAndChangedChunks::CollectionAndChangedChunks( + boost::optional<UUID> collUuid, const OID& collEpoch, const BSONObj& collShardKeyPattern, const BSONObj& collDefaultCollation, bool collShardKeyIsUnique, std::vector<ChunkType> chunks) - : epoch(collEpoch), + : uuid(collUuid), + epoch(collEpoch), shardKeyPattern(collShardKeyPattern), defaultCollation(collDefaultCollation), shardKeyIsUnique(collShardKeyIsUnique), diff --git a/src/mongo/s/catalog_cache_loader.h b/src/mongo/s/catalog_cache_loader.h index ed16cb0f178..ebafdff76fd 100644 --- a/src/mongo/s/catalog_cache_loader.h +++ b/src/mongo/s/catalog_cache_loader.h @@ -38,6 +38,7 @@ #include "mongo/s/chunk_version.h" #include "mongo/stdx/memory.h" #include "mongo/util/concurrency/notification.h" +#include "mongo/util/uuid.h" namespace mongo { @@ -67,13 +68,15 @@ public: */ struct CollectionAndChangedChunks { CollectionAndChangedChunks(); - CollectionAndChangedChunks(const OID& collEpoch, + CollectionAndChangedChunks(boost::optional<UUID> uuid, + const OID& collEpoch, const BSONObj& collShardKeyPattern, const BSONObj& collDefaultCollation, bool collShardKeyIsUnique, std::vector<ChunkType> chunks); // Information about the entire collection + boost::optional<UUID> uuid; OID epoch; BSONObj shardKeyPattern; BSONObj defaultCollation; diff --git a/src/mongo/s/chunk_manager.cpp b/src/mongo/s/chunk_manager.cpp index a7bc21d39df..a54e311b61b 100644 --- a/src/mongo/s/chunk_manager.cpp +++ b/src/mongo/s/chunk_manager.cpp @@ -60,6 +60,7 @@ void checkAllElementsAreOfType(BSONType type, const BSONObj& o) { } // namespace ChunkManager::ChunkManager(NamespaceString nss, + boost::optional<UUID> uuid, KeyPattern shardKeyPattern, std::unique_ptr<CollatorInterface> defaultCollator, bool unique, @@ -67,6 +68,7 @@ ChunkManager::ChunkManager(NamespaceString nss, ChunkVersion collectionVersion) : _sequenceNumber(nextCMSequenceNumber.addAndFetch(1)), _nss(std::move(nss)), + _uuid(uuid), _shardKeyPattern(shardKeyPattern), _defaultCollator(std::move(defaultCollator)), _unique(unique), @@ -426,6 +428,7 @@ ChunkManager::ChunkMapViews ChunkManager::_constructChunkMapViews(const OID& epo std::shared_ptr<ChunkManager> ChunkManager::makeNew( NamespaceString nss, + boost::optional<UUID> uuid, KeyPattern shardKeyPattern, std::unique_ptr<CollatorInterface> defaultCollator, bool unique, @@ -434,6 +437,7 @@ std::shared_ptr<ChunkManager> ChunkManager::makeNew( return ChunkManager( std::move(nss), + uuid, std::move(shardKeyPattern), std::move(defaultCollator), std::move(unique), @@ -489,6 +493,7 @@ std::shared_ptr<ChunkManager> ChunkManager::makeUpdated( return std::shared_ptr<ChunkManager>( new ChunkManager(_nss, + _uuid, KeyPattern(getShardKeyPattern().getKeyPattern()), CollatorInterface::cloneCollator(getDefaultCollator()), isUnique(), diff --git a/src/mongo/s/chunk_manager.h b/src/mongo/s/chunk_manager.h index bb2580f8b4a..51bc9df1e5c 100644 --- a/src/mongo/s/chunk_manager.h +++ b/src/mongo/s/chunk_manager.h @@ -115,6 +115,7 @@ public: * chunk version, and adhere to the requirements of the routing table update algorithm. */ static std::shared_ptr<ChunkManager> makeNew(NamespaceString nss, + boost::optional<UUID>, KeyPattern shardKeyPattern, std::unique_ptr<CollatorInterface> defaultCollator, bool unique, @@ -235,6 +236,10 @@ public: std::string toString() const; + bool uuidMatches(UUID uuid) const { + return _uuid && *_uuid == uuid; + } + private: /** * Represents a range of chunk keys [getMin(), getMax()) and the id of the shard on which they @@ -275,6 +280,7 @@ private: static ChunkMapViews _constructChunkMapViews(const OID& epoch, const ChunkMap& chunkMap); ChunkManager(NamespaceString nss, + boost::optional<UUID>, KeyPattern shardKeyPattern, std::unique_ptr<CollatorInterface> defaultCollator, bool unique, @@ -288,6 +294,9 @@ private: // Namespace to which this routing information corresponds const NamespaceString _nss; + // The invariant UUID of the collection. This is optional in 3.6, except in change streams. + const boost::optional<UUID> _uuid; + // The key pattern used to shard the collection const ShardKeyPattern _shardKeyPattern; diff --git a/src/mongo/s/config_server_catalog_cache_loader.cpp b/src/mongo/s/config_server_catalog_cache_loader.cpp index 5f5f10e316f..bd6d8964fcf 100644 --- a/src/mongo/s/config_server_catalog_cache_loader.cpp +++ b/src/mongo/s/config_server_catalog_cache_loader.cpp @@ -122,11 +122,12 @@ CollectionAndChangedChunks getChangedChunks(OperationContext* opCtx, "No chunks were found for the collection", !changedChunks.empty()); - return {coll.getEpoch(), - coll.getKeyPattern().toBSON(), - coll.getDefaultCollation(), - coll.getUnique(), - std::move(changedChunks)}; + return CollectionAndChangedChunks(coll.getUUID(), + coll.getEpoch(), + coll.getKeyPattern().toBSON(), + coll.getDefaultCollation(), + coll.getUnique(), + std::move(changedChunks)); } } // namespace diff --git a/src/mongo/util/uuid.h b/src/mongo/util/uuid.h index 87939e91e96..d5c3f7c71b3 100644 --- a/src/mongo/util/uuid.h +++ b/src/mongo/util/uuid.h @@ -180,7 +180,7 @@ public: private: UUID(const UUIDStorage& uuid) : _uuid(uuid) {} - UUIDStorage _uuid; // UUID in network byte order + UUIDStorage _uuid{}; // UUID in network byte order }; inline std::ostream& operator<<(std::ostream& s, const UUID& uuid) { |