diff options
author | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2016-10-11 17:05:02 -0400 |
---|---|---|
committer | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2016-10-18 15:58:56 -0400 |
commit | a0fd9c9714cdcd6be7eae05c31a578c17ed6d780 (patch) | |
tree | 0d105fa6a407c40bdbf106668c48b3e63cbb799e /src/mongo/db/s | |
parent | cc8e8a138b7116ddd2b6eff56da2f4219262e837 (diff) | |
download | mongo-a0fd9c9714cdcd6be7eae05c31a578c17ed6d780.tar.gz |
SERVER-25665 Persist chunk version as part of the active migration document
Diffstat (limited to 'src/mongo/db/s')
-rw-r--r-- | src/mongo/db/s/balancer/balancer.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/s/balancer/balancer_chunk_selection_policy_impl.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/s/balancer/balancer_policy.cpp | 27 | ||||
-rw-r--r-- | src/mongo/db/s/balancer/balancer_policy.h | 24 | ||||
-rw-r--r-- | src/mongo/db/s/balancer/balancer_policy_test.cpp | 15 | ||||
-rw-r--r-- | src/mongo/db/s/balancer/migration_manager_test.cpp | 87 | ||||
-rw-r--r-- | src/mongo/db/s/balancer/scoped_migration_request.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/s/balancer/scoped_migration_request_test.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/s/balancer/type_migration.cpp | 54 | ||||
-rw-r--r-- | src/mongo/db/s/balancer/type_migration.h | 15 | ||||
-rw-r--r-- | src/mongo/db/s/balancer/type_migration_test.cpp | 37 |
11 files changed, 155 insertions, 117 deletions
diff --git a/src/mongo/db/s/balancer/balancer.cpp b/src/mongo/db/s/balancer/balancer.cpp index 1cc7d850ada..d2d6f3cc261 100644 --- a/src/mongo/db/s/balancer/balancer.cpp +++ b/src/mongo/db/s/balancer/balancer.cpp @@ -275,11 +275,8 @@ Status Balancer::moveSingleChunk(OperationContext* txn, return moveAllowedStatus; } - return _migrationManager.executeManualMigration(txn, - MigrateInfo(chunk.getNS(), newShardId, chunk), - maxChunkSizeBytes, - secondaryThrottle, - waitForDelete); + return _migrationManager.executeManualMigration( + txn, MigrateInfo(newShardId, chunk), maxChunkSizeBytes, secondaryThrottle, waitForDelete); } void Balancer::report(OperationContext* txn, BSONObjBuilder* builder) { diff --git a/src/mongo/db/s/balancer/balancer_chunk_selection_policy_impl.cpp b/src/mongo/db/s/balancer/balancer_chunk_selection_policy_impl.cpp index 2dc4f48bddf..ef688f73dab 100644 --- a/src/mongo/db/s/balancer/balancer_chunk_selection_policy_impl.cpp +++ b/src/mongo/db/s/balancer/balancer_chunk_selection_policy_impl.cpp @@ -76,6 +76,7 @@ StatusWith<DistributionStatus> createCollectionDistributionStatus( const auto& chunkEntry = entry.second; ChunkType chunk; + chunk.setNS(chunkMgr->getns()); chunk.setMin(chunkEntry->getMin()); chunk.setMax(chunkEntry->getMax()); chunk.setJumbo(chunkEntry->isJumbo()); diff --git a/src/mongo/db/s/balancer/balancer_policy.cpp b/src/mongo/db/s/balancer/balancer_policy.cpp index 5b53cfc0320..ea8365f6524 100644 --- a/src/mongo/db/s/balancer/balancer_policy.cpp +++ b/src/mongo/db/s/balancer/balancer_policy.cpp @@ -143,7 +143,8 @@ Status DistributionStatus::addRangeToZone(const ZoneRange& range) { } } - _zoneRanges[range.max.getOwned()] = range; + // This must be a new entry + _zoneRanges.emplace(range.max.getOwned(), range); _allTags.insert(range.zone); return Status::OK(); } @@ -337,7 +338,7 @@ vector<MigrateInfo> BalancerPolicy::balance(const ShardStatisticsVector& shardSt } invariant(to != stat.shardId); - migrations.emplace_back(distribution.nss().ns(), to, chunk); + migrations.emplace_back(to, chunk); invariant(usedShards.insert(stat.shardId).second); invariant(usedShards.insert(to).second); break; @@ -384,7 +385,7 @@ vector<MigrateInfo> BalancerPolicy::balance(const ShardStatisticsVector& shardSt } invariant(to != stat.shardId); - migrations.emplace_back(distribution.nss().ns(), to, chunk); + migrations.emplace_back(to, chunk); invariant(usedShards.insert(stat.shardId).second); invariant(usedShards.insert(to).second); break; @@ -421,7 +422,7 @@ boost::optional<MigrateInfo> BalancerPolicy::balanceSingleChunk( return boost::optional<MigrateInfo>(); } - return MigrateInfo(distribution.nss().ns(), newShardId, chunk); + return MigrateInfo(newShardId, chunk); } bool BalancerPolicy::_singleZoneBalance(const ShardStatisticsVector& shardStats, @@ -500,7 +501,7 @@ bool BalancerPolicy::_singleZoneBalance(const ShardStatisticsVector& shardStats, continue; } - migrations->emplace_back(distribution.nss().ns(), to, chunk); + migrations->emplace_back(to, chunk); invariant(usedShards->insert(chunk.getShard()).second); invariant(usedShards->insert(to).second); return true; @@ -515,10 +516,26 @@ bool BalancerPolicy::_singleZoneBalance(const ShardStatisticsVector& shardStats, return false; } +ZoneRange::ZoneRange(const BSONObj& a_min, const BSONObj& a_max, const std::string& _zone) + : min(a_min.getOwned()), max(a_max.getOwned()), zone(_zone) {} + string ZoneRange::toString() const { return str::stream() << min << " -->> " << max << " on " << zone; } +MigrateInfo::MigrateInfo(const ShardId& a_to, const ChunkType& a_chunk) { + invariantOK(a_chunk.validate()); + invariant(a_to.isValid()); + + to = a_to; + + ns = a_chunk.getNS(); + from = a_chunk.getShard(); + minKey = a_chunk.getMin(); + maxKey = a_chunk.getMax(); + version = a_chunk.getVersion(); +} + std::string MigrateInfo::getName() const { return ChunkType::genID(ns, minKey); } diff --git a/src/mongo/db/s/balancer/balancer_policy.h b/src/mongo/db/s/balancer/balancer_policy.h index c1438ba995e..c08aee77ceb 100644 --- a/src/mongo/db/s/balancer/balancer_policy.h +++ b/src/mongo/db/s/balancer/balancer_policy.h @@ -37,14 +37,8 @@ namespace mongo { -class ChunkManager; -class OperationContext; - struct ZoneRange { - ZoneRange() = default; - - ZoneRange(const BSONObj& a_min, const BSONObj& a_max, const std::string& _zone) - : min(a_min.getOwned()), max(a_max.getOwned()), zone(_zone) {} + ZoneRange(const BSONObj& a_min, const BSONObj& a_max, const std::string& _zone); std::string toString() const; @@ -54,21 +48,10 @@ struct ZoneRange { }; struct MigrateInfo { - MigrateInfo(const std::string& a_ns, const ShardId& a_to, const ChunkType& a_chunk) - : ns(a_ns), - to(a_to), - from(a_chunk.getShard()), - minKey(a_chunk.getMin()), - maxKey(a_chunk.getMax()) {} - - MigrateInfo(const std::string& a_ns, - const ShardId& a_to, - const ShardId& a_from, - const BSONObj& a_minKey, - const BSONObj& a_maxKey) - : ns(a_ns), to(a_to), from(a_from), minKey(a_minKey), maxKey(a_maxKey) {} + MigrateInfo(const ShardId& a_to, const ChunkType& a_chunk); std::string getName() const; + std::string toString() const; std::string ns; @@ -76,6 +59,7 @@ struct MigrateInfo { ShardId from; BSONObj minKey; BSONObj maxKey; + ChunkVersion version; }; typedef std::vector<ClusterStatistics::ShardStatistics> ShardStatisticsVector; diff --git a/src/mongo/db/s/balancer/balancer_policy_test.cpp b/src/mongo/db/s/balancer/balancer_policy_test.cpp index 35da7c7bf7f..86258c723d8 100644 --- a/src/mongo/db/s/balancer/balancer_policy_test.cpp +++ b/src/mongo/db/s/balancer/balancer_policy_test.cpp @@ -30,6 +30,7 @@ #include "mongo/platform/basic.h" +#include "mongo/db/keypattern.h" #include "mongo/db/s/balancer/balancer_policy.h" #include "mongo/platform/random.h" #include "mongo/s/catalog/type_chunk.h" @@ -76,6 +77,10 @@ std::pair<ShardStatisticsVector, ShardToChunksMap> generateCluster( int64_t currentChunk = 0; + ChunkVersion chunkVersion(1, 0, OID::gen()); + + const KeyPattern shardKeyPattern(BSON("x" << 1)); + for (auto it = shardsAndNumChunks.begin(); it != shardsAndNumChunks.end(); it++) { ShardStatistics shard = std::move(it->first); const size_t numChunks = it->second; @@ -85,10 +90,16 @@ std::pair<ShardStatisticsVector, ShardToChunksMap> generateCluster( for (size_t i = 0; i < numChunks; i++, currentChunk++) { ChunkType chunk; - chunk.setMin(currentChunk == 0 ? kMinBSONKey : BSON("x" << currentChunk)); - chunk.setMax(currentChunk == totalNumChunks - 1 ? kMaxBSONKey + + chunk.setNS(kNamespace.ns()); + chunk.setMin(currentChunk == 0 ? shardKeyPattern.globalMin() + : BSON("x" << currentChunk)); + chunk.setMax(currentChunk == totalNumChunks - 1 ? shardKeyPattern.globalMax() : BSON("x" << currentChunk + 1)); chunk.setShard(shard.shardId); + chunk.setVersion(chunkVersion); + + chunkVersion.incMajor(); chunkMap[shard.shardId].push_back(std::move(chunk)); } diff --git a/src/mongo/db/s/balancer/migration_manager_test.cpp b/src/mongo/db/s/balancer/migration_manager_test.cpp index 87353c5dc4b..41e2f6419d0 100644 --- a/src/mongo/db/s/balancer/migration_manager_test.cpp +++ b/src/mongo/db/s/balancer/migration_manager_test.cpp @@ -113,11 +113,7 @@ protected: /** * Inserts a document into the config.migrations collection as an active migration. */ - void setUpMigration(const std::string& collName, - const BSONObj& minKey, - const BSONObj& maxKey, - const ShardId& toShard, - const ShardId& fromShard); + void setUpMigration(const ChunkType& chunk, const ShardId& toShard); /** * Asserts that config.migrations is empty and config.locks contains no locked documents, both @@ -219,17 +215,15 @@ ChunkType MigrationManagerTest::setUpChunk(const std::string& collName, return chunk; } -void MigrationManagerTest::setUpMigration(const std::string& collName, - const BSONObj& minKey, - const BSONObj& maxKey, - const ShardId& toShard, - const ShardId& fromShard) { +void MigrationManagerTest::setUpMigration(const ChunkType& chunk, const ShardId& toShard) { BSONObjBuilder builder; - builder.append(MigrationType::ns(), collName); - builder.append(MigrationType::min(), minKey); - builder.append(MigrationType::max(), maxKey); + builder.append(MigrationType::ns(), chunk.getNS()); + builder.append(MigrationType::min(), chunk.getMin()); + builder.append(MigrationType::max(), chunk.getMax()); builder.append(MigrationType::toShard(), toShard.toString()); - builder.append(MigrationType::fromShard(), fromShard.toString()); + builder.append(MigrationType::fromShard(), chunk.getShard().toString()); + chunk.getVersion().appendWithFieldForCommands(&builder, "chunkVersion"); + MigrationType migrationType = assertGet(MigrationType::fromBSON(builder.obj())); ASSERT_OK(catalogClient()->insertConfigDocument(operationContext(), MigrationType::ConfigNS, @@ -319,8 +313,7 @@ TEST_F(MigrationManagerTest, OneCollectionTwoMigrations) { setUpChunk(collName, BSON(kPattern << 49), kKeyPattern.globalMax(), kShardId2, version); // Going to request that these two chunks get migrated. - const std::vector<MigrateInfo> migrationRequests{{chunk1.getNS(), kShardId1, chunk1}, - {chunk2.getNS(), kShardId3, chunk2}}; + const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1}, {kShardId3, chunk2}}; auto future = launchAsync([this, migrationRequests] { Client::initThreadIfNotAlready("Test"); @@ -379,10 +372,10 @@ TEST_F(MigrationManagerTest, TwoCollectionsTwoMigrationsEach) { setUpChunk(collName2, BSON(kPattern << 49), kKeyPattern.globalMax(), kShardId2, version2); // Going to request that these four chunks get migrated. - const std::vector<MigrateInfo> migrationRequests{{chunk1coll1.getNS(), kShardId1, chunk1coll1}, - {chunk2coll1.getNS(), kShardId3, chunk2coll1}, - {chunk1coll2.getNS(), kShardId1, chunk1coll2}, - {chunk2coll2.getNS(), kShardId3, chunk2coll2}}; + const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1coll1}, + {kShardId3, chunk2coll1}, + {kShardId1, chunk1coll2}, + {kShardId3, chunk2coll2}}; auto future = launchAsync([this, migrationRequests] { Client::initThreadIfNotAlready("Test"); @@ -437,8 +430,7 @@ TEST_F(MigrationManagerTest, SameCollectionOldShardMigration) { setUpChunk(collName, BSON(kPattern << 49), kKeyPattern.globalMax(), kShardId2, version); // Going to request that these two chunks get migrated. - const std::vector<MigrateInfo> migrationRequests{{chunk1.getNS(), kShardId1, chunk1}, - {chunk2.getNS(), kShardId3, chunk2}}; + const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1}, {kShardId3, chunk2}}; auto future = launchAsync([this, migrationRequests] { Client::initThreadIfNotAlready("Test"); @@ -491,7 +483,7 @@ TEST_F(MigrationManagerTest, SameOldShardFailsToAcquireDistributedLockTwice) { setUpChunk(collName, kKeyPattern.globalMin(), kKeyPattern.globalMax(), kShardId0, version); // Going to request that this chunk get migrated. - const std::vector<MigrateInfo> migrationRequests{{chunk1.getNS(), kShardId1, chunk1}}; + const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1}}; auto future = launchAsync([this, migrationRequests] { Client::initThreadIfNotAlready("Test"); @@ -550,8 +542,7 @@ TEST_F(MigrationManagerTest, SameCollectionTwoOldShardMigrations) { setUpChunk(collName, BSON(kPattern << 49), kKeyPattern.globalMax(), kShardId2, version); // Going to request that these two chunks get migrated. - const std::vector<MigrateInfo> migrationRequests{{chunk1.getNS(), kShardId1, chunk1}, - {chunk2.getNS(), kShardId3, chunk2}}; + const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1}, {kShardId3, chunk2}}; auto future = launchAsync([this, migrationRequests] { Client::initThreadIfNotAlready("Test"); @@ -614,8 +605,7 @@ TEST_F(MigrationManagerTest, FailToAcquireDistributedLock) { setUpChunk(collName, BSON(kPattern << 49), kKeyPattern.globalMax(), kShardId2, version); // Going to request that these two chunks get migrated. - const std::vector<MigrateInfo> migrationRequests{{chunk1.getNS(), kShardId1, chunk1}, - {chunk2.getNS(), kShardId3, chunk2}}; + const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1}, {kShardId3, chunk2}}; shardTargeterMock(operationContext(), kShardId0)->setFindHostReturnValue(kShardHost0); shardTargeterMock(operationContext(), kShardId2)->setFindHostReturnValue(kShardHost2); @@ -662,8 +652,7 @@ TEST_F(MigrationManagerTest, SourceShardNotFound) { setUpChunk(collName, BSON(kPattern << 49), kKeyPattern.globalMax(), kShardId2, version); // Going to request that these two chunks get migrated. - const std::vector<MigrateInfo> migrationRequests{{chunk1.getNS(), kShardId1, chunk1}, - {chunk2.getNS(), kShardId3, chunk2}}; + const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1}, {kShardId3, chunk2}}; auto future = launchAsync([this, chunk1, chunk2, migrationRequests] { Client::initThreadIfNotAlready("Test"); @@ -708,7 +697,7 @@ TEST_F(MigrationManagerTest, JumboChunkResponseBackwardsCompatibility) { setUpChunk(collName, kKeyPattern.globalMin(), kKeyPattern.globalMax(), kShardId0, version); // Going to request that this chunk gets migrated. - const std::vector<MigrateInfo> migrationRequests{{chunk1.getNS(), kShardId1, chunk1}}; + const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1}}; auto future = launchAsync([this, chunk1, migrationRequests] { Client::initThreadIfNotAlready("Test"); @@ -757,7 +746,7 @@ TEST_F(MigrationManagerTest, InterruptMigration) { shardTargeterMock(txn.get(), kShardId0)->setFindHostReturnValue(kShardHost0); ASSERT_NOT_OK(_migrationManager->executeManualMigration( - txn.get(), {chunk.getNS(), kShardId1, chunk}, 0, kDefaultSecondaryThrottle, false)); + txn.get(), {kShardId1, chunk}, 0, kDefaultSecondaryThrottle, false)); }); // Wait till the move chunk request gets sent and pretend that it is stuck by never responding @@ -779,11 +768,8 @@ TEST_F(MigrationManagerTest, InterruptMigration) { future.timed_get(kFutureTimeout); // Ensure that no new migrations can be scheduled - ASSERT_NOT_OK(_migrationManager->executeManualMigration(operationContext(), - {chunk.getNS(), kShardId1, chunk}, - 0, - kDefaultSecondaryThrottle, - false)); + ASSERT_NOT_OK(_migrationManager->executeManualMigration( + operationContext(), {kShardId1, chunk}, 0, kDefaultSecondaryThrottle, false)); // Ensure that the migration manager is no longer handling any migrations. _migrationManager->drainActiveMigrations(); @@ -846,7 +832,7 @@ TEST_F(MigrationManagerTest, RestartMigrationManager) { shardTargeterMock(txn.get(), kShardId0)->setFindHostReturnValue(kShardHost0); ASSERT_OK(_migrationManager->executeManualMigration( - txn.get(), {chunk1.getNS(), kShardId1, chunk1}, 0, kDefaultSecondaryThrottle, false)); + txn.get(), {kShardId1, chunk1}, 0, kDefaultSecondaryThrottle, false)); }); // Expect only one moveChunk command to be called. @@ -866,12 +852,13 @@ TEST_F(MigrationManagerTest, MigrationRecovery) { // Set up the database and collection as sharded in the metadata. std::string dbName = "foo"; std::string collName = "foo.bar"; - ChunkVersion version(2, 0, OID::gen()); + ChunkVersion version(1, 0, OID::gen()); setUpDatabase(dbName, kShardId0); setUpCollection(collName, version); - // Set up two chunks in the metadata. + // Set up two chunks in the metadata and set up two fake active migrations by writing documents + // to the config.migrations collection. ChunkType chunk1 = setUpChunk(collName, kKeyPattern.globalMin(), BSON(kPattern << 49), kShardId0, version); version.incMinor(); @@ -881,17 +868,8 @@ TEST_F(MigrationManagerTest, MigrationRecovery) { _migrationManager->interruptAndDisableMigrations(); _migrationManager->drainActiveMigrations(); - // Set up two fake active migrations by writing documents to the config.migrations collection. - setUpMigration(collName, - chunk1.getMin(), - chunk1.getMax(), - kShardId1.toString(), - chunk1.getShard().toString()); - setUpMigration(collName, - chunk2.getMin(), - chunk2.getMax(), - kShardId3.toString(), - chunk2.getShard().toString()); + setUpMigration(chunk1, kShardId1.toString()); + setUpMigration(chunk2, kShardId3.toString()); _migrationManager->startRecoveryAndAcquireDistLocks(operationContext()); @@ -925,7 +903,7 @@ TEST_F(MigrationManagerTest, FailMigrationRecovery) { // Set up the database and collection as sharded in the metadata. std::string dbName = "foo"; std::string collName = "foo.bar"; - ChunkVersion version(2, 0, OID::gen()); + ChunkVersion version(1, 0, OID::gen()); setUpDatabase(dbName, kShardId0); setUpCollection(collName, version); @@ -940,12 +918,7 @@ TEST_F(MigrationManagerTest, FailMigrationRecovery) { _migrationManager->interruptAndDisableMigrations(); _migrationManager->drainActiveMigrations(); - // Set up a parsable fake active migration document in the config.migrations collection. - setUpMigration(collName, - chunk1.getMin(), - chunk1.getMax(), - kShardId1.toString(), - chunk1.getShard().toString()); + setUpMigration(chunk1, kShardId1.toString()); // Set up a fake active migration document that will fail MigrationType parsing -- missing // field. diff --git a/src/mongo/db/s/balancer/scoped_migration_request.cpp b/src/mongo/db/s/balancer/scoped_migration_request.cpp index ebc3e293814..fc4667c1f0c 100644 --- a/src/mongo/db/s/balancer/scoped_migration_request.cpp +++ b/src/mongo/db/s/balancer/scoped_migration_request.cpp @@ -95,7 +95,8 @@ StatusWith<ScopedMigrationRequest> ScopedMigrationRequest::writeMigration( OperationContext* txn, const MigrateInfo& migrateInfo) { // Try to write a unique migration document to config.migrations. - MigrationType migrationType(migrateInfo); + const MigrationType migrationType(migrateInfo); + for (int retry = 0; retry < kDuplicateKeyErrorMaxRetries; ++retry) { Status result = grid.catalogClient(txn)->insertConfigDocument( txn, MigrationType::ConfigNS, migrationType.toBSON(), kMajorityWriteConcern); diff --git a/src/mongo/db/s/balancer/scoped_migration_request_test.cpp b/src/mongo/db/s/balancer/scoped_migration_request_test.cpp index 0b6474eaa46..7e870c0ae49 100644 --- a/src/mongo/db/s/balancer/scoped_migration_request_test.cpp +++ b/src/mongo/db/s/balancer/scoped_migration_request_test.cpp @@ -104,7 +104,7 @@ MigrateInfo makeMigrateInfo() { ChunkType chunkType = assertGet(ChunkType::fromBSON(chunkBuilder.obj())); ASSERT_OK(chunkType.validate()); - return MigrateInfo(kNs, kToShard, chunkType); + return MigrateInfo(kToShard, chunkType); } TEST_F(ScopedMigrationRequestTest, CreateScopedMigrationRequest) { diff --git a/src/mongo/db/s/balancer/type_migration.cpp b/src/mongo/db/s/balancer/type_migration.cpp index 6dd2fe50c23..a9a3a9c6ffc 100644 --- a/src/mongo/db/s/balancer/type_migration.cpp +++ b/src/mongo/db/s/balancer/type_migration.cpp @@ -34,6 +34,11 @@ #include "mongo/s/catalog/type_chunk.h" namespace mongo { +namespace { + +const StringData kChunkVersion = "chunkVersion"_sd; + +} // namespace const std::string MigrationType::ConfigNS = "config.migrations"; @@ -51,7 +56,8 @@ MigrationType::MigrationType(MigrateInfo info) _min(info.minKey), _max(info.maxKey), _fromShard(info.from), - _toShard(info.to) {} + _toShard(info.to), + _chunkVersion(info.version) {} StatusWith<MigrationType> MigrationType::fromBSON(const BSONObj& source) { MigrationType migrationType; @@ -79,7 +85,7 @@ StatusWith<MigrationType> MigrationType::fromBSON(const BSONObj& source) { Status status = bsonExtractStringField(source, toShard.name(), &migrationToShard); if (!status.isOK()) return status; - migrationType._toShard = migrationToShard; + migrationType._toShard = std::move(migrationToShard); } { @@ -87,7 +93,15 @@ StatusWith<MigrationType> MigrationType::fromBSON(const BSONObj& source) { Status status = bsonExtractStringField(source, fromShard.name(), &migrationFromShard); if (!status.isOK()) return status; - migrationType._fromShard = migrationFromShard; + migrationType._fromShard = std::move(migrationFromShard); + } + + { + auto chunkVersionStatus = + ChunkVersion::parseFromBSONWithFieldForCommands(source, kChunkVersion); + if (!chunkVersionStatus.isOK()) + return chunkVersionStatus.getStatus(); + migrationType._chunkVersion = chunkVersionStatus.getValue(); } return migrationType; @@ -95,28 +109,34 @@ StatusWith<MigrationType> MigrationType::fromBSON(const BSONObj& source) { BSONObj MigrationType::toBSON() const { BSONObjBuilder builder; - if (_nss && _min) - builder.append(name.name(), getName()); - if (_nss) - builder.append(ns.name(), _nss->ns()); - if (_min) - builder.append(min.name(), _min.get()); - if (_max) - builder.append(max.name(), _max.get()); - if (_fromShard) - builder.append(fromShard.name(), _fromShard->toString()); - if (_toShard) - builder.append(toShard.name(), _toShard->toString()); + + builder.append(name.name(), getName()); + builder.append(ns.name(), _nss.ns()); + + builder.append(min.name(), _min); + builder.append(max.name(), _max); + + builder.append(fromShard.name(), _fromShard.toString()); + builder.append(toShard.name(), _toShard.toString()); + + _chunkVersion.appendWithFieldForCommands(&builder, kChunkVersion); return builder.obj(); } MigrateInfo MigrationType::toMigrateInfo() const { - return MigrateInfo(_nss->ns(), _toShard.get(), _fromShard.get(), _min.get(), _max.get()); + ChunkType chunk; + chunk.setNS(_nss.ns()); + chunk.setShard(_fromShard); + chunk.setMin(_min); + chunk.setMax(_max); + chunk.setVersion(_chunkVersion); + + return MigrateInfo(_toShard, chunk); } std::string MigrationType::getName() const { - return ChunkType::genID(_nss->ns(), _min.get()); + return ChunkType::genID(_nss.ns(), _min); } } // namespace mongo diff --git a/src/mongo/db/s/balancer/type_migration.h b/src/mongo/db/s/balancer/type_migration.h index 41d6ed72f48..bf741e30f3d 100644 --- a/src/mongo/db/s/balancer/type_migration.h +++ b/src/mongo/db/s/balancer/type_migration.h @@ -52,8 +52,6 @@ public: static const BSONField<BSONObj> max; static const BSONField<std::string> fromShard; static const BSONField<std::string> toShard; - static const BSONField<std::string> chunkVersionField; - static const BSONField<std::string> collectionVersionField; /** * The Balancer encapsulates migration information in MigrateInfo objects, so this facilitates @@ -85,12 +83,13 @@ public: private: MigrationType(); - // Required fields for config.migrations. - boost::optional<NamespaceString> _nss; - boost::optional<BSONObj> _min; - boost::optional<BSONObj> _max; - boost::optional<ShardId> _fromShard; - boost::optional<ShardId> _toShard; + // All required fields for config.migrations + NamespaceString _nss; + BSONObj _min; + BSONObj _max; + ShardId _fromShard; + ShardId _toShard; + ChunkVersion _chunkVersion; }; } // namespace mongo diff --git a/src/mongo/db/s/balancer/type_migration_test.cpp b/src/mongo/db/s/balancer/type_migration_test.cpp index ffd0de4127b..eb04d585305 100644 --- a/src/mongo/db/s/balancer/type_migration_test.cpp +++ b/src/mongo/db/s/balancer/type_migration_test.cpp @@ -60,7 +60,7 @@ TEST(MigrationTypeTest, ConvertFromMigrationInfo) { ChunkType chunkType = assertGet(ChunkType::fromBSON(chunkBuilder.obj())); ASSERT_OK(chunkType.validate()); - MigrateInfo migrateInfo(kNs, kToShard, chunkType); + MigrateInfo migrateInfo(kToShard, chunkType); MigrationType migrationType(migrateInfo); BSONObjBuilder builder; @@ -70,6 +70,7 @@ TEST(MigrationTypeTest, ConvertFromMigrationInfo) { builder.append(MigrationType::max(), kMax); builder.append(MigrationType::fromShard(), kFromShard.toString()); builder.append(MigrationType::toShard(), kToShard.toString()); + version.appendWithFieldForCommands(&builder, "chunkVersion"); BSONObj obj = builder.obj(); @@ -77,6 +78,8 @@ TEST(MigrationTypeTest, ConvertFromMigrationInfo) { } TEST(MigrationTypeTest, FromAndToBSON) { + const ChunkVersion version(1, 2, OID::gen()); + BSONObjBuilder builder; builder.append(MigrationType::name(), kName); builder.append(MigrationType::ns(), kNs); @@ -84,6 +87,7 @@ TEST(MigrationTypeTest, FromAndToBSON) { builder.append(MigrationType::max(), kMax); builder.append(MigrationType::fromShard(), kFromShard.toString()); builder.append(MigrationType::toShard(), kToShard.toString()); + version.appendWithFieldForCommands(&builder, "chunkVersion"); BSONObj obj = builder.obj(); @@ -92,11 +96,14 @@ TEST(MigrationTypeTest, FromAndToBSON) { } TEST(MigrationTypeTest, MissingRequiredNamespaceField) { + const ChunkVersion version(1, 2, OID::gen()); + BSONObjBuilder builder; builder.append(MigrationType::min(), kMin); builder.append(MigrationType::max(), kMax); builder.append(MigrationType::fromShard(), kFromShard.toString()); builder.append(MigrationType::toShard(), kToShard.toString()); + version.appendWithFieldForCommands(&builder, "chunkVersion"); BSONObj obj = builder.obj(); @@ -106,11 +113,14 @@ TEST(MigrationTypeTest, MissingRequiredNamespaceField) { } TEST(MigrationTypeTest, MissingRequiredMinField) { + const ChunkVersion version(1, 2, OID::gen()); + BSONObjBuilder builder; builder.append(MigrationType::ns(), kNs); builder.append(MigrationType::max(), kMax); builder.append(MigrationType::fromShard(), kFromShard.toString()); builder.append(MigrationType::toShard(), kToShard.toString()); + version.appendWithFieldForCommands(&builder, "chunkVersion"); BSONObj obj = builder.obj(); @@ -120,11 +130,14 @@ TEST(MigrationTypeTest, MissingRequiredMinField) { } TEST(MigrationTypeTest, MissingRequiredMaxField) { + const ChunkVersion version(1, 2, OID::gen()); + BSONObjBuilder builder; builder.append(MigrationType::ns(), kNs); builder.append(MigrationType::min(), kMin); builder.append(MigrationType::fromShard(), kFromShard.toString()); builder.append(MigrationType::toShard(), kToShard.toString()); + version.appendWithFieldForCommands(&builder, "chunkVersion"); BSONObj obj = builder.obj(); @@ -134,11 +147,14 @@ TEST(MigrationTypeTest, MissingRequiredMaxField) { } TEST(MigrationTypeTest, MissingRequiredFromShardField) { + const ChunkVersion version(1, 2, OID::gen()); + BSONObjBuilder builder; builder.append(MigrationType::ns(), kNs); builder.append(MigrationType::min(), kMin); builder.append(MigrationType::max(), kMax); builder.append(MigrationType::toShard(), kToShard.toString()); + version.appendWithFieldForCommands(&builder, "chunkVersion"); BSONObj obj = builder.obj(); @@ -148,11 +164,14 @@ TEST(MigrationTypeTest, MissingRequiredFromShardField) { } TEST(MigrationTypeTest, MissingRequiredToShardField) { + const ChunkVersion version(1, 2, OID::gen()); + BSONObjBuilder builder; builder.append(MigrationType::ns(), kNs); builder.append(MigrationType::min(), kMin); builder.append(MigrationType::max(), kMax); builder.append(MigrationType::fromShard(), kFromShard.toString()); + version.appendWithFieldForCommands(&builder, "chunkVersion"); BSONObj obj = builder.obj(); @@ -161,5 +180,21 @@ TEST(MigrationTypeTest, MissingRequiredToShardField) { ASSERT_STRING_CONTAINS(migrationType.getStatus().reason(), MigrationType::toShard.name()); } +TEST(MigrationTypeTest, MissingRequiredVersionField) { + BSONObjBuilder builder; + builder.append(MigrationType::name(), kName); + builder.append(MigrationType::ns(), kNs); + builder.append(MigrationType::min(), kMin); + builder.append(MigrationType::max(), kMax); + builder.append(MigrationType::fromShard(), kFromShard.toString()); + builder.append(MigrationType::toShard(), kToShard.toString()); + + BSONObj obj = builder.obj(); + + StatusWith<MigrationType> migrationType = MigrationType::fromBSON(obj); + ASSERT_EQUALS(migrationType.getStatus(), ErrorCodes::NoSuchKey); + ASSERT_STRING_CONTAINS(migrationType.getStatus().reason(), "chunkVersion"); +} + } // namespace } // namespace mongo |