diff options
-rw-r--r-- | src/mongo/db/repl/initial_syncer.cpp | 18 | ||||
-rw-r--r-- | src/mongo/db/repl/storage_interface.h | 7 | ||||
-rw-r--r-- | src/mongo/db/repl/storage_interface_impl.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/repl/storage_interface_impl.h | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/storage_interface_mock.h | 4 |
5 files changed, 30 insertions, 6 deletions
diff --git a/src/mongo/db/repl/initial_syncer.cpp b/src/mongo/db/repl/initial_syncer.cpp index 0cf95dfe417..9c77306ef0b 100644 --- a/src/mongo/db/repl/initial_syncer.cpp +++ b/src/mongo/db/repl/initial_syncer.cpp @@ -802,6 +802,7 @@ void InitialSyncer::_lastOplogEntryFetcherCallbackForStopTimestamp( const StatusWith<Fetcher::QueryResponse>& result, std::shared_ptr<OnCompletionGuard> onCompletionGuard) { Timestamp oplogSeedDocTimestamp; + OpTimeWithHash optimeWithHash; { stdx::lock_guard<stdx::mutex> lock(_mutex); auto status = _checkForShutdownAndConvertStatus_inlock( @@ -817,15 +818,11 @@ void InitialSyncer::_lastOplogEntryFetcherCallbackForStopTimestamp( lock, optimeWithHashStatus.getStatus()); return; } - auto&& optimeWithHash = optimeWithHashStatus.getValue(); + optimeWithHash = optimeWithHashStatus.getValue(); oplogSeedDocTimestamp = _initialSyncState->stopTimestamp = optimeWithHash.opTime.getTimestamp(); - if (_initialSyncState->beginTimestamp == _initialSyncState->stopTimestamp) { - _lastApplied = optimeWithHash; - log() << "No need to apply operations. (currently at " - << _initialSyncState->stopTimestamp.toBSON() << ")"; - } else { + if (_initialSyncState->beginTimestamp != _initialSyncState->stopTimestamp) { invariant(_lastApplied.opTime.isNull()); _checkApplierProgressAndScheduleGetNextApplierBatch_inlock(lock, onCompletionGuard); return; @@ -854,9 +851,18 @@ void InitialSyncer::_lastOplogEntryFetcherCallbackForStopTimestamp( onCompletionGuard->setResultAndCancelRemainingWork_inlock(lock, status); return; } + + // This is necessary to ensure that the seed doc is visible in the oplog prior to setting + // _lastApplied. That way if any other node attempts to read from this node's oplog, it + // won't appear empty. + _storage->waitForAllEarlierOplogWritesToBeVisible(opCtx.get()); } stdx::lock_guard<stdx::mutex> lock(_mutex); + _lastApplied = optimeWithHash; + log() << "No need to apply operations. (currently at " + << _initialSyncState->stopTimestamp.toBSON() << ")"; + // This sets the error in 'onCompletionGuard' and shuts down the OplogFetcher on error. _scheduleRollbackCheckerCheckForRollback_inlock(lock, onCompletionGuard); } diff --git a/src/mongo/db/repl/storage_interface.h b/src/mongo/db/repl/storage_interface.h index 27507e790e8..840b40e2c16 100644 --- a/src/mongo/db/repl/storage_interface.h +++ b/src/mongo/db/repl/storage_interface.h @@ -305,6 +305,13 @@ public: * The 'stable' timestamp is set by calling StorageInterface::setStableTimestamp. */ virtual Status recoverToStableTimestamp(ServiceContext* serviceCtx) = 0; + + /** + * Waits for oplog writes to be visible in the oplog. + * This function is used to ensure tests do not fail due to initial sync receiving an empty + * batch. + */ + virtual void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) = 0; }; } // namespace repl diff --git a/src/mongo/db/repl/storage_interface_impl.cpp b/src/mongo/db/repl/storage_interface_impl.cpp index 35e67cbbe9f..db090542ed6 100644 --- a/src/mongo/db/repl/storage_interface_impl.cpp +++ b/src/mongo/db/repl/storage_interface_impl.cpp @@ -967,5 +967,10 @@ Status StorageInterfaceImpl::isAdminDbValid(OperationContext* opCtx) { return Status::OK(); } +void StorageInterfaceImpl::waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) { + AutoGetCollection oplog(opCtx, NamespaceString::kRsOplogNamespace, MODE_IS); + oplog.getCollection()->getRecordStore()->waitForAllEarlierOplogWritesToBeVisible(opCtx); +} + } // namespace repl } // namespace mongo diff --git a/src/mongo/db/repl/storage_interface_impl.h b/src/mongo/db/repl/storage_interface_impl.h index 572cf4eb992..2b8ba24f022 100644 --- a/src/mongo/db/repl/storage_interface_impl.h +++ b/src/mongo/db/repl/storage_interface_impl.h @@ -145,6 +145,8 @@ public: */ Status isAdminDbValid(OperationContext* opCtx) override; + void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) override; + private: const NamespaceString _rollbackIdNss; }; diff --git a/src/mongo/db/repl/storage_interface_mock.h b/src/mongo/db/repl/storage_interface_mock.h index 7526acfafa8..a0cd570cf8d 100644 --- a/src/mongo/db/repl/storage_interface_mock.h +++ b/src/mongo/db/repl/storage_interface_mock.h @@ -260,6 +260,10 @@ public: return isAdminDbValidFn(opCtx); }; + void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) override { + return; + } + // Testing functions. CreateCollectionForBulkFn createCollectionForBulkFn = [](const NamespaceString& nss, |