summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorSpencer T Brody <spencer@mongodb.com>2018-09-07 13:24:55 -0400
committerSpencer T Brody <spencer@mongodb.com>2018-09-10 16:54:26 -0400
commit976b19732685d132e636c34a5b2fe7462def0818 (patch)
tree9027b5976101da89a026dd9c75ed08bde161857f /src/mongo
parentb226e55c4ca7b8c1275d51f6a1300cfed2ec7d24 (diff)
downloadmongo-976b19732685d132e636c34a5b2fe7462def0818.tar.gz
SERVER-37048 Hold global intent lock whenever accessing the oplog collection pointer
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state.h7
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state_impl.cpp18
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state_impl.h1
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state_mock.cpp3
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state_mock.h1
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.cpp2
-rw-r--r--src/mongo/db/repl/storage_interface_impl.cpp6
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp2
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);