summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2015-02-04 14:40:58 -0500
committerRamon Fernandez <ramon@mongodb.com>2015-02-15 10:27:19 -0500
commite71db695221e39b3b6aa972d7503ca8c52c8fd55 (patch)
tree79097883f56123180bde4975d0ea2fcaaad0eda2
parent79492d9cc1885d74b31b5fe24194dbc227096d6e (diff)
downloadmongo-e71db695221e39b3b6aa972d7503ca8c52c8fd55.tar.gz
SERVER-17175 Use X lock for $isolated updates and deletes
(cherry picked from commit 7286fb36c36daaa8ee4941fa5f6c225b0a25dc61)
-rw-r--r--src/mongo/db/commands/write_commands/batch_executor.cpp6
-rw-r--r--src/mongo/db/instance.cpp8
-rw-r--r--src/mongo/db/ops/parsed_delete.cpp12
-rw-r--r--src/mongo/db/ops/parsed_delete.h5
-rw-r--r--src/mongo/db/ops/parsed_update.cpp12
-rw-r--r--src/mongo/db/ops/parsed_update.h5
6 files changed, 36 insertions, 12 deletions
diff --git a/src/mongo/db/commands/write_commands/batch_executor.cpp b/src/mongo/db/commands/write_commands/batch_executor.cpp
index 0d2560b486e..d42d4e1a826 100644
--- a/src/mongo/db/commands/write_commands/batch_executor.cpp
+++ b/src/mongo/db/commands/write_commands/batch_executor.cpp
@@ -1247,7 +1247,7 @@ namespace mongo {
Lock::DBLock dbLock(txn->lockState(), nsString.db(), MODE_IX);
Lock::CollectionLock colLock(txn->lockState(),
nsString.ns(),
- MODE_IX);
+ parsedUpdate.isIsolated() ? MODE_X : MODE_IX);
///////////////////////////////////////////
if (!checkIsMasterForDatabase(nsString, result)) {
@@ -1388,7 +1388,9 @@ namespace mongo {
break;
}
- Lock::CollectionLock collLock(txn->lockState(), nss.ns(), MODE_IX);
+ Lock::CollectionLock collLock(txn->lockState(),
+ nss.ns(),
+ parsedDelete.isIsolated() ? MODE_X : MODE_IX);
// getExecutorDelete() also checks if writes are allowed.
if (!checkIsMasterForDatabase(nss, result)) {
diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp
index 0b75def0e27..7b86671e723 100644
--- a/src/mongo/db/instance.cpp
+++ b/src/mongo/db/instance.cpp
@@ -594,7 +594,9 @@ namespace mongo {
// If DB doesn't exist, don't implicitly create it in Client::Context
break;
}
- Lock::CollectionLock colLock(txn->lockState(), ns.ns(), MODE_IX);
+ Lock::CollectionLock collLock(txn->lockState(),
+ ns.ns(),
+ parsedUpdate.isIsolated() ? MODE_X : MODE_IX);
Client::Context ctx(txn, ns);
// The common case: no implicit collection creation
@@ -707,7 +709,9 @@ namespace mongo {
break;
}
- Lock::CollectionLock colLock(txn->lockState(), ns.ns(), MODE_IX);
+ Lock::CollectionLock collLock(txn->lockState(),
+ ns.ns(),
+ parsedDelete.isIsolated() ? MODE_X : MODE_IX);
Client::Context ctx(txn, ns);
PlanExecutor* rawExec;
diff --git a/src/mongo/db/ops/parsed_delete.cpp b/src/mongo/db/ops/parsed_delete.cpp
index 1eb22ebab78..64a67c50f80 100644
--- a/src/mongo/db/ops/parsed_delete.cpp
+++ b/src/mongo/db/ops/parsed_delete.cpp
@@ -85,10 +85,14 @@ namespace mongo {
bool ParsedDelete::canYield() const {
return !_request->isGod() &&
- PlanExecutor::YIELD_AUTO == _request->getYieldPolicy() && (
- _canonicalQuery.get() ?
- !QueryPlannerCommon::hasNode(_canonicalQuery->root(), MatchExpression::ATOMIC) :
- !LiteParsedQuery::isQueryIsolated(_request->getQuery()));
+ PlanExecutor::YIELD_AUTO == _request->getYieldPolicy() &&
+ !isIsolated();
+ }
+
+ bool ParsedDelete::isIsolated() const {
+ return _canonicalQuery.get()
+ ? QueryPlannerCommon::hasNode(_canonicalQuery->root(), MatchExpression::ATOMIC)
+ : LiteParsedQuery::isQueryIsolated(_request->getQuery());
}
bool ParsedDelete::hasParsedQuery() const {
diff --git a/src/mongo/db/ops/parsed_delete.h b/src/mongo/db/ops/parsed_delete.h
index c117db28cb7..cb189bfccc8 100644
--- a/src/mongo/db/ops/parsed_delete.h
+++ b/src/mongo/db/ops/parsed_delete.h
@@ -84,6 +84,11 @@ namespace mongo {
bool canYield() const;
/**
+ * Is this update supposed to be isolated?
+ */
+ bool isIsolated() const;
+
+ /**
* As an optimization, we don't create a canonical query for updates with simple _id
* queries. Use this method to determine whether or not we actually parsed the query.
*/
diff --git a/src/mongo/db/ops/parsed_update.cpp b/src/mongo/db/ops/parsed_update.cpp
index 8570ee212d8..d6a26fdaed2 100644
--- a/src/mongo/db/ops/parsed_update.cpp
+++ b/src/mongo/db/ops/parsed_update.cpp
@@ -107,10 +107,14 @@ namespace mongo {
bool ParsedUpdate::canYield() const {
return !_request->isGod() &&
- PlanExecutor::YIELD_AUTO == _request->getYieldPolicy() && (
- _canonicalQuery.get() ?
- !QueryPlannerCommon::hasNode(_canonicalQuery->root(), MatchExpression::ATOMIC) :
- !LiteParsedQuery::isQueryIsolated(_request->getQuery()));
+ PlanExecutor::YIELD_AUTO == _request->getYieldPolicy() &&
+ !isIsolated();
+ }
+
+ bool ParsedUpdate::isIsolated() const {
+ return _canonicalQuery.get()
+ ? QueryPlannerCommon::hasNode(_canonicalQuery->root(), MatchExpression::ATOMIC)
+ : LiteParsedQuery::isQueryIsolated(_request->getQuery());
}
bool ParsedUpdate::hasParsedQuery() const {
diff --git a/src/mongo/db/ops/parsed_update.h b/src/mongo/db/ops/parsed_update.h
index f93a264b3b8..5a7854f93fa 100644
--- a/src/mongo/db/ops/parsed_update.h
+++ b/src/mongo/db/ops/parsed_update.h
@@ -89,6 +89,11 @@ namespace mongo {
bool canYield() const;
/**
+ * Is this update supposed to be isolated?
+ */
+ bool isIsolated() const;
+
+ /**
* As an optimization, we don't create a canonical query for updates with simple _id
* queries. Use this method to determine whether or not we actually parsed the query.
*/