diff options
Diffstat (limited to 'src/mongo/db/s/collection_range_deleter_test.cpp')
-rw-r--r-- | src/mongo/db/s/collection_range_deleter_test.cpp | 298 |
1 files changed, 123 insertions, 175 deletions
diff --git a/src/mongo/db/s/collection_range_deleter_test.cpp b/src/mongo/db/s/collection_range_deleter_test.cpp index 2927379ff1c..a5b4813d5e6 100644 --- a/src/mongo/db/s/collection_range_deleter_test.cpp +++ b/src/mongo/db/s/collection_range_deleter_test.cpp @@ -30,55 +30,84 @@ #include "mongo/db/s/collection_range_deleter.h" +#include "mongo/bson/bsonobj.h" +#include "mongo/bson/bsonobjbuilder.h" #include "mongo/client/query.h" +#include "mongo/client/remote_command_targeter_mock.h" #include "mongo/db/client.h" #include "mongo/db/db_raii.h" #include "mongo/db/dbdirectclient.h" +#include "mongo/db/index/index_descriptor.h" #include "mongo/db/keypattern.h" #include "mongo/db/repl/replication_coordinator_global.h" #include "mongo/db/repl/replication_coordinator_mock.h" #include "mongo/db/s/collection_sharding_state.h" #include "mongo/db/s/sharding_state.h" #include "mongo/db/service_context_d_test_fixture.h" +#include "mongo/s/catalog/dist_lock_catalog_impl.h" +#include "mongo/s/catalog/dist_lock_manager_mock.h" +#include "mongo/s/catalog/sharding_catalog_client_mock.h" #include "mongo/s/chunk_version.h" +#include "mongo/s/client/shard_registry.h" +#include "mongo/s/sharding_mongod_test_fixture.h" namespace mongo { using unittest::assertGet; - -const NamespaceString kNamespaceString = NamespaceString("foo", "bar"); +const NamespaceString kNss = NamespaceString("foo", "bar"); const std::string kPattern = "_id"; const BSONObj kKeyPattern = BSON(kPattern << 1); +const std::string kShardName{"a"}; +const HostAndPort dummyHost("dummy", 123); -class CollectionRangeDeleterTest : public ServiceContextMongoDTest { +class CollectionRangeDeleterTest : public ShardingMongodTestFixture { protected: - ServiceContext::UniqueOperationContext _opCtx; - MetadataManager* _metadataManager; - std::unique_ptr<DBDirectClient> _dbDirectClient; + bool next(CollectionRangeDeleter& rangeDeleter, int maxToDelete) { + return CollectionRangeDeleter::cleanUpNextRange( + operationContext(), kNss, maxToDelete, &rangeDeleter); + } + std::shared_ptr<RemoteCommandTargeterMock> configTargeter() { + return RemoteCommandTargeterMock::get(shardRegistry()->getConfigShard()->getTargeter()); + } - OperationContext* operationContext(); private: void setUp() override; void tearDown() override; + + std::unique_ptr<DistLockCatalog> makeDistLockCatalog(ShardRegistry* shardRegistry) override { + invariant(shardRegistry); + return stdx::make_unique<DistLockCatalogImpl>(shardRegistry); + } + + std::unique_ptr<DistLockManager> makeDistLockManager( + std::unique_ptr<DistLockCatalog> distLockCatalog) override { + return stdx::make_unique<DistLockManagerMock>(std::move(distLockCatalog)); + } + + std::unique_ptr<ShardingCatalogClient> makeShardingCatalogClient( + std::unique_ptr<DistLockManager> distLockManager) override { + return stdx::make_unique<ShardingCatalogClientMock>(std::move(distLockManager)); + } }; void CollectionRangeDeleterTest::setUp() { - ServiceContextMongoDTest::setUp(); - const repl::ReplSettings replSettings = {}; - repl::setGlobalReplicationCoordinator( - new repl::ReplicationCoordinatorMock(getServiceContext(), replSettings)); - repl::getGlobalReplicationCoordinator()->setFollowerMode(repl::MemberState::RS_PRIMARY); - _opCtx = getServiceContext()->makeOperationContext(&cc()); - _dbDirectClient = stdx::make_unique<DBDirectClient>(operationContext()); + serverGlobalParams.clusterRole = ClusterRole::ShardServer; + ShardingMongodTestFixture::setUp(); + replicationCoordinator()->alwaysAllowWrites(true); + initializeGlobalShardingStateForMongodForTest(ConnectionString(dummyHost)); + // RemoteCommandTargeterMock::get(shardRegistry()->getConfigShard()->getTargeter()) + // ->setConnectionStringReturnValue(kConfigConnStr); + + configTargeter()->setFindHostReturnValue(dummyHost); + + DBDirectClient(operationContext()).createCollection(kNss.ns()); { + AutoGetCollection autoColl(operationContext(), kNss, MODE_IX); + auto collectionShardingState = CollectionShardingState::get(operationContext(), kNss); const OID epoch = OID::gen(); - - AutoGetCollection autoColl(operationContext(), kNamespaceString, MODE_IX); - auto collectionShardingState = - CollectionShardingState::get(operationContext(), kNamespaceString); collectionShardingState->refreshMetadata( operationContext(), stdx::make_unique<CollectionMetadata>( @@ -86,208 +115,127 @@ void CollectionRangeDeleterTest::setUp() { ChunkVersion(1, 0, epoch), ChunkVersion(0, 0, epoch), SimpleBSONObjComparator::kInstance.makeBSONObjIndexedMap<CachedChunkInfo>())); - _metadataManager = collectionShardingState->getMetadataManagerForTest(); } } void CollectionRangeDeleterTest::tearDown() { { - AutoGetCollection autoColl(operationContext(), kNamespaceString, MODE_IX); - auto collectionShardingState = - CollectionShardingState::get(operationContext(), kNamespaceString); + AutoGetCollection autoColl(operationContext(), kNss, MODE_IX); + auto collectionShardingState = CollectionShardingState::get(operationContext(), kNss); collectionShardingState->refreshMetadata(operationContext(), nullptr); } - _dbDirectClient.reset(); - _opCtx.reset(); - ServiceContextMongoDTest::tearDown(); - repl::setGlobalReplicationCoordinator(nullptr); -} - -OperationContext* CollectionRangeDeleterTest::operationContext() { - invariant(_opCtx); - return _opCtx.get(); + ShardingMongodTestFixture::tearDown(); } namespace { // Tests the case that there is nothing in the database. TEST_F(CollectionRangeDeleterTest, EmptyDatabase) { - CollectionRangeDeleter rangeDeleter(kNamespaceString); - ASSERT_FALSE(rangeDeleter.cleanupNextRange(operationContext(), 1)); + CollectionRangeDeleter rangeDeleter; + ASSERT_FALSE(next(rangeDeleter, 1)); } // Tests the case that there is data, but it is not in a range to clean. TEST_F(CollectionRangeDeleterTest, NoDataInGivenRangeToClean) { - CollectionRangeDeleter rangeDeleter(kNamespaceString); + CollectionRangeDeleter rangeDeleter; const BSONObj insertedDoc = BSON(kPattern << 25); + DBDirectClient dbclient(operationContext()); + dbclient.insert(kNss.toString(), insertedDoc); + ASSERT_BSONOBJ_EQ(insertedDoc, dbclient.findOne(kNss.toString(), QUERY(kPattern << 25))); - _dbDirectClient->insert(kNamespaceString.toString(), insertedDoc); - ASSERT_BSONOBJ_EQ(insertedDoc, - _dbDirectClient->findOne(kNamespaceString.toString(), QUERY(kPattern << 25))); + rangeDeleter.add(ChunkRange(BSON(kPattern << 0), BSON(kPattern << 10))); + ASSERT_TRUE(next(rangeDeleter, 1)); - _metadataManager->addRangeToClean(ChunkRange(BSON(kPattern << 0), BSON(kPattern << 10))); - ASSERT_FALSE(rangeDeleter.cleanupNextRange(operationContext(), 1)); + ASSERT_BSONOBJ_EQ(insertedDoc, dbclient.findOne(kNss.toString(), QUERY(kPattern << 25))); - ASSERT_BSONOBJ_EQ(insertedDoc, - _dbDirectClient->findOne(kNamespaceString.toString(), QUERY(kPattern << 25))); + ASSERT_FALSE(next(rangeDeleter, 1)); } // Tests the case that there is a single document within a range to clean. TEST_F(CollectionRangeDeleterTest, OneDocumentInOneRangeToClean) { - CollectionRangeDeleter rangeDeleter(kNamespaceString); + CollectionRangeDeleter rangeDeleter; const BSONObj insertedDoc = BSON(kPattern << 5); + DBDirectClient dbclient(operationContext()); + dbclient.insert(kNss.toString(), BSON(kPattern << 5)); + ASSERT_BSONOBJ_EQ(insertedDoc, dbclient.findOne(kNss.toString(), QUERY(kPattern << 5))); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 5)); - ASSERT_BSONOBJ_EQ(insertedDoc, - _dbDirectClient->findOne(kNamespaceString.toString(), QUERY(kPattern << 5))); - - _metadataManager->addRangeToClean(ChunkRange(BSON(kPattern << 0), BSON(kPattern << 10))); + rangeDeleter.add(ChunkRange(BSON(kPattern << 0), BSON(kPattern << 10))); - ASSERT_TRUE(rangeDeleter.cleanupNextRange(operationContext(), 1)); - ASSERT_TRUE( - _dbDirectClient->findOne(kNamespaceString.toString(), QUERY(kPattern << 5)).isEmpty()); - - ASSERT_FALSE(rangeDeleter.cleanupNextRange(operationContext(), 1)); + ASSERT_TRUE(next(rangeDeleter, 1)); + ASSERT_TRUE(next(rangeDeleter, 1)); + ASSERT_TRUE(dbclient.findOne(kNss.toString(), QUERY(kPattern << 5)).isEmpty()); + ASSERT_FALSE(next(rangeDeleter, 1)); } // Tests the case that there are multiple documents within a range to clean. TEST_F(CollectionRangeDeleterTest, MultipleDocumentsInOneRangeToClean) { - CollectionRangeDeleter rangeDeleter(kNamespaceString); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 1)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 2)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 3)); - ASSERT_EQUALS(3ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 5))); - - _metadataManager->addRangeToClean(ChunkRange(BSON(kPattern << 0), BSON(kPattern << 10))); - - ASSERT_TRUE(rangeDeleter.cleanupNextRange(operationContext(), 100)); - ASSERT_EQUALS(0ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 5))); - - ASSERT_FALSE(rangeDeleter.cleanupNextRange(operationContext(), 100)); + CollectionRangeDeleter rangeDeleter; + DBDirectClient dbclient(operationContext()); + dbclient.insert(kNss.toString(), BSON(kPattern << 1)); + dbclient.insert(kNss.toString(), BSON(kPattern << 2)); + dbclient.insert(kNss.toString(), BSON(kPattern << 3)); + ASSERT_EQUALS(3ULL, dbclient.count(kNss.toString(), BSON(kPattern << LT << 5))); + + rangeDeleter.add(ChunkRange(BSON(kPattern << 0), BSON(kPattern << 10))); + + ASSERT_TRUE(next(rangeDeleter, 100)); + ASSERT_TRUE(next(rangeDeleter, 100)); + ASSERT_EQUALS(0ULL, dbclient.count(kNss.toString(), BSON(kPattern << LT << 5))); + ASSERT_FALSE(next(rangeDeleter, 100)); } // Tests the case that there are multiple documents within a range to clean, and the range deleter // has a max deletion rate of one document per run. -TEST_F(CollectionRangeDeleterTest, MultipleCleanupNextRangeCallsToCleanOneRange) { - CollectionRangeDeleter rangeDeleter(kNamespaceString); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 1)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 2)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 3)); - ASSERT_EQUALS(3ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 5))); - - _metadataManager->addRangeToClean(ChunkRange(BSON(kPattern << 0), BSON(kPattern << 10))); - - ASSERT_TRUE(rangeDeleter.cleanupNextRange(operationContext(), 1)); - ASSERT_EQUALS(2ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 5))); - - ASSERT_TRUE(rangeDeleter.cleanupNextRange(operationContext(), 1)); - ASSERT_EQUALS(1ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 5))); - - ASSERT_TRUE(rangeDeleter.cleanupNextRange(operationContext(), 1)); - ASSERT_EQUALS(0ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 5))); - - ASSERT_FALSE(rangeDeleter.cleanupNextRange(operationContext(), 1)); +TEST_F(CollectionRangeDeleterTest, MultipleCleanupNextRangeCalls) { + CollectionRangeDeleter rangeDeleter; + DBDirectClient dbclient(operationContext()); + dbclient.insert(kNss.toString(), BSON(kPattern << 1)); + dbclient.insert(kNss.toString(), BSON(kPattern << 2)); + dbclient.insert(kNss.toString(), BSON(kPattern << 3)); + ASSERT_EQUALS(3ULL, dbclient.count(kNss.toString(), BSON(kPattern << LT << 5))); + + rangeDeleter.add(ChunkRange(BSON(kPattern << 0), BSON(kPattern << 10))); + + ASSERT_TRUE(next(rangeDeleter, 1)); + ASSERT_EQUALS(2ULL, dbclient.count(kNss.toString(), BSON(kPattern << LT << 5))); + + ASSERT_TRUE(next(rangeDeleter, 1)); + ASSERT_EQUALS(1ULL, dbclient.count(kNss.toString(), BSON(kPattern << LT << 5))); + + ASSERT_TRUE(next(rangeDeleter, 1)); + ASSERT_TRUE(next(rangeDeleter, 1)); + ASSERT_EQUALS(0ULL, dbclient.count(kNss.toString(), BSON(kPattern << LT << 5))); + ASSERT_FALSE(next(rangeDeleter, 1)); } // Tests the case that there are two ranges to clean, each containing multiple documents. TEST_F(CollectionRangeDeleterTest, MultipleDocumentsInMultipleRangesToClean) { - CollectionRangeDeleter rangeDeleter(kNamespaceString); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 1)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 2)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 3)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 4)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 5)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 6)); - ASSERT_EQUALS(6ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 10))); + CollectionRangeDeleter rangeDeleter; + DBDirectClient dbclient(operationContext()); + dbclient.insert(kNss.toString(), BSON(kPattern << 1)); + dbclient.insert(kNss.toString(), BSON(kPattern << 2)); + dbclient.insert(kNss.toString(), BSON(kPattern << 3)); + dbclient.insert(kNss.toString(), BSON(kPattern << 4)); + dbclient.insert(kNss.toString(), BSON(kPattern << 5)); + dbclient.insert(kNss.toString(), BSON(kPattern << 6)); + ASSERT_EQUALS(6ULL, dbclient.count(kNss.toString(), BSON(kPattern << LT << 10))); const ChunkRange chunkRange1 = ChunkRange(BSON(kPattern << 0), BSON(kPattern << 4)); const ChunkRange chunkRange2 = ChunkRange(BSON(kPattern << 4), BSON(kPattern << 7)); - _metadataManager->addRangeToClean(chunkRange1); - _metadataManager->addRangeToClean(chunkRange2); - - ASSERT_TRUE(rangeDeleter.cleanupNextRange(operationContext(), 100)); - ASSERT_EQUALS(0ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 4))); - ASSERT_EQUALS(3ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 10))); - - ASSERT_TRUE(rangeDeleter.cleanupNextRange(operationContext(), 100)); - ASSERT_TRUE(rangeDeleter.cleanupNextRange(operationContext(), 100)); - ASSERT_EQUALS(0ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 10))); - - ASSERT_FALSE(rangeDeleter.cleanupNextRange(operationContext(), 1)); -} - -// Tests the case that there is a range to clean, and halfway through a deletion a chunk -// within the range is received -TEST_F(CollectionRangeDeleterTest, MultipleCallstoCleanupNextRangeWithChunkReceive) { - CollectionRangeDeleter rangeDeleter(kNamespaceString); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 1)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 2)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 3)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 4)); - const BSONObj insertedDoc5 = BSON(kPattern << 5); // not to be deleted - _dbDirectClient->insert(kNamespaceString.toString(), insertedDoc5); - ASSERT_EQUALS(5ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 10))); - - _metadataManager->addRangeToClean(ChunkRange(BSON(kPattern << 0), BSON(kPattern << 10))); - - ASSERT_TRUE(rangeDeleter.cleanupNextRange(operationContext(), 2)); - ASSERT_EQUALS(3ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 10))); - - _metadataManager->beginReceive(ChunkRange(BSON(kPattern << 5), BSON(kPattern << 6))); - - // insertedDoc5 is no longer eligible for deletion - - ASSERT_TRUE(rangeDeleter.cleanupNextRange(operationContext(), 2)); - ASSERT_EQUALS(1ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 10))); - - ASSERT_TRUE(rangeDeleter.cleanupNextRange(operationContext(), 2)); - ASSERT_EQUALS(1ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 10))); - - ASSERT_FALSE(rangeDeleter.cleanupNextRange(operationContext(), 2)); - - ASSERT_BSONOBJ_EQ( - insertedDoc5, - _dbDirectClient->findOne(kNamespaceString.toString(), QUERY(kPattern << GT << 0))); -} - -TEST_F(CollectionRangeDeleterTest, CalltoCleanupNextRangeWithChunkReceive) { - CollectionRangeDeleter rangeDeleter(kNamespaceString); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 1)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 2)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 3)); - _dbDirectClient->insert(kNamespaceString.toString(), BSON(kPattern << 4)); - ASSERT_EQUALS(4ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 10))); - - _metadataManager->addRangeToClean(ChunkRange(BSON(kPattern << 0), BSON(kPattern << 10))); - - ASSERT_TRUE(rangeDeleter.cleanupNextRange(operationContext(), 2)); - ASSERT_EQUALS(2ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 10))); - - _metadataManager->beginReceive(ChunkRange(BSON(kPattern << 0), BSON(kPattern << 10))); - - ASSERT_FALSE(rangeDeleter.cleanupNextRange(operationContext(), 2)); - - ASSERT_EQUALS(2ULL, - _dbDirectClient->count(kNamespaceString.toString(), BSON(kPattern << LT << 10))); + rangeDeleter.add(chunkRange1); + rangeDeleter.add(chunkRange2); + + ASSERT_TRUE(next(rangeDeleter, 100)); + ASSERT_EQUALS(0ULL, dbclient.count(kNss.toString(), BSON(kPattern << LT << 4))); + ASSERT_EQUALS(3ULL, dbclient.count(kNss.toString(), BSON(kPattern << LT << 10))); + + ASSERT_TRUE(next(rangeDeleter, 100)); // discover there are no more < 4, pop range 1 + ASSERT_TRUE(next(rangeDeleter, 100)); // delete the remaining documents + ASSERT_TRUE(next(rangeDeleter, 1)); // discover there are no more, pop range 2 + ASSERT_EQUALS(0ULL, dbclient.count(kNss.toString(), BSON(kPattern << LT << 10))); + ASSERT_FALSE(next(rangeDeleter, 1)); // discover there are no more ranges } } // unnamed namespace - } // namespace mongo |