summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2014-10-21 15:37:06 -0400
committerDavid Storch <david.storch@10gen.com>2014-10-21 17:43:50 -0400
commit11ad1edebfafea650ff00912bdf7a3a48dede144 (patch)
tree6b8c4aa4fc88bad42ff5cb8a1888fe5708d070cb
parenta1a2e24b34d818cfed86b3ad5eb01d62bc375eaa (diff)
downloadmongo-11ad1edebfafea650ff00912bdf7a3a48dede144.tar.gz
SERVER-15760 internally issued update and delete requests should not yield
This change adds a default yield policy of YIELD_MANUAL in the UpdateRequest and DeleteRequest, only setting it to YIELD_AUTO as needed. This prevents yielding in internal plans used for repl while inside a WriteUnitOfWork.
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp6
-rw-r--r--src/mongo/db/commands/write_commands/batch_executor.cpp7
-rw-r--r--src/mongo/db/commands/write_commands/write_commands.cpp6
-rw-r--r--src/mongo/db/dbhelpers.cpp2
-rw-r--r--src/mongo/db/instance.cpp6
-rw-r--r--src/mongo/db/ops/delete.cpp2
-rw-r--r--src/mongo/db/ops/delete.h2
-rw-r--r--src/mongo/db/ops/delete_executor.cpp3
-rw-r--r--src/mongo/db/ops/delete_request.h6
-rw-r--r--src/mongo/db/ops/update_executor.cpp3
-rw-r--r--src/mongo/db/ops/update_request.h14
-rw-r--r--src/mongo/db/repl/oplog.cpp2
-rw-r--r--src/mongo/db/repl/rs_rollback.cpp1
-rw-r--r--src/mongo/db/ttl.cpp2
-rw-r--r--src/mongo/s/d_migrate.cpp1
15 files changed, 55 insertions, 8 deletions
diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp
index 54e20e0f035..19d2db39f34 100644
--- a/src/mongo/db/commands/find_and_modify.cpp
+++ b/src/mongo/db/commands/find_and_modify.cpp
@@ -267,7 +267,8 @@ namespace mongo {
if ( remove ) {
_appendHelper(result, doc, found, fields, whereCallback);
if ( found ) {
- deleteObjects(txn, cx.db(), ns, queryModified, true, true);
+ deleteObjects(txn, cx.db(), ns, queryModified, PlanExecutor::YIELD_AUTO,
+ true, true);
BSONObjBuilder le( result.subobjStart( "lastErrorObject" ) );
le.appendNumber( "n" , 1 );
le.done();
@@ -293,6 +294,9 @@ namespace mongo {
request.setUpdates(update);
request.setUpsert(upsert);
request.setUpdateOpLog();
+
+ request.setYieldPolicy(PlanExecutor::YIELD_AUTO);
+
// TODO(greg) We need to send if we are ignoring
// the shard version below, but for now no
UpdateLifecycleImpl updateLifecycle(false, requestNs);
diff --git a/src/mongo/db/commands/write_commands/batch_executor.cpp b/src/mongo/db/commands/write_commands/batch_executor.cpp
index 2d9a32db49e..21a1014d5ce 100644
--- a/src/mongo/db/commands/write_commands/batch_executor.cpp
+++ b/src/mongo/db/commands/write_commands/batch_executor.cpp
@@ -1137,6 +1137,9 @@ namespace mongo {
UpdateLifecycleImpl updateLifecycle(true, request.getNamespaceString());
request.setLifecycle(&updateLifecycle);
+ // Updates from the write commands path can yield.
+ request.setYieldPolicy(PlanExecutor::YIELD_AUTO);
+
UpdateExecutor executor(&request, &txn->getCurOp()->debug());
Status status = executor.prepare();
if (!status.isOK()) {
@@ -1249,6 +1252,10 @@ namespace mongo {
request.setMulti( removeItem.getDelete()->getLimit() != 1 );
request.setUpdateOpLog(true);
request.setGod( false );
+
+ // Deletes running through the write commands path can yield.
+ request.setYieldPolicy(PlanExecutor::YIELD_AUTO);
+
DeleteExecutor executor( &request );
Status status = executor.prepare();
if ( !status.isOK() ) {
diff --git a/src/mongo/db/commands/write_commands/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp
index ad455c2edb3..c2c00052214 100644
--- a/src/mongo/db/commands/write_commands/write_commands.cpp
+++ b/src/mongo/db/commands/write_commands/write_commands.cpp
@@ -201,6 +201,9 @@ namespace mongo {
updateRequest.setLifecycle( &updateLifecycle );
updateRequest.setExplain();
+ // Explained updates can yield.
+ updateRequest.setYieldPolicy(PlanExecutor::YIELD_AUTO);
+
// Use the request to create an UpdateExecutor, and from it extract the
// plan tree which will be used to execute this update.
UpdateExecutor updateExecutor( &updateRequest, &txn->getCurOp()->debug() );
@@ -236,6 +239,9 @@ namespace mongo {
deleteRequest.setGod( false );
deleteRequest.setExplain();
+ // Explained deletes can yield.
+ deleteRequest.setYieldPolicy(PlanExecutor::YIELD_AUTO);
+
// Use the request to create a DeleteExecutor, and from it extract the
// plan tree which will be used to execute this update.
DeleteExecutor deleteExecutor( &deleteRequest );
diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp
index 2adb42d3d87..116fa9e9379 100644
--- a/src/mongo/db/dbhelpers.cpp
+++ b/src/mongo/db/dbhelpers.cpp
@@ -583,7 +583,7 @@ namespace mongo {
void Helpers::emptyCollection(OperationContext* txn, const char *ns) {
Client::Context context(txn, ns);
- deleteObjects(txn, context.db(), ns, BSONObj(), false);
+ deleteObjects(txn, context.db(), ns, BSONObj(), PlanExecutor::YIELD_MANUAL, false);
}
Helpers::RemoveSaver::RemoveSaver( const string& a , const string& b , const string& why)
diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp
index dc442c6782d..114f8d74ba8 100644
--- a/src/mongo/db/instance.cpp
+++ b/src/mongo/db/instance.cpp
@@ -619,6 +619,9 @@ namespace mongo {
request.setUpdateOpLog(); // TODO: This is wasteful if repl is not active.
UpdateLifecycleImpl updateLifecycle(broadcast, ns);
request.setLifecycle(&updateLifecycle);
+
+ request.setYieldPolicy(PlanExecutor::YIELD_AUTO);
+
UpdateExecutor executor(&request, &op.debug());
uassertStatusOK(executor.prepare());
@@ -698,6 +701,9 @@ namespace mongo {
request.setQuery(pattern);
request.setMulti(!justOne);
request.setUpdateOpLog(true);
+
+ request.setYieldPolicy(PlanExecutor::YIELD_AUTO);
+
DeleteExecutor executor(&request);
uassertStatusOK(executor.prepare());
diff --git a/src/mongo/db/ops/delete.cpp b/src/mongo/db/ops/delete.cpp
index bd50b671a14..34016c91a92 100644
--- a/src/mongo/db/ops/delete.cpp
+++ b/src/mongo/db/ops/delete.cpp
@@ -42,6 +42,7 @@ namespace mongo {
Database* db,
const StringData& ns,
BSONObj pattern,
+ PlanExecutor::YieldPolicy policy,
bool justOne,
bool logop,
bool god,
@@ -53,6 +54,7 @@ namespace mongo {
request.setUpdateOpLog(logop);
request.setGod(god);
request.setFromMigrate(fromMigrate);
+ request.setYieldPolicy(policy);
DeleteExecutor executor(&request);
return executor.execute(db);
}
diff --git a/src/mongo/db/ops/delete.h b/src/mongo/db/ops/delete.h
index a947167f985..0367ce8c165 100644
--- a/src/mongo/db/ops/delete.h
+++ b/src/mongo/db/ops/delete.h
@@ -31,6 +31,7 @@
#pragma once
#include "mongo/db/jsobj.h"
+#include "mongo/db/query/plan_executor.h"
namespace mongo {
@@ -43,6 +44,7 @@ namespace mongo {
Database* db,
const StringData& ns,
BSONObj pattern,
+ PlanExecutor::YieldPolicy policy,
bool justOne,
bool logop = false,
bool god = false,
diff --git a/src/mongo/db/ops/delete_executor.cpp b/src/mongo/db/ops/delete_executor.cpp
index aca3a86bb97..aa7515d9f44 100644
--- a/src/mongo/db/ops/delete_executor.cpp
+++ b/src/mongo/db/ops/delete_executor.cpp
@@ -128,7 +128,8 @@ namespace mongo {
// If yielding is allowed for this plan, then set an auto yield policy. Otherwise set
// a manual yield policy.
- const bool canYield = !_request->isGod() && (
+ const bool canYield = !_request->isGod() &&
+ PlanExecutor::YIELD_AUTO == _request->getYieldPolicy() && (
_canonicalQuery.get() ?
!QueryPlannerCommon::hasNode(_canonicalQuery->root(), MatchExpression::ATOMIC) :
!LiteParsedQuery::isQueryIsolated(_request->getQuery()));
diff --git a/src/mongo/db/ops/delete_request.h b/src/mongo/db/ops/delete_request.h
index ee58c59d476..f1378da5533 100644
--- a/src/mongo/db/ops/delete_request.h
+++ b/src/mongo/db/ops/delete_request.h
@@ -46,7 +46,8 @@ namespace mongo {
_logop(false),
_god(false),
_fromMigrate(false),
- _isExplain(false) {}
+ _isExplain(false),
+ _yieldPolicy(PlanExecutor::YIELD_MANUAL) {}
void setQuery(const BSONObj& query) { _query = query; }
void setMulti(bool multi = true) { _multi = multi; }
@@ -54,6 +55,7 @@ namespace mongo {
void setGod(bool god = true) { _god = god; }
void setFromMigrate(bool fromMigrate = true) { _fromMigrate = fromMigrate; }
void setExplain(bool isExplain = true) { _isExplain = isExplain; }
+ void setYieldPolicy(PlanExecutor::YieldPolicy yieldPolicy) { _yieldPolicy = yieldPolicy; }
const NamespaceString& getNamespaceString() const { return _nsString; }
const BSONObj& getQuery() const { return _query; }
@@ -63,6 +65,7 @@ namespace mongo {
bool isFromMigrate() const { return _fromMigrate; }
bool isExplain() const { return _isExplain; }
OperationContext* getOpCtx() const { return _txn; }
+ PlanExecutor::YieldPolicy getYieldPolicy() const { return _yieldPolicy; }
std::string toString() const;
@@ -75,6 +78,7 @@ namespace mongo {
bool _god;
bool _fromMigrate;
bool _isExplain;
+ PlanExecutor::YieldPolicy _yieldPolicy;
};
} // namespace mongo
diff --git a/src/mongo/db/ops/update_executor.cpp b/src/mongo/db/ops/update_executor.cpp
index c5de729a45f..7e7748f4159 100644
--- a/src/mongo/db/ops/update_executor.cpp
+++ b/src/mongo/db/ops/update_executor.cpp
@@ -162,7 +162,8 @@ namespace mongo {
// If yielding is allowed for this plan, then set an auto yield policy. Otherwise set
// a manual yield policy.
- const bool canYield = !_request->isGod() && (
+ const bool canYield = !_request->isGod() &&
+ PlanExecutor::YIELD_AUTO == _request->getYieldPolicy() && (
_canonicalQuery.get() ?
!QueryPlannerCommon::hasNode(_canonicalQuery->root(), MatchExpression::ATOMIC) :
!LiteParsedQuery::isQueryIsolated(_request->getQuery()));
diff --git a/src/mongo/db/ops/update_request.h b/src/mongo/db/ops/update_request.h
index 8bc42db69d4..381a012912b 100644
--- a/src/mongo/db/ops/update_request.h
+++ b/src/mongo/db/ops/update_request.h
@@ -53,7 +53,8 @@ namespace mongo {
, _fromMigration(false)
, _fromReplication(false)
, _lifecycle(NULL)
- , _isExplain(false) {}
+ , _isExplain(false)
+ , _yieldPolicy(PlanExecutor::YIELD_MANUAL) {}
const NamespaceString& getNamespaceString() const {
return _nsString;
@@ -146,6 +147,14 @@ namespace mongo {
return _isExplain;
}
+ inline void setYieldPolicy(PlanExecutor::YieldPolicy yieldPolicy) {
+ _yieldPolicy = yieldPolicy;
+ }
+
+ inline PlanExecutor::YieldPolicy getYieldPolicy() const {
+ return _yieldPolicy;
+ }
+
const std::string toString() const {
return str::stream()
<< " query: " << _query
@@ -198,6 +207,9 @@ namespace mongo {
// Whether or not we are requesting an explained update. Explained updates are read-only.
bool _isExplain;
+ // Whether or not the update should yield. Defaults to YIELD_MANUAL.
+ PlanExecutor::YieldPolicy _yieldPolicy;
+
};
} // namespace mongo
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index 5d72d19647a..dede9d0f475 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -736,7 +736,7 @@ namespace repl {
else if ( *opType == 'd' ) {
opCounters->gotDelete();
if ( opType[1] == 0 )
- deleteObjects(txn, db, ns, o, /*justOne*/ valueB);
+ deleteObjects(txn, db, ns, o, PlanExecutor::YIELD_MANUAL, /*justOne*/ valueB);
else
verify( opType[1] == 'b' ); // "db" advertisement
}
diff --git a/src/mongo/db/repl/rs_rollback.cpp b/src/mongo/db/repl/rs_rollback.cpp
index 12d3a028db2..97cafc3d849 100644
--- a/src/mongo/db/repl/rs_rollback.cpp
+++ b/src/mongo/db/repl/rs_rollback.cpp
@@ -630,6 +630,7 @@ namespace {
ctx.db(),
doc.ns,
pattern,
+ PlanExecutor::YIELD_MANUAL,
true, // justone
false, // logop
true); // god
diff --git a/src/mongo/db/ttl.cpp b/src/mongo/db/ttl.cpp
index 01666e0541e..9eafb0ef964 100644
--- a/src/mongo/db/ttl.cpp
+++ b/src/mongo/db/ttl.cpp
@@ -236,7 +236,7 @@ namespace mongo {
}
WriteUnitOfWork uow( txn );
- n = deleteObjects( txn, db, ns, query, false, true );
+ n = deleteObjects( txn, db, ns, query, PlanExecutor::YIELD_AUTO, false, true );
ttlDeletedDocuments.increment( n );
uow.commit();
}
diff --git a/src/mongo/s/d_migrate.cpp b/src/mongo/s/d_migrate.cpp
index a992d044be4..20a7edfc3f1 100644
--- a/src/mongo/s/d_migrate.cpp
+++ b/src/mongo/s/d_migrate.cpp
@@ -2149,6 +2149,7 @@ namespace mongo {
ctx.db(),
ns,
id,
+ PlanExecutor::YIELD_MANUAL,
true /* justOne */,
true /* logOp */,
false /* god */,