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:55:41 -0400
commitd60fb7f0d2093519d9939aed3486fea3f9ab3228 (patch)
tree2cbadc05b79d599024ccb2296cb5b176ff3a61a0 /src/mongo
parentce32b09281eb8b661f4440e12fe72371d49fc2c1 (diff)
downloadmongo-d60fb7f0d2093519d9939aed3486fea3f9ab3228.tar.gz
SERVER-37048 Hold global intent lock whenever accessing the oplog collection pointer
(cherry picked from commit 976b19732685d132e636c34a5b2fe7462def0818)
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 58536d534c4..979ead025d1 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state.h
+++ b/src/mongo/db/repl/replication_coordinator_external_state.h
@@ -121,13 +121,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 e88fd127d56..543ac0108e8 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp
@@ -423,7 +423,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
@@ -457,22 +457,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 8607be1af20..78ed36f1a8e 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state_impl.h
+++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.h
@@ -78,7 +78,6 @@ public:
virtual ThreadPool* getDbWorkThreadPool() const override;
virtual Status runRepairOnLocalDB(OperationContext* opCtx) override;
virtual Status initializeReplSetStorage(OperationContext* opCtx, const BSONObj& config);
- virtual void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx);
void onDrainComplete(OperationContext* opCtx) override;
OpTime onTransitionToPrimary(OperationContext* opCtx, bool isV1ElectionProtocol) 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 5a4ab25d6e4..c168ab668df 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp
+++ b/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp
@@ -81,9 +81,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 e8169616079..dfff768c1fb 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state_mock.h
+++ b/src/mongo/db/repl/replication_coordinator_external_state_mock.h
@@ -67,7 +67,6 @@ public:
virtual ThreadPool* getDbWorkThreadPool() const override;
virtual Status runRepairOnLocalDB(OperationContext* opCtx) override;
virtual Status initializeReplSetStorage(OperationContext* opCtx, const BSONObj& config);
- virtual void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx);
void onDrainComplete(OperationContext* opCtx) override;
OpTime onTransitionToPrimary(OperationContext* opCtx, bool isV1ElectionProtocol) 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 271f5f64195..b6d1a634a9f 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl.cpp
@@ -1272,7 +1272,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 927d57b8f61..735ee035376 100644
--- a/src/mongo/db/repl/storage_interface_impl.cpp
+++ b/src/mongo/db/repl/storage_interface_impl.cpp
@@ -1125,16 +1125,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 07e1e0e8088..b08716f7a32 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
@@ -2015,7 +2015,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);