summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/commands/count.cpp2
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp9
-rw-r--r--src/mongo/db/commands/geo_near_cmd.cpp2
-rw-r--r--src/mongo/db/commands/group.cpp2
-rw-r--r--src/mongo/db/commands/index_filter_commands.cpp32
-rw-r--r--src/mongo/db/commands/index_filter_commands.h10
-rw-r--r--src/mongo/db/commands/index_filter_commands_test.cpp58
-rw-r--r--src/mongo/db/commands/mr.cpp4
-rw-r--r--src/mongo/db/commands/plan_cache_commands.cpp26
-rw-r--r--src/mongo/db/commands/plan_cache_commands.h16
-rw-r--r--src/mongo/db/commands/plan_cache_commands_test.cpp58
-rw-r--r--src/mongo/db/commands/write_commands/batch_executor.cpp8
-rw-r--r--src/mongo/db/dbhelpers.cpp14
-rw-r--r--src/mongo/db/exec/stagedebug_cmd.cpp2
-rw-r--r--src/mongo/db/exec/subplan.cpp2
-rw-r--r--src/mongo/db/fts/fts_command_mongod.cpp2
-rw-r--r--src/mongo/db/instance.cpp14
-rw-r--r--src/mongo/db/matcher/expression_parser.h12
-rw-r--r--src/mongo/db/matcher/expression_where.cpp26
-rw-r--r--src/mongo/db/ops/delete.cpp4
-rw-r--r--src/mongo/db/ops/delete_executor.cpp26
-rw-r--r--src/mongo/db/ops/delete_executor.h2
-rw-r--r--src/mongo/db/ops/delete_request.h5
-rw-r--r--src/mongo/db/ops/update.cpp47
-rw-r--r--src/mongo/db/ops/update.h6
-rw-r--r--src/mongo/db/ops/update_executor.cpp8
-rw-r--r--src/mongo/db/ops/update_executor.h2
-rw-r--r--src/mongo/db/ops/update_request.h12
-rw-r--r--src/mongo/db/pipeline/pipeline_d.cpp2
-rw-r--r--src/mongo/db/query/get_executor.cpp8
-rw-r--r--src/mongo/db/query/get_runner.cpp6
-rw-r--r--src/mongo/db/query/idhack_runner.cpp2
-rw-r--r--src/mongo/db/query/new_find.cpp2
-rw-r--r--src/mongo/db/query/stage_builder.cpp2
-rw-r--r--src/mongo/db/query/subplan_runner.cpp2
-rw-r--r--src/mongo/db/repl/master_slave.cpp4
-rw-r--r--src/mongo/db/repl/oplog.cpp12
-rw-r--r--src/mongo/db/repl/rs_rollback.cpp4
-rw-r--r--src/mongo/dbtests/matchertests.cpp2
39 files changed, 276 insertions, 181 deletions
diff --git a/src/mongo/db/commands/count.cpp b/src/mongo/db/commands/count.cpp
index e630ff21dc9..f68f7488785 100644
--- a/src/mongo/db/commands/count.cpp
+++ b/src/mongo/db/commands/count.cpp
@@ -209,7 +209,7 @@ namespace mongo {
const BSONObj hintObj = hint.empty() ? BSONObj() : BSON("$hint" << hint);
StringData dbnameData(dbname);
- const WhereCallbackReal whereCallback(dbnameData);
+ const WhereCallbackReal whereCallback(txn, dbnameData);
CanonicalQuery* cq;
uassertStatusOK(CanonicalQuery::canonicalize(ns,
diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp
index f242327f935..9df4c363b62 100644
--- a/src/mongo/db/commands/find_and_modify.cpp
+++ b/src/mongo/db/commands/find_and_modify.cpp
@@ -142,7 +142,7 @@ namespace mongo {
Collection* collection = cx.db()->getCollection( txn, ns );
- const WhereCallbackReal whereCallback = WhereCallbackReal(StringData(ns));
+ const WhereCallbackReal whereCallback = WhereCallbackReal(txn, StringData(ns));
BSONObj doc;
bool found = false;
@@ -247,7 +247,7 @@ namespace mongo {
}
const NamespaceString requestNs(ns);
- UpdateRequest request(requestNs);
+ UpdateRequest request(txn, requestNs);
request.setQuery(queryModified);
request.setUpdates(update);
@@ -257,8 +257,7 @@ namespace mongo {
// the shard version below, but for now no
UpdateLifecycleImpl updateLifecycle(false, requestNs);
request.setLifecycle(&updateLifecycle);
- UpdateResult res = mongo::update(txn,
- cx.db(),
+ UpdateResult res = mongo::update(cx.db(),
request,
&txn->getCurOp()->debug());
@@ -328,7 +327,7 @@ namespace mongo {
Projection projection;
if (fields) {
- projection.init(fieldsHolder, WhereCallbackReal(StringData(dbname)));
+ projection.init(fieldsHolder, WhereCallbackReal(txn, StringData(dbname)));
if (!projection.includeID()) {
fields = NULL; // do projection in post-processing
}
diff --git a/src/mongo/db/commands/geo_near_cmd.cpp b/src/mongo/db/commands/geo_near_cmd.cpp
index f994004e2b2..7fb6b972efd 100644
--- a/src/mongo/db/commands/geo_near_cmd.cpp
+++ b/src/mongo/db/commands/geo_near_cmd.cpp
@@ -171,7 +171,7 @@ namespace mongo {
CanonicalQuery* cq;
const NamespaceString nss(dbname);
- const WhereCallbackReal whereCallback(nss.db());
+ const WhereCallbackReal whereCallback(txn, nss.db());
if (!CanonicalQuery::canonicalize(ns,
rewritten,
diff --git a/src/mongo/db/commands/group.cpp b/src/mongo/db/commands/group.cpp
index 519a5989dd1..aed8e699e83 100644
--- a/src/mongo/db/commands/group.cpp
+++ b/src/mongo/db/commands/group.cpp
@@ -134,7 +134,7 @@ namespace mongo {
Collection* collection = db->getCollection( txn, ns );
- const WhereCallbackReal whereCallback(StringData(db->name()));
+ const WhereCallbackReal whereCallback(txn, StringData(db->name()));
map<BSONObj,int,BSONObjCmp> map;
list<BSONObj> blah;
diff --git a/src/mongo/db/commands/index_filter_commands.cpp b/src/mongo/db/commands/index_filter_commands.cpp
index e0d5be5255a..139350b3002 100644
--- a/src/mongo/db/commands/index_filter_commands.cpp
+++ b/src/mongo/db/commands/index_filter_commands.cpp
@@ -67,9 +67,11 @@ namespace {
/**
* Retrieves a collection's query settings and plan cache from the database.
*/
- Status getQuerySettingsAndPlanCache(OperationContext* txn, Database* db, const string& ns,
- QuerySettings** querySettingsOut,
- PlanCache** planCacheOut) {
+ static Status getQuerySettingsAndPlanCache(OperationContext* txn,
+ Database* db,
+ const string& ns,
+ QuerySettings** querySettingsOut,
+ PlanCache** planCacheOut) {
invariant(db);
Collection* collection = db->getCollection(txn, ns);
@@ -238,12 +240,15 @@ namespace mongo {
// No collection - do nothing.
return Status::OK();
}
- return clear(querySettings, planCache, ns, cmdObj);
+ return clear(txn, querySettings, planCache, ns, cmdObj);
}
// static
- Status ClearFilters::clear(QuerySettings* querySettings, PlanCache* planCache,
- const std::string& ns, const BSONObj& cmdObj) {
+ Status ClearFilters::clear(OperationContext* txn,
+ QuerySettings* querySettings,
+ PlanCache* planCache,
+ const std::string& ns,
+ const BSONObj& cmdObj) {
invariant(querySettings);
// According to the specification, the planCacheClearFilters command runs in two modes:
@@ -252,7 +257,7 @@ namespace mongo {
// command arguments.
if (cmdObj.hasField("query")) {
CanonicalQuery* cqRaw;
- Status status = PlanCacheCommand::canonicalize(ns, cmdObj, &cqRaw);
+ Status status = PlanCacheCommand::canonicalize(txn, ns, cmdObj, &cqRaw);
if (!status.isOK()) {
return status;
}
@@ -281,7 +286,7 @@ namespace mongo {
querySettings->clearAllowedIndices();
const NamespaceString nss(ns);
- const WhereCallbackReal whereCallback(nss.db());
+ const WhereCallbackReal whereCallback(txn, nss.db());
// Remove corresponding entries from plan cache.
// Admin hints affect the planning process directly. If there were
@@ -328,12 +333,15 @@ namespace mongo {
if (!status.isOK()) {
return status;
}
- return set(querySettings, planCache, ns, cmdObj);
+ return set(txn, querySettings, planCache, ns, cmdObj);
}
// static
- Status SetFilter::set(QuerySettings* querySettings, PlanCache* planCache,
- const string& ns, const BSONObj& cmdObj) {
+ Status SetFilter::set(OperationContext* txn,
+ QuerySettings* querySettings,
+ PlanCache* planCache,
+ const string& ns,
+ const BSONObj& cmdObj) {
// indexes - required
BSONElement indexesElt = cmdObj.getField("indexes");
if (indexesElt.eoo()) {
@@ -362,7 +370,7 @@ namespace mongo {
}
CanonicalQuery* cqRaw;
- Status status = PlanCacheCommand::canonicalize(ns, cmdObj, &cqRaw);
+ Status status = PlanCacheCommand::canonicalize(txn, ns, cmdObj, &cqRaw);
if (!status.isOK()) {
return status;
}
diff --git a/src/mongo/db/commands/index_filter_commands.h b/src/mongo/db/commands/index_filter_commands.h
index f6ba8fa9efb..2f106b16f36 100644
--- a/src/mongo/db/commands/index_filter_commands.h
+++ b/src/mongo/db/commands/index_filter_commands.h
@@ -138,7 +138,10 @@ namespace mongo {
* Namespace argument ns is ignored if we are clearing the entire cache.
* Removes corresponding entries from plan cache.
*/
- static Status clear(QuerySettings* querySettings, PlanCache* planCache, const std::string& ns,
+ static Status clear(OperationContext* txn,
+ QuerySettings* querySettings,
+ PlanCache* planCache,
+ const std::string& ns,
const BSONObj& cmdObj);
};
@@ -167,7 +170,10 @@ namespace mongo {
* Sets index filter for a query shape.
* Removes entry for query shape from plan cache.
*/
- static Status set(QuerySettings* querySettings, PlanCache* planCache, const std::string& ns,
+ static Status set(OperationContext* txn,
+ QuerySettings* querySettings,
+ PlanCache* planCache,
+ const std::string& ns,
const BSONObj& cmdObj);
};
diff --git a/src/mongo/db/commands/index_filter_commands_test.cpp b/src/mongo/db/commands/index_filter_commands_test.cpp
index c3a5fc1d6a5..e892bcee7a8 100644
--- a/src/mongo/db/commands/index_filter_commands_test.cpp
+++ b/src/mongo/db/commands/index_filter_commands_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/db/commands/index_filter_commands.h"
#include "mongo/db/json.h"
+#include "mongo/db/operation_context_noop.h"
#include "mongo/db/query/plan_ranker.h"
#include "mongo/db/query/query_solution.h"
#include "mongo/unittest/unittest.h"
@@ -181,35 +182,39 @@ namespace {
TEST(IndexFilterCommandsTest, ClearFiltersInvalidParameter) {
QuerySettings empty;
PlanCache planCache;
+ OperationContextNoop txn;
+
// If present, query has to be an object.
- ASSERT_NOT_OK(ClearFilters::clear(&empty, &planCache, ns, fromjson("{query: 1234}")));
+ ASSERT_NOT_OK(ClearFilters::clear(&txn, &empty, &planCache, ns, fromjson("{query: 1234}")));
// If present, sort must be an object.
- ASSERT_NOT_OK(ClearFilters::clear(&empty, &planCache, ns,
+ ASSERT_NOT_OK(ClearFilters::clear(&txn, &empty, &planCache, ns,
fromjson("{query: {a: 1}, sort: 1234}")));
// If present, projection must be an object.
- ASSERT_NOT_OK(ClearFilters::clear(&empty, &planCache, ns,
+ ASSERT_NOT_OK(ClearFilters::clear(&txn, &empty, &planCache, ns,
fromjson("{query: {a: 1}, projection: 1234}")));
// Query must pass canonicalization.
- ASSERT_NOT_OK(ClearFilters::clear(&empty, &planCache, ns,
+ ASSERT_NOT_OK(ClearFilters::clear(&txn, &empty, &planCache, ns,
fromjson("{query: {a: {$no_such_op: 1}}}")));
// Sort present without query is an error.
- ASSERT_NOT_OK(ClearFilters::clear(&empty, &planCache, ns, fromjson("{sort: {a: 1}}")));
+ ASSERT_NOT_OK(ClearFilters::clear(&txn, &empty, &planCache, ns, fromjson("{sort: {a: 1}}")));
// Projection present without query is an error.
- ASSERT_NOT_OK(ClearFilters::clear(&empty, &planCache, ns,
+ ASSERT_NOT_OK(ClearFilters::clear(&txn, &empty, &planCache, ns,
fromjson("{projection: {_id: 0, a: 1}}")));
}
TEST(IndexFilterCommandsTest, ClearNonexistentHint) {
QuerySettings querySettings;
PlanCache planCache;
- ASSERT_OK(SetFilter::set(&querySettings, &planCache, ns,
+ OperationContextNoop txn;
+
+ ASSERT_OK(SetFilter::set(&txn, &querySettings, &planCache, ns,
fromjson("{query: {a: 1}, indexes: [{a: 1}]}")));
vector<BSONObj> filters = getFilters(querySettings);
ASSERT_EQUALS(filters.size(), 1U);
// Clear nonexistent hint.
// Command should succeed and cache should remain unchanged.
- ASSERT_OK(ClearFilters::clear(&querySettings, &planCache, ns, fromjson("{query: {b: 1}}")));
+ ASSERT_OK(ClearFilters::clear(&txn, &querySettings, &planCache, ns, fromjson("{query: {b: 1}}")));
filters = getFilters(querySettings);
ASSERT_EQUALS(filters.size(), 1U);
}
@@ -221,46 +226,49 @@ namespace {
TEST(IndexFilterCommandsTest, SetFilterInvalidParameter) {
QuerySettings empty;
PlanCache planCache;
- ASSERT_NOT_OK(SetFilter::set(&empty, &planCache, ns, fromjson("{}")));
+ OperationContextNoop txn;
+
+ ASSERT_NOT_OK(SetFilter::set(&txn, &empty, &planCache, ns, fromjson("{}")));
// Missing required query field.
- ASSERT_NOT_OK(SetFilter::set(&empty, &planCache, ns, fromjson("{indexes: [{a: 1}]}")));
+ ASSERT_NOT_OK(SetFilter::set(&txn, &empty, &planCache, ns, fromjson("{indexes: [{a: 1}]}")));
// Missing required indexes field.
- ASSERT_NOT_OK(SetFilter::set(&empty, &planCache, ns, fromjson("{query: {a: 1}}")));
+ ASSERT_NOT_OK(SetFilter::set(&txn, &empty, &planCache, ns, fromjson("{query: {a: 1}}")));
// Query has to be an object.
- ASSERT_NOT_OK(SetFilter::set(&empty, &planCache, ns,
+ ASSERT_NOT_OK(SetFilter::set(&txn, &empty, &planCache, ns,
fromjson("{query: 1234, indexes: [{a: 1}, {b: 1}]}")));
// Indexes field has to be an array.
- ASSERT_NOT_OK(SetFilter::set(&empty, &planCache, ns,
+ ASSERT_NOT_OK(SetFilter::set(&txn, &empty, &planCache, ns,
fromjson("{query: {a: 1}, indexes: 1234}")));
// Array indexes field cannot empty.
- ASSERT_NOT_OK(SetFilter::set(&empty, &planCache, ns,
+ ASSERT_NOT_OK(SetFilter::set(&txn, &empty, &planCache, ns,
fromjson("{query: {a: 1}, indexes: []}")));
// Elements in indexes have to be objects.
- ASSERT_NOT_OK(SetFilter::set(&empty, &planCache, ns,
+ ASSERT_NOT_OK(SetFilter::set(&txn, &empty, &planCache, ns,
fromjson("{query: {a: 1}, indexes: [{a: 1}, 99]}")));
// Objects in indexes cannot be empty.
- ASSERT_NOT_OK(SetFilter::set(&empty, &planCache, ns,
+ ASSERT_NOT_OK(SetFilter::set(&txn, &empty, &planCache, ns,
fromjson("{query: {a: 1}, indexes: [{a: 1}, {}]}")));
// If present, sort must be an object.
- ASSERT_NOT_OK(SetFilter::set(&empty, &planCache, ns,
+ ASSERT_NOT_OK(SetFilter::set(&txn, &empty, &planCache, ns,
fromjson("{query: {a: 1}, sort: 1234, indexes: [{a: 1}, {b: 1}]}")));
// If present, projection must be an object.
- ASSERT_NOT_OK(SetFilter::set(&empty, &planCache, ns,
+ ASSERT_NOT_OK(SetFilter::set(&txn, &empty, &planCache, ns,
fromjson("{query: {a: 1}, projection: 1234, indexes: [{a: 1}, {b: 1}]}")));
// Query must pass canonicalization.
- ASSERT_NOT_OK(SetFilter::set(&empty, &planCache, ns,
+ ASSERT_NOT_OK(SetFilter::set(&txn, &empty, &planCache, ns,
fromjson("{query: {a: {$no_such_op: 1}}, indexes: [{a: 1}, {b: 1}]}")));
}
TEST(IndexFilterCommandsTest, SetAndClearFilters) {
QuerySettings querySettings;
PlanCache planCache;
+ OperationContextNoop txn;
// Inject query shape into plan cache.
addQueryShapeToPlanCache(&planCache, "{a: 1, b: 1}", "{a: -1}", "{_id: 0, a: 1}");
ASSERT_TRUE(planCacheContains(planCache, "{a: 1, b: 1}", "{a: -1}", "{_id: 0, a: 1}"));
- ASSERT_OK(SetFilter::set(&querySettings, &planCache, ns,
+ ASSERT_OK(SetFilter::set(&txn, &querySettings, &planCache, ns,
fromjson("{query: {a: 1, b: 1}, sort: {a: -1}, projection: {_id: 0, a: 1}, "
"indexes: [{a: 1}]}")));
vector<BSONObj> filters = getFilters(querySettings);
@@ -276,20 +284,20 @@ namespace {
// Replacing the hint for the same query shape ({a: 1, b: 1} and {b: 2, a: 3}
// share same shape) should not change the query settings size.
- ASSERT_OK(SetFilter::set(&querySettings, &planCache, ns,
+ ASSERT_OK(SetFilter::set(&txn, &querySettings, &planCache, ns,
fromjson("{query: {b: 2, a: 3}, sort: {a: -1}, projection: {_id: 0, a: 1}, "
"indexes: [{a: 1, b: 1}]}")));
filters = getFilters(querySettings);
ASSERT_EQUALS(filters.size(), 1U);
// Add hint for different query shape.
- ASSERT_OK(SetFilter::set(&querySettings, &planCache, ns,
+ ASSERT_OK(SetFilter::set(&txn, &querySettings, &planCache, ns,
fromjson("{query: {b: 1}, indexes: [{b: 1}]}")));
filters = getFilters(querySettings);
ASSERT_EQUALS(filters.size(), 2U);
// Add hint for 3rd query shape. This is to prepare for ClearHint tests.
- ASSERT_OK(SetFilter::set(&querySettings, &planCache, ns,
+ ASSERT_OK(SetFilter::set(&txn, &querySettings, &planCache, ns,
fromjson("{query: {a: 1}, indexes: [{a: 1}]}")));
filters = getFilters(querySettings);
ASSERT_EQUALS(filters.size(), 3U);
@@ -299,7 +307,7 @@ namespace {
addQueryShapeToPlanCache(&planCache, "{b: 1}", "{}", "{}");
// Clear single hint.
- ASSERT_OK(ClearFilters::clear(&querySettings, &planCache, ns,
+ ASSERT_OK(ClearFilters::clear(&txn, &querySettings, &planCache, ns,
fromjson("{query: {a: 1}}")));
filters = getFilters(querySettings);
ASSERT_EQUALS(filters.size(), 2U);
@@ -309,7 +317,7 @@ namespace {
ASSERT_TRUE(planCacheContains(planCache, "{b: 1}", "{}", "{}"));
// Clear all filters
- ASSERT_OK(ClearFilters::clear(&querySettings, &planCache, ns, fromjson("{}")));
+ ASSERT_OK(ClearFilters::clear(&txn, &querySettings, &planCache, ns, fromjson("{}")));
filters = getFilters(querySettings);
ASSERT_TRUE(filters.empty());
diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp
index 58360d4cdd0..df0a6e7b9e3 100644
--- a/src/mongo/db/commands/mr.cpp
+++ b/src/mongo/db/commands/mr.cpp
@@ -977,7 +977,7 @@ namespace mongo {
_db.count(_config.incLong, BSONObj(), QueryOption_SlaveOk)));
const NamespaceString nss(_config.incLong);
- const WhereCallbackReal whereCallback(nss.db());
+ const WhereCallbackReal whereCallback(_txn, nss.db());
CanonicalQuery* cq;
verify(CanonicalQuery::canonicalize(_config.incLong,
@@ -1317,7 +1317,7 @@ namespace mongo {
scoped_ptr<Client::Context> ctx(new Client::Context(txn, config.ns, false));
const NamespaceString nss(config.ns);
- const WhereCallbackReal whereCallback(nss.db());
+ const WhereCallbackReal whereCallback(txn, nss.db());
CanonicalQuery* cq;
if (!CanonicalQuery::canonicalize(config.ns,
diff --git a/src/mongo/db/commands/plan_cache_commands.cpp b/src/mongo/db/commands/plan_cache_commands.cpp
index 7436ecc9eea..2a8bb83ef8c 100644
--- a/src/mongo/db/commands/plan_cache_commands.cpp
+++ b/src/mongo/db/commands/plan_cache_commands.cpp
@@ -157,7 +157,9 @@ namespace mongo {
}
// static
- Status PlanCacheCommand::canonicalize(const string& ns, const BSONObj& cmdObj,
+ Status PlanCacheCommand::canonicalize(OperationContext* txn,
+ const string& ns,
+ const BSONObj& cmdObj,
CanonicalQuery** canonicalQueryOut) {
// query - required
BSONElement queryElt = cmdObj.getField("query");
@@ -196,7 +198,7 @@ namespace mongo {
CanonicalQuery* cqRaw;
const NamespaceString nss(ns);
- const WhereCallbackReal whereCallback(nss.db());
+ const WhereCallbackReal whereCallback(txn, nss.db());
Status result = CanonicalQuery::canonicalize(
ns, queryObj, sortObj, projObj, &cqRaw, whereCallback);
@@ -273,11 +275,14 @@ namespace mongo {
// No collection - nothing to do. Return OK status.
return Status::OK();
}
- return clear(planCache, ns, cmdObj);
+ return clear(txn, planCache, ns, cmdObj);
}
// static
- Status PlanCacheClear::clear(PlanCache* planCache, const string& ns, const BSONObj& cmdObj) {
+ Status PlanCacheClear::clear(OperationContext* txn,
+ PlanCache* planCache,
+ const string& ns,
+ const BSONObj& cmdObj) {
invariant(planCache);
// According to the specification, the planCacheClear command runs in two modes:
@@ -286,7 +291,7 @@ namespace mongo {
// command arguments.
if (cmdObj.hasField("query")) {
CanonicalQuery* cqRaw;
- Status status = PlanCacheCommand::canonicalize(ns, cmdObj, &cqRaw);
+ Status status = PlanCacheCommand::canonicalize(txn, ns, cmdObj, &cqRaw);
if (!status.isOK()) {
return status;
}
@@ -346,14 +351,17 @@ namespace mongo {
plansBuilder.doneFast();
return Status::OK();
}
- return list(*planCache, ns, cmdObj, bob);
+ return list(txn, *planCache, ns, cmdObj, bob);
}
// static
- Status PlanCacheListPlans::list(const PlanCache& planCache, const std::string& ns,
- const BSONObj& cmdObj, BSONObjBuilder* bob) {
+ Status PlanCacheListPlans::list(OperationContext* txn,
+ const PlanCache& planCache,
+ const std::string& ns,
+ const BSONObj& cmdObj,
+ BSONObjBuilder* bob) {
CanonicalQuery* cqRaw;
- Status status = canonicalize(ns, cmdObj, &cqRaw);
+ Status status = canonicalize(txn, ns, cmdObj, &cqRaw);
if (!status.isOK()) {
return status;
}
diff --git a/src/mongo/db/commands/plan_cache_commands.h b/src/mongo/db/commands/plan_cache_commands.h
index 507d4fe4927..1a4a49a3c4f 100644
--- a/src/mongo/db/commands/plan_cache_commands.h
+++ b/src/mongo/db/commands/plan_cache_commands.h
@@ -89,7 +89,9 @@ namespace mongo {
/**
* Validatess query shape from command object and returns canonical query.
*/
- static Status canonicalize(const std::string& ns, const BSONObj& cmdObj,
+ static Status canonicalize(OperationContext* txn,
+ const std::string& ns,
+ const BSONObj& cmdObj,
CanonicalQuery** canonicalQueryOut);
private:
@@ -141,7 +143,10 @@ namespace mongo {
* Clears collection's plan cache.
* If query shape is provided, clears plans for that single query shape only.
*/
- static Status clear(PlanCache* planCache, const std::string& ns, const BSONObj& cmdObj);
+ static Status clear(OperationContext* txn,
+ PlanCache* planCache,
+ const std::string& ns,
+ const BSONObj& cmdObj);
};
/**
@@ -166,8 +171,11 @@ namespace mongo {
/**
* Displays the cached plans for a query shape.
*/
- static Status list(const PlanCache& planCache, const std::string& ns,
- const BSONObj& cmdObj, BSONObjBuilder* bob);
+ static Status list(OperationContext* txn,
+ const PlanCache& planCache,
+ const std::string& ns,
+ const BSONObj& cmdObj,
+ BSONObjBuilder* bob);
};
} // namespace mongo
diff --git a/src/mongo/db/commands/plan_cache_commands_test.cpp b/src/mongo/db/commands/plan_cache_commands_test.cpp
index 5a6775cdb74..d2cae74ac12 100644
--- a/src/mongo/db/commands/plan_cache_commands_test.cpp
+++ b/src/mongo/db/commands/plan_cache_commands_test.cpp
@@ -34,6 +34,7 @@
#include <algorithm>
#include "mongo/db/json.h"
+#include "mongo/db/operation_context_noop.h"
#include "mongo/db/query/plan_ranker.h"
#include "mongo/db/query/query_solution.h"
#include "mongo/unittest/unittest.h"
@@ -154,6 +155,8 @@ namespace {
// Plan cache with one entry
PlanCache planCache;
QuerySolution qs;
+ OperationContextNoop txn;
+
qs.cacheData.reset(createSolutionCacheData());
std::vector<QuerySolution*> solns;
solns.push_back(&qs);
@@ -161,7 +164,7 @@ namespace {
ASSERT_EQUALS(getShapes(planCache).size(), 1U);
// Clear cache and confirm number of keys afterwards.
- ASSERT_OK(PlanCacheClear::clear(&planCache, ns, BSONObj()));
+ ASSERT_OK(PlanCacheClear::clear(&txn, &planCache, ns, BSONObj()));
ASSERT_EQUALS(getShapes(planCache).size(), 0U);
}
@@ -173,35 +176,37 @@ namespace {
TEST(PlanCacheCommandsTest, Canonicalize) {
// Invalid parameters
CanonicalQuery* cqRaw;
+ OperationContextNoop txn;
+
// Missing query field
- ASSERT_NOT_OK(PlanCacheCommand::canonicalize(ns, fromjson("{}"), &cqRaw));
+ ASSERT_NOT_OK(PlanCacheCommand::canonicalize(&txn, ns, fromjson("{}"), &cqRaw));
// Query needs to be an object
- ASSERT_NOT_OK(PlanCacheCommand::canonicalize(ns, fromjson("{query: 1}"), &cqRaw));
+ ASSERT_NOT_OK(PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: 1}"), &cqRaw));
// Sort needs to be an object
- ASSERT_NOT_OK(PlanCacheCommand::canonicalize(ns, fromjson("{query: {}, sort: 1}"),
+ ASSERT_NOT_OK(PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: {}, sort: 1}"),
&cqRaw));
// Bad query (invalid sort order)
- ASSERT_NOT_OK(PlanCacheCommand::canonicalize(ns, fromjson("{query: {}, sort: {a: 0}}"),
+ ASSERT_NOT_OK(PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: {}, sort: {a: 0}}"),
&cqRaw));
// Valid parameters
- ASSERT_OK(PlanCacheCommand::canonicalize(ns, fromjson("{query: {a: 1, b: 1}}"), &cqRaw));
+ ASSERT_OK(PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: {a: 1, b: 1}}"), &cqRaw));
scoped_ptr<CanonicalQuery> query(cqRaw);
// Equivalent query should generate same key.
- ASSERT_OK(PlanCacheCommand::canonicalize(ns, fromjson("{query: {b: 1, a: 1}}"), &cqRaw));
+ ASSERT_OK(PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: {b: 1, a: 1}}"), &cqRaw));
scoped_ptr<CanonicalQuery> equivQuery(cqRaw);
ASSERT_EQUALS(query->getPlanCacheKey(), equivQuery->getPlanCacheKey());
// Sort query should generate different key from unsorted query.
- ASSERT_OK(PlanCacheCommand::canonicalize(ns,
+ ASSERT_OK(PlanCacheCommand::canonicalize(&txn, ns,
fromjson("{query: {a: 1, b: 1}, sort: {a: 1}}"), &cqRaw));
scoped_ptr<CanonicalQuery> sortQuery(cqRaw);
ASSERT_NOT_EQUALS(query->getPlanCacheKey(), sortQuery->getPlanCacheKey());
// Projected query should generate different key from unprojected query.
- ASSERT_OK(PlanCacheCommand::canonicalize(ns,
+ ASSERT_OK(PlanCacheCommand::canonicalize(&txn, ns,
fromjson("{query: {a: 1, b: 1}, projection: {_id: 0, a: 1}}"), &cqRaw));
scoped_ptr<CanonicalQuery> projectionQuery(cqRaw);
ASSERT_NOT_EQUALS(query->getPlanCacheKey(), projectionQuery->getPlanCacheKey());
@@ -213,22 +218,26 @@ namespace {
TEST(PlanCacheCommandsTest, planCacheClearInvalidParameter) {
PlanCache planCache;
+ OperationContextNoop txn;
+
// Query field type must be BSON object.
- ASSERT_NOT_OK(PlanCacheClear::clear(&planCache, ns, fromjson("{query: 12345}")));
- ASSERT_NOT_OK(PlanCacheClear::clear(&planCache, ns, fromjson("{query: /keyisnotregex/}")));
+ ASSERT_NOT_OK(PlanCacheClear::clear(&txn, &planCache, ns, fromjson("{query: 12345}")));
+ ASSERT_NOT_OK(PlanCacheClear::clear(&txn, &planCache, ns, fromjson("{query: /keyisnotregex/}")));
// Query must pass canonicalization.
- ASSERT_NOT_OK(PlanCacheClear::clear(&planCache, ns,
+ ASSERT_NOT_OK(PlanCacheClear::clear(&txn, &planCache, ns,
fromjson("{query: {a: {$no_such_op: 1}}}")));
// Sort present without query is an error.
- ASSERT_NOT_OK(PlanCacheClear::clear(&planCache, ns, fromjson("{sort: {a: 1}}")));
+ ASSERT_NOT_OK(PlanCacheClear::clear(&txn, &planCache, ns, fromjson("{sort: {a: 1}}")));
// Projection present without query is an error.
- ASSERT_NOT_OK(PlanCacheClear::clear(&planCache, ns,
+ ASSERT_NOT_OK(PlanCacheClear::clear(&txn, &planCache, ns,
fromjson("{projection: {_id: 0, a: 1}}")));
}
TEST(PlanCacheCommandsTest, planCacheClearUnknownKey) {
PlanCache planCache;
- ASSERT_OK(PlanCacheClear::clear(&planCache, ns, fromjson("{query: {a: 1}}")));
+ OperationContextNoop txn;
+
+ ASSERT_OK(PlanCacheClear::clear(&txn, &planCache, ns, fromjson("{query: {a: 1}}")));
}
TEST(PlanCacheCommandsTest, planCacheClearOneKey) {
@@ -260,7 +269,9 @@ namespace {
// Drop {b: 1} from cache. Make sure {a: 1} is still in cache afterwards.
BSONObjBuilder bob;
- ASSERT_OK(PlanCacheClear::clear(&planCache, ns, BSON("query" << cqB->getQueryObj())));
+ OperationContextNoop txn;
+
+ ASSERT_OK(PlanCacheClear::clear(&txn, &planCache, ns, BSON("query" << cqB->getQueryObj())));
vector<BSONObj> shapesAfter = getShapes(planCache);
ASSERT_EQUALS(shapesAfter.size(), 1U);
ASSERT_EQUALS(shapesAfter[0], shapeA);
@@ -308,9 +319,11 @@ namespace {
*/
vector<BSONObj> getPlans(const PlanCache& planCache, const BSONObj& query,
const BSONObj& sort, const BSONObj& projection) {
+ OperationContextNoop txn;
+
BSONObjBuilder bob;
BSONObj cmdObj = BSON("query" << query << "sort" << sort << "projection" << projection);
- ASSERT_OK(PlanCacheListPlans::list(planCache, ns, cmdObj, &bob));
+ ASSERT_OK(PlanCacheListPlans::list(&txn, planCache, ns, cmdObj, &bob));
BSONObj resultObj = bob.obj();
BSONElement plansElt = resultObj.getField("plans");
ASSERT_EQUALS(plansElt.type(), mongo::Array);
@@ -324,21 +337,24 @@ namespace {
TEST(PlanCacheCommandsTest, planCacheListPlansInvalidParameter) {
PlanCache planCache;
BSONObjBuilder ignored;
+ OperationContextNoop txn;
+
// Missing query field is not ok.
- ASSERT_NOT_OK(PlanCacheListPlans::list(planCache, ns, BSONObj(), &ignored));
+ ASSERT_NOT_OK(PlanCacheListPlans::list(&txn, planCache, ns, BSONObj(), &ignored));
// Query field type must be BSON object.
- ASSERT_NOT_OK(PlanCacheListPlans::list(planCache, ns, fromjson("{query: 12345}"),
+ ASSERT_NOT_OK(PlanCacheListPlans::list(&txn, planCache, ns, fromjson("{query: 12345}"),
&ignored));
- ASSERT_NOT_OK(PlanCacheListPlans::list(planCache, ns, fromjson("{query: /keyisnotregex/}"),
+ ASSERT_NOT_OK(PlanCacheListPlans::list(&txn, planCache, ns, fromjson("{query: /keyisnotregex/}"),
&ignored));
}
TEST(PlanCacheCommandsTest, planCacheListPlansUnknownKey) {
// Leave the plan cache empty.
PlanCache planCache;
+ OperationContextNoop txn;
BSONObjBuilder ignored;
- ASSERT_OK(PlanCacheListPlans::list(planCache, ns, fromjson("{query: {a: 1}}"), &ignored));
+ ASSERT_OK(PlanCacheListPlans::list(&txn, planCache, ns, fromjson("{query: {a: 1}}"), &ignored));
}
TEST(PlanCacheCommandsTest, planCacheListPlansOnlyOneSolutionTrue) {
diff --git a/src/mongo/db/commands/write_commands/batch_executor.cpp b/src/mongo/db/commands/write_commands/batch_executor.cpp
index 2f3a39fa3d7..419c01be9c6 100644
--- a/src/mongo/db/commands/write_commands/batch_executor.cpp
+++ b/src/mongo/db/commands/write_commands/batch_executor.cpp
@@ -1088,7 +1088,7 @@ namespace mongo {
WriteOpResult* result ) {
const NamespaceString nsString(updateItem.getRequest()->getNS());
- UpdateRequest request(nsString);
+ UpdateRequest request(txn, nsString);
request.setQuery(updateItem.getUpdate()->getQuery());
request.setUpdates(updateItem.getUpdate()->getUpdateExpr());
request.setMulti(updateItem.getUpdate()->getMulti());
@@ -1115,7 +1115,7 @@ namespace mongo {
Client::Context ctx(txn, nsString.ns(), false /* don't check version */);
try {
- UpdateResult res = executor.execute(txn, ctx.db());
+ UpdateResult res = executor.execute(ctx.db());
const long long numDocsModified = res.numDocsModified;
const long long numMatched = res.numMatched;
@@ -1149,7 +1149,7 @@ namespace mongo {
WriteOpResult* result ) {
const NamespaceString nss( removeItem.getRequest()->getNS() );
- DeleteRequest request( nss );
+ DeleteRequest request(txn, nss);
request.setQuery( removeItem.getDelete()->getQuery() );
request.setMulti( removeItem.getDelete()->getLimit() != 1 );
request.setUpdateOpLog(true);
@@ -1178,7 +1178,7 @@ namespace mongo {
Client::Context writeContext(txn, nss.ns(), false /* don't check version */);
try {
- result->getStats().n = executor.execute(txn, writeContext.db());
+ result->getStats().n = executor.execute(writeContext.db());
}
catch ( const DBException& ex ) {
status = ex.toStatus();
diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp
index 8cc0eb0bd1c..ae6b560dbad 100644
--- a/src/mongo/db/dbhelpers.cpp
+++ b/src/mongo/db/dbhelpers.cpp
@@ -107,7 +107,7 @@ namespace mongo {
return DiskLoc();
CanonicalQuery* cq;
- const WhereCallbackReal whereCallback(collection->ns().db());
+ const WhereCallbackReal whereCallback(txn, collection->ns().db());
massert(17244, "Could not canonicalize " + query.toString(),
CanonicalQuery::canonicalize(collection->ns(), query, &cq, whereCallback).isOK());
@@ -216,7 +216,7 @@ namespace mongo {
Client::Context context(txn, ns);
const NamespaceString requestNs(ns);
- UpdateRequest request(requestNs);
+ UpdateRequest request(txn, requestNs);
request.setQuery(id);
request.setUpdates(o);
@@ -226,7 +226,7 @@ namespace mongo {
UpdateLifecycleImpl updateLifecycle(true, requestNs);
request.setLifecycle(&updateLifecycle);
- update(txn, context.db(), request, &debug);
+ update(context.db(), request, &debug);
}
void Helpers::putSingleton(OperationContext* txn, const char *ns, BSONObj obj) {
@@ -234,7 +234,7 @@ namespace mongo {
Client::Context context(txn, ns);
const NamespaceString requestNs(ns);
- UpdateRequest request(requestNs);
+ UpdateRequest request(txn, requestNs);
request.setUpdates(obj);
request.setUpsert();
@@ -242,7 +242,7 @@ namespace mongo {
UpdateLifecycleImpl updateLifecycle(true, requestNs);
request.setLifecycle(&updateLifecycle);
- update(txn, context.db(), request, &debug);
+ update(context.db(), request, &debug);
context.getClient()->curop()->done();
}
@@ -252,14 +252,14 @@ namespace mongo {
Client::Context context(txn, ns);
const NamespaceString requestNs(ns);
- UpdateRequest request(requestNs);
+ UpdateRequest request(txn, requestNs);
request.setGod();
request.setUpdates(obj);
request.setUpsert();
request.setUpdateOpLog(logTheOp);
- update(txn, context.db(), request, &debug);
+ update(context.db(), request, &debug);
context.getClient()->curop()->done();
}
diff --git a/src/mongo/db/exec/stagedebug_cmd.cpp b/src/mongo/db/exec/stagedebug_cmd.cpp
index 346d481d8be..952b3b1e104 100644
--- a/src/mongo/db/exec/stagedebug_cmd.cpp
+++ b/src/mongo/db/exec/stagedebug_cmd.cpp
@@ -177,7 +177,7 @@ namespace mongo {
BSONObj argObj = e.Obj();
if (filterTag == e.fieldName()) {
StatusWithMatchExpression swme = MatchExpressionParser::parse(
- argObj, WhereCallbackReal(collection->ns().db()));
+ argObj, WhereCallbackReal(txn, collection->ns().db()));
if (!swme.isOK()) { return NULL; }
// exprs is what will wind up deleting this.
matcher = swme.getValue();
diff --git a/src/mongo/db/exec/subplan.cpp b/src/mongo/db/exec/subplan.cpp
index 245450998b3..4019aae418b 100644
--- a/src/mongo/db/exec/subplan.cpp
+++ b/src/mongo/db/exec/subplan.cpp
@@ -156,7 +156,7 @@ namespace mongo {
QLOG() << "Subplanner: index " << i << " is " << ie.toString() << endl;
}
- const WhereCallbackReal whereCallback(_collection->ns().db());
+ const WhereCallbackReal whereCallback(_txn, _collection->ns().db());
for (size_t i = 0; i < theOr->numChildren(); ++i) {
// Turn the i-th child into its own query.
diff --git a/src/mongo/db/fts/fts_command_mongod.cpp b/src/mongo/db/fts/fts_command_mongod.cpp
index a2c4b35e165..bebfa07cdfc 100644
--- a/src/mongo/db/fts/fts_command_mongod.cpp
+++ b/src/mongo/db/fts/fts_command_mongod.cpp
@@ -106,7 +106,7 @@ namespace mongo {
limit,
BSONObj(),
&cq,
- WhereCallbackReal(StringData(dbname)));
+ WhereCallbackReal(txn, StringData(dbname)));
if (!canonicalizeStatus.isOK()) {
errmsg = canonicalizeStatus.reason();
return false;
diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp
index da48a427e23..fe90ef4b588 100644
--- a/src/mongo/db/instance.cpp
+++ b/src/mongo/db/instance.cpp
@@ -104,7 +104,7 @@ namespace mongo {
MONGO_FP_DECLARE(rsStopGetMore);
- static void inProgCmd( Message &m, DbResponse &dbresponse ) {
+ static void inProgCmd(OperationContext* txn, Message &m, DbResponse &dbresponse) {
DbMessage d(m);
QueryMessage q(d);
BSONObjBuilder b;
@@ -139,7 +139,7 @@ namespace mongo {
Client& me = cc();
scoped_lock bl(Client::clientsMutex);
- Matcher m(filter, WhereCallbackReal(nss.db()));
+ Matcher m(filter, WhereCallbackReal(txn, nss.db()));
for( set<Client*>::iterator i = Client::clients.begin(); i != Client::clients.end(); i++ ) {
Client *c = *i;
verify( c );
@@ -346,7 +346,7 @@ namespace mongo {
opwrite(m);
if( strstr(ns, ".$cmd.sys.") ) {
if( strstr(ns, "$cmd.sys.inprog") ) {
- inProgCmd(m, dbresponse);
+ inProgCmd(txn, m, dbresponse);
return;
}
if( strstr(ns, "$cmd.sys.killop") ) {
@@ -587,7 +587,7 @@ namespace mongo {
op.debug().query = query;
op.setQuery(query);
- UpdateRequest request(ns);
+ UpdateRequest request(txn, ns);
request.setUpsert(upsert);
request.setMulti(multi);
@@ -609,7 +609,7 @@ namespace mongo {
Client::Context ctx(txn, ns );
- UpdateResult res = executor.execute(txn, ctx.db());
+ UpdateResult res = executor.execute(ctx.db());
// for getlasterror
lastError.getSafe()->recordUpdate( res.existing , res.numMatched , res.upserted );
@@ -635,7 +635,7 @@ namespace mongo {
op.debug().query = pattern;
op.setQuery(pattern);
- DeleteRequest request(ns);
+ DeleteRequest request(txn, ns);
request.setQuery(pattern);
request.setMulti(!justOne);
request.setUpdateOpLog(true);
@@ -650,7 +650,7 @@ namespace mongo {
Client::Context ctx(txn, ns);
- long long n = executor.execute(txn, ctx.db());
+ long long n = executor.execute(ctx.db());
lastError.getSafe()->recordDelete( n );
op.debug().ndeleted = n;
wunit.commit();
diff --git a/src/mongo/db/matcher/expression_parser.h b/src/mongo/db/matcher/expression_parser.h
index b463d84f64a..0ba4013aa80 100644
--- a/src/mongo/db/matcher/expression_parser.h
+++ b/src/mongo/db/matcher/expression_parser.h
@@ -39,6 +39,8 @@
namespace mongo {
+ class OperationContext;
+
typedef StatusWith<MatchExpression*> StatusWithMatchExpression;
class MatchExpressionParser {
@@ -174,11 +176,19 @@ namespace mongo {
*/
class WhereCallbackReal : public MatchExpressionParser::WhereCallback {
public:
- WhereCallbackReal(const StringData& dbName);
+
+ /**
+ * The OperationContext passed here is not owned, but just referenced. It gets assigned to
+ * any $where parsers, which this callback generates. Therefore, the op context must only
+ * be destroyed after these parsers and their clones (shallowClone) have been destroyed.
+ */
+ WhereCallbackReal(OperationContext* txn, const StringData& dbName);
virtual StatusWithMatchExpression parseWhere(const BSONElement& where) const;
private:
+ //
+ OperationContext* _txn;
const StringData _dbName;
};
diff --git a/src/mongo/db/matcher/expression_where.cpp b/src/mongo/db/matcher/expression_where.cpp
index 909c648063c..cef554357dc 100644
--- a/src/mongo/db/matcher/expression_where.cpp
+++ b/src/mongo/db/matcher/expression_where.cpp
@@ -43,7 +43,15 @@ namespace mongo {
class WhereMatchExpression : public MatchExpression {
public:
- WhereMatchExpression() : MatchExpression( WHERE ){ _func = 0; }
+ WhereMatchExpression(OperationContext* txn)
+ : MatchExpression(WHERE),
+ _txn(txn) {
+
+ invariant(_txn != NULL);
+
+ _func = 0;
+ }
+
virtual ~WhereMatchExpression(){}
Status init(const StringData& dbName, const StringData& theCode, const BSONObj& scope);
@@ -55,9 +63,9 @@ namespace mongo {
}
virtual MatchExpression* shallowClone() const {
- WhereMatchExpression* e = new WhereMatchExpression();
+ WhereMatchExpression* e = new WhereMatchExpression(_txn);
e->init(_dbName, _code, _userScope);
- if ( getTag() ) {
+ if (getTag()) {
e->setTag(getTag()->clone());
}
return e;
@@ -72,12 +80,16 @@ namespace mongo {
virtual void resetTag() { setTag(NULL); }
private:
+
string _dbName;
string _code;
BSONObj _userScope;
auto_ptr<Scope> _scope;
ScriptingFunction _func;
+
+ // Not owned. See comments insde WhereCallbackReal for the lifetime of this pointer.
+ OperationContext* _txn;
};
Status WhereMatchExpression::init( const StringData& dbName,
@@ -98,6 +110,7 @@ namespace mongo {
const string userToken = ClientBasic::getCurrent()->getAuthorizationSession()
->getAuthenticatedUserNamesToken();
+
_scope = globalScriptEngine->getPooledScope(_dbName, "where" + userToken);
_func = _scope->createFunction( _code.c_str() );
@@ -159,8 +172,9 @@ namespace mongo {
_userScope == realOther->_userScope;
}
- WhereCallbackReal::WhereCallbackReal(const StringData& dbName)
- : _dbName(dbName) {
+ WhereCallbackReal::WhereCallbackReal(OperationContext* txn, const StringData& dbName)
+ : _txn(txn),
+ _dbName(dbName) {
}
@@ -169,7 +183,7 @@ namespace mongo {
return StatusWithMatchExpression(ErrorCodes::BadValue,
"no globalScriptEngine in $where parsing");
- auto_ptr<WhereMatchExpression> exp(new WhereMatchExpression());
+ auto_ptr<WhereMatchExpression> exp(new WhereMatchExpression(_txn));
if (where.type() == String || where.type() == Code) {
Status s = exp->init(_dbName, where.valuestr(), BSONObj());
if (!s.isOK())
diff --git a/src/mongo/db/ops/delete.cpp b/src/mongo/db/ops/delete.cpp
index c78ca1692f1..38b1b2aefe3 100644
--- a/src/mongo/db/ops/delete.cpp
+++ b/src/mongo/db/ops/delete.cpp
@@ -46,13 +46,13 @@ namespace mongo {
bool logop,
bool god) {
NamespaceString nsString(ns);
- DeleteRequest request(nsString);
+ DeleteRequest request(txn, nsString);
request.setQuery(pattern);
request.setMulti(!justOne);
request.setUpdateOpLog(logop);
request.setGod(god);
DeleteExecutor executor(&request);
- return executor.execute(txn, db);
+ return executor.execute(db);
}
} // namespace mongo
diff --git a/src/mongo/db/ops/delete_executor.cpp b/src/mongo/db/ops/delete_executor.cpp
index e7eb2a9546c..d2c36f3ba3c 100644
--- a/src/mongo/db/ops/delete_executor.cpp
+++ b/src/mongo/db/ops/delete_executor.cpp
@@ -66,7 +66,8 @@ namespace mongo {
}
CanonicalQuery* cqRaw;
- const WhereCallbackReal whereCallback(_request->getNamespaceString().db());
+ const WhereCallbackReal whereCallback(
+ _request->getOpCtx(), _request->getNamespaceString().db());
Status status = CanonicalQuery::canonicalize(_request->getNamespaceString().ns(),
_request->getQuery(),
@@ -80,7 +81,7 @@ namespace mongo {
return status;
}
- long long DeleteExecutor::execute(OperationContext* txn, Database* db) {
+ long long DeleteExecutor::execute(Database* db) {
uassertStatusOK(prepare());
uassert(17417,
mongoutils::str::stream() <<
@@ -100,7 +101,7 @@ namespace mongo {
}
}
- Collection* collection = db->getCollection(txn, ns.ns());
+ Collection* collection = db->getCollection(_request->getOpCtx(), ns.ns());
if (NULL == collection) {
return 0;
}
@@ -118,11 +119,14 @@ namespace mongo {
Runner* rawRunner;
if (_canonicalQuery.get()) {
- uassertStatusOK(getRunner(txn, collection, _canonicalQuery.release(), &rawRunner));
+ uassertStatusOK(getRunner(_request->getOpCtx(),
+ collection,
+ _canonicalQuery.release(),
+ &rawRunner));
}
else {
CanonicalQuery* ignored;
- uassertStatusOK(getRunner(txn,
+ uassertStatusOK(getRunner(_request->getOpCtx(),
collection,
ns.ns(),
_request->getQuery(),
@@ -135,7 +139,7 @@ namespace mongo {
DiskLoc rloc;
Runner::RunnerState state;
- CurOp* curOp = txn->getCurOp();
+ CurOp* curOp = _request->getOpCtx()->getCurOp();
int oldYieldCount = curOp->numYields();
while (Runner::RUNNER_ADVANCED == (state = runner->getNext(NULL, &rloc))) {
if (oldYieldCount != curOp->numYields()) {
@@ -151,8 +155,9 @@ namespace mongo {
// TODO: do we want to buffer docs and delete them in a group rather than
// saving/restoring state repeatedly?
runner->saveState();
- collection->deleteDocument(txn, rloc, false, false, logop ? &toDelete : NULL );
- runner->restoreState(txn);
+ collection->deleteDocument(
+ _request->getOpCtx(), rloc, false, false, logop ? &toDelete : NULL);
+ runner->restoreState(_request->getOpCtx());
nDeleted++;
@@ -163,7 +168,8 @@ namespace mongo {
}
else {
bool replJustOne = true;
- repl::logOp(txn, "d", ns.ns().c_str(), toDelete, 0, &replJustOne);
+ repl::logOp(
+ _request->getOpCtx(), "d", ns.ns().c_str(), toDelete, 0, &replJustOne);
}
}
@@ -172,7 +178,7 @@ namespace mongo {
}
if (!_request->isGod()) {
- txn->recoveryUnit()->commitIfNeeded();
+ _request->getOpCtx()->recoveryUnit()->commitIfNeeded();
}
if (debug && _request->isGod() && nDeleted == 100) {
diff --git a/src/mongo/db/ops/delete_executor.h b/src/mongo/db/ops/delete_executor.h
index 475df92a105..c0324b14901 100644
--- a/src/mongo/db/ops/delete_executor.h
+++ b/src/mongo/db/ops/delete_executor.h
@@ -92,7 +92,7 @@ namespace mongo {
*
* Returns the number of documents deleted.
*/
- long long execute(OperationContext* txn, Database* db);
+ long long execute(Database* db);
private:
/// Unowned pointer to the request object that this executor will process.
diff --git a/src/mongo/db/ops/delete_request.h b/src/mongo/db/ops/delete_request.h
index 4e10cb409c2..3ce0a0bb9fd 100644
--- a/src/mongo/db/ops/delete_request.h
+++ b/src/mongo/db/ops/delete_request.h
@@ -39,7 +39,8 @@ namespace mongo {
class DeleteRequest {
MONGO_DISALLOW_COPYING(DeleteRequest);
public:
- explicit DeleteRequest(const NamespaceString& nsString) :
+ explicit DeleteRequest(OperationContext* txn, const NamespaceString& nsString) :
+ _txn(txn),
_nsString(nsString),
_multi(false),
_logop(false),
@@ -55,10 +56,12 @@ namespace mongo {
bool isMulti() const { return _multi; }
bool shouldCallLogOp() const { return _logop; }
bool isGod() const { return _god; }
+ OperationContext* getOpCtx() const { return _txn; }
std::string toString() const;
private:
+ OperationContext* _txn;
const NamespaceString& _nsString;
BSONObj _query;
bool _multi;
diff --git a/src/mongo/db/ops/update.cpp b/src/mongo/db/ops/update.cpp
index 53e67a9baf9..f872f39a97d 100644
--- a/src/mongo/db/ops/update.cpp
+++ b/src/mongo/db/ops/update.cpp
@@ -421,22 +421,19 @@ namespace mongo {
}
} // namespace
- UpdateResult update(OperationContext* txn,
- Database* db,
+ UpdateResult update(Database* db,
const UpdateRequest& request,
OpDebug* opDebug) {
UpdateExecutor executor(&request, opDebug);
- return executor.execute(txn, db);
+ return executor.execute(db);
}
- UpdateResult update(
- OperationContext* txn,
- Database* db,
- const UpdateRequest& request,
- OpDebug* opDebug,
- UpdateDriver* driver,
- CanonicalQuery* cq) {
+ UpdateResult update(Database* db,
+ const UpdateRequest& request,
+ OpDebug* opDebug,
+ UpdateDriver* driver,
+ CanonicalQuery* cq) {
LOG(3) << "processing update : " << request;
@@ -444,7 +441,7 @@ namespace mongo {
const NamespaceString& nsString = request.getNamespaceString();
UpdateLifecycle* lifecycle = request.getLifecycle();
- Collection* collection = db->getCollection(txn, nsString.ns());
+ Collection* collection = db->getCollection(request.getOpCtx(), nsString.ns());
validateUpdate(nsString.ns().c_str(), request.getUpdates(), request.getQuery());
@@ -459,8 +456,9 @@ namespace mongo {
PlanExecutor* rawExec;
Status status = cq ?
- getExecutor(txn, collection, cqHolder.release(), &rawExec) :
- getExecutor(txn, collection, nsString.ns(), request.getQuery(), &rawExec);
+ getExecutor(request.getOpCtx(), collection, cqHolder.release(), &rawExec) :
+ getExecutor(request.getOpCtx(), collection, nsString.ns(), request.getQuery(), &rawExec);
+
uassert(17243,
"could not get executor" + request.getQuery().toString() + "; " + causedBy(status),
status.isOK());
@@ -628,7 +626,7 @@ namespace mongo {
// If a set of modifiers were all no-ops, we are still 'in place', but there is
// no work to do, in which case we want to consider the object unchanged.
if (!damages.empty() ) {
- collection->updateDocumentWithDamages( txn, loc, source, damages );
+ collection->updateDocumentWithDamages(request.getOpCtx(), loc, source, damages);
docWasModified = true;
opDebug->fastmod = true;
}
@@ -647,7 +645,7 @@ namespace mongo {
str::stream() << "Resulting document after update is larger than "
<< BSONObjMaxUserSize,
newObj.objsize() <= BSONObjMaxUserSize);
- StatusWith<DiskLoc> res = collection->updateDocument(txn,
+ StatusWith<DiskLoc> res = collection->updateDocument(request.getOpCtx(),
loc,
newObj,
true,
@@ -674,7 +672,7 @@ namespace mongo {
// Call logOp if requested.
if (request.shouldCallLogOp() && !logObj.isEmpty()) {
BSONObj idQuery = driver->makeOplogEntryQuery(newObj, request.isMulti());
- repl::logOp(txn, "u", nsString.ns().c_str(), logObj , &idQuery,
+ repl::logOp(request.getOpCtx(), "u", nsString.ns().c_str(), logObj, &idQuery,
NULL, request.isFromMigration());
}
@@ -687,7 +685,7 @@ namespace mongo {
}
// Opportunity for journaling to write during the update.
- txn->recoveryUnit()->commitIfNeeded();
+ request.getOpCtx()->recoveryUnit()->commitIfNeeded();
}
// Get summary information about the plan.
@@ -775,9 +773,9 @@ namespace mongo {
// Only create the collection if the doc will be inserted.
if (!collection) {
- collection = db->getCollection(txn, request.getNamespaceString().ns());
+ collection = db->getCollection(request.getOpCtx(), request.getNamespaceString().ns());
if (!collection) {
- collection = db->createCollection(txn, request.getNamespaceString().ns());
+ collection = db->createCollection(request.getOpCtx(), request.getNamespaceString().ns());
}
}
@@ -787,13 +785,18 @@ namespace mongo {
str::stream() << "Document to upsert is larger than " << BSONObjMaxUserSize,
newObj.objsize() <= BSONObjMaxUserSize);
- StatusWith<DiskLoc> newLoc = collection->insertDocument(txn,
+ StatusWith<DiskLoc> newLoc = collection->insertDocument(request.getOpCtx(),
newObj,
!request.isGod() /*enforceQuota*/);
uassertStatusOK(newLoc.getStatus());
if (request.shouldCallLogOp()) {
- repl::logOp(txn, "i", nsString.ns().c_str(), newObj,
- NULL, NULL, request.isFromMigration());
+ repl::logOp(request.getOpCtx(),
+ "i",
+ nsString.ns().c_str(),
+ newObj,
+ NULL,
+ NULL,
+ request.isFromMigration());
}
opDebug->nMatched = 1;
diff --git a/src/mongo/db/ops/update.h b/src/mongo/db/ops/update.h
index f950fbaf08c..cff79a0d90b 100644
--- a/src/mongo/db/ops/update.h
+++ b/src/mongo/db/ops/update.h
@@ -46,8 +46,7 @@ namespace mongo {
*
* Caller must hold the appropriate database locks.
*/
- UpdateResult update(OperationContext* txn,
- Database* db,
+ UpdateResult update(Database* db,
const UpdateRequest& request,
OpDebug* opDebug);
@@ -59,8 +58,7 @@ namespace mongo {
*
* TODO: Move this into a private method of UpdateExecutor.
*/
- UpdateResult update(OperationContext* txn,
- Database* db,
+ UpdateResult update(Database* db,
const UpdateRequest& request,
OpDebug* opDebug,
UpdateDriver* driver,
diff --git a/src/mongo/db/ops/update_executor.cpp b/src/mongo/db/ops/update_executor.cpp
index fd2f11701a7..268e7616d3c 100644
--- a/src/mongo/db/ops/update_executor.cpp
+++ b/src/mongo/db/ops/update_executor.cpp
@@ -62,10 +62,9 @@ namespace mongo {
return Status::OK();
}
- UpdateResult UpdateExecutor::execute(OperationContext* txn, Database* db) {
+ UpdateResult UpdateExecutor::execute(Database* db) {
uassertStatusOK(prepare());
- return update(txn,
- db,
+ return update(db,
*_request,
_opDebug,
&_driver,
@@ -85,7 +84,8 @@ namespace mongo {
}
CanonicalQuery* cqRaw;
- const WhereCallbackReal whereCallback(_request->getNamespaceString().db());
+ const WhereCallbackReal whereCallback(
+ _request->getOpCtx(), _request->getNamespaceString().db());
Status status = CanonicalQuery::canonicalize(_request->getNamespaceString().ns(),
_request->getQuery(),
diff --git a/src/mongo/db/ops/update_executor.h b/src/mongo/db/ops/update_executor.h
index 881c0cc0d36..f4a62224c59 100644
--- a/src/mongo/db/ops/update_executor.h
+++ b/src/mongo/db/ops/update_executor.h
@@ -91,7 +91,7 @@ namespace mongo {
* Execute an update. Requires the caller to hold the database lock on the
* appropriate resources for the request.
*/
- UpdateResult execute(OperationContext* txn, Database* db);
+ UpdateResult execute(Database* db);
private:
/**
diff --git a/src/mongo/db/ops/update_request.h b/src/mongo/db/ops/update_request.h
index db0dcbf1e5e..5ed6eca209a 100644
--- a/src/mongo/db/ops/update_request.h
+++ b/src/mongo/db/ops/update_request.h
@@ -42,8 +42,9 @@ namespace mongo {
class UpdateRequest {
public:
- inline UpdateRequest(const NamespaceString& nsString)
- : _nsString(nsString)
+ inline UpdateRequest(OperationContext* txn, const NamespaceString& nsString)
+ : _txn(txn)
+ , _nsString(nsString)
, _god(false)
, _upsert(false)
, _multi(false)
@@ -131,6 +132,10 @@ namespace mongo {
return _lifecycle;
}
+ inline OperationContext* getOpCtx() const {
+ return _txn;
+ }
+
const std::string toString() const {
return str::stream()
<< " query: " << _query
@@ -144,6 +149,9 @@ namespace mongo {
}
private:
+ // Not owned. Must live as long as the request lives.
+ OperationContext* _txn;
+
const NamespaceString& _nsString;
// Contains the query that selects documents to update.
diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp
index 1f6f93f1274..9259a2a8072 100644
--- a/src/mongo/db/pipeline/pipeline_d.cpp
+++ b/src/mongo/db/pipeline/pipeline_d.cpp
@@ -167,7 +167,7 @@ namespace {
boost::shared_ptr<Runner> runner;
bool sortInRunner = false;
- const WhereCallbackReal whereCallback(pExpCtx->ns.db());
+ const WhereCallbackReal whereCallback(pExpCtx->opCtx, pExpCtx->ns.db());
if (sortStage) {
CanonicalQuery* cq;
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp
index f153434e3b0..4b56863eeaa 100644
--- a/src/mongo/db/query/get_executor.cpp
+++ b/src/mongo/db/query/get_executor.cpp
@@ -181,7 +181,7 @@ namespace mongo {
if (!CanonicalQuery::isSimpleIdQuery(unparsedQuery) ||
!collection->getIndexCatalog()->findIdIndex()) {
- const WhereCallbackReal whereCallback(collection->ns().db());
+ const WhereCallbackReal whereCallback(txn, collection->ns().db());
CanonicalQuery* cq;
Status status = CanonicalQuery::canonicalize(
collection->ns(), unparsedQuery, &cq, whereCallback);
@@ -230,7 +230,7 @@ namespace mongo {
// so we don't support covered projections. However, we might use the simple inclusion
// fast path.
if (NULL != canonicalQuery->getProj()) {
- ProjectionStageParams params(WhereCallbackReal(collection->ns().db()));
+ ProjectionStageParams params(WhereCallbackReal(txn, collection->ns().db()));
params.projObj = canonicalQuery->getProj()->getProjObj();
// Stuff the right data into the params depending on what proj impl we use.
@@ -652,7 +652,7 @@ namespace mongo {
PlanExecutor** execOut) {
invariant(collection);
- const WhereCallbackReal whereCallback(collection->ns().db());
+ const WhereCallbackReal whereCallback(txn, collection->ns().db());
CanonicalQuery* cq;
uassertStatusOK(CanonicalQuery::canonicalize(collection->ns().ns(),
@@ -759,7 +759,7 @@ namespace mongo {
}
}
- const WhereCallbackReal whereCallback(collection->ns().db());
+ const WhereCallbackReal whereCallback(txn, collection->ns().db());
// If there are no suitable indices for the distinct hack bail out now into regular planning
// with no projection.
diff --git a/src/mongo/db/query/get_runner.cpp b/src/mongo/db/query/get_runner.cpp
index 429cbc15d33..e93d670a898 100644
--- a/src/mongo/db/query/get_runner.cpp
+++ b/src/mongo/db/query/get_runner.cpp
@@ -88,7 +88,7 @@ namespace mongo {
if (!CanonicalQuery::isSimpleIdQuery(unparsedQuery) ||
!collection->getIndexCatalog()->findIdIndex()) {
- const WhereCallbackReal whereCallback(collection->ns().db());
+ const WhereCallbackReal whereCallback(txn, collection->ns().db());
Status status = CanonicalQuery::canonicalize(
collection->ns(), unparsedQuery, outCanonicalQuery, whereCallback);
if (!status.isOK())
@@ -516,7 +516,7 @@ namespace mongo {
Runner** out) {
verify(collection);
- const WhereCallbackReal whereCallback(collection->ns().db());
+ const WhereCallbackReal whereCallback(txn, collection->ns().db());
CanonicalQuery* cq;
uassertStatusOK(CanonicalQuery::canonicalize(collection->ns().ns(),
@@ -573,7 +573,7 @@ namespace mongo {
}
}
- const WhereCallbackReal whereCallback(collection->ns().db());
+ const WhereCallbackReal whereCallback(txn, collection->ns().db());
// If there are no suitable indices for the distinct hack bail out now into regular planning
// with no projection.
diff --git a/src/mongo/db/query/idhack_runner.cpp b/src/mongo/db/query/idhack_runner.cpp
index 5382a4e4bfa..cf8f8dc78f5 100644
--- a/src/mongo/db/query/idhack_runner.cpp
+++ b/src/mongo/db/query/idhack_runner.cpp
@@ -174,7 +174,7 @@ namespace mongo {
BSONObj projectedObj;
ProjectionExec projExec(projObj,
_query->root(),
- WhereCallbackReal(_collection->ns().db()));
+ WhereCallbackReal(_txn, _collection->ns().db()));
projExec.transform(docObj, &projectedObj);
return projectedObj;
}
diff --git a/src/mongo/db/query/new_find.cpp b/src/mongo/db/query/new_find.cpp
index 09ab4104d15..3cc4a035a6e 100644
--- a/src/mongo/db/query/new_find.cpp
+++ b/src/mongo/db/query/new_find.cpp
@@ -496,7 +496,7 @@ namespace mongo {
// Parse the qm into a CanonicalQuery.
CanonicalQuery* cq;
Status canonStatus = CanonicalQuery::canonicalize(
- q, &cq, WhereCallbackReal(StringData(ctx.ctx().db()->name())));
+ q, &cq, WhereCallbackReal(txn, StringData(ctx.ctx().db()->name())));
if (!canonStatus.isOK()) {
uasserted(17287, str::stream() << "Can't canonicalize query: " << canonStatus.toString());
}
diff --git a/src/mongo/db/query/stage_builder.cpp b/src/mongo/db/query/stage_builder.cpp
index b0441eb0a25..bec04c13fba 100644
--- a/src/mongo/db/query/stage_builder.cpp
+++ b/src/mongo/db/query/stage_builder.cpp
@@ -113,7 +113,7 @@ namespace mongo {
PlanStage* childStage = buildStages(txn, collection, qsol, pn->children[0], ws);
if (NULL == childStage) { return NULL; }
- ProjectionStageParams params(WhereCallbackReal(collection->ns().db()));
+ ProjectionStageParams params(WhereCallbackReal(txn, collection->ns().db()));
params.projObj = pn->projection;
// Stuff the right data into the params depending on what proj impl we use.
diff --git a/src/mongo/db/query/subplan_runner.cpp b/src/mongo/db/query/subplan_runner.cpp
index c107f829c77..4682c29b2b4 100644
--- a/src/mongo/db/query/subplan_runner.cpp
+++ b/src/mongo/db/query/subplan_runner.cpp
@@ -203,7 +203,7 @@ namespace mongo {
QLOG() << "Subplanner: index " << i << " is " << ie.toString() << endl;
}
- const WhereCallbackReal whereCallback(_collection->ns().db());
+ const WhereCallbackReal whereCallback(_txn, _collection->ns().db());
for (size_t i = 0; i < theOr->numChildren(); ++i) {
// Turn the i-th child into its own query.
diff --git a/src/mongo/db/repl/master_slave.cpp b/src/mongo/db/repl/master_slave.cpp
index 0e216cdd05b..5e591b41f4f 100644
--- a/src/mongo/db/repl/master_slave.cpp
+++ b/src/mongo/db/repl/master_slave.cpp
@@ -207,13 +207,13 @@ namespace repl {
Client::Context ctx(txn, "local.sources");
const NamespaceString requestNs("local.sources");
- UpdateRequest request(requestNs);
+ UpdateRequest request(txn, requestNs);
request.setQuery(pattern);
request.setUpdates(o);
request.setUpsert();
- UpdateResult res = update(txn, ctx.db(), request, &debug);
+ UpdateResult res = update(ctx.db(), request, &debug);
verify( ! res.modifiers );
verify( res.numMatched == 1 );
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index e911c19a852..36d7d7810da 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -619,7 +619,7 @@ namespace repl {
Timer t;
const NamespaceString requestNs(ns);
- UpdateRequest request(requestNs);
+ UpdateRequest request(txn, requestNs);
request.setQuery(o);
request.setUpdates(o);
@@ -628,7 +628,7 @@ namespace repl {
UpdateLifecycleImpl updateLifecycle(true, requestNs);
request.setLifecycle(&updateLifecycle);
- update(txn, db, request, &debug);
+ update(db, request, &debug);
if( t.millis() >= 2 ) {
RARELY OCCASIONALLY log() << "warning, repl doing slow updates (no _id field) for " << ns << endl;
@@ -648,7 +648,7 @@ namespace repl {
b.append(_id);
const NamespaceString requestNs(ns);
- UpdateRequest request(requestNs);
+ UpdateRequest request(txn, requestNs);
request.setQuery(b.done());
request.setUpdates(o);
@@ -657,7 +657,7 @@ namespace repl {
UpdateLifecycleImpl updateLifecycle(true, requestNs);
request.setLifecycle(&updateLifecycle);
- update(txn, db, request, &debug);
+ update(db, request, &debug);
}
}
}
@@ -675,7 +675,7 @@ namespace repl {
const bool upsert = valueB || convertUpdateToUpsert;
const NamespaceString requestNs(ns);
- UpdateRequest request(requestNs);
+ UpdateRequest request(txn, requestNs);
request.setQuery(updateCriteria);
request.setUpdates(o);
@@ -684,7 +684,7 @@ namespace repl {
UpdateLifecycleImpl updateLifecycle(true, requestNs);
request.setLifecycle(&updateLifecycle);
- UpdateResult ur = update(txn, db, request, &debug);
+ UpdateResult ur = update(db, request, &debug);
if( ur.numMatched == 0 ) {
if( ur.modifiers ) {
diff --git a/src/mongo/db/repl/rs_rollback.cpp b/src/mongo/db/repl/rs_rollback.cpp
index 445183fc5c9..b65dbb324bb 100644
--- a/src/mongo/db/repl/rs_rollback.cpp
+++ b/src/mongo/db/repl/rs_rollback.cpp
@@ -632,7 +632,7 @@ namespace repl {
updates++;
const NamespaceString requestNs(doc.ns);
- UpdateRequest request(requestNs);
+ UpdateRequest request(txn, requestNs);
request.setQuery(pattern);
request.setUpdates(it->second);
@@ -641,7 +641,7 @@ namespace repl {
UpdateLifecycleImpl updateLifecycle(true, requestNs);
request.setLifecycle(&updateLifecycle);
- update(txn, ctx.db(), request, &debug);
+ update(ctx.db(), request, &debug);
}
}
diff --git a/src/mongo/dbtests/matchertests.cpp b/src/mongo/dbtests/matchertests.cpp
index cee3995395c..efe21b9cb88 100644
--- a/src/mongo/dbtests/matchertests.cpp
+++ b/src/mongo/dbtests/matchertests.cpp
@@ -222,7 +222,7 @@ namespace MatcherTests {
Client::ReadContext ctx(&txn, "unittests.matchertests");
M m(BSON("$where" << "function(){ return this.a == 1; }"),
- WhereCallbackReal(StringData("unittests")));
+ WhereCallbackReal(&txn, StringData("unittests")));
ASSERT( m.matches( BSON( "a" << 1 ) ) );
ASSERT( !m.matches( BSON( "a" << 2 ) ) );
}