diff options
author | Eliot Horowitz <eliot@10gen.com> | 2014-11-03 11:42:15 -0500 |
---|---|---|
committer | Eliot Horowitz <eliot@10gen.com> | 2014-11-03 14:01:16 -0500 |
commit | 9b96c72ec4b8adb65480f33f752fd43b333414f0 (patch) | |
tree | 2d7cca0743617a471ebbc8e651a018089d702ebc /src/mongo | |
parent | ab7a1d27f130d0f920651181eafe19316c247b13 (diff) | |
download | mongo-9b96c72ec4b8adb65480f33f752fd43b333414f0.tar.gz |
SERVER-15888: WriteContext will switch from MODE_IX to MODE_X if collection doesn't exist
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/client.cpp | 9 | ||||
-rw-r--r-- | src/mongo/db/client.h | 4 | ||||
-rw-r--r-- | src/mongo/db/concurrency/d_concurrency.cpp | 13 | ||||
-rw-r--r-- | src/mongo/db/concurrency/d_concurrency.h | 2 |
4 files changed, 27 insertions, 1 deletions
diff --git a/src/mongo/db/client.cpp b/src/mongo/db/client.cpp index 9773f982c7f..7601acc5d42 100644 --- a/src/mongo/db/client.cpp +++ b/src/mongo/db/client.cpp @@ -279,7 +279,14 @@ namespace mongo { _autodb(opCtx, _nss.db(), MODE_IX), _collk(opCtx->lockState(), ns, MODE_IX), _c(opCtx, ns, _autodb.getDb(), _autodb.justCreated()) { - } + _collection = _c.db()->getCollection( _txn, ns ); + if ( !_collection && !_autodb.justCreated() ) { + // relock in MODE_X + _collk.relockWithMode( MODE_X, _autodb.lock() ); + Database* db = dbHolder().get(_txn, ns ); + invariant( db == _c.db() ); + } + } void Client::Context::checkNotStale() const { switch ( _client->_curOp->getOp() ) { diff --git a/src/mongo/db/client.h b/src/mongo/db/client.h index ce2d50717de..86cc28f8c39 100644 --- a/src/mongo/db/client.h +++ b/src/mongo/db/client.h @@ -106,6 +106,9 @@ namespace mongo { bool justCreated() { return _justCreated; } + + Lock::DBLock& lock() { return _dbLock; } + private: Lock::DBLock _dbLock; // not const, as we may need to relock for implicit create Database* _db; @@ -309,6 +312,7 @@ namespace mongo { AutoGetOrCreateDb _autodb; Lock::CollectionLock _collk; Context _c; + Collection* _collection; }; }; // class Client diff --git a/src/mongo/db/concurrency/d_concurrency.cpp b/src/mongo/db/concurrency/d_concurrency.cpp index f133466d9d7..4615b6ceb79 100644 --- a/src/mongo/db/concurrency/d_concurrency.cpp +++ b/src/mongo/db/concurrency/d_concurrency.cpp @@ -287,6 +287,19 @@ namespace mongo { } } + void Lock::CollectionLock::relockWithMode(LockMode mode, Lock::DBLock& dbLock ) { + if (supportsDocLocking() || enableCollectionLocking) { + _lockState->unlock(_id); + } + + dbLock.relockWithMode( mode ); + + if (supportsDocLocking() || enableCollectionLocking) { + _lockState->lock(_id, mode); + } + + } + Lock::ResourceLock::ResourceLock(Locker* lockState, ResourceId rid, LockMode mode) : _rid(rid), _lockState(lockState) { diff --git a/src/mongo/db/concurrency/d_concurrency.h b/src/mongo/db/concurrency/d_concurrency.h index bc2454469d1..9ae00cf2db4 100644 --- a/src/mongo/db/concurrency/d_concurrency.h +++ b/src/mongo/db/concurrency/d_concurrency.h @@ -211,6 +211,8 @@ namespace mongo { public: CollectionLock(Locker* lockState, const StringData& ns, const LockMode); virtual ~CollectionLock(); + + void relockWithMode( const LockMode mode, Lock::DBLock& dblock ); private: const ResourceId _id; Locker* _lockState; |