diff options
-rw-r--r-- | jstests/sharding/movechunk_interrupt_at_primary_stepdown.js | 14 | ||||
-rw-r--r-- | src/mongo/base/error_codes.err | 2 | ||||
-rw-r--r-- | src/mongo/db/s/active_migrations_registry_test.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/s/balancer/migration_manager.cpp | 188 | ||||
-rw-r--r-- | src/mongo/db/s/balancer/migration_manager.h | 36 | ||||
-rw-r--r-- | src/mongo/db/s/balancer/migration_manager_test.cpp | 257 | ||||
-rw-r--r-- | src/mongo/db/s/config/configsvr_commit_chunk_migration_command.cpp | 55 | ||||
-rw-r--r-- | src/mongo/db/s/migration_chunk_cloner_source_legacy_test.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/s/migration_source_manager.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/s/move_chunk_command.cpp | 52 | ||||
-rw-r--r-- | src/mongo/s/move_chunk_request.cpp | 19 | ||||
-rw-r--r-- | src/mongo/s/move_chunk_request.h | 10 | ||||
-rw-r--r-- | src/mongo/s/move_chunk_request_test.cpp | 6 | ||||
-rw-r--r-- | src/mongo/s/request_types/commit_chunk_migration_request_test.cpp | 9 | ||||
-rw-r--r-- | src/mongo/s/request_types/commit_chunk_migration_request_type.cpp | 13 | ||||
-rw-r--r-- | src/mongo/s/request_types/commit_chunk_migration_request_type.h | 13 |
16 files changed, 80 insertions, 599 deletions
diff --git a/jstests/sharding/movechunk_interrupt_at_primary_stepdown.js b/jstests/sharding/movechunk_interrupt_at_primary_stepdown.js index 055e4c70c6d..5c8ec946907 100644 --- a/jstests/sharding/movechunk_interrupt_at_primary_stepdown.js +++ b/jstests/sharding/movechunk_interrupt_at_primary_stepdown.js @@ -66,20 +66,6 @@ load('./jstests/libs/chunk_manipulation_util.js'); assert.eq(0, mongos.getDB('config').chunks.find({shard: st.shard0.shardName}).itcount()); assert.eq(1, mongos.getDB('config').chunks.find({shard: st.shard1.shardName}).itcount()); - // migrationCommitError -- tell the shard that the migration cannot be committed because the - // collection distlock was lost during the migration because the balancer was interrupted and - // the collection could be incompatible now with this migration. - assert.commandWorked(st.configRS.getPrimary().getDB("admin").runCommand( - {configureFailPoint: 'migrationCommitError', mode: 'alwaysOn'})); - - assert.commandFailedWithCode( - mongos.getDB("admin").runCommand( - {moveChunk: coll + "", find: {Key: 0}, to: st.shard0.shardName}), - ErrorCodes.BalancerLostDistributedLock); - - assert.commandWorked(st.configRS.getPrimary().getDB("admin").runCommand( - {configureFailPoint: 'migrationCommitError', mode: 'off'})); - // migrationCommitVersionError -- tell the shard that the migration cannot be committed // because the collection version epochs do not match, meaning the collection has been dropped // since the migration began, which means the Balancer must have lost the distributed lock for diff --git a/src/mongo/base/error_codes.err b/src/mongo/base/error_codes.err index 280f83133a9..efedba69baa 100644 --- a/src/mongo/base/error_codes.err +++ b/src/mongo/base/error_codes.err @@ -189,7 +189,7 @@ error_code("LinearizableReadConcernError", 187) error_code("IncompatibleServerVersion", 188) error_code("PrimarySteppedDown", 189) error_code("MasterSlaveConnectionFailure", 190) -error_code("BalancerLostDistributedLock", 191) +error_code("OBSOLETE_BalancerLostDistributedLock", 191) error_code("FailPointEnabled", 192) error_code("NoShardingEnabled", 193) error_code("BalancerInterrupted", 194) diff --git a/src/mongo/db/s/active_migrations_registry_test.cpp b/src/mongo/db/s/active_migrations_registry_test.cpp index 74ec900fc49..c5eb63f71a3 100644 --- a/src/mongo/db/s/active_migrations_registry_test.cpp +++ b/src/mongo/db/s/active_migrations_registry_test.cpp @@ -80,7 +80,6 @@ MoveChunkRequest createMoveChunkRequest(const NamespaceString& nss) { chunkVersion, 1024, MigrationSecondaryThrottleOptions::create(MigrationSecondaryThrottleOptions::kOff), - true, true); return assertGet(MoveChunkRequest::createFromCommand(nss, builder.obj())); } diff --git a/src/mongo/db/s/balancer/migration_manager.cpp b/src/mongo/db/s/balancer/migration_manager.cpp index bd8465338f0..6bccabf7326 100644 --- a/src/mongo/db/s/balancer/migration_manager.cpp +++ b/src/mongo/db/s/balancer/migration_manager.cpp @@ -61,15 +61,17 @@ using str::stream; namespace { -const char kChunkTooBig[] = "chunkTooBig"; +const char kChunkTooBig[] = "chunkTooBig"; // TODO: delete in 3.8 const WriteConcernOptions kMajorityWriteConcern(WriteConcernOptions::kMajority, WriteConcernOptions::SyncMode::UNSET, Seconds(15)); /** * Parses the 'commandResponse' and converts it to a status to use as the outcome of the command. - * Preserves backwards compatibility with 3.2 and earlier shards that, rather than use a ChunkTooBig + * Preserves backwards compatibility with 3.4 and earlier shards that, rather than use a ChunkTooBig * error code, include an extra field in the response. + * + * TODO: Delete in 3.8 */ Status extractMigrationStatusFromCommandResponse(const BSONObj& commandResponse) { Status commandStatus = getStatusFromCommandResult(commandResponse); @@ -98,23 +100,13 @@ StatusWith<DistLockHandle> acquireDistLock(OperationContext* txn, txn, nss.ns(), whyMessage, lockSessionID, DistLockManager::kSingleLockAttemptTimeout); if (!statusWithDistLockHandle.isOK()) { - // If we get LockBusy while trying to acquire the collection distributed lock, this implies - // that a concurrent collection operation is running either on a 3.2 shard or on mongos. - // Convert it to ConflictingOperationInProgress to better indicate the error. - // - // In addition, the code which re-schedules parallel migrations serially for 3.2 shard - // compatibility uses the LockBusy code as a hint to do the reschedule. - const ErrorCodes::Error code = (statusWithDistLockHandle == ErrorCodes::LockBusy - ? ErrorCodes::ConflictingOperationInProgress - : statusWithDistLockHandle.getStatus().code()); - - return {code, + return {statusWithDistLockHandle.getStatus().code(), stream() << "Could not acquire collection lock for " << nss.ns() << " to migrate chunks, due to " << statusWithDistLockHandle.getStatus().reason()}; } - return std::move(statusWithDistLockHandle.getValue()); + return statusWithDistLockHandle; } /** @@ -134,7 +126,7 @@ MigrationManager::MigrationManager(ServiceContext* serviceContext) MigrationManager::~MigrationManager() { // The migration manager must be completely quiesced at destruction time - invariant(_activeMigrationsWithoutDistLock.empty()); + invariant(_activeMigrations.empty()); } MigrationStatuses MigrationManager::executeMigrationsForAutoBalance( @@ -146,8 +138,6 @@ MigrationStatuses MigrationManager::executeMigrationsForAutoBalance( MigrationStatuses migrationStatuses; - vector<MigrateInfo> rescheduledMigrations; - { std::map<MigrationIdentifier, ScopedMigrationRequest> scopedMigrationRequests; vector<std::pair<shared_ptr<Notification<RemoteCommandResponse>>, MigrateInfo>> responses; @@ -165,18 +155,12 @@ MigrationStatuses MigrationManager::executeMigrationsForAutoBalance( scopedMigrationRequests.emplace(migrateInfo.getName(), std::move(statusWithScopedMigrationRequest.getValue())); - responses.emplace_back(_schedule(txn, - migrateInfo, - false, // Config server takes the collection dist lock - maxChunkSizeBytes, - secondaryThrottle, - waitForDelete), - migrateInfo); + responses.emplace_back( + _schedule(txn, migrateInfo, maxChunkSizeBytes, secondaryThrottle, waitForDelete), + migrateInfo); } - // Wait for all the scheduled migrations to complete and note the ones, which failed with a - // LockBusy error code. These need to be executed serially, without the distributed lock - // being held by the config server for backwards compatibility with 3.2 shards. + // Wait for all the scheduled migrations to complete. for (auto& response : responses) { auto notification = std::move(response.first); auto migrateInfo = std::move(response.second); @@ -187,39 +171,8 @@ MigrationStatuses MigrationManager::executeMigrationsForAutoBalance( invariant(it != scopedMigrationRequests.end()); Status commandStatus = _processRemoteCommandResponse(remoteCommandResponse, &it->second); - if (commandStatus == ErrorCodes::LockBusy) { - rescheduledMigrations.emplace_back(std::move(migrateInfo)); - } else { - migrationStatuses.emplace(migrateInfo.getName(), std::move(commandStatus)); - } - } - } - - // Schedule all 3.2 compatibility migrations sequentially - for (const auto& migrateInfo : rescheduledMigrations) { - // Write a document to the config.migrations collection, in case this migration must be - // recovered by the Balancer. Fail if the chunk is already moving. - auto statusWithScopedMigrationRequest = - ScopedMigrationRequest::writeMigration(txn, migrateInfo, waitForDelete); - if (!statusWithScopedMigrationRequest.isOK()) { - migrationStatuses.emplace(migrateInfo.getName(), - std::move(statusWithScopedMigrationRequest.getStatus())); - continue; + migrationStatuses.emplace(migrateInfo.getName(), std::move(commandStatus)); } - - RemoteCommandResponse remoteCommandResponse = - _schedule(txn, - migrateInfo, - true, // Shard takes the collection dist lock - maxChunkSizeBytes, - secondaryThrottle, - waitForDelete) - ->get(); - - Status commandStatus = _processRemoteCommandResponse( - remoteCommandResponse, &statusWithScopedMigrationRequest.getValue()); - - migrationStatuses.emplace(migrateInfo.getName(), std::move(commandStatus)); } invariant(migrationStatuses.size() == migrateInfos.size()); @@ -244,13 +197,7 @@ Status MigrationManager::executeManualMigration( } RemoteCommandResponse remoteCommandResponse = - _schedule(txn, - migrateInfo, - false, // Config server takes the collection dist lock - maxChunkSizeBytes, - secondaryThrottle, - waitForDelete) - ->get(); + _schedule(txn, migrateInfo, maxChunkSizeBytes, secondaryThrottle, waitForDelete)->get(); auto scopedCMStatus = ScopedChunkManager::refreshAndGet(txn, NamespaceString(migrateInfo.ns)); if (!scopedCMStatus.isOK()) { @@ -343,10 +290,7 @@ void MigrationManager::startRecoveryAndAcquireDistLocks(OperationContext* txn) { auto statusWithDistLockHandle = distLockManager->tryLockWithLocalWriteConcern( txn, migrateType.getNss().ns(), whyMessage, _lockSessionID); - if (!statusWithDistLockHandle.isOK() && - statusWithDistLockHandle.getStatus() != ErrorCodes::LockBusy) { - // LockBusy is alright because that should mean a 3.2 shard has it for the active - // migration. + if (!statusWithDistLockHandle.isOK()) { log() << "Failed to acquire distributed lock for collection '" << migrateType.getNss().ns() << "' during balancer recovery of an active migration. Abandoning" @@ -432,12 +376,8 @@ void MigrationManager::finishRecovery(OperationContext* txn, scheduledMigrations++; - responses.emplace_back(_schedule(txn, - migrationInfo, - false, // Config server takes the collection dist lock - maxChunkSizeBytes, - secondaryThrottle, - waitForDelete)); + responses.emplace_back( + _schedule(txn, migrationInfo, maxChunkSizeBytes, secondaryThrottle, waitForDelete)); } // If no migrations were scheduled for this namespace, free the dist lock @@ -473,7 +413,7 @@ void MigrationManager::interruptAndDisableMigrations() { _state = State::kStopping; // Interrupt any active migrations with dist lock - for (auto& cmsEntry : _activeMigrationsWithDistLock) { + for (auto& cmsEntry : _activeMigrations) { auto* cms = &cmsEntry.second; for (auto& migration : cms->migrations) { @@ -483,13 +423,6 @@ void MigrationManager::interruptAndDisableMigrations() { } } - // Interrupt any active migrations without dist lock - for (auto& migration : _activeMigrationsWithoutDistLock) { - if (migration.callbackHandle) { - executor->cancel(*migration.callbackHandle); - } - } - _checkDrained_inlock(); } @@ -499,18 +432,13 @@ void MigrationManager::drainActiveMigrations() { if (_state == State::kStopped) return; invariant(_state == State::kStopping); - - _condVar.wait(lock, [this] { - return _activeMigrationsWithDistLock.empty() && _activeMigrationsWithoutDistLock.empty(); - }); - + _condVar.wait(lock, [this] { return _activeMigrations.empty(); }); _state = State::kStopped; } shared_ptr<Notification<RemoteCommandResponse>> MigrationManager::_schedule( OperationContext* txn, const MigrateInfo& migrateInfo, - bool shardTakesCollectionDistLock, uint64_t maxChunkSizeBytes, const MigrationSecondaryThrottleOptions& secondaryThrottle, bool waitForDelete) { @@ -575,8 +503,7 @@ shared_ptr<Notification<RemoteCommandResponse>> MigrationManager::_schedule( chunk->getLastmod(), maxChunkSizeBytes, secondaryThrottle, - waitForDelete, - shardTakesCollectionDistLock); + waitForDelete); stdx::lock_guard<stdx::mutex> lock(_mutex); @@ -590,24 +517,20 @@ shared_ptr<Notification<RemoteCommandResponse>> MigrationManager::_schedule( auto retVal = migration.completionNotification; - if (shardTakesCollectionDistLock) { - _scheduleWithoutDistLock_inlock(txn, fromHostStatus.getValue(), std::move(migration)); - } else { - _scheduleWithDistLock_inlock(txn, fromHostStatus.getValue(), std::move(migration)); - } + _schedule_inlock(txn, fromHostStatus.getValue(), std::move(migration)); return retVal; } -void MigrationManager::_scheduleWithDistLock_inlock(OperationContext* txn, - const HostAndPort& targetHost, - Migration migration) { +void MigrationManager::_schedule_inlock(OperationContext* txn, + const HostAndPort& targetHost, + Migration migration) { executor::TaskExecutor* const executor = Grid::get(txn)->getExecutorPool()->getFixedExecutor(); const NamespaceString nss(migration.nss); - auto it = _activeMigrationsWithDistLock.find(nss); - if (it == _activeMigrationsWithDistLock.end()) { + auto it = _activeMigrations.find(nss); + if (it == _activeMigrations.end()) { // Acquire the collection distributed lock (blocking call) auto distLockHandleStatus = acquireDistLock(txn, _lockSessionID, nss); if (!distLockHandleStatus.isOK()) { @@ -615,7 +538,7 @@ void MigrationManager::_scheduleWithDistLock_inlock(OperationContext* txn, return; } - it = _activeMigrationsWithDistLock + it = _activeMigrations .insert(std::make_pair( nss, CollectionMigrationsState(std::move(distLockHandleStatus.getValue())))) .first; @@ -640,7 +563,7 @@ void MigrationManager::_scheduleWithDistLock_inlock(OperationContext* txn, auto txn = cc().makeOperationContext(); stdx::lock_guard<stdx::mutex> lock(_mutex); - _completeWithDistLock_inlock(txn.get(), itMigration, args.response); + _complete_inlock(txn.get(), itMigration, args.response); }); if (callbackHandleWithStatus.isOK()) { @@ -648,13 +571,12 @@ void MigrationManager::_scheduleWithDistLock_inlock(OperationContext* txn, return; } - _completeWithDistLock_inlock(txn, itMigration, std::move(callbackHandleWithStatus.getStatus())); + _complete_inlock(txn, itMigration, std::move(callbackHandleWithStatus.getStatus())); } -void MigrationManager::_completeWithDistLock_inlock( - OperationContext* txn, - MigrationsList::iterator itMigration, - const RemoteCommandResponse& remoteCommandResponse) { +void MigrationManager::_complete_inlock(OperationContext* txn, + MigrationsList::iterator itMigration, + const RemoteCommandResponse& remoteCommandResponse) { const NamespaceString nss(itMigration->nss); // Make sure to signal the notification last, after the distributed lock is freed, so that we @@ -662,8 +584,8 @@ void MigrationManager::_completeWithDistLock_inlock( // still acquired. auto notificationToSignal = itMigration->completionNotification; - auto it = _activeMigrationsWithDistLock.find(nss); - invariant(it != _activeMigrationsWithDistLock.end()); + auto it = _activeMigrations.find(nss); + invariant(it != _activeMigrations.end()); auto collectionMigrationState = &it->second; collectionMigrationState->migrations.erase(itMigration); @@ -671,58 +593,20 @@ void MigrationManager::_completeWithDistLock_inlock( if (collectionMigrationState->migrations.empty()) { Grid::get(txn)->catalogClient(txn)->getDistLockManager()->unlock( txn, collectionMigrationState->distLockHandle, nss.ns()); - _activeMigrationsWithDistLock.erase(it); + _activeMigrations.erase(it); _checkDrained_inlock(); } notificationToSignal->set(remoteCommandResponse); } -void MigrationManager::_scheduleWithoutDistLock_inlock(OperationContext* txn, - const HostAndPort& targetHost, - Migration migration) { - executor::TaskExecutor* const executor = Grid::get(txn)->getExecutorPool()->getFixedExecutor(); - - _activeMigrationsWithoutDistLock.push_front(std::move(migration)); - auto itMigration = _activeMigrationsWithoutDistLock.begin(); - - const RemoteCommandRequest remoteRequest( - targetHost, NamespaceString::kAdminDb.toString(), itMigration->moveChunkCmdObj, txn); - - StatusWith<executor::TaskExecutor::CallbackHandle> callbackHandleWithStatus = - executor->scheduleRemoteCommand( - remoteRequest, - [this, itMigration](const executor::TaskExecutor::RemoteCommandCallbackArgs& args) { - auto notificationToSignal = itMigration->completionNotification; - - stdx::lock_guard<stdx::mutex> lock(_mutex); - - _activeMigrationsWithoutDistLock.erase(itMigration); - _checkDrained_inlock(); - - notificationToSignal->set(args.response); - }); - - if (callbackHandleWithStatus.isOK()) { - itMigration->callbackHandle = std::move(callbackHandleWithStatus.getValue()); - return; - } - - auto notificationToSignal = itMigration->completionNotification; - - _activeMigrationsWithoutDistLock.erase(itMigration); - _checkDrained_inlock(); - - notificationToSignal->set(std::move(callbackHandleWithStatus.getStatus())); -} - void MigrationManager::_checkDrained_inlock() { if (_state == State::kEnabled || _state == State::kRecovering) { return; } invariant(_state == State::kStopping); - if (_activeMigrationsWithDistLock.empty() && _activeMigrationsWithoutDistLock.empty()) { + if (_activeMigrations.empty()) { _condVar.notify_all(); } } @@ -758,6 +642,7 @@ void MigrationManager::_abandonActiveMigrationsAndEnableManager(OperationContext Status MigrationManager::_processRemoteCommandResponse( const RemoteCommandResponse& remoteCommandResponse, ScopedMigrationRequest* scopedMigrationRequest) { + stdx::lock_guard<stdx::mutex> lock(_mutex); Status commandStatus(ErrorCodes::InternalError, "Uninitialized value."); @@ -774,6 +659,7 @@ Status MigrationManager::_processRemoteCommandResponse( if (!remoteCommandResponse.isOK()) { commandStatus = remoteCommandResponse.status; } else { + // TODO: delete in 3.8 commandStatus = extractMigrationStatusFromCommandResponse(remoteCommandResponse.data); } diff --git a/src/mongo/db/s/balancer/migration_manager.h b/src/mongo/db/s/balancer/migration_manager.h index b6ae1dd3ff3..b9611498148 100644 --- a/src/mongo/db/s/balancer/migration_manager.h +++ b/src/mongo/db/s/balancer/migration_manager.h @@ -60,8 +60,6 @@ typedef std::map<MigrationIdentifier, Status> MigrationStatuses; /** * Manages and executes parallel migrations for the balancer. - * - * TODO: for v3.6, remove code making compatible with v3.2 shards that take distlock. */ class MigrationManager { MONGO_DISALLOW_COPYING(MigrationManager); @@ -202,14 +200,10 @@ private: * specified parameters. May block for distributed lock acquisition. If dist lock acquisition is * successful (or not done), schedules the migration request and returns a notification which * can be used to obtain the outcome of the operation. - * - * The 'shardTakesCollectionDistLock' parameter controls whether the distributed lock is - * acquired by the migration manager or by the shard executing the migration request. */ std::shared_ptr<Notification<executor::RemoteCommandResponse>> _schedule( OperationContext* txn, const MigrateInfo& migrateInfo, - bool shardTakesCollectionDistLock, uint64_t maxChunkSizeBytes, const MigrationSecondaryThrottleOptions& secondaryThrottle, bool waitForDelete); @@ -221,9 +215,9 @@ private: * The distributed lock is acquired before scheduling the first migration for the collection and * is only released when all active migrations on the collection have finished. */ - void _scheduleWithDistLock_inlock(OperationContext* txn, - const HostAndPort& targetHost, - Migration migration); + void _schedule_inlock(OperationContext* txn, + const HostAndPort& targetHost, + Migration migration); /** * Used internally for migrations scheduled with the distributed lock acquired by the config @@ -231,21 +225,9 @@ private: * passed iterator and if this is the last migration for the collection will free the collection * distributed lock. */ - void _completeWithDistLock_inlock(OperationContext* txn, - MigrationsList::iterator itMigration, - const executor::RemoteCommandResponse& remoteCommandResponse); - - /** - * Immediately schedules the specified migration without attempting to acquire the collection - * distributed lock or checking that it is not being held. - * - * This method is only used for retrying migrations that have failed with LockBusy errors - * returned by the shard, which only happens with legacy 3.2 shards that take the collection - * distributed lock themselves. - */ - void _scheduleWithoutDistLock_inlock(OperationContext* txn, - const HostAndPort& targetHost, - Migration migration); + void _complete_inlock(OperationContext* txn, + MigrationsList::iterator itMigration, + const executor::RemoteCommandResponse& remoteCommandResponse); /** * If the state of the migration manager is kStopping, checks whether there are any outstanding @@ -306,11 +288,7 @@ private: // Holds information about each collection's distributed lock and active migrations via a // CollectionMigrationState object. - CollectionMigrationsStateMap _activeMigrationsWithDistLock; - - // Holds information about migrations, which have been scheduled without the collection - // distributed lock acquired (i.e., the shard is asked to acquire it). - MigrationsList _activeMigrationsWithoutDistLock; + CollectionMigrationsStateMap _activeMigrations; }; } // namespace mongo diff --git a/src/mongo/db/s/balancer/migration_manager_test.cpp b/src/mongo/db/s/balancer/migration_manager_test.cpp index 1c5ead4acbf..bcca90e4e25 100644 --- a/src/mongo/db/s/balancer/migration_manager_test.cpp +++ b/src/mongo/db/s/balancer/migration_manager_test.cpp @@ -128,11 +128,9 @@ protected: */ void expectMoveChunkCommand(const ChunkType& chunk, const ShardId& toShardId, - const bool& takeDistLock, const BSONObj& response); void expectMoveChunkCommand(const ChunkType& chunk, const ShardId& toShardId, - const bool& takeDistLock, const Status& returnStatus); // Random static initialization order can result in X constructor running before Y constructor @@ -260,9 +258,8 @@ void MigrationManagerTest::checkMigrationsCollectionIsEmptyAndLocksAreUnlocked() void MigrationManagerTest::expectMoveChunkCommand(const ChunkType& chunk, const ShardId& toShardId, - const bool& takeDistLock, const BSONObj& response) { - onCommand([&chunk, &toShardId, &takeDistLock, &response](const RemoteCommandRequest& request) { + onCommand([&chunk, &toShardId, &response](const RemoteCommandRequest& request) { NamespaceString nss(request.cmdObj.firstElement().valueStringData()); ASSERT_EQ(chunk.getNS(), nss.ns()); @@ -276,7 +273,6 @@ void MigrationManagerTest::expectMoveChunkCommand(const ChunkType& chunk, ASSERT_EQ(chunk.getShard(), moveChunkRequestWithStatus.getValue().getFromShardId()); ASSERT_EQ(toShardId, moveChunkRequestWithStatus.getValue().getToShardId()); - ASSERT_EQ(takeDistLock, moveChunkRequestWithStatus.getValue().getTakeDistLock()); return response; }); @@ -284,11 +280,10 @@ void MigrationManagerTest::expectMoveChunkCommand(const ChunkType& chunk, void MigrationManagerTest::expectMoveChunkCommand(const ChunkType& chunk, const ShardId& toShardId, - const bool& takeDistLock, const Status& returnStatus) { BSONObjBuilder resultBuilder; Command::appendCommandStatus(resultBuilder, returnStatus); - expectMoveChunkCommand(chunk, toShardId, takeDistLock, resultBuilder.obj()); + expectMoveChunkCommand(chunk, toShardId, resultBuilder.obj()); } TEST_F(MigrationManagerTest, OneCollectionTwoMigrations) { @@ -334,8 +329,8 @@ TEST_F(MigrationManagerTest, OneCollectionTwoMigrations) { }); // Expect two moveChunk commands. - expectMoveChunkCommand(chunk1, kShardId1, false, Status::OK()); - expectMoveChunkCommand(chunk2, kShardId3, false, Status::OK()); + expectMoveChunkCommand(chunk1, kShardId1, Status::OK()); + expectMoveChunkCommand(chunk2, kShardId3, Status::OK()); // Run the MigrationManager code. future.timed_get(kFutureTimeout); @@ -396,238 +391,15 @@ TEST_F(MigrationManagerTest, TwoCollectionsTwoMigrationsEach) { }); // Expect four moveChunk commands. - expectMoveChunkCommand(chunk1coll1, kShardId1, false, Status::OK()); - expectMoveChunkCommand(chunk2coll1, kShardId3, false, Status::OK()); - expectMoveChunkCommand(chunk1coll2, kShardId1, false, Status::OK()); - expectMoveChunkCommand(chunk2coll2, kShardId3, false, Status::OK()); + expectMoveChunkCommand(chunk1coll1, kShardId1, Status::OK()); + expectMoveChunkCommand(chunk2coll1, kShardId3, Status::OK()); + expectMoveChunkCommand(chunk1coll2, kShardId1, Status::OK()); + expectMoveChunkCommand(chunk2coll2, kShardId3, Status::OK()); // Run the MigrationManager code. future.timed_get(kFutureTimeout); } -// Old v3.2 shards expect to take the distributed lock before executing a moveChunk command. The -// MigrationManager should take the distlock and fail the first moveChunk command with an old shard, -// and then release the lock and retry the command successfully. -TEST_F(MigrationManagerTest, SameCollectionOldShardMigration) { - // Set up two shards in the metadata. - ASSERT_OK(catalogClient()->insertConfigDocument( - operationContext(), ShardType::ConfigNS, kShard0, kMajorityWriteConcern)); - ASSERT_OK(catalogClient()->insertConfigDocument( - operationContext(), ShardType::ConfigNS, kShard2, kMajorityWriteConcern)); - - // 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()); - - setUpDatabase(dbName, kShardId0); - setUpCollection(collName, version); - - // Set up two chunks in the metadata. - ChunkType chunk1 = - setUpChunk(collName, kKeyPattern.globalMin(), BSON(kPattern << 49), kShardId0, version); - version.incMinor(); - ChunkType chunk2 = - setUpChunk(collName, BSON(kPattern << 49), kKeyPattern.globalMax(), kShardId2, version); - - // Going to request that these two chunks get migrated. - const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1}, {kShardId3, chunk2}}; - - auto future = launchAsync([this, migrationRequests] { - Client::initThreadIfNotAlready("Test"); - auto txn = cc().makeOperationContext(); - - // Scheduling the moveChunk commands requires finding a host to which to send the command. - // Set up dummy hosts for the source shards. - shardTargeterMock(txn.get(), kShardId0)->setFindHostReturnValue(kShardHost0); - shardTargeterMock(txn.get(), kShardId2)->setFindHostReturnValue(kShardHost2); - - MigrationStatuses migrationStatuses = _migrationManager->executeMigrationsForAutoBalance( - txn.get(), migrationRequests, 0, kDefaultSecondaryThrottle, false); - - for (const auto& migrateInfo : migrationRequests) { - ASSERT_OK(migrationStatuses.at(migrateInfo.getName())); - } - }); - - // Expect two moveChunk commands. - expectMoveChunkCommand( - chunk1, - kShardId1, - false, - Status(ErrorCodes::LockBusy, "SameCollectionOldShardMigration generated error.")); - expectMoveChunkCommand(chunk2, kShardId3, false, Status::OK()); - expectMoveChunkCommand(chunk1, kShardId1, true, Status::OK()); - - // Run the MigrationManager code. - future.timed_get(kFutureTimeout); -} - -// Fail a migration if an old v3.2 shard fails to acquire the distributed lock more than once. The -// first LockBusy error identifies the shard as an old shard to the MigrationManager, the second -// indicates the lock is held elsewhere and unavailable. -TEST_F(MigrationManagerTest, SameOldShardFailsToAcquireDistributedLockTwice) { - // Set up a shard in the metadata. - ASSERT_OK(catalogClient()->insertConfigDocument( - operationContext(), ShardType::ConfigNS, kShard0, kMajorityWriteConcern)); - - // 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()); - - setUpDatabase(dbName, kShardId0); - setUpCollection(collName, version); - - // Set up a chunk in the metadata. - ChunkType chunk1 = - setUpChunk(collName, kKeyPattern.globalMin(), kKeyPattern.globalMax(), kShardId0, version); - - // Going to request that this chunk get migrated. - const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1}}; - - auto future = launchAsync([this, migrationRequests] { - Client::initThreadIfNotAlready("Test"); - auto txn = cc().makeOperationContext(); - - // Scheduling the moveChunk commands requires finding a host to which to send the command. - // Set up a dummy host for the source shard. - shardTargeterMock(txn.get(), kShardId0)->setFindHostReturnValue(kShardHost0); - - MigrationStatuses migrationStatuses = _migrationManager->executeMigrationsForAutoBalance( - txn.get(), migrationRequests, 0, kDefaultSecondaryThrottle, false); - - for (const auto& migrateInfo : migrationRequests) { - ASSERT_EQ(ErrorCodes::LockBusy, migrationStatuses.at(migrateInfo.getName())); - } - }); - - // Expect two sequential moveChunk commands to the same shard, both of which fail with LockBusy. - expectMoveChunkCommand( - chunk1, - kShardId1, - false, - Status(ErrorCodes::LockBusy, "SameCollectionOldShardMigrations generated error.")); - expectMoveChunkCommand( - chunk1, - kShardId1, - true, - Status(ErrorCodes::LockBusy, "SameCollectionOldShardMigrations generated error.")); - - // Run the MigrationManager code. - future.timed_get(kFutureTimeout); -} - -// If in the same collection a migration is scheduled with an old v3.2 shard, a second migration in -// the collection with a different old v3.2 shard should get rescheduled. -TEST_F(MigrationManagerTest, SameCollectionTwoOldShardMigrations) { - // Set up two shards in the metadata. - ASSERT_OK(catalogClient()->insertConfigDocument( - operationContext(), ShardType::ConfigNS, kShard0, kMajorityWriteConcern)); - ASSERT_OK(catalogClient()->insertConfigDocument( - operationContext(), ShardType::ConfigNS, kShard2, kMajorityWriteConcern)); - - // 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()); - - setUpDatabase(dbName, kShardId0); - setUpCollection(collName, version); - - // Set up two chunks in the metadata. - ChunkType chunk1 = - setUpChunk(collName, kKeyPattern.globalMin(), BSON(kPattern << 49), kShardId0, version); - version.incMinor(); - ChunkType chunk2 = - setUpChunk(collName, BSON(kPattern << 49), kKeyPattern.globalMax(), kShardId2, version); - - // Going to request that these two chunks get migrated. - const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1}, {kShardId3, chunk2}}; - - auto future = launchAsync([this, migrationRequests] { - Client::initThreadIfNotAlready("Test"); - auto txn = cc().makeOperationContext(); - - // Scheduling the moveChunk commands requires finding a host to which to send the command. - // Set up dummy hosts for the source shards. - shardTargeterMock(txn.get(), kShardId0)->setFindHostReturnValue(kShardHost0); - shardTargeterMock(txn.get(), kShardId2)->setFindHostReturnValue(kShardHost2); - - MigrationStatuses migrationStatuses = _migrationManager->executeMigrationsForAutoBalance( - txn.get(), migrationRequests, 0, kDefaultSecondaryThrottle, false); - - for (const auto& migrateInfo : migrationRequests) { - ASSERT_OK(migrationStatuses.at(migrateInfo.getName())); - } - }); - - // Expect two failed moveChunk commands, then two successful moveChunk commands after the - // balancer releases the distributed lock. - expectMoveChunkCommand( - chunk1, - kShardId1, - false, - Status(ErrorCodes::LockBusy, "SameCollectionOldShardMigration generated error.")); - expectMoveChunkCommand( - chunk2, - kShardId3, - false, - Status(ErrorCodes::LockBusy, "SameCollectionOldShardMigration generated error.")); - expectMoveChunkCommand(chunk1, kShardId1, true, Status::OK()); - expectMoveChunkCommand(chunk2, kShardId3, true, Status::OK()); - - // Run the MigrationManager code. - future.timed_get(kFutureTimeout); -} - -// Takes the distributed lock for a collection so that that the MigrationManager is unable to -// schedule migrations for that collection. -TEST_F(MigrationManagerTest, FailToAcquireDistributedLock) { - // Set up two shards in the metadata. - ASSERT_OK(catalogClient()->insertConfigDocument( - operationContext(), ShardType::ConfigNS, kShard0, kMajorityWriteConcern)); - ASSERT_OK(catalogClient()->insertConfigDocument( - operationContext(), ShardType::ConfigNS, kShard2, kMajorityWriteConcern)); - - // 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()); - - setUpDatabase(dbName, kShardId0); - setUpCollection(collName, version); - - // Set up two chunks in the metadata. - ChunkType chunk1 = - setUpChunk(collName, kKeyPattern.globalMin(), BSON(kPattern << 49), kShardId0, version); - version.incMinor(); - ChunkType chunk2 = - setUpChunk(collName, BSON(kPattern << 49), kKeyPattern.globalMax(), kShardId2, version); - - // Going to request that these two chunks get migrated. - const std::vector<MigrateInfo> migrationRequests{{kShardId1, chunk1}, {kShardId3, chunk2}}; - - shardTargeterMock(operationContext(), kShardId0)->setFindHostReturnValue(kShardHost0); - shardTargeterMock(operationContext(), kShardId2)->setFindHostReturnValue(kShardHost2); - - // Take the distributed lock for the collection before scheduling via the MigrationManager. - const std::string whyMessage("FailToAcquireDistributedLock unit-test taking distributed lock"); - DistLockManager::ScopedDistLock distLockStatus = assertGet( - catalogClient()->getDistLockManager()->lock(operationContext(), - chunk1.getNS(), - whyMessage, - DistLockManager::kSingleLockAttemptTimeout)); - - MigrationStatuses migrationStatuses = _migrationManager->executeMigrationsForAutoBalance( - operationContext(), migrationRequests, 0, kDefaultSecondaryThrottle, false); - - for (const auto& migrateInfo : migrationRequests) { - ASSERT_EQ(ErrorCodes::ConflictingOperationInProgress, - migrationStatuses.at(migrateInfo.getName())); - } -} - // The MigrationManager should fail the migration if a host is not found for the source shard. // Scheduling a moveChunk command requires finding a host to which to send the command. TEST_F(MigrationManagerTest, SourceShardNotFound) { @@ -674,12 +446,13 @@ TEST_F(MigrationManagerTest, SourceShardNotFound) { }); // Expect only one moveChunk command to be called. - expectMoveChunkCommand(chunk1, kShardId1, false, Status::OK()); + expectMoveChunkCommand(chunk1, kShardId1, Status::OK()); // Run the MigrationManager code. future.timed_get(kFutureTimeout); } +// TODO: Delete in 3.8 TEST_F(MigrationManagerTest, JumboChunkResponseBackwardsCompatibility) { // Set up one shard in the metadata. ASSERT_OK(catalogClient()->insertConfigDocument( @@ -715,7 +488,7 @@ TEST_F(MigrationManagerTest, JumboChunkResponseBackwardsCompatibility) { }); // Expect only one moveChunk command to be called. - expectMoveChunkCommand(chunk1, kShardId1, false, BSON("ok" << 0 << "chunkTooBig" << true)); + expectMoveChunkCommand(chunk1, kShardId1, BSON("ok" << 0 << "chunkTooBig" << true)); // Run the MigrationManager code. future.timed_get(kFutureTimeout); @@ -839,7 +612,7 @@ TEST_F(MigrationManagerTest, RestartMigrationManager) { }); // Expect only one moveChunk command to be called. - expectMoveChunkCommand(chunk1, kShardId1, false, Status::OK()); + expectMoveChunkCommand(chunk1, kShardId1, Status::OK()); // Run the MigrationManager code. future.timed_get(kFutureTimeout); @@ -893,8 +666,8 @@ TEST_F(MigrationManagerTest, MigrationRecovery) { }); // Expect two moveChunk commands. - expectMoveChunkCommand(chunk1, kShardId1, false, Status::OK()); - expectMoveChunkCommand(chunk2, kShardId3, false, Status::OK()); + expectMoveChunkCommand(chunk1, kShardId1, Status::OK()); + expectMoveChunkCommand(chunk2, kShardId3, Status::OK()); // Run the MigrationManager code. future.timed_get(kFutureTimeout); @@ -1005,7 +778,6 @@ TEST_F(MigrationManagerTest, RemoteCallErrorConversionToOperationFailed) { expectMoveChunkCommand( chunk1, kShardId1, - false, Status(ErrorCodes::NotMasterOrSecondary, "RemoteCallErrorConversionToOperationFailedCheck generated error.")); @@ -1013,7 +785,6 @@ TEST_F(MigrationManagerTest, RemoteCallErrorConversionToOperationFailed) { expectMoveChunkCommand( chunk2, kShardId3, - false, Status(ErrorCodes::ExceededTimeLimit, "RemoteCallErrorConversionToOperationFailedCheck generated error.")); diff --git a/src/mongo/db/s/config/configsvr_commit_chunk_migration_command.cpp b/src/mongo/db/s/config/configsvr_commit_chunk_migration_command.cpp index 10da0444a4a..6e0f96328ee 100644 --- a/src/mongo/db/s/config/configsvr_commit_chunk_migration_command.cpp +++ b/src/mongo/db/s/config/configsvr_commit_chunk_migration_command.cpp @@ -46,15 +46,11 @@ #include "mongo/s/client/shard_registry.h" #include "mongo/s/grid.h" #include "mongo/s/request_types/commit_chunk_migration_request_type.h" -#include "mongo/util/fail_point.h" -#include "mongo/util/fail_point_service.h" #include "mongo/util/log.h" namespace mongo { namespace { -MONGO_FP_DECLARE(migrationCommitError); // delete this in 3.5 - /** * This command takes the chunk being migrated ("migratedChunk") and generates a new version for it * that is written along with its new shard location ("toShard") to the chunks collection. It also @@ -78,7 +74,6 @@ MONGO_FP_DECLARE(migrationCommitError); // delete this in 3.5 * migratedChunk: {min: <min_value>, max: <max_value>, etc. }, * controlChunk: {min: <min_value>, max: <max_value>, etc. }, (optional) * fromShardCollectionVersion: { shardVersionField: <version> }, (for backward compatibility only) - * shardHasDistributedLock: true/false (for backward compatibility only) * } * * Returns: @@ -122,49 +117,6 @@ public: return parseNsFullyQualified(dbname, cmdObj); } - /** - * Assures that the balancer still holds the collection distributed lock for this collection. If - * it no longer does, fail because we don't know if the collection state has changed -- e.g. - * whether it was/is dropping, whether another imcompatible migration is running, etc.. - */ - static Status checkBalancerHasDistLock(OperationContext* txn, - const NamespaceString& nss, - const ChunkType& chunk) { - auto balancerDistLockProcessID = - Grid::get(txn)->catalogClient(txn)->getDistLockManager()->getProcessID(); - - // Must use local read concern because we're going to perform subsequent writes. - auto lockQueryResponseWith = - Grid::get(txn)->shardRegistry()->getConfigShard()->exhaustiveFindOnConfig( - txn, - ReadPreferenceSetting{ReadPreference::PrimaryOnly}, - repl::ReadConcernLevel::kLocalReadConcern, - NamespaceString(LocksType::ConfigNS), - BSON(LocksType::process(balancerDistLockProcessID) << LocksType::name(nss.ns())), - BSONObj(), - boost::none); - if (!lockQueryResponseWith.isOK()) { - return lockQueryResponseWith.getStatus(); - } - - invariant(lockQueryResponseWith.getValue().docs.size() <= 1); - - if (MONGO_FAIL_POINT(migrationCommitError)) { - lockQueryResponseWith.getValue().docs.clear(); - } - - if (lockQueryResponseWith.getValue().docs.size() != 1) { - return Status( - ErrorCodes::BalancerLostDistributedLock, - str::stream() << "The distributed lock for collection '" << nss.ns() - << "' was lost by the balancer since this migration began. Cannot " - << "proceed with the migration commit for chunk (" - << chunk.getRange().toString() - << ") because it could corrupt other operations."); - } - return Status::OK(); - } - bool run(OperationContext* txn, const std::string& dbName, BSONObj& cmdObj, @@ -177,13 +129,6 @@ public: auto commitRequest = uassertStatusOK(CommitChunkMigrationRequest::createFromCommand(nss, cmdObj)); - if (!commitRequest.shardHasDistributedLock()) { - auto check = checkBalancerHasDistLock(txn, nss, commitRequest.getMigratedChunk()); - if (!check.isOK()) { - return appendCommandStatus(result, check); - } - } - StatusWith<BSONObj> response = Grid::get(txn)->catalogManager()->commitChunkMigration( txn, nss, diff --git a/src/mongo/db/s/migration_chunk_cloner_source_legacy_test.cpp b/src/mongo/db/s/migration_chunk_cloner_source_legacy_test.cpp index f0d4a42ecc9..fa83a3bd69e 100644 --- a/src/mongo/db/s/migration_chunk_cloner_source_legacy_test.cpp +++ b/src/mongo/db/s/migration_chunk_cloner_source_legacy_test.cpp @@ -145,7 +145,6 @@ protected: ChunkVersion(1, 0, OID::gen()), 1024 * 1024, MigrationSecondaryThrottleOptions::create(MigrationSecondaryThrottleOptions::kDefault), - false, false); return assertGet(MoveChunkRequest::createFromCommand(kNss, cmdBuilder.obj())); diff --git a/src/mongo/db/s/migration_source_manager.cpp b/src/mongo/db/s/migration_source_manager.cpp index f5ab20c0e37..3cca0606180 100644 --- a/src/mongo/db/s/migration_source_manager.cpp +++ b/src/mongo/db/s/migration_source_manager.cpp @@ -317,8 +317,7 @@ Status MigrationSourceManager::commitChunkMetadataOnConfig(OperationContext* txn _args.getToShardId(), migratedChunkType, controlChunkType, - _collectionMetadata->getCollVersion(), - _args.getTakeDistLock()); + _collectionMetadata->getCollVersion()); builder.append(kWriteConcernField, kMajorityWriteConcern.toBSON()); diff --git a/src/mongo/db/s/move_chunk_command.cpp b/src/mongo/db/s/move_chunk_command.cpp index 20b649a17df..d00b54b80c4 100644 --- a/src/mongo/db/s/move_chunk_command.cpp +++ b/src/mongo/db/s/move_chunk_command.cpp @@ -42,7 +42,6 @@ #include "mongo/db/s/migration_source_manager.h" #include "mongo/db/s/move_timing_helper.h" #include "mongo/db/s/sharding_state.h" -#include "mongo/s/catalog/dist_lock_manager.h" #include "mongo/s/client/shard_registry.h" #include "mongo/s/grid.h" #include "mongo/s/migration_secondary_throttle_options.h" @@ -58,30 +57,6 @@ using std::string; namespace { /** - * Acquires a distributed lock for the specified collection or throws if lock cannot be acquired. - */ -DistLockManager::ScopedDistLock acquireCollectionDistLock(OperationContext* txn, - const MoveChunkRequest& args) { - const string whyMessage(str::stream() - << "migrating chunk " - << ChunkRange(args.getMinKey(), args.getMaxKey()).toString() - << " in " - << args.getNss().ns()); - auto distLockStatus = Grid::get(txn)->catalogClient(txn)->getDistLockManager()->lock( - txn, args.getNss().ns(), whyMessage, DistLockManager::kSingleLockAttemptTimeout); - if (!distLockStatus.isOK()) { - const string msg = str::stream() - << "Could not acquire collection lock for " << args.getNss().ns() - << " to migrate chunk [" << redact(args.getMinKey()) << "," << redact(args.getMaxKey()) - << ") due to " << distLockStatus.getStatus().toString(); - warning() << msg; - uasserted(distLockStatus.getStatus().code(), msg); - } - - return std::move(distLockStatus.getValue()); -} - -/** * If the specified status is not OK logs a warning and throws a DBException corresponding to the * specified status. */ @@ -184,11 +159,11 @@ public: if (status == ErrorCodes::ChunkTooBig) { // This code is for compatibility with pre-3.2 balancer, which does not recognize the - // ChunkTooBig error code and instead uses the "chunkTooBig" field in the response. - // TODO: Remove after 3.4 is released. - errmsg = status.reason(); + // ChunkTooBig error code and instead uses the "chunkTooBig" field in the response, + // and the 3.4 shard, which failed to set the ChunkTooBig status code. + // TODO: Remove after 3.6 is released. result.appendBool("chunkTooBig", true); - return false; + return appendCommandStatus(result, status); } uassertStatusOK(status); @@ -232,12 +207,6 @@ private: BSONObj shardKeyPattern; { - // Acquire the collection distributed lock if necessary - boost::optional<DistLockManager::ScopedDistLock> scopedCollectionDistLock; - if (moveChunkRequest.getTakeDistLock()) { - scopedCollectionDistLock = acquireCollectionDistLock(txn, moveChunkRequest); - } - MigrationSourceManager migrationSourceManager( txn, moveChunkRequest, donorConnStr, recipientHost); @@ -254,19 +223,6 @@ private: moveTimingHelper.done(4); MONGO_FAIL_POINT_PAUSE_WHILE_SET(moveChunkHangAtStep4); - // Ensure the distributed lock is still held if this shard owns it. - if (moveChunkRequest.getTakeDistLock()) { - Status checkDistLockStatus = scopedCollectionDistLock->checkStatus(); - if (!checkDistLockStatus.isOK()) { - migrationSourceManager.cleanupOnError(txn); - - uassertStatusOKWithWarning( - {checkDistLockStatus.code(), - str::stream() << "not entering migrate critical section due to " - << checkDistLockStatus.toString()}); - } - } - uassertStatusOKWithWarning(migrationSourceManager.enterCriticalSection(txn)); uassertStatusOKWithWarning(migrationSourceManager.commitChunkOnRecipient(txn)); moveTimingHelper.done(5); diff --git a/src/mongo/s/move_chunk_request.cpp b/src/mongo/s/move_chunk_request.cpp index 1cfa5998c84..67174f71242 100644 --- a/src/mongo/s/move_chunk_request.cpp +++ b/src/mongo/s/move_chunk_request.cpp @@ -45,7 +45,7 @@ const char kFromShardId[] = "fromShard"; const char kToShardId[] = "toShard"; const char kMaxChunkSizeBytes[] = "maxChunkSizeBytes"; const char kWaitForDelete[] = "waitForDelete"; -const char kTakeDistLock[] = "takeDistLock"; +const char kTakeDistLock[] = "takeDistLock"; // TODO: delete in 3.8 } // namespace @@ -134,11 +134,13 @@ StatusWith<MoveChunkRequest> MoveChunkRequest::createFromCommand(NamespaceString request._maxChunkSizeBytes = static_cast<int64_t>(maxChunkSizeBytes); } - { - Status status = - bsonExtractBooleanFieldWithDefault(obj, kTakeDistLock, true, &request._takeDistLock); - if (!status.isOK()) { - return status; + { // TODO: delete this block in 3.8 + bool takeDistLock = false; + Status status = bsonExtractBooleanField(obj, kTakeDistLock, &takeDistLock); + if (status.isOK() && takeDistLock) { + return Status{ErrorCodes::IncompatibleShardingConfigVersion, + str::stream() + << "Request received from an older, incompatible mongodb version"}; } } @@ -155,8 +157,7 @@ void MoveChunkRequest::appendAsCommand(BSONObjBuilder* builder, ChunkVersion chunkVersion, int64_t maxChunkSizeBytes, const MigrationSecondaryThrottleOptions& secondaryThrottle, - bool waitForDelete, - bool takeDistLock) { + bool waitForDelete) { invariant(builder->asTempObj().isEmpty()); invariant(nss.isValid()); @@ -171,7 +172,7 @@ void MoveChunkRequest::appendAsCommand(BSONObjBuilder* builder, builder->append(kMaxChunkSizeBytes, static_cast<long long>(maxChunkSizeBytes)); secondaryThrottle.append(builder); builder->append(kWaitForDelete, waitForDelete); - builder->append(kTakeDistLock, takeDistLock); + builder->append(kTakeDistLock, false); } bool MoveChunkRequest::operator==(const MoveChunkRequest& other) const { diff --git a/src/mongo/s/move_chunk_request.h b/src/mongo/s/move_chunk_request.h index 538ab756fa3..3851acb703b 100644 --- a/src/mongo/s/move_chunk_request.h +++ b/src/mongo/s/move_chunk_request.h @@ -72,8 +72,7 @@ public: ChunkVersion chunkVersion, int64_t maxChunkSizeBytes, const MigrationSecondaryThrottleOptions& secondaryThrottle, - bool waitForDelete, - bool takeDistLock); + bool waitForDelete); const NamespaceString& getNss() const { return _nss; @@ -119,10 +118,6 @@ public: return _waitForDelete; } - bool getTakeDistLock() const { - return _takeDistLock; - } - /** * Returns true if the requests match exactly in terms of the field values and the order of * elements within the BSON-typed fields. @@ -172,9 +167,6 @@ private: // Whether to block and wait for the range deleter to cleanup the orphaned documents at the end // of move. bool _waitForDelete; - - // Whether to take the distributed lock for the collection or not. - bool _takeDistLock; }; } // namespace mongo diff --git a/src/mongo/s/move_chunk_request_test.cpp b/src/mongo/s/move_chunk_request_test.cpp index e4e60a46dfc..96053082832 100644 --- a/src/mongo/s/move_chunk_request_test.cpp +++ b/src/mongo/s/move_chunk_request_test.cpp @@ -58,7 +58,6 @@ TEST(MoveChunkRequest, Roundtrip) { chunkVersion, 1024, MigrationSecondaryThrottleOptions::create(MigrationSecondaryThrottleOptions::kOff), - true, true); BSONObj cmdObj = builder.obj(); @@ -77,7 +76,6 @@ TEST(MoveChunkRequest, Roundtrip) { ASSERT_EQ(MigrationSecondaryThrottleOptions::kOff, request.getSecondaryThrottle().getSecondaryThrottle()); ASSERT_EQ(true, request.getWaitForDelete()); - ASSERT_EQ(true, request.getTakeDistLock()); } TEST(MoveChunkRequest, BackwardsCompatibilityNoChunkVersionAndDefaults) { @@ -113,7 +111,6 @@ TEST(MoveChunkRequest, BackwardsCompatibilityNoChunkVersionAndDefaults) { ASSERT_EQ(MigrationSecondaryThrottleOptions::kDefault, request.getSecondaryThrottle().getSecondaryThrottle()); ASSERT_EQ(false, request.getWaitForDelete()); - ASSERT_EQ(true, request.getTakeDistLock()); } TEST(MoveChunkRequest, EqualityOperatorSameValue) { @@ -132,7 +129,6 @@ TEST(MoveChunkRequest, EqualityOperatorSameValue) { chunkVersion, 1024, MigrationSecondaryThrottleOptions::create(MigrationSecondaryThrottleOptions::kOff), - true, true); BSONObj obj = builder.obj(); @@ -162,7 +158,6 @@ TEST(MoveChunkRequest, EqualityOperatorDifferentValues) { chunkVersion, 1024, MigrationSecondaryThrottleOptions::create(MigrationSecondaryThrottleOptions::kOff), - true, true); auto value1 = assertGet( @@ -180,7 +175,6 @@ TEST(MoveChunkRequest, EqualityOperatorDifferentValues) { chunkVersion, 1024, MigrationSecondaryThrottleOptions::create(MigrationSecondaryThrottleOptions::kOff), - true, true); auto value2 = assertGet( MoveChunkRequest::createFromCommand(NamespaceString("TestDB", "TestColl"), builder2.obj())); diff --git a/src/mongo/s/request_types/commit_chunk_migration_request_test.cpp b/src/mongo/s/request_types/commit_chunk_migration_request_test.cpp index d9201693f2a..9c5f513ac60 100644 --- a/src/mongo/s/request_types/commit_chunk_migration_request_test.cpp +++ b/src/mongo/s/request_types/commit_chunk_migration_request_test.cpp @@ -40,7 +40,6 @@ using unittest::assertGet; namespace { const auto kNamespaceString = NamespaceString("TestDB", "TestColl"); -const auto kShardHasDistributedLock = false; const auto kShardId0 = ShardId("shard0"); const auto kShardId1 = ShardId("shard1"); @@ -72,8 +71,7 @@ TEST(CommitChunkMigrationRequest, WithControlChunk) { kShardId1, migratedChunk, controlChunkOpt, - fromShardCollectionVersion, - kShardHasDistributedLock); + fromShardCollectionVersion); BSONObj cmdObj = builder.obj(); @@ -89,7 +87,6 @@ TEST(CommitChunkMigrationRequest, WithControlChunk) { ASSERT_BSONOBJ_EQ(kKey2, request.getControlChunk()->getMin()); ASSERT_BSONOBJ_EQ(kKey3, request.getControlChunk()->getMax()); ASSERT_EQ(fromShardCollectionVersion.epoch(), request.getCollectionEpoch()); - ASSERT_EQ(kShardHasDistributedLock, request.shardHasDistributedLock()); } TEST(CommitChunkMigrationRequest, WithoutControlChunk) { @@ -107,8 +104,7 @@ TEST(CommitChunkMigrationRequest, WithoutControlChunk) { kShardId1, migratedChunk, boost::none, - fromShardCollectionVersion, - kShardHasDistributedLock); + fromShardCollectionVersion); BSONObj cmdObj = builder.obj(); @@ -122,7 +118,6 @@ TEST(CommitChunkMigrationRequest, WithoutControlChunk) { ASSERT_BSONOBJ_EQ(kKey1, request.getMigratedChunk().getMax()); ASSERT(!request.getControlChunk()); ASSERT_EQ(fromShardCollectionVersion.epoch(), request.getCollectionEpoch()); - ASSERT_EQ(kShardHasDistributedLock, request.shardHasDistributedLock()); } } // namespace diff --git a/src/mongo/s/request_types/commit_chunk_migration_request_type.cpp b/src/mongo/s/request_types/commit_chunk_migration_request_type.cpp index 4b9fbfd149d..d2998b43f1b 100644 --- a/src/mongo/s/request_types/commit_chunk_migration_request_type.cpp +++ b/src/mongo/s/request_types/commit_chunk_migration_request_type.cpp @@ -41,7 +41,6 @@ const char kToShard[] = "toShard"; const char kMigratedChunk[] = "migratedChunk"; const char kControlChunk[] = "controlChunk"; const char kFromShardCollectionVersion[] = "fromShardCollectionVersion"; -const char kShardHasDistributedLock[] = "shardHasDistributedLock"; /** * Attempts to parse a (range-only!) ChunkType from "field" in "source". @@ -133,14 +132,6 @@ StatusWith<CommitChunkMigrationRequest> CommitChunkMigrationRequest::createFromC request._collectionEpoch = statusWithChunkVersion.getValue().epoch(); } - { - Status shardHasDistLockStatus = bsonExtractBooleanField( - obj, kShardHasDistributedLock, &request._shardHasDistributedLock); - if (!shardHasDistLockStatus.isOK()) { - return shardHasDistLockStatus; - } - } - return request; } @@ -150,8 +141,7 @@ void CommitChunkMigrationRequest::appendAsCommand(BSONObjBuilder* builder, const ShardId& toShard, const ChunkType& migratedChunk, const boost::optional<ChunkType>& controlChunk, - const ChunkVersion& fromShardCollectionVersion, - const bool& shardHasDistributedLock) { + const ChunkVersion& fromShardCollectionVersion) { invariant(builder->asTempObj().isEmpty()); invariant(nss.isValid()); @@ -160,7 +150,6 @@ void CommitChunkMigrationRequest::appendAsCommand(BSONObjBuilder* builder, builder->append(kToShard, toShard.toString()); builder->append(kMigratedChunk, migratedChunk.toBSON()); fromShardCollectionVersion.appendWithFieldForCommands(builder, kFromShardCollectionVersion); - builder->append(kShardHasDistributedLock, shardHasDistributedLock); if (controlChunk) { builder->append(kControlChunk, controlChunk->toBSON()); diff --git a/src/mongo/s/request_types/commit_chunk_migration_request_type.h b/src/mongo/s/request_types/commit_chunk_migration_request_type.h index c1f97f5c7fc..919db71870d 100644 --- a/src/mongo/s/request_types/commit_chunk_migration_request_type.h +++ b/src/mongo/s/request_types/commit_chunk_migration_request_type.h @@ -41,7 +41,7 @@ namespace mongo { struct CommitChunkMigrationRequest { CommitChunkMigrationRequest(const NamespaceString& nss, const ChunkType& chunk) - : _nss(nss), _migratedChunk(chunk), _shardHasDistributedLock() {} + : _nss(nss), _migratedChunk(chunk) {} /** * Parses the input command and produces a request corresponding to its arguments. @@ -60,8 +60,7 @@ struct CommitChunkMigrationRequest { const ShardId& toShard, const ChunkType& migratedChunkType, const boost::optional<ChunkType>& controlChunkType, - const ChunkVersion& fromShardChunkVersion, - const bool& shardHasDistributedLock); + const ChunkVersion& fromShardChunkVersion); const NamespaceString& getNss() const { return _nss; @@ -78,11 +77,6 @@ struct CommitChunkMigrationRequest { const boost::optional<ChunkType>& getControlChunk() const { return _controlChunk; } - - bool shardHasDistributedLock() { - return _shardHasDistributedLock; - } - const OID& getCollectionEpoch() { return _collectionEpoch; } @@ -102,9 +96,6 @@ struct CommitChunkMigrationRequest { // A chunk on the shard moved from, if any remain. boost::optional<ChunkType> _controlChunk; - // Flag to indicate whether the shard has the distlock. - bool _shardHasDistributedLock; - OID _collectionEpoch; }; |