diff options
Diffstat (limited to 'src/mongo/db/s/shard_server_catalog_cache_loader_test.cpp')
-rw-r--r-- | src/mongo/db/s/shard_server_catalog_cache_loader_test.cpp | 223 |
1 files changed, 165 insertions, 58 deletions
diff --git a/src/mongo/db/s/shard_server_catalog_cache_loader_test.cpp b/src/mongo/db/s/shard_server_catalog_cache_loader_test.cpp index 06002ad2a1c..a488c7eac41 100644 --- a/src/mongo/db/s/shard_server_catalog_cache_loader_test.cpp +++ b/src/mongo/db/s/shard_server_catalog_cache_loader_test.cpp @@ -79,7 +79,7 @@ public: /** * Sets up the _shardLoader with the results of makeFiveChunks(). */ - vector<ChunkType> setUpChunkLoaderWithFiveChunks(); + std::pair<CollectionType, vector<ChunkType>> setUpChunkLoaderWithFiveChunks(); void refreshCollectionEpochOnRemoteLoader(); @@ -199,7 +199,8 @@ CollectionType ShardServerCatalogCacheLoaderTest::makeCollectionType( return coll; } -vector<ChunkType> ShardServerCatalogCacheLoaderTest::setUpChunkLoaderWithFiveChunks() { +std::pair<CollectionType, vector<ChunkType>> +ShardServerCatalogCacheLoaderTest::setUpChunkLoaderWithFiveChunks() { ChunkVersion collectionVersion(1, 0, OID::gen(), boost::none /* timestamp */); CollectionType collectionType = makeCollectionType(collectionVersion); @@ -216,7 +217,7 @@ vector<ChunkType> ShardServerCatalogCacheLoaderTest::setUpChunkLoaderWithFiveChu ASSERT_BSONOBJ_EQ(collAndChunksRes.changedChunks[i].toShardBSON(), chunks[i].toShardBSON()); } - return chunks; + return std::pair{collectionType, std::move(chunks)}; } TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromUnshardedToUnsharded) { @@ -233,8 +234,8 @@ TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromUnshardedToUnsharded) { TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedToUnsharded) { // First set up the shard chunk loader as sharded. - - auto chunks = setUpChunkLoaderWithFiveChunks(); + auto collAndChunks = setUpChunkLoaderWithFiveChunks(); + auto& chunks = collAndChunks.second; // Then return a NamespaceNotFound error, which means the collection must have been dropped, // clearing the chunk metadata. @@ -251,8 +252,8 @@ TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedToUnsharded) { TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedAndFindNoDiff) { // First set up the shard chunk loader as sharded. - - vector<ChunkType> chunks = setUpChunkLoaderWithFiveChunks(); + auto collAndChunks = setUpChunkLoaderWithFiveChunks(); + auto& chunks = collAndChunks.second; // Then set up the remote loader to return a single document we've already seen -- indicates // there's nothing new. @@ -275,8 +276,8 @@ TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedAndFindNoDiff) { // routing table, rather than diff from a known version. TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedAndFindNoDiffRequestAll) { // First set up the shard chunk loader as sharded. - - vector<ChunkType> chunks = setUpChunkLoaderWithFiveChunks(); + auto collAndChunks = setUpChunkLoaderWithFiveChunks(); + auto& chunks = collAndChunks.second; // Then set up the remote loader to return a single document we've already seen -- indicates // there's nothing new. @@ -297,8 +298,8 @@ TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedAndFindNoDiffReq TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedAndFindDiff) { // First set up the shard chunk loader as sharded. - - vector<ChunkType> chunks = setUpChunkLoaderWithFiveChunks(); + auto collAndChunks = setUpChunkLoaderWithFiveChunks(); + auto& chunks = collAndChunks.second; // Then refresh again and find updated chunks. @@ -323,8 +324,8 @@ TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedAndFindDiff) { TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedAndFindDiffRequestAll) { // First set up the shard chunk loader as sharded. - - vector<ChunkType> chunks = setUpChunkLoaderWithFiveChunks(); + auto collAndChunks = setUpChunkLoaderWithFiveChunks(); + auto& chunks = collAndChunks.second; // First cause a remote refresh to find the updated chunks. Then wait for persistence, so that // we ensure that nothing is enqueued and the next getChunksSince call will return a predictable @@ -363,8 +364,8 @@ TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedAndFindDiffReque TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedAndFindNewEpoch) { // First set up the shard chunk loader as sharded. - - vector<ChunkType> chunks = setUpChunkLoaderWithFiveChunks(); + auto collAndChunks = setUpChunkLoaderWithFiveChunks(); + auto& chunks = collAndChunks.second; // Then refresh again and find that the collection has been dropped and recreated. @@ -389,14 +390,12 @@ TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedAndFindNewEpoch) TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedAndFindMixedChunkVersions) { // First set up the shard chunk loader as sharded. - - vector<ChunkType> chunks = setUpChunkLoaderWithFiveChunks(); + auto collAndChunks = setUpChunkLoaderWithFiveChunks(); + auto& chunks = collAndChunks.second; // Then refresh again and retrieve chunks from the config server that have mixed epoches, like // as if the chunks read yielded around a drop and recreate of the collection. - CollectionType originalCollectionType = makeCollectionType(chunks.back().getVersion()); - ChunkVersion collVersionWithNewEpoch(1, 0, OID::gen(), boost::none /* timestamp */); CollectionType collectionTypeWithNewEpoch = makeCollectionType(collVersionWithNewEpoch); vector<ChunkType> chunksWithNewEpoch = makeFiveChunks(collVersionWithNewEpoch); @@ -439,57 +438,165 @@ TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedAndFindMixedChun } } -TEST_F(ShardServerCatalogCacheLoaderTest, - PrimaryLoadFromShardedAndFindCollAndChunksMetadataFormatChanged) { +TEST_F(ShardServerCatalogCacheLoaderTest, PrimaryLoadFromShardedWithChangeOnMetadataFormat) { // First set up the shard chunk loader as sharded. - vector<ChunkType> chunks = setUpChunkLoaderWithFiveChunks(); - - // Simulating that the config server added timestamps to all chunks - { - vector<ChunkType> newChunks = chunks; - for (auto& chunk : newChunks) { - const ChunkVersion v = chunk.getVersion(); - chunk.setVersion( - ChunkVersion(v.majorVersion(), v.minorVersion(), v.epoch(), Timestamp(42))); - } - - CollectionType collectionTypeWithNewEpoch = - makeCollectionType(newChunks.back().getVersion()); - _remoteLoaderMock->setCollectionRefreshReturnValue(collectionTypeWithNewEpoch); - _remoteLoaderMock->setChunkRefreshReturnValue(newChunks); - - auto collAndChunksRes = _shardLoader->getChunksSince(kNss, newChunks[0].getVersion()).get(); - ASSERT_EQUALS(collAndChunksRes.epoch, collectionTypeWithNewEpoch.getEpoch()); - ASSERT_EQUALS(collAndChunksRes.creationTime, Timestamp(42)); + auto collAndChunks = setUpChunkLoaderWithFiveChunks(); + auto& collType = collAndChunks.first; + auto& chunks = collAndChunks.second; + + auto changeMetadataFormat = [&](const boost::optional<Timestamp>& timestamp) { + auto lastChunk = chunks.back(); + lastChunk.setVersion([&]() { + const auto v = lastChunk.getVersion(); + return ChunkVersion(v.majorVersion(), v.minorVersion(), v.epoch(), timestamp); + }()); + + collType.setTimestamp(timestamp); + _remoteLoaderMock->setCollectionRefreshReturnValue(collType); + _remoteLoaderMock->setChunkRefreshReturnValue(std::vector{lastChunk}); + + auto collAndChunksRes = _shardLoader->getChunksSince(kNss, chunks[0].getVersion()).get(); + ASSERT_EQUALS(collAndChunksRes.epoch, collType.getEpoch()); + ASSERT_EQUALS(collAndChunksRes.creationTime, timestamp); ASSERT_EQUALS(collAndChunksRes.changedChunks.size(), 5UL); for (const auto& changedChunk : collAndChunksRes.changedChunks) { - ASSERT_EQUALS(changedChunk.getVersion().getTimestamp(), Timestamp(42)); + ASSERT_EQUALS(changedChunk.getVersion().getTimestamp(), timestamp); ASSERT_EQUALS(changedChunk.getVersion().epoch(), collAndChunksRes.epoch); } + }; + + // Upgrading the metadata format to 5.0 + changeMetadataFormat(Timestamp(42)); + // Downgrading the medata format to 4.4 + changeMetadataFormat(boost::none /* timestamp */); +} + +TEST_F(ShardServerCatalogCacheLoaderTest, + PrimaryLoadFromShardedWithChangeOnMetadataFormatBecauseUpgrade) { + const auto timestamp = Timestamp(42); + ChunkVersion collectionVersion(1, 0, OID::gen(), boost::none /* timestamp */); + CollectionType collectionType = makeCollectionType(collectionVersion); + vector<ChunkType> chunks = makeFiveChunks(collectionVersion); + + // 1st refresh as if we were in 4.4: the loader discovers one new chunk without timestamp + { + _remoteLoaderMock->setCollectionRefreshReturnValue(collectionType); + _remoteLoaderMock->setChunkRefreshReturnValue(std::vector{chunks[0]}); + const auto collAndChunksRes = + _shardLoader->getChunksSince(kNss, chunks[0].getVersion()).get(); + ASSERT_EQUALS(collAndChunksRes.changedChunks.size(), 1UL); + ASSERT_EQUALS(collAndChunksRes.creationTime, boost::none); + ASSERT_EQUALS(collAndChunksRes.changedChunks[0].getVersion().getTimestamp(), boost::none); } - // Simulating that the config server removed timestamps from all chunks + // 2nd refresh as if we were in the phase 1 of the setFCV process to upgrade to 5.0: the loader + // discovers a few new chunks with timestamp but the collection doesn't have it yet. { - vector<ChunkType> newChunks = chunks; - for (auto& chunk : newChunks) { - const ChunkVersion v = chunk.getVersion(); - chunk.setVersion( - ChunkVersion(v.majorVersion(), v.minorVersion(), v.epoch(), boost::none)); + for (size_t i = 1; i < chunks.size() - 1; ++i) { + chunks[i].setVersion([&]() { + const auto v = chunks[i].getVersion(); + return ChunkVersion(v.majorVersion(), v.minorVersion(), v.epoch(), timestamp); + }()); } - CollectionType collectionTypeWithNewEpoch = - makeCollectionType(newChunks.back().getVersion()); - _remoteLoaderMock->setCollectionRefreshReturnValue(collectionTypeWithNewEpoch); - _remoteLoaderMock->setChunkRefreshReturnValue(newChunks); - - auto collAndChunksRes = _shardLoader->getChunksSince(kNss, newChunks[0].getVersion()).get(); - ASSERT_EQUALS(collAndChunksRes.epoch, collectionTypeWithNewEpoch.getEpoch()); + _remoteLoaderMock->setCollectionRefreshReturnValue(collectionType); + _remoteLoaderMock->setChunkRefreshReturnValue( + std::vector<ChunkType>(chunks.begin() + 1, chunks.end() - 1)); + const auto collAndChunksRes = + _shardLoader->getChunksSince(kNss, chunks[0].getVersion()).get(); + const auto& changedChunks = collAndChunksRes.changedChunks; + ASSERT_EQUALS(changedChunks.size(), 4UL); ASSERT_EQUALS(collAndChunksRes.creationTime, boost::none); - ASSERT_EQUALS(collAndChunksRes.changedChunks.size(), 5UL); - for (const auto& changedChunk : collAndChunksRes.changedChunks) { - ASSERT_EQUALS(changedChunk.getVersion().getTimestamp(), boost::none); - ASSERT_EQUALS(changedChunk.getVersion().epoch(), collAndChunksRes.epoch); + ASSERT_EQUALS(changedChunks[0].getVersion().getTimestamp(), boost::none); + for (size_t i = 1; i < chunks.size() - 1; ++i) + ASSERT_EQUALS(changedChunks[i].getVersion().getTimestamp(), timestamp); + } + + // 3rd refresh as if we were in 5.0: the loader discovers a new chunk. All chunks and the + // collection have timestamps. + { + chunks.back().setVersion([&]() { + const auto v = chunks.back().getVersion(); + return ChunkVersion(v.majorVersion(), v.minorVersion(), v.epoch(), timestamp); + }()); + collectionType.setTimestamp(timestamp); + + _remoteLoaderMock->setCollectionRefreshReturnValue(collectionType); + _remoteLoaderMock->setChunkRefreshReturnValue(std::vector{chunks.back()}); + const auto collAndChunksRes = + _shardLoader->getChunksSince(kNss, chunks[0].getVersion()).get(); + const auto& changedChunks = collAndChunksRes.changedChunks; + ASSERT_EQUALS(changedChunks.size(), 5UL); + ASSERT_EQUALS(collAndChunksRes.creationTime, timestamp); + for (size_t i = 0; i < chunks.size(); ++i) + ASSERT_EQUALS(changedChunks[i].getVersion().getTimestamp(), timestamp); + } +} + +TEST_F(ShardServerCatalogCacheLoaderTest, + PrimaryLoadFromShardedWithChangeOnMetadataFormatBecauseDowngrade) { + const auto timestamp = Timestamp(42); + ChunkVersion collectionVersion(1, 0, OID::gen(), timestamp); + CollectionType collectionType = makeCollectionType(collectionVersion); + vector<ChunkType> chunks = makeFiveChunks(collectionVersion); + + // 1st refresh as if we were in 5.0: the loader discovers one new chunk with timestamp. The + // collection also has timestamps. + { + _remoteLoaderMock->setCollectionRefreshReturnValue(collectionType); + _remoteLoaderMock->setChunkRefreshReturnValue(std::vector{chunks[0]}); + const auto collAndChunksRes = + _shardLoader->getChunksSince(kNss, chunks[0].getVersion()).get(); + ASSERT_EQUALS(collAndChunksRes.changedChunks.size(), 1UL); + ASSERT_EQUALS(collAndChunksRes.creationTime, timestamp); + ASSERT_EQUALS(collAndChunksRes.changedChunks[0].getVersion().getTimestamp(), timestamp); + } + + // 2nd refresh: the loader discovers a few new chunks without timestamp but the collection still + // has it. + { + for (size_t i = 1; i < chunks.size() - 1; ++i) { + chunks[i].setVersion([&]() { + const auto v = chunks[i].getVersion(); + return ChunkVersion( + v.majorVersion(), v.minorVersion(), v.epoch(), boost::none /* timestamp */); + }()); } + + _remoteLoaderMock->setCollectionRefreshReturnValue(collectionType); + _remoteLoaderMock->setChunkRefreshReturnValue( + std::vector<ChunkType>(chunks.begin() + 1, chunks.end() - 1)); + const auto collAndChunksRes = + _shardLoader->getChunksSince(kNss, chunks[0].getVersion()).get(); + const auto& changedChunks = collAndChunksRes.changedChunks; + ASSERT_EQUALS(changedChunks.size(), 4UL); + ASSERT_EQUALS(collAndChunksRes.creationTime, timestamp); + ASSERT_EQUALS(changedChunks[0].getVersion().getTimestamp(), timestamp); + for (size_t i = 1; i < chunks.size() - 1; ++i) + ASSERT_EQUALS(changedChunks[i].getVersion().getTimestamp(), + boost::none /* timestamp */); + } + + // 3rd refresh as if we were in 4.4: the loader discovers a new chunk. All chunks and the + // collection don't have timestamps. + { + chunks.back().setVersion([&]() { + const auto v = chunks.back().getVersion(); + return ChunkVersion( + v.majorVersion(), v.minorVersion(), v.epoch(), boost::none /* timestamp */); + }()); + collectionType.setTimestamp(boost::none /* timestamp */); + + _remoteLoaderMock->setCollectionRefreshReturnValue(collectionType); + _remoteLoaderMock->setChunkRefreshReturnValue(std::vector{chunks.back()}); + const auto collAndChunksRes = + _shardLoader->getChunksSince(kNss, chunks[0].getVersion()).get(); + const auto& changedChunks = collAndChunksRes.changedChunks; + ASSERT_EQUALS(changedChunks.size(), 5UL); + ASSERT_EQUALS(collAndChunksRes.creationTime, boost::none /* timestamp */); + for (size_t i = 0; i < chunks.size(); ++i) + ASSERT_EQUALS(changedChunks[i].getVersion().getTimestamp(), + boost::none /* timestamp */); } } |