summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2014-01-31 11:31:48 -0500
committerBenety Goh <benety@mongodb.com>2014-02-05 15:34:25 -0500
commit4bd3299bc5de987f61098135171692e6f39e725c (patch)
treed3d9767b3ed2da4452f9870f371984df24ac0f13
parent3c577a31cbdbb2722ebc2dd71c64e5ed2aab5f0f (diff)
downloadmongo-4bd3299bc5de987f61098135171692e6f39e725c.tar.gz
SERVER-12526 fold planCacheDrop into planCacheClear
-rw-r--r--jstests/plan_cache_commands.js10
-rw-r--r--src/mongo/db/commands/plan_cache_commands.cpp65
-rw-r--r--src/mongo/db/commands/plan_cache_commands.h35
-rw-r--r--src/mongo/db/commands/plan_cache_commands_test.cpp32
-rw-r--r--src/mongo/s/commands/cluster_plan_cache_cmd.cpp7
-rw-r--r--src/mongo/shell/collection.js2
6 files changed, 68 insertions, 83 deletions
diff --git a/jstests/plan_cache_commands.js b/jstests/plan_cache_commands.js
index 6415eea54d9..0a4b1377279 100644
--- a/jstests/plan_cache_commands.js
+++ b/jstests/plan_cache_commands.js
@@ -4,9 +4,7 @@
* Cache-wide Commands
* - planCacheListQueryShapes
* - planCacheClear
- *
- * Query-specific Commands
- * - planCacheDrop
+ * Removes plans for one or all query shapes.
* - planCacheListPlans
*/
@@ -55,16 +53,16 @@ assert.eq({query: queryA1, sort: sortA1, projection: projectionA1}, shapes[0],
//
-// Tests for planCacheDrop
+// Tests for planCacheClear (one query shape)
//
// Invalid key should be an error.
-assert.commandFailed(t.runCommand('planCacheDrop', {query: {unknownfield: 1}}));
+assert.commandFailed(t.runCommand('planCacheClear', {query: {unknownfield: 1}}));
// Run a new query shape and drop it from the cache
assert.eq(0, t.find({a: 1, b: 1}).itcount(), 'unexpected document count');
assert.eq(2, getShapes().length, 'unexpected cache size after running 2nd query');
-assert.commandWorked(t.runCommand('planCacheDrop', {query: {a: 1, b: 1}}));
+assert.commandWorked(t.runCommand('planCacheClear', {query: {a: 1, b: 1}}));
assert.eq(1, getShapes().length, 'unexpected cache size after dropping 2nd query from cache');
diff --git a/src/mongo/db/commands/plan_cache_commands.cpp b/src/mongo/db/commands/plan_cache_commands.cpp
index da280a7c172..2728fc322e8 100644
--- a/src/mongo/db/commands/plan_cache_commands.cpp
+++ b/src/mongo/db/commands/plan_cache_commands.cpp
@@ -94,7 +94,6 @@ namespace {
// the ActionType construction will be completed first.
new PlanCacheListQueryShapes();
new PlanCacheClear();
- new PlanCacheDrop();
new PlanCacheListPlans();
return Status::OK();
@@ -244,7 +243,7 @@ namespace mongo {
}
PlanCacheClear::PlanCacheClear() : PlanCacheCommand("planCacheClear",
- "Drops all cached queries in a collection.",
+ "Drops one or all cached queries in a collection.",
ActionType::planCacheWrite) { }
Status PlanCacheClear::runPlanCacheCommand(const string& ns, BSONObj& cmdObj,
@@ -257,53 +256,47 @@ namespace mongo {
if (!status.isOK()) {
return status;
}
- return clear(ns, planCache);
+ return clear(planCache, ns, cmdObj);
}
// static
- Status PlanCacheClear::clear(const std::string& ns, PlanCache* planCache) {
+ Status PlanCacheClear::clear(PlanCache* planCache, const string& ns, const BSONObj& cmdObj) {
invariant(planCache);
- planCache->clear();
-
- LOG(1) << ns << ": cleared plan cache";
+ // According to the specification, the planCacheClear command runs in two modes:
+ // - clear all query shapes; or
+ // - clear plans for single query shape when a query shape is described in the
+ // command arguments.
+ if (cmdObj.hasField("query")) {
+ CanonicalQuery* cqRaw;
+ Status status = PlanCacheCommand::canonicalize(ns, cmdObj, &cqRaw);
+ if (!status.isOK()) {
+ return status;
+ }
- return Status::OK();
- }
+ scoped_ptr<CanonicalQuery> cq(cqRaw);
+ Status result = planCache->remove(*cq);
+ if (!result.isOK()) {
+ return result;
+ }
- PlanCacheDrop::PlanCacheDrop() : PlanCacheCommand("planCacheDrop",
- "Drops query shape from plan cache.",
- ActionType::planCacheWrite) { }
+ LOG(1) << ns << ": removed plan cache entry - " << cq->getQueryObj().toString()
+ << "(sort: " << cq->getParsed().getSort()
+ << "; projection: " << cq->getParsed().getProj() << ")";
- Status PlanCacheDrop::runPlanCacheCommand(const string& ns, BSONObj& cmdObj,
- BSONObjBuilder* bob) {
- Client::ReadContext readCtx(ns);
- Client::Context& ctx = readCtx.ctx();
- PlanCache* planCache;
- Status status = getPlanCache(ctx.db(), ns, &planCache);
- if (!status.isOK()) {
- return status;
+ return Status::OK();
}
- return drop(planCache, ns, cmdObj);
- }
- // static
- Status PlanCacheDrop::drop(PlanCache* planCache, const string& ns, const BSONObj& cmdObj) {
- CanonicalQuery* cqRaw;
- Status status = canonicalize(ns, cmdObj, &cqRaw);
- if (!status.isOK()) {
- return status;
+ // If query is not provided, make sure sort and projection are not in arguments.
+ // We do not want to clear the entire cache inadvertently when the user
+ // forgets to provide a value for "query".
+ if (cmdObj.hasField("sort") || cmdObj.hasField("projection")) {
+ return Status(ErrorCodes::BadValue, "sort or projection provided without query");
}
- scoped_ptr<CanonicalQuery> cq(cqRaw);
- Status result = planCache->remove(*cq);
- if (!result.isOK()) {
- return result;
- }
+ planCache->clear();
- LOG(1) << ns << ": removed plan cache entry - " << cq->getQueryObj().toString()
- << "(sort: " << cq->getParsed().getSort()
- << "; projection: " << cq->getParsed().getProj() << ")";
+ LOG(1) << ns << ": cleared plan cache";
return Status::OK();
}
diff --git a/src/mongo/db/commands/plan_cache_commands.h b/src/mongo/db/commands/plan_cache_commands.h
index fd3c0832089..6cf666bce36 100644
--- a/src/mongo/db/commands/plan_cache_commands.h
+++ b/src/mongo/db/commands/plan_cache_commands.h
@@ -120,7 +120,12 @@ namespace mongo {
/**
* planCacheClear
*
- * { planCacheClear: <collection> }
+ * {
+ * planCacheClear: <collection>,
+ * query: <query>,
+ * sort: <sort>,
+ * projection: <projection>
+ * }
*
*/
class PlanCacheClear : public PlanCacheCommand {
@@ -130,32 +135,20 @@ namespace mongo {
/**
* Clears collection's plan cache.
+ * If query shape is provided, clears plans for that single query shape only.
*/
- static Status clear(const std::string& ns, PlanCache* planCache);
- };
-
- /**
- * planCacheDrop
- *
- * { planCacheDrop: <collection>, key: <key> } }
- *
- */
- class PlanCacheDrop : public PlanCacheCommand {
- public:
- PlanCacheDrop();
- virtual Status runPlanCacheCommand(const std::string& ns, BSONObj& cmdObj,
- BSONObjBuilder* bob);
-
- /**
- * Drops using a cache key.
- */
- static Status drop(PlanCache* planCache,const std::string& ns, const BSONObj& cmdObj);
+ static Status clear(PlanCache* planCache, const std::string& ns, const BSONObj& cmdObj);
};
/**
* planCacheListPlans
*
- * { planCacheListPlans: <collection>, key: <key> } }
+ * {
+ * planCacheListPlans: <collection>,
+ * query: <query>,
+ * sort: <sort>,
+ * projection: <projection>
+ * }
*
*/
class PlanCacheListPlans : public PlanCacheCommand {
diff --git a/src/mongo/db/commands/plan_cache_commands_test.cpp b/src/mongo/db/commands/plan_cache_commands_test.cpp
index 66d8a3c9c29..0fdfad7da19 100644
--- a/src/mongo/db/commands/plan_cache_commands_test.cpp
+++ b/src/mongo/db/commands/plan_cache_commands_test.cpp
@@ -144,7 +144,7 @@ namespace {
* Tests for planCacheClear
*/
- TEST(PlanCacheCommandsTest, planCacheClearOneKey) {
+ TEST(PlanCacheCommandsTest, planCacheClearAllShapes) {
// Create a canonical query
CanonicalQuery* cqRaw;
ASSERT_OK(CanonicalQuery::canonicalize(ns, fromjson("{a: 1}"), &cqRaw));
@@ -160,7 +160,7 @@ namespace {
ASSERT_EQUALS(getShapes(planCache).size(), 1U);
// Clear cache and confirm number of keys afterwards.
- ASSERT_OK(PlanCacheClear::clear(ns, &planCache));
+ ASSERT_OK(PlanCacheClear::clear(&planCache, ns, BSONObj()));
ASSERT_EQUALS(getShapes(planCache).size(), 0U);
}
@@ -207,24 +207,30 @@ namespace {
}
/**
- * Tests for planCacheDrop
+ * Tests for planCacheClear (single query shape)
*/
- TEST(PlanCacheCommandsTest, planCacheDropInvalidParameter) {
+ TEST(PlanCacheCommandsTest, planCacheClearInvalidParameter) {
PlanCache planCache;
- // Missing query field is not ok.
- ASSERT_NOT_OK(PlanCacheDrop::drop(&planCache, ns, BSONObj()));
- // Query field type must be PlanCacheKey.
- ASSERT_NOT_OK(PlanCacheDrop::drop(&planCache, ns, fromjson("{query: 12345}")));
- ASSERT_NOT_OK(PlanCacheDrop::drop(&planCache, ns, fromjson("{query: /keyisnotregex/}")));
+ // 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/}")));
+ // Query must pass canonicalization.
+ ASSERT_NOT_OK(PlanCacheClear::clear(&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}}")));
+ // Projection present without query is an error.
+ ASSERT_NOT_OK(PlanCacheClear::clear(&planCache, ns,
+ fromjson("{projection: {_id: 0, a: 1}}")));
}
- TEST(PlanCacheCommandsTest, planCacheDropUnknownKey) {
+ TEST(PlanCacheCommandsTest, planCacheClearUnknownKey) {
PlanCache planCache;
- ASSERT_NOT_OK(PlanCacheDrop::drop(&planCache, ns, fromjson("{query: {a: 1}}")));
+ ASSERT_NOT_OK(PlanCacheClear::clear(&planCache, ns, fromjson("{query: {a: 1}}")));
}
- TEST(PlanCacheCommandsTest, planCacheDropOneKey) {
+ TEST(PlanCacheCommandsTest, planCacheClearOneKey) {
// Create 2 canonical queries.
CanonicalQuery* cqRaw;
ASSERT_OK(CanonicalQuery::canonicalize(ns, fromjson("{a: 1}"), &cqRaw));
@@ -253,7 +259,7 @@ namespace {
// Drop {b: 1} from cache. Make sure {a: 1} is still in cache afterwards.
BSONObjBuilder bob;
- ASSERT_OK(PlanCacheDrop::drop(&planCache, ns, BSON("query" << cqB->getQueryObj())));
+ ASSERT_OK(PlanCacheClear::clear(&planCache, ns, BSON("query" << cqB->getQueryObj())));
vector<BSONObj> shapesAfter = getShapes(planCache);
ASSERT_EQUALS(shapesAfter.size(), 1U);
ASSERT_EQUALS(shapesAfter[0], shapeA);
diff --git a/src/mongo/s/commands/cluster_plan_cache_cmd.cpp b/src/mongo/s/commands/cluster_plan_cache_cmd.cpp
index be041dd6cc8..4596bee27d7 100644
--- a/src/mongo/s/commands/cluster_plan_cache_cmd.cpp
+++ b/src/mongo/s/commands/cluster_plan_cache_cmd.cpp
@@ -166,12 +166,7 @@ namespace mongo {
new ClusterPlanCacheCmd(
"planCacheClear",
- "Drops all cached queries in a collection.",
- ActionType::planCacheWrite );
-
- new ClusterPlanCacheCmd(
- "planCacheDrop",
- "Drops query shape from plan cache.",
+ "Drops one or all cached queries in a collection.",
ActionType::planCacheWrite );
new ClusterPlanCacheCmd(
diff --git a/src/mongo/shell/collection.js b/src/mongo/shell/collection.js
index 1661be94148..c53c4b3714f 100644
--- a/src/mongo/shell/collection.js
+++ b/src/mongo/shell/collection.js
@@ -1457,6 +1457,6 @@ PlanCache.prototype.getPlansByQuery = function(query, projection, sort) {
* Drop query shape from the plan cache.
*/
PlanCache.prototype.clearPlansByQuery = function(query, projection, sort) {
- this._runCommandThrowOnError("planCacheDrop", this._parseQueryShape(query, projection, sort));
+ this._runCommandThrowOnError("planCacheClear", this._parseQueryShape(query, projection, sort));
return;
}