summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2014-11-03 11:42:15 -0500
committerEliot Horowitz <eliot@10gen.com>2014-11-03 14:01:16 -0500
commit9b96c72ec4b8adb65480f33f752fd43b333414f0 (patch)
tree2d7cca0743617a471ebbc8e651a018089d702ebc /src/mongo
parentab7a1d27f130d0f920651181eafe19316c247b13 (diff)
downloadmongo-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.cpp9
-rw-r--r--src/mongo/db/client.h4
-rw-r--r--src/mongo/db/concurrency/d_concurrency.cpp13
-rw-r--r--src/mongo/db/concurrency/d_concurrency.h2
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;