diff options
author | Spencer T Brody <spencer@mongodb.com> | 2018-09-07 13:24:55 -0400 |
---|---|---|
committer | Spencer T Brody <spencer@mongodb.com> | 2018-09-10 16:54:26 -0400 |
commit | 976b19732685d132e636c34a5b2fe7462def0818 (patch) | |
tree | 9027b5976101da89a026dd9c75ed08bde161857f /src/mongo | |
parent | b226e55c4ca7b8c1275d51f6a1300cfed2ec7d24 (diff) | |
download | mongo-976b19732685d132e636c34a5b2fe7462def0818.tar.gz |
SERVER-37048 Hold global intent lock whenever accessing the oplog collection pointer
Diffstat (limited to 'src/mongo')
8 files changed, 7 insertions, 33 deletions
diff --git a/src/mongo/db/repl/replication_coordinator_external_state.h b/src/mongo/db/repl/replication_coordinator_external_state.h index c60353128d7..05b9a8e85d2 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state.h +++ b/src/mongo/db/repl/replication_coordinator_external_state.h @@ -115,13 +115,6 @@ public: virtual Status initializeReplSetStorage(OperationContext* opCtx, const BSONObj& config) = 0; /** - * Waits for all committed writes to be visible in the oplog. Committed writes will be hidden - * if there are uncommitted writes ahead of them, and some operations require that all committed - * writes are visible before proceeding. Throws if the oplog does not exist. - */ - virtual void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) = 0; - - /** * Called when a node on way to becoming a primary is ready to leave drain mode. It is called * outside of the global X lock and the replication coordinator mutex. * diff --git a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp index a640cf33987..cefbf8d3bd9 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp @@ -430,7 +430,7 @@ Status ReplicationCoordinatorExternalStateImpl::initializeReplSetStorage(Operati // retries and they will succeed. Unfortunately, initial sync will // fail if it finds its sync source has an empty oplog. Thus, we // need to wait here until the seed document is visible in our oplog. - waitForAllEarlierOplogWritesToBeVisible(opCtx); + _storageInterface->waitForAllEarlierOplogWritesToBeVisible(opCtx); }); // Update unique index format version for all non-replicated collections. It is possible @@ -463,22 +463,6 @@ Status ReplicationCoordinatorExternalStateImpl::initializeReplSetStorage(Operati return Status::OK(); } -void ReplicationCoordinatorExternalStateImpl::waitForAllEarlierOplogWritesToBeVisible( - OperationContext* opCtx) { - Collection* oplog; - { - // We don't want to be holding the collection lock while blocking, to avoid deadlocks. - // It is safe to store and access the oplog's Collection object after dropping the lock - // because the oplog is special and cannot be deleted on a running process. - // TODO(spencer): It should be possible to get the pointer to the oplog Collection object - // without ever having to take the collection lock. - AutoGetCollection oplogLock(opCtx, NamespaceString::kRsOplogNamespace, MODE_IS); - oplog = oplogLock.getCollection(); - } - uassert(ErrorCodes::NotYetInitialized, "The oplog does not exist", oplog); - oplog->getRecordStore()->waitForAllEarlierOplogWritesToBeVisible(opCtx); -} - void ReplicationCoordinatorExternalStateImpl::onDrainComplete(OperationContext* opCtx) { invariant(!opCtx->lockState()->isLocked()); diff --git a/src/mongo/db/repl/replication_coordinator_external_state_impl.h b/src/mongo/db/repl/replication_coordinator_external_state_impl.h index 4f8be81a4ba..57969506c85 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state_impl.h +++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.h @@ -77,7 +77,6 @@ public: virtual executor::TaskExecutor* getTaskExecutor() const override; virtual ThreadPool* getDbWorkThreadPool() const override; virtual Status initializeReplSetStorage(OperationContext* opCtx, const BSONObj& config); - virtual void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx); void onDrainComplete(OperationContext* opCtx) override; OpTime onTransitionToPrimary(OperationContext* opCtx) override; virtual void forwardSlaveProgress(); diff --git a/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp b/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp index 842fcf4fd27..614668b2a68 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp +++ b/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp @@ -77,9 +77,6 @@ Status ReplicationCoordinatorExternalStateMock::initializeReplSetStorage(Operati return storeLocalConfigDocument(opCtx, config); } -void ReplicationCoordinatorExternalStateMock::waitForAllEarlierOplogWritesToBeVisible( - OperationContext* opCtx) {} - void ReplicationCoordinatorExternalStateMock::shutdown(OperationContext*) {} executor::TaskExecutor* ReplicationCoordinatorExternalStateMock::getTaskExecutor() const { diff --git a/src/mongo/db/repl/replication_coordinator_external_state_mock.h b/src/mongo/db/repl/replication_coordinator_external_state_mock.h index 84e615280dd..d78589bd109 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state_mock.h +++ b/src/mongo/db/repl/replication_coordinator_external_state_mock.h @@ -66,7 +66,6 @@ public: virtual executor::TaskExecutor* getTaskExecutor() const override; virtual ThreadPool* getDbWorkThreadPool() const override; virtual Status initializeReplSetStorage(OperationContext* opCtx, const BSONObj& config); - virtual void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx); void onDrainComplete(OperationContext* opCtx) override; OpTime onTransitionToPrimary(OperationContext* opCtx) override; virtual void forwardSlaveProgress(); diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index b44c58039cd..dd1ad0f4ec9 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -1276,7 +1276,7 @@ Status ReplicationCoordinatorImpl::_waitUntilOpTime(OperationContext* opCtx, // This assumes the read concern is "local" level. // We need to wait for all committed writes to be visible, even in the oplog (which uses // special visibility rules). - _externalState->waitForAllEarlierOplogWritesToBeVisible(opCtx); + _storage->waitForAllEarlierOplogWritesToBeVisible(opCtx); } stdx::unique_lock<stdx::mutex> lock(_mutex); diff --git a/src/mongo/db/repl/storage_interface_impl.cpp b/src/mongo/db/repl/storage_interface_impl.cpp index e0775d5c0aa..0ff07324b01 100644 --- a/src/mongo/db/repl/storage_interface_impl.cpp +++ b/src/mongo/db/repl/storage_interface_impl.cpp @@ -1132,16 +1132,18 @@ Status StorageInterfaceImpl::isAdminDbValid(OperationContext* opCtx) { } void StorageInterfaceImpl::waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) { + Lock::GlobalLock lk(opCtx, MODE_IS); Collection* oplog; { // We don't want to be holding the collection lock while blocking, to avoid deadlocks. - // It is safe to store and access the oplog's Collection object after dropping the lock - // because the oplog is special and cannot be deleted on a running process. + // It is safe to store and access the oplog's Collection object with just the global IS + // lock because of the special concurrency rules for the oplog. // TODO(spencer): It should be possible to get the pointer to the oplog Collection object // without ever having to take the collection lock. AutoGetCollection oplogLock(opCtx, NamespaceString::kRsOplogNamespace, MODE_IS); oplog = oplogLock.getCollection(); } + uassert(ErrorCodes::NotYetInitialized, "The oplog does not exist", oplog); oplog->getRecordStore()->waitForAllEarlierOplogWritesToBeVisible(opCtx); } diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp index 72e9e39b064..82606cd83b5 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp @@ -2080,7 +2080,7 @@ void StandardWiredTigerRecordStore::setKey(WT_CURSOR* cursor, RecordId id) const std::unique_ptr<SeekableRecordCursor> StandardWiredTigerRecordStore::getCursor( OperationContext* opCtx, bool forward) const { - dassert(opCtx->lockState()->isReadLocked() || _isOplog); + dassert(opCtx->lockState()->isReadLocked()); if (_isOplog && forward) { WiredTigerRecoveryUnit* wru = WiredTigerRecoveryUnit::get(opCtx); |