diff options
author | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2018-03-13 15:19:40 -0400 |
---|---|---|
committer | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2018-03-13 18:54:52 -0400 |
commit | 296f242fedb66eff99861f4fa3cda1ffc552ad9d (patch) | |
tree | 53eb40b543826af099429e06c36ef2575122efb6 | |
parent | a1b194059660d78afba0d8750231f48e4f77f2a6 (diff) | |
download | mongo-296f242fedb66eff99861f4fa3cda1ffc552ad9d.tar.gz |
SERVER-29908 Move the migration critical section out of MigrationSourceManager
-rw-r--r-- | src/mongo/db/s/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/s/collection_sharding_state.cpp | 35 | ||||
-rw-r--r-- | src/mongo/db/s/collection_sharding_state.h | 18 | ||||
-rw-r--r-- | src/mongo/db/s/database_sharding_state.cpp | 23 | ||||
-rw-r--r-- | src/mongo/db/s/database_sharding_state.h | 27 | ||||
-rw-r--r-- | src/mongo/db/s/flush_routing_table_cache_updates_command.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/s/migration_source_manager.cpp | 22 | ||||
-rw-r--r-- | src/mongo/db/s/migration_source_manager.h | 26 | ||||
-rw-r--r-- | src/mongo/db/s/set_shard_version_command.cpp | 34 | ||||
-rw-r--r-- | src/mongo/db/s/sharding_migration_critical_section.cpp | 70 | ||||
-rw-r--r-- | src/mongo/db/s/sharding_migration_critical_section.h | 91 |
11 files changed, 244 insertions, 115 deletions
diff --git a/src/mongo/db/s/SConscript b/src/mongo/db/s/SConscript index 4dbfef30d60..9d361d32ad0 100644 --- a/src/mongo/db/s/SConscript +++ b/src/mongo/db/s/SConscript @@ -15,6 +15,7 @@ env.Library( 'database_sharding_state.cpp', 'operation_sharding_state.cpp', 'sharded_connection_info.cpp', + 'sharding_migration_critical_section.cpp', ], LIBDEPS=[ '$BUILD_DIR/mongo/base', diff --git a/src/mongo/db/s/collection_sharding_state.cpp b/src/mongo/db/s/collection_sharding_state.cpp index a6a6765d754..9fd8c6c887e 100644 --- a/src/mongo/db/s/collection_sharding_state.cpp +++ b/src/mongo/db/s/collection_sharding_state.cpp @@ -37,7 +37,6 @@ #include "mongo/db/catalog_raii.h" #include "mongo/db/client.h" #include "mongo/db/operation_context.h" -#include "mongo/db/s/migration_chunk_cloner_source.h" #include "mongo/db/s/migration_source_manager.h" #include "mongo/db/s/operation_sharding_state.h" #include "mongo/db/s/sharded_connection_info.h" @@ -221,9 +220,19 @@ std::vector<ScopedCollectionMetadata> CollectionShardingState::overlappingMetada return _metadataManager->overlappingMetadata(_metadataManager, range); } +void CollectionShardingState::enterCriticalSectionCatchUpPhase(OperationContext* opCtx) { + invariant(opCtx->lockState()->isCollectionLockedForMode(_nss.ns(), MODE_X)); + _critSec.enterCriticalSectionCatchUpPhase(); +} + +void CollectionShardingState::enterCriticalSectionCommitPhase(OperationContext* opCtx) { + invariant(opCtx->lockState()->isCollectionLockedForMode(_nss.ns(), MODE_X)); + _critSec.enterCriticalSectionCommitPhase(); +} -MigrationSourceManager* CollectionShardingState::getMigrationSourceManager() { - return _sourceMgr; +void CollectionShardingState::exitCriticalSection(OperationContext* opCtx) { + invariant(opCtx->lockState()->isCollectionLockedForMode(_nss.ns(), MODE_X)); + _critSec.exitCriticalSection(); } void CollectionShardingState::setMigrationSourceManager(OperationContext* opCtx, @@ -401,18 +410,16 @@ bool CollectionShardingState::_checkShardVersionOk(OperationContext* opCtx, auto metadata = getMetadata(); *actualShardVersion = metadata ? metadata->getShardVersion() : ChunkVersion::UNSHARDED(); - if (_sourceMgr) { - const bool isReader = !opCtx->lockState()->isWriteLocked(); - - auto criticalSectionSignal = _sourceMgr->getMigrationCriticalSectionSignal(isReader); - if (criticalSectionSignal) { - *errmsg = str::stream() << "migration commit in progress for " << _nss.ns(); + auto criticalSectionSignal = _critSec.getSignal(opCtx->lockState()->isWriteLocked() + ? ShardingMigrationCriticalSection::kWrite + : ShardingMigrationCriticalSection::kRead); + if (criticalSectionSignal) { + *errmsg = str::stream() << "migration commit in progress for " << _nss.ns(); - // Set migration critical section on operation sharding state: operation will wait for - // the migration to finish before returning failure and retrying. - oss.setMigrationCriticalSectionSignal(criticalSectionSignal); - return false; - } + // Set migration critical section on operation sharding state: operation will wait for + // the migration to finish before returning failure and retrying. + oss.setMigrationCriticalSectionSignal(criticalSectionSignal); + return false; } if (expectedShardVersion->isWriteCompatibleWith(*actualShardVersion)) { diff --git a/src/mongo/db/s/collection_sharding_state.h b/src/mongo/db/s/collection_sharding_state.h index 14b403cd93f..51ff7d26435 100644 --- a/src/mongo/db/s/collection_sharding_state.h +++ b/src/mongo/db/s/collection_sharding_state.h @@ -35,6 +35,7 @@ #include "mongo/bson/bsonobj.h" #include "mongo/db/namespace_string.h" #include "mongo/db/s/metadata_manager.h" +#include "mongo/db/s/sharding_migration_critical_section.h" namespace mongo { @@ -153,9 +154,16 @@ public: std::vector<ScopedCollectionMetadata> overlappingMetadata(ChunkRange const& range) const; /** - * Returns the active migration source manager, if one is available. + * Methods to control the collection's critical section. Must be called with the collection X + * lock held. */ - MigrationSourceManager* getMigrationSourceManager(); + void enterCriticalSectionCatchUpPhase(OperationContext* opCtx); + void enterCriticalSectionCommitPhase(OperationContext* opCtx); + void exitCriticalSection(OperationContext* opCtx); + + auto getCriticalSectionSignal(ShardingMigrationCriticalSection::Operation op) const { + return _critSec.getSignal(op); + } /** * Attaches a migration source manager to this collection's sharding state. Must be called with @@ -164,6 +172,10 @@ public: */ void setMigrationSourceManager(OperationContext* opCtx, MigrationSourceManager* sourceMgr); + auto getMigrationSourceManager() const { + return _sourceMgr; + } + /** * Removes a migration source manager from this collection's sharding state. Must be called with * collection X lock. May not be called if there isn't a migration source manager installed @@ -255,6 +267,8 @@ private: // Contains all the metadata associated with this collection. std::shared_ptr<MetadataManager> _metadataManager; + ShardingMigrationCriticalSection _critSec; + // If this collection is serving as a source shard for chunk migration, this value will be // non-null. To write this value there needs to be X-lock on the collection in order to // synchronize with other callers, which read it. diff --git a/src/mongo/db/s/database_sharding_state.cpp b/src/mongo/db/s/database_sharding_state.cpp index a08d5dbcca6..ccd642527fc 100644 --- a/src/mongo/db/s/database_sharding_state.cpp +++ b/src/mongo/db/s/database_sharding_state.cpp @@ -45,28 +45,26 @@ const Database::Decoration<DatabaseShardingState> DatabaseShardingState::get = DatabaseShardingState::DatabaseShardingState() = default; -void DatabaseShardingState::enterCriticalSection(OperationContext* opCtx) { +void DatabaseShardingState::enterCriticalSectionCatchUpPhase(OperationContext* opCtx) { invariant(opCtx->lockState()->isDbLockedForMode(get.owner(this)->name(), MODE_X)); - invariant(!_critSecSignal); - _critSecSignal = std::make_shared<Notification<void>>(); + _critSec.enterCriticalSectionCatchUpPhase(); // TODO (SERVER-33313): call CursorManager::invalidateAll() on all collections in this database // with 'fromMovePrimary=true' and a predicate to only invalidate the cursor if the opCtx on its // PlanExecutor has a client dbVersion. } +void DatabaseShardingState::enterCriticalSectionCommitPhase(OperationContext* opCtx) { + invariant(opCtx->lockState()->isDbLockedForMode(get.owner(this)->name(), MODE_X)); + _critSec.enterCriticalSectionCommitPhase(); +} + void DatabaseShardingState::exitCriticalSection(OperationContext* opCtx, boost::optional<DatabaseVersion> newDbVersion) { invariant(opCtx->lockState()->isDbLockedForMode(get.owner(this)->name(), MODE_X)); - invariant(_critSecSignal); - _critSecSignal->set(); - _critSecSignal.reset(); + _critSec.exitCriticalSection(); _dbVersion = newDbVersion; } -std::shared_ptr<Notification<void>> DatabaseShardingState::getCriticalSectionSignal() const { - return _critSecSignal; -} - void DatabaseShardingState::setDbVersion(OperationContext* opCtx, boost::optional<DatabaseVersion> newDbVersion) { invariant(opCtx->lockState()->isDbLockedForMode(get.owner(this)->name(), MODE_X)); @@ -88,7 +86,10 @@ void DatabaseShardingState::checkDbVersion(OperationContext* opCtx) const { return; } - if (_critSecSignal) { + auto criticalSectionSignal = _critSec.getSignal(opCtx->lockState()->isWriteLocked() + ? ShardingMigrationCriticalSection::kWrite + : ShardingMigrationCriticalSection::kRead); + if (criticalSectionSignal) { // TODO (SERVER-33773): Set movePrimary critical section signal on the // OperationShardingState (so that the operation can wait outside the DBLock for the // movePrimary critical section to end before returning to the client). diff --git a/src/mongo/db/s/database_sharding_state.h b/src/mongo/db/s/database_sharding_state.h index 50e6e0239eb..d5e09aa55f0 100644 --- a/src/mongo/db/s/database_sharding_state.h +++ b/src/mongo/db/s/database_sharding_state.h @@ -30,6 +30,7 @@ #include "mongo/base/disallow_copying.h" #include "mongo/db/catalog/database.h" +#include "mongo/db/s/sharding_migration_critical_section.h" #include "mongo/s/database_version_gen.h" namespace mongo { @@ -49,25 +50,17 @@ public: ~DatabaseShardingState() = default; /** - * Assigns a new Notification to _critSecSignal and invalidates all yielded readers and writers - * on collections in Database that have a client dbVersion on their OperationContext. - * - * Invariants that _critSecSignal was null and that the caller holds the DBLock in X mode. - */ - void enterCriticalSection(OperationContext* opCtx); - - /** - * Signals and clears _critSecSignal, and sets _dbVersion to 'newDbVersion'. - * - * Invariants that _critSecSignal was not null and that the caller holds the DBLock in X mode. + * Methods to control the databases's critical section. Must be called with the database X lock + * held. */ + void enterCriticalSectionCatchUpPhase(OperationContext* opCtx); + void enterCriticalSectionCommitPhase(OperationContext* opCtx); void exitCriticalSection(OperationContext* opCtx, boost::optional<DatabaseVersion> newDbVersion); - /** - * Returns a shared_ptr to _critSecSignal if it's non-null, otherwise nullptr. - */ - std::shared_ptr<Notification<void>> getCriticalSectionSignal() const; + auto getCriticalSectionSignal(ShardingMigrationCriticalSection::Operation op) const { + return _critSec.getSignal(op); + } /** * Sets this shard server's cached dbVersion to newVersion. @@ -88,9 +81,7 @@ private: // mode is acceptable for reading it. (Note: accessing this class at all requires holding the // DBLock in some mode, since it requires having a pointer to the Database). - // Is non-null if this shard server is in a movePrimary critical section for the database. - // Stored as shared_ptr rather than boost::optional so callers can wait on it outside a DBLock. - std::shared_ptr<Notification<void>> _critSecSignal; + ShardingMigrationCriticalSection _critSec; // This shard server's cached dbVersion. If boost::none, indicates this shard server does not // know the dbVersion. diff --git a/src/mongo/db/s/flush_routing_table_cache_updates_command.cpp b/src/mongo/db/s/flush_routing_table_cache_updates_command.cpp index 660e86ee436..bd3d203ea53 100644 --- a/src/mongo/db/s/flush_routing_table_cache_updates_command.cpp +++ b/src/mongo/db/s/flush_routing_table_cache_updates_command.cpp @@ -129,13 +129,11 @@ public: // finish on the primary in case a secondary's caller has an afterClusterTime inclusive // of the commit (and new writes to the committed chunk) that hasn't yet propagated back // to this shard. This ensures the read your own writes causal consistency guarantee. - auto css = CollectionShardingState::get(opCtx, nss); - if (css->getMigrationSourceManager()) { - auto criticalSectionSignal = - css->getMigrationSourceManager()->getMigrationCriticalSectionSignal(true); - if (criticalSectionSignal) { - oss.setMigrationCriticalSectionSignal(criticalSectionSignal); - } + auto const css = CollectionShardingState::get(opCtx, nss); + auto criticalSectionSignal = + css->getCriticalSectionSignal(ShardingMigrationCriticalSection::kRead); + if (criticalSectionSignal) { + oss.setMigrationCriticalSectionSignal(criticalSectionSignal); } } diff --git a/src/mongo/db/s/migration_source_manager.cpp b/src/mongo/db/s/migration_source_manager.cpp index a7d0ed12d44..8f113193f1e 100644 --- a/src/mongo/db/s/migration_source_manager.cpp +++ b/src/mongo/db/s/migration_source_manager.cpp @@ -320,7 +320,8 @@ Status MigrationSourceManager::enterCriticalSection(OperationContext* opCtx) { AutoGetCollection autoColl(opCtx, getNss(), MODE_IX, MODE_X); // IMPORTANT: After this line, the critical section is in place and needs to be signaled - _critSecSignal = std::make_shared<Notification<void>>(); + CollectionShardingState::get(opCtx, _args.getNss()) + ->enterCriticalSectionCatchUpPhase(opCtx); } _state = kCriticalSection; @@ -423,7 +424,7 @@ Status MigrationSourceManager::commitChunkMetadataOnConfig(OperationContext* opC { UninterruptibleLockGuard noInterrupt(opCtx->lockState()); AutoGetCollection autoColl(opCtx, getNss(), MODE_IX, MODE_X); - _readsShouldWaitOnCritSec = true; + CollectionShardingState::get(opCtx, _args.getNss())->enterCriticalSectionCommitPhase(opCtx); } Timer t; @@ -692,9 +693,7 @@ void MigrationSourceManager::_cleanup(OperationContext* opCtx) { css->clearMigrationSourceManager(opCtx); // Leave the critical section. - if (_critSecSignal) { - _critSecSignal->set(); - } + CollectionShardingState::get(opCtx, _args.getNss())->exitCriticalSection(opCtx); return std::move(_cloneDriver); }(); @@ -731,19 +730,6 @@ void MigrationSourceManager::_cleanup(OperationContext* opCtx) { _state = kDone; } -std::shared_ptr<Notification<void>> MigrationSourceManager::getMigrationCriticalSectionSignal( - bool isForReadOnlyOperation) const { - if (!isForReadOnlyOperation) { - return _critSecSignal; - } - - if (_readsShouldWaitOnCritSec) { - return _critSecSignal; - } - - return nullptr; -} - BSONObj MigrationSourceManager::getMigrationStatusReport() const { return migrationutil::makeMigrationStatusDocument(getNss(), _args.getFromShardId(), diff --git a/src/mongo/db/s/migration_source_manager.h b/src/mongo/db/s/migration_source_manager.h index cb24599e519..9c37802441e 100644 --- a/src/mongo/db/s/migration_source_manager.h +++ b/src/mongo/db/s/migration_source_manager.h @@ -32,13 +32,12 @@ #include "mongo/base/disallow_copying.h" #include "mongo/db/s/collection_sharding_state.h" +#include "mongo/db/s/migration_chunk_cloner_source.h" #include "mongo/s/request_types/move_chunk_request.h" -#include "mongo/util/concurrency/notification.h" #include "mongo/util/timer.h" namespace mongo { -class MigrationChunkClonerSource; class OperationContext; struct ShardingStatistics; @@ -168,16 +167,6 @@ public: } /** - * Retrieves a critical section object to wait on. Will return nullptr if the migration is not - * yet in the critical section or if the caller is a reader and the migration is still in the - * process of transferring the last batch of chunk modifications. - * - * Must be called with some form of lock on the collection namespace. - */ - std::shared_ptr<Notification<void>> getMigrationCriticalSectionSignal( - bool isForReadOnlyOperation) const; - - /** * Returns a report on the active migration. * * Must be called with some form of lock on the collection namespace. @@ -238,19 +227,6 @@ private: // completed. std::unique_ptr<MigrationChunkClonerSource> _cloneDriver; - // Whether the source manager is in a critical section. Tracked as a shared pointer so that - // callers don't have to hold collection lock in order to wait on it. Available after the - // critical section stage has completed. - std::shared_ptr<Notification<void>> _critSecSignal; - - // Used to delay blocking reads up until the commit of the metadata on the config server needs - // to happen. This allows the shard to serve reads during transfer of the last batch of mods in - // the migration critical section. - // - // The transition from false to true is protected by the collection X-lock, which happens just - // before the config server metadata commit is scheduled. - bool _readsShouldWaitOnCritSec{false}; - // The statistics about a chunk migration to be included in moveChunk.commit BSONObj _recipientCloneCounts; }; diff --git a/src/mongo/db/s/set_shard_version_command.cpp b/src/mongo/db/s/set_shard_version_command.cpp index 076c00a820d..63818e7fe89 100644 --- a/src/mongo/db/s/set_shard_version_command.cpp +++ b/src/mongo/db/s/set_shard_version_command.cpp @@ -292,16 +292,13 @@ public: // TODO: Refactor all of this if (requestedVersion < collectionShardVersion && requestedVersion.epoch() == collectionShardVersion.epoch()) { - if (css->getMigrationSourceManager()) { - auto critSecSignal = - css->getMigrationSourceManager()->getMigrationCriticalSectionSignal( - false); - if (critSecSignal) { - collLock.reset(); - autoDb.reset(); - log() << "waiting till out of critical section"; - critSecSignal->waitFor(opCtx, Seconds(10)); - } + auto critSecSignal = + css->getCriticalSectionSignal(ShardingMigrationCriticalSection::kWrite); + if (critSecSignal) { + collLock.reset(); + autoDb.reset(); + log() << "waiting till out of critical section"; + critSecSignal->waitFor(opCtx, Seconds(10)); } errmsg = str::stream() << "shard global version for collection is higher " @@ -316,16 +313,13 @@ public: if (!collectionShardVersion.isSet() && !authoritative) { // Needed b/c when the last chunk is moved off a shard, the version gets reset // to zero, which should require a reload. - if (css->getMigrationSourceManager()) { - auto critSecSignal = - css->getMigrationSourceManager()->getMigrationCriticalSectionSignal( - false); - if (critSecSignal) { - collLock.reset(); - autoDb.reset(); - log() << "waiting till out of critical section"; - critSecSignal->waitFor(opCtx, Seconds(10)); - } + auto critSecSignal = + css->getCriticalSectionSignal(ShardingMigrationCriticalSection::kWrite); + if (critSecSignal) { + collLock.reset(); + autoDb.reset(); + log() << "waiting till out of critical section"; + critSecSignal->waitFor(opCtx, Seconds(10)); } // need authoritative for first look diff --git a/src/mongo/db/s/sharding_migration_critical_section.cpp b/src/mongo/db/s/sharding_migration_critical_section.cpp new file mode 100644 index 00000000000..210b9218c90 --- /dev/null +++ b/src/mongo/db/s/sharding_migration_critical_section.cpp @@ -0,0 +1,70 @@ +/** + * Copyright (C) 2018 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects + * for all of the code used other than as permitted herein. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you do not + * wish to do so, delete this exception statement from your version. If you + * delete this exception statement from all source files in the program, + * then also delete it in the license file. + */ + +#include "mongo/platform/basic.h" + +#include "mongo/db/s/sharding_migration_critical_section.h" + +namespace mongo { + +ShardingMigrationCriticalSection::ShardingMigrationCriticalSection() = default; + +ShardingMigrationCriticalSection::~ShardingMigrationCriticalSection() { + invariant(!_critSecSignal); +} + +void ShardingMigrationCriticalSection::enterCriticalSectionCatchUpPhase() { + invariant(!_critSecSignal); + _critSecSignal = std::make_shared<Notification<void>>(); + _readsShouldWaitOnCritSec = false; +} + +void ShardingMigrationCriticalSection::enterCriticalSectionCommitPhase() { + invariant(_critSecSignal); + _readsShouldWaitOnCritSec = true; +} + +void ShardingMigrationCriticalSection::exitCriticalSection() { + if (_critSecSignal) { + _critSecSignal->set(); + _critSecSignal.reset(); + } +} + +std::shared_ptr<Notification<void>> ShardingMigrationCriticalSection::getSignal( + Operation op) const { + if (!_critSecSignal) + return nullptr; + + if (op == kWrite || _readsShouldWaitOnCritSec) + return _critSecSignal; + + return nullptr; +} + +} // namespace mongo diff --git a/src/mongo/db/s/sharding_migration_critical_section.h b/src/mongo/db/s/sharding_migration_critical_section.h new file mode 100644 index 00000000000..32aa32f3b36 --- /dev/null +++ b/src/mongo/db/s/sharding_migration_critical_section.h @@ -0,0 +1,91 @@ +/** + * Copyright (C) 2018 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects + * for all of the code used other than as permitted herein. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you do not + * wish to do so, delete this exception statement from your version. If you + * delete this exception statement from all source files in the program, + * then also delete it in the license file. + */ + +#pragma once + +#include "mongo/base/disallow_copying.h" +#include "mongo/util/concurrency/notification.h" + +namespace mongo { + +/** + * Implements the critical section logic for particular collection or database in the sharding + * subsystem. It supports two phases - catch-up and commit. During the catch-up phase, only writes + * are disallowed, but reads can still proceed. In the commit phase, both reads and writes are + * disallowed. + * + * Currently, only collections stay in the catch-up phase while the last batch of mods is + * transferred to the recipient shard. Databases effectively only support the commit phase. + */ +class ShardingMigrationCriticalSection { + MONGO_DISALLOW_COPYING(ShardingMigrationCriticalSection); + +public: + ShardingMigrationCriticalSection(); + ~ShardingMigrationCriticalSection(); + + /** + * Enters the critical section in a mode, which still allows reads. + * + * NOTE: Must be called under the appropriate X lock (collection or database). + */ + void enterCriticalSectionCatchUpPhase(); + + /** + * Sets the critical section in a mode, which disallows reads. + */ + void enterCriticalSectionCommitPhase(); + + /** + * Leaves the critical section. + */ + void exitCriticalSection(); + + /** + * Retrieves a critical section notification to wait on. Will return nullptr if the migration is + * not yet in the critical section or if the caller is a reader and the migration is not yet in + * the commit phase. + */ + enum Operation { kRead, kWrite }; + std::shared_ptr<Notification<void>> getSignal(Operation op) const; + +private: + // Whether the migration source is in a critical section. Tracked as a shared pointer so that + // callers don't have to hold metadata locks in order to wait on it. + std::shared_ptr<Notification<void>> _critSecSignal; + + // Used to delay blocking reads up until the commit of the metadata on the config server needs + // to happen. This allows the shard to serve reads up until the config server metadata update + // needs to be committed. + // + // The transition from false to true is protected by the database or collection X-lock, which + // happens just before the config server metadata commit is scheduled. + bool _readsShouldWaitOnCritSec{false}; +}; + +} // namespace mongo |