summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@mongodb.com>2014-10-20 18:28:02 -0400
committerAndy Schwerin <schwerin@mongodb.com>2014-10-21 13:01:50 -0400
commitda9927d08b550c4bec17ffc1b1d93ca3519285f6 (patch)
treea3e3f2032160ccf9cad91f16a793ef2cda455dd5 /src/mongo
parent6358990a2481ac63944e4758a96a383126895087 (diff)
downloadmongo-da9927d08b550c4bec17ffc1b1d93ca3519285f6.tar.gz
SERVER-15750 Break deadlock cycle by not holding the global lock while acquiring the bgsync mutex.
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/repl/bgsync.cpp28
-rw-r--r--src/mongo/db/repl/bgsync.h2
2 files changed, 19 insertions, 11 deletions
diff --git a/src/mongo/db/repl/bgsync.cpp b/src/mongo/db/repl/bgsync.cpp
index 46daa2a0816..f8679ead280 100644
--- a/src/mongo/db/repl/bgsync.cpp
+++ b/src/mongo/db/repl/bgsync.cpp
@@ -462,17 +462,13 @@ namespace {
void BackgroundSync::start(OperationContext* txn) {
massert(16235, "going to start syncing, but buffer is not empty", _buffer.empty());
- boost::unique_lock<boost::mutex> lock(_mutex);
+ long long updatedLastAppliedHash = _readLastAppliedHash(txn);
+ boost::lock_guard<boost::mutex> lk(_mutex);
_pause = false;
// reset _last fields with current oplog data
+ _lastAppliedHash = updatedLastAppliedHash;
_lastOpTimeFetched = _replCoord->getMyLastOptime();
- {
- Lock::DBLock lk(txn->lockState(), "local", MODE_X);
- WriteUnitOfWork uow(txn);
- loadLastAppliedHash(txn);
- uow.commit();
- }
_lastFetchedHash = _lastAppliedHash;
LOG(1) << "replset bgsync fetch queue set to: " << _lastOpTimeFetched <<
@@ -509,13 +505,23 @@ namespace {
}
void BackgroundSync::loadLastAppliedHash(OperationContext* txn) {
+ long long result = _readLastAppliedHash(txn);
+ boost::lock_guard<boost::mutex> lk(_mutex);
+ _lastAppliedHash = result;
+ }
+
+ long long BackgroundSync::_readLastAppliedHash(OperationContext* txn) {
BSONObj oplogEntry;
try {
- if (!Helpers::getLast(txn, rsoplog, oplogEntry)) {
+ // Uses WuoW because there is no way to demarcate a read transaction boundary.
+ Lock::DBLock lk(txn->lockState(), "local", MODE_X);
+ WriteUnitOfWork uow(txn);
+ bool success = Helpers::getLast(txn, rsoplog, oplogEntry);
+ uow.commit();
+ if (!success) {
// This can happen when we are to do an initial sync. lastHash will be set
// after the initial sync is complete.
- _lastAppliedHash = 0;
- return;
+ return 0;
}
}
catch (const DBException& ex) {
@@ -534,7 +540,7 @@ namespace {
typeName(hashElement.type());
fassertFailed(18903);
}
- _lastAppliedHash = hashElement.safeNumberLong();
+ return hashElement.safeNumberLong();
}
bool BackgroundSync::getInitialSyncRequestedFlag() {
diff --git a/src/mongo/db/repl/bgsync.h b/src/mongo/db/repl/bgsync.h
index 67b9a74d0d1..5d16e18f6c2 100644
--- a/src/mongo/db/repl/bgsync.h
+++ b/src/mongo/db/repl/bgsync.h
@@ -167,6 +167,8 @@ namespace repl {
// restart syncing
void start(OperationContext* txn);
+ long long _readLastAppliedHash(OperationContext* txn);
+
// A pointer to the replication coordinator running the show.
ReplicationCoordinator* _replCoord;