diff options
author | Andy Schwerin <schwerin@mongodb.com> | 2014-10-20 18:28:02 -0400 |
---|---|---|
committer | Andy Schwerin <schwerin@mongodb.com> | 2014-10-21 13:01:50 -0400 |
commit | da9927d08b550c4bec17ffc1b1d93ca3519285f6 (patch) | |
tree | a3e3f2032160ccf9cad91f16a793ef2cda455dd5 /src/mongo | |
parent | 6358990a2481ac63944e4758a96a383126895087 (diff) | |
download | mongo-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.cpp | 28 | ||||
-rw-r--r-- | src/mongo/db/repl/bgsync.h | 2 |
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; |