summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/plan_cache_index_create.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/noPassthrough/plan_cache_index_create.js')
-rw-r--r--jstests/noPassthrough/plan_cache_index_create.js285
1 files changed, 142 insertions, 143 deletions
diff --git a/jstests/noPassthrough/plan_cache_index_create.js b/jstests/noPassthrough/plan_cache_index_create.js
index ee36f4d96eb..cc79a81bb25 100644
--- a/jstests/noPassthrough/plan_cache_index_create.js
+++ b/jstests/noPassthrough/plan_cache_index_create.js
@@ -4,159 +4,158 @@
* @tags: [requires_replication]
*/
(function() {
- "use strict";
-
- const dbName = "test";
- const collName = "coll";
-
- // Returns whether there is an active index build.
- function indexBuildIsRunning(testDB, indexName) {
- const indexBuildFilter = {
- "command.createIndexes": collName,
- "command.indexes.0.name": indexName,
- "msg": /^Index Build/
- };
- const curOp =
- testDB.getSiblingDB("admin").aggregate([{$currentOp: {}}, {$match: indexBuildFilter}]);
- return curOp.hasNext();
+"use strict";
+
+const dbName = "test";
+const collName = "coll";
+
+// Returns whether there is an active index build.
+function indexBuildIsRunning(testDB, indexName) {
+ const indexBuildFilter = {
+ "command.createIndexes": collName,
+ "command.indexes.0.name": indexName,
+ "msg": /^Index Build/
+ };
+ const curOp =
+ testDB.getSiblingDB("admin").aggregate([{$currentOp: {}}, {$match: indexBuildFilter}]);
+ return curOp.hasNext();
+}
+
+// Returns whether a cached plan exists for 'query'.
+function assertDoesNotHaveCachedPlan(coll, query) {
+ const key = {query: query};
+ const cmdRes = assert.commandWorked(coll.runCommand('planCacheListPlans', key));
+ assert(cmdRes.hasOwnProperty('plans') && cmdRes.plans.length == 0, tojson(cmdRes));
+}
+
+// Returns the cached plan for 'query'.
+function getIndexNameForCachedPlan(coll, query) {
+ const key = {query: query};
+ const cmdRes = assert.commandWorked(coll.runCommand('planCacheListPlans', key));
+ assert(Array.isArray(cmdRes.plans) && cmdRes.plans.length > 0, tojson(cmdRes));
+ return cmdRes.plans[0].reason.stats.inputStage.indexName;
+}
+
+function runTest({rst, readDB, writeDB}) {
+ const readColl = readDB.getCollection(collName);
+ const writeColl = writeDB.getCollection(collName);
+
+ assert.commandWorked(writeDB.runCommand({dropDatabase: 1, writeConcern: {w: "majority"}}));
+
+ const bulk = writeColl.initializeUnorderedBulkOp();
+ for (let i = 0; i < 100; ++i) {
+ bulk.insert({x: i, y: i % 10, z: 0});
}
+ assert.commandWorked(bulk.execute({w: "majority"}));
+ // We start with a baseline of 2 existing indexes as we will not cache plans when only a
+ // single plan exists.
+ assert.commandWorked(writeDB.runCommand({
+ createIndexes: collName,
+ indexes: [
+ {key: {y: 1}, name: "less_selective", background: false},
+ {key: {z: 1}, name: "least_selective", background: false}
+ ],
+ writeConcern: {w: "majority"}
+ }));
+
+ rst.waitForAllIndexBuildsToFinish(dbName, collName);
+
+ //
+ // Confirm that the plan cache is reset on start and completion of a background index build.
+ //
+
+ // Execute a find and confirm that a cached plan exists for an existing index.
+ const filter = {x: 50, y: 0, z: 0};
+ assert.eq(readColl.find(filter).itcount(), 1);
+ assert.eq("less_selective", getIndexNameForCachedPlan(readColl, filter));
+
+ // Enable a failpoint that will cause an index build to block just after start. This will
+ // allow us to examine PlanCache contents while index creation is in flight.
+ assert.commandWorked(
+ readDB.adminCommand({configureFailPoint: 'hangAfterStartingIndexBuild', mode: 'alwaysOn'}));
+
+ // Build a "most selective" index in the background.
+ TestData.dbName = dbName;
+ TestData.collName = collName;
+ const createIdxShell = startParallelShell(function() {
+ const testDB = db.getSiblingDB(TestData.dbName);
+ assert.commandWorked(testDB.runCommand({
+ createIndexes: TestData.collName,
+ indexes: [{key: {x: 1}, name: "most_selective", background: true}],
+ writeConcern: {w: "majority"}
+ }));
+ }, writeDB.getMongo().port);
- // Returns whether a cached plan exists for 'query'.
- function assertDoesNotHaveCachedPlan(coll, query) {
- const key = {query: query};
- const cmdRes = assert.commandWorked(coll.runCommand('planCacheListPlans', key));
- assert(cmdRes.hasOwnProperty('plans') && cmdRes.plans.length == 0, tojson(cmdRes));
- }
+ // Confirm that the index build has started.
+ assert.soon(() => indexBuildIsRunning(readDB, "most_selective"),
+ "Index build operation not found after starting via parallelShell");
- // Returns the cached plan for 'query'.
- function getIndexNameForCachedPlan(coll, query) {
- const key = {query: query};
- const cmdRes = assert.commandWorked(coll.runCommand('planCacheListPlans', key));
- assert(Array.isArray(cmdRes.plans) && cmdRes.plans.length > 0, tojson(cmdRes));
- return cmdRes.plans[0].reason.stats.inputStage.indexName;
- }
+ // Confirm that there are no cached plans post index build start.
+ assertDoesNotHaveCachedPlan(readColl, filter);
- function runTest({rst, readDB, writeDB}) {
- const readColl = readDB.getCollection(collName);
- const writeColl = writeDB.getCollection(collName);
-
- assert.commandWorked(writeDB.runCommand({dropDatabase: 1, writeConcern: {w: "majority"}}));
-
- const bulk = writeColl.initializeUnorderedBulkOp();
- for (let i = 0; i < 100; ++i) {
- bulk.insert({x: i, y: i % 10, z: 0});
- }
- assert.commandWorked(bulk.execute({w: "majority"}));
- // We start with a baseline of 2 existing indexes as we will not cache plans when only a
- // single plan exists.
- assert.commandWorked(writeDB.runCommand({
- createIndexes: collName,
- indexes: [
- {key: {y: 1}, name: "less_selective", background: false},
- {key: {z: 1}, name: "least_selective", background: false}
- ],
- writeConcern: {w: "majority"}
- }));
+ // Execute a find and confirm that a previously built index is the cached plan.
+ assert.eq(readColl.find(filter).itcount(), 1);
+ assert.eq("less_selective", getIndexNameForCachedPlan(readColl, filter));
- rst.waitForAllIndexBuildsToFinish(dbName, collName);
-
- //
- // Confirm that the plan cache is reset on start and completion of a background index build.
- //
-
- // Execute a find and confirm that a cached plan exists for an existing index.
- const filter = {x: 50, y: 0, z: 0};
- assert.eq(readColl.find(filter).itcount(), 1);
- assert.eq("less_selective", getIndexNameForCachedPlan(readColl, filter));
-
- // Enable a failpoint that will cause an index build to block just after start. This will
- // allow us to examine PlanCache contents while index creation is in flight.
- assert.commandWorked(readDB.adminCommand(
- {configureFailPoint: 'hangAfterStartingIndexBuild', mode: 'alwaysOn'}));
-
- // Build a "most selective" index in the background.
- TestData.dbName = dbName;
- TestData.collName = collName;
- const createIdxShell = startParallelShell(function() {
- const testDB = db.getSiblingDB(TestData.dbName);
- assert.commandWorked(testDB.runCommand({
- createIndexes: TestData.collName,
- indexes: [{key: {x: 1}, name: "most_selective", background: true}],
- writeConcern: {w: "majority"}
- }));
-
- }, writeDB.getMongo().port);
-
- // Confirm that the index build has started.
- assert.soon(() => indexBuildIsRunning(readDB, "most_selective"),
- "Index build operation not found after starting via parallelShell");
-
- // Confirm that there are no cached plans post index build start.
- assertDoesNotHaveCachedPlan(readColl, filter);
-
- // Execute a find and confirm that a previously built index is the cached plan.
- assert.eq(readColl.find(filter).itcount(), 1);
- assert.eq("less_selective", getIndexNameForCachedPlan(readColl, filter));
-
- // Disable the hang and wait for the index build to complete.
- assert.commandWorked(
- readDB.adminCommand({configureFailPoint: 'hangAfterStartingIndexBuild', mode: 'off'}));
- assert.soon(() => !indexBuildIsRunning(readDB, "most_selective"));
- createIdxShell({checkExitSuccess: true});
-
- rst.waitForAllIndexBuildsToFinish(dbName, collName);
-
- // Confirm that there are no cached plans post index build.
- assertDoesNotHaveCachedPlan(readColl, filter);
-
- // Now that the index has been built, execute another find and confirm that the newly
- // created index is used.
- assert.eq(readColl.find(filter).itcount(), 1);
- assert.eq("most_selective", getIndexNameForCachedPlan(readColl, filter));
-
- // Drop the newly created index and confirm that the plan cache has been cleared.
- assert.commandWorked(writeDB.runCommand(
- {dropIndexes: collName, index: {x: 1}, writeConcern: {w: "majority"}}));
- assertDoesNotHaveCachedPlan(readColl, filter);
-
- //
- // Confirm that the plan cache is reset post foreground index build.
- //
-
- // Execute a find and confirm that an existing index is in the cache.
- assert.eq(readColl.find(filter).itcount(), 1);
- assert.eq("less_selective", getIndexNameForCachedPlan(readColl, filter));
-
- // Build a "most selective" index in the foreground.
- assert.commandWorked(writeDB.runCommand({
- createIndexes: collName,
- indexes: [{key: {x: 1}, name: "most_selective", background: false}],
- writeConcern: {w: "majority"}
- }));
+ // Disable the hang and wait for the index build to complete.
+ assert.commandWorked(
+ readDB.adminCommand({configureFailPoint: 'hangAfterStartingIndexBuild', mode: 'off'}));
+ assert.soon(() => !indexBuildIsRunning(readDB, "most_selective"));
+ createIdxShell({checkExitSuccess: true});
- rst.waitForAllIndexBuildsToFinish(dbName, collName);
+ rst.waitForAllIndexBuildsToFinish(dbName, collName);
- // Confirm that there are no cached plans post index build.
- assertDoesNotHaveCachedPlan(readColl, filter);
+ // Confirm that there are no cached plans post index build.
+ assertDoesNotHaveCachedPlan(readColl, filter);
- // Execute a find and confirm that the newly created index is used.
- assert.eq(readColl.find(filter).itcount(), 1);
- assert.eq("most_selective", getIndexNameForCachedPlan(readColl, filter));
+ // Now that the index has been built, execute another find and confirm that the newly
+ // created index is used.
+ assert.eq(readColl.find(filter).itcount(), 1);
+ assert.eq("most_selective", getIndexNameForCachedPlan(readColl, filter));
- // Drop the newly created index and confirm that the plan cache has been cleared.
- assert.commandWorked(writeDB.runCommand(
- {dropIndexes: collName, index: {x: 1}, writeConcern: {w: "majority"}}));
- assertDoesNotHaveCachedPlan(readColl, filter);
- }
+ // Drop the newly created index and confirm that the plan cache has been cleared.
+ assert.commandWorked(
+ writeDB.runCommand({dropIndexes: collName, index: {x: 1}, writeConcern: {w: "majority"}}));
+ assertDoesNotHaveCachedPlan(readColl, filter);
+
+ //
+ // Confirm that the plan cache is reset post foreground index build.
+ //
+
+ // Execute a find and confirm that an existing index is in the cache.
+ assert.eq(readColl.find(filter).itcount(), 1);
+ assert.eq("less_selective", getIndexNameForCachedPlan(readColl, filter));
+
+ // Build a "most selective" index in the foreground.
+ assert.commandWorked(writeDB.runCommand({
+ createIndexes: collName,
+ indexes: [{key: {x: 1}, name: "most_selective", background: false}],
+ writeConcern: {w: "majority"}
+ }));
+
+ rst.waitForAllIndexBuildsToFinish(dbName, collName);
+
+ // Confirm that there are no cached plans post index build.
+ assertDoesNotHaveCachedPlan(readColl, filter);
+
+ // Execute a find and confirm that the newly created index is used.
+ assert.eq(readColl.find(filter).itcount(), 1);
+ assert.eq("most_selective", getIndexNameForCachedPlan(readColl, filter));
+
+ // Drop the newly created index and confirm that the plan cache has been cleared.
+ assert.commandWorked(
+ writeDB.runCommand({dropIndexes: collName, index: {x: 1}, writeConcern: {w: "majority"}}));
+ assertDoesNotHaveCachedPlan(readColl, filter);
+}
- const rst = new ReplSetTest({nodes: 2});
- rst.startSet();
- rst.initiate();
- const primaryDB = rst.getPrimary().getDB(dbName);
- const secondaryDB = rst.getSecondary().getDB(dbName);
+const rst = new ReplSetTest({nodes: 2});
+rst.startSet();
+rst.initiate();
+const primaryDB = rst.getPrimary().getDB(dbName);
+const secondaryDB = rst.getSecondary().getDB(dbName);
- runTest({rst: rst, readDB: primaryDB, writeDB: primaryDB});
- runTest({rst: rst, readDB: secondaryDB, writeDB: primaryDB});
+runTest({rst: rst, readDB: primaryDB, writeDB: primaryDB});
+runTest({rst: rst, readDB: secondaryDB, writeDB: primaryDB});
- rst.stopSet();
+rst.stopSet();
})();