diff options
-rw-r--r-- | src/mongo/db/repl/initial_syncer.h | 4 | ||||
-rw-r--r-- | src/mongo/db/repl/initial_syncer_interface.h | 6 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_impl.cpp | 18 |
3 files changed, 28 insertions, 0 deletions
diff --git a/src/mongo/db/repl/initial_syncer.h b/src/mongo/db/repl/initial_syncer.h index 566bde4919f..177122e12d9 100644 --- a/src/mongo/db/repl/initial_syncer.h +++ b/src/mongo/db/repl/initial_syncer.h @@ -162,6 +162,10 @@ public: std::string getInitialSyncMethod() const final; + bool allowLocalDbAccess() const final { + return true; + } + Status startup(OperationContext* opCtx, std::uint32_t maxAttempts) noexcept final; Status shutdown() final; diff --git a/src/mongo/db/repl/initial_syncer_interface.h b/src/mongo/db/repl/initial_syncer_interface.h index 9bf683e99b8..b4a787bbc94 100644 --- a/src/mongo/db/repl/initial_syncer_interface.h +++ b/src/mongo/db/repl/initial_syncer_interface.h @@ -121,6 +121,12 @@ public: * Returns the initial sync method that this initial syncer is using. */ virtual std::string getInitialSyncMethod() const = 0; + + /** + * Returns whether user access to db 'local' should be allowed during this initial sync. + * Should be constant, and must not take any locks. + */ + virtual bool allowLocalDbAccess() const = 0; }; } // namespace repl diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index 4e4d1fa1aac..8ab52737ad5 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -2969,6 +2969,24 @@ Status ReplicationCoordinatorImpl::checkCanServeReadsFor_UNSAFE(OperationContext } } + // Non-oplog local reads from the user are not allowed during initial sync when the initial + // sync method disallows it. "isFromUserConnection" means DBDirectClient reads are not blocked; + // "isInternalClient" means reads from other cluster members are not blocked. + if (!isPrimaryOrSecondary && getReplicationMode() == modeReplSet && ns.db() == kLocalDB && + client->isFromUserConnection()) { + stdx::lock_guard<Latch> lock(_mutex); + auto isInternalClient = !client->session() || + (client->session()->getTags() & transport::Session::kInternalClient); + if (!isInternalClient && _memberState.startup2() && _initialSyncer && + !_initialSyncer->allowLocalDbAccess()) { + return Status{ErrorCodes::NotPrimaryOrSecondary, + str::stream() << "Local reads are not allowed during initial sync with " + "current initial sync method: " + << _initialSyncer->getInitialSyncMethod()}; + } + } + + if (canAcceptWritesFor_UNSAFE(opCtx, ns)) { return Status::OK(); } |