diff options
author | David Storch <david.storch@10gen.com> | 2014-10-21 15:37:06 -0400 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2014-10-21 17:43:50 -0400 |
commit | 11ad1edebfafea650ff00912bdf7a3a48dede144 (patch) | |
tree | 6b8c4aa4fc88bad42ff5cb8a1888fe5708d070cb | |
parent | a1a2e24b34d818cfed86b3ad5eb01d62bc375eaa (diff) | |
download | mongo-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.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/commands/write_commands/batch_executor.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/commands/write_commands/write_commands.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/dbhelpers.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/instance.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/ops/delete.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/ops/delete.h | 2 | ||||
-rw-r--r-- | src/mongo/db/ops/delete_executor.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/ops/delete_request.h | 6 | ||||
-rw-r--r-- | src/mongo/db/ops/update_executor.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/ops/update_request.h | 14 | ||||
-rw-r--r-- | src/mongo/db/repl/oplog.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/rs_rollback.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/ttl.cpp | 2 | ||||
-rw-r--r-- | src/mongo/s/d_migrate.cpp | 1 |
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 */, |