diff options
author | Benety Goh <benety@mongodb.com> | 2014-01-31 11:31:48 -0500 |
---|---|---|
committer | Benety Goh <benety@mongodb.com> | 2014-02-05 15:34:25 -0500 |
commit | 4bd3299bc5de987f61098135171692e6f39e725c (patch) | |
tree | d3d9767b3ed2da4452f9870f371984df24ac0f13 | |
parent | 3c577a31cbdbb2722ebc2dd71c64e5ed2aab5f0f (diff) | |
download | mongo-4bd3299bc5de987f61098135171692e6f39e725c.tar.gz |
SERVER-12526 fold planCacheDrop into planCacheClear
-rw-r--r-- | jstests/plan_cache_commands.js | 10 | ||||
-rw-r--r-- | src/mongo/db/commands/plan_cache_commands.cpp | 65 | ||||
-rw-r--r-- | src/mongo/db/commands/plan_cache_commands.h | 35 | ||||
-rw-r--r-- | src/mongo/db/commands/plan_cache_commands_test.cpp | 32 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_plan_cache_cmd.cpp | 7 | ||||
-rw-r--r-- | src/mongo/shell/collection.js | 2 |
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; } |