Skip to content

Commit 49e92c7

Browse files
committed
SERVER-16415: Use new OplogIntentWriteLock
1 parent faaf37e commit 49e92c7

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

src/mongo/db/concurrency/d_concurrency.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030

3131
#include "mongo/db/concurrency/d_concurrency.h"
3232

33+
#include <string>
34+
3335
#include "mongo/db/concurrency/locker.h"
3436
#include "mongo/db/global_environment_experiment.h"
3537
#include "mongo/db/namespace_string.h"
@@ -49,6 +51,10 @@ namespace mongo {
4951
// SERVER-14668: Remove or invert sense once MMAPv1 CLL can be default
5052
MONGO_EXPORT_STARTUP_SERVER_PARAMETER(enableCollectionLocking, bool, true);
5153

54+
// Local Oplog. Used by OplogLock.
55+
static const ResourceId resourceIdOplog =
56+
ResourceId(RESOURCE_COLLECTION, StringData("local.oplog.rs"));
57+
5258
DBTryLockTimeoutException::DBTryLockTimeoutException() {}
5359
DBTryLockTimeoutException::~DBTryLockTimeoutException() throw() { }
5460

@@ -213,6 +219,29 @@ namespace mongo {
213219
}
214220
}
215221

222+
namespace {
223+
boost::mutex oplogSerialization; // for OplogIntentWriteLock
224+
} // namespace
225+
226+
Lock::OplogIntentWriteLock::OplogIntentWriteLock(Locker* lockState)
227+
: _lockState(lockState),
228+
_serialized(false) {
229+
_lockState->lock(resourceIdOplog, MODE_IX);
230+
}
231+
232+
Lock::OplogIntentWriteLock::~OplogIntentWriteLock() {
233+
if (_serialized) {
234+
oplogSerialization.unlock();
235+
}
236+
_lockState->unlock(resourceIdOplog);
237+
}
238+
239+
void Lock::OplogIntentWriteLock::serializeIfNeeded() {
240+
if (!supportsDocLocking() && !_serialized) {
241+
oplogSerialization.lock();
242+
_serialized = true;
243+
}
244+
}
216245

217246
Lock::ResourceLock::ResourceLock(Locker* lockState, ResourceId rid, LockMode mode)
218247
: _rid(rid),

src/mongo/db/concurrency/d_concurrency.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,22 @@ namespace mongo {
191191
Locker* const _lockState;
192192
};
193193

194+
/**
195+
* Like the CollectionLock, but optimized for the local oplog. Always locks in MODE_IX,
196+
* must call serializeIfNeeded() before doing any concurrent operations in order to
197+
* support storage engines without document level locking. It is an error, checked with a
198+
* dassert(), to not have a suitable database lock when taking this lock.
199+
*/
200+
class OplogIntentWriteLock {
201+
MONGO_DISALLOW_COPYING(OplogIntentWriteLock);
202+
public:
203+
explicit OplogIntentWriteLock(Locker* lockState);
204+
~OplogIntentWriteLock();
205+
void serializeIfNeeded();
206+
private:
207+
Locker* const _lockState;
208+
bool _serialized;
209+
};
194210

195211
/**
196212
* General purpose RAII wrapper for a resource managed by the lock manager

src/mongo/db/repl/oplog.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ namespace {
220220

221221
ScopedTransaction transaction(txn, MODE_IX);
222222
Lock::DBLock lk(txn->lockState(), "local", MODE_IX);
223-
Lock::CollectionLock lk2(txn->lockState(), rsoplog, MODE_IX);
223+
Lock::OplogIntentWriteLock oplogLk(txn->lockState());
224224

225225
DEV verify( logNS == 0 ); // check this was never a master/slave master
226226

@@ -241,11 +241,12 @@ namespace {
241241
Client::Context ctx(txn, rsoplog, localDB);
242242
WriteUnitOfWork wunit(txn);
243243

244-
std::pair<OpTime,long long> slot = getNextOpTime(txn,
245-
localOplogRSCollection,
246-
ns,
247-
replCoord,
248-
opstr);
244+
oplogLk.serializeIfNeeded();
245+
std::pair<OpTime, long long> slot = getNextOpTime(txn,
246+
localOplogRSCollection,
247+
ns,
248+
replCoord,
249+
opstr);
249250

250251
/* we jump through a bunch of hoops here to avoid copying the obj buffer twice --
251252
instead we do a single copy to the destination position in the memory mapped file.

0 commit comments

Comments
 (0)