diff options
author | James Wahlin <james.wahlin@10gen.com> | 2016-09-28 10:46:08 -0400 |
---|---|---|
committer | James Wahlin <james.wahlin@10gen.com> | 2016-10-03 09:02:34 -0400 |
commit | ab912a90501ffa988591ab5173773b538cc22cac (patch) | |
tree | 496cbb3d6ee0484ec3b7982be27dd5201c864d34 | |
parent | 445abe2e01db50dad295ba8af4971eb243b02546 (diff) | |
download | mongo-ab912a90501ffa988591ab5173773b538cc22cac.tar.gz |
SERVER-26367 index_killop.js should use failpoint
-rw-r--r-- | jstests/noPassthrough/index_killop.js | 69 | ||||
-rw-r--r-- | jstests/noPassthroughWithMongod/index_killop.js | 63 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_create.cpp | 16 |
3 files changed, 80 insertions, 68 deletions
diff --git a/jstests/noPassthrough/index_killop.js b/jstests/noPassthrough/index_killop.js new file mode 100644 index 00000000000..734053ce06a --- /dev/null +++ b/jstests/noPassthrough/index_killop.js @@ -0,0 +1,69 @@ +/** + * Confirms that both foreground and background index builds can be aborted using killop. + */ +(function() { + "use strict"; + + const conn = MongoRunner.runMongod({smallfiles: "", nojournal: ""}); + assert.neq(null, conn, "mongod was unable to start up"); + + const testDB = conn.getDB("test"); + assert.commandWorked(testDB.dropDatabase()); + testDB.test.insertOne({a: 1}); + + // Returns the op id for the running index build, or -1 if there is no current index build. + function getIndexBuildOpId() { + const result = testDB.currentOp(); + assert.commandWorked(result); + let indexBuildOpId = -1; + + result.inprog.forEach(function(op) { + // Identify the index build as the createIndex command + // It is assumed that no other clients are concurrently + // accessing the 'test' database. + if ((op.op == 'query' || op.op == 'command') && 'createIndexes' in op.query) { + indexBuildOpId = op.opid; + } + }); + return indexBuildOpId; + } + + // Test that building an index with 'options' can be aborted using killop. + function testAbortIndexBuild(options) { + assert.commandWorked(testDB.adminCommand( + {configureFailPoint: 'hangAfterStartingIndexBuild', mode: 'alwaysOn'})); + + const createIdx = startParallelShell( + "let coll = db.getSiblingDB('test').test;" + + "assert.commandWorked(coll.createIndex({ a: 1 }, " + tojson(options) + "));", + conn.port); + + // When the index build starts, find its op id. + let opId; + assert.soon(function() { + return (opId = getIndexBuildOpId()) != -1; + }, "Index build operation not found after starting via parallelShell"); + + // Kill the index build. + assert.commandWorked(testDB.killOp(opId)); + + assert.commandWorked( + testDB.adminCommand({configureFailPoint: 'hangAfterStartingIndexBuild', mode: 'off'})); + + // Wait for the index build to stop. + assert.soon(function() { + return getIndexBuildOpId() == -1; + }); + + const exitCode = createIdx({checkExitSuccess: false}); + assert.neq( + 0, exitCode, 'expected shell to exit abnormally due to index build being terminated'); + + // Check that no new index has been created. This verifies that the index build was aborted + // rather than successfully completed. + assert.eq([{_id: 1}], testDB.test.getIndexKeys()); + } + + testAbortIndexBuild({background: true}); + testAbortIndexBuild({background: false}); +})(); diff --git a/jstests/noPassthroughWithMongod/index_killop.js b/jstests/noPassthroughWithMongod/index_killop.js deleted file mode 100644 index 95b0f995848..00000000000 --- a/jstests/noPassthroughWithMongod/index_killop.js +++ /dev/null @@ -1,63 +0,0 @@ -// Both foreground and background index builds can be aborted using killop. SERVER-3067 - -t = db.jstests_slownightly_index_killop; -t.drop(); - -// Insert a large number of documents, enough to ensure that an index build on these documents will -// be interrupted before complete. -var bulk = t.initializeUnorderedBulkOp(); -for (i = 0; i < 1e6; ++i) { - bulk.insert({a: i}); -} -assert.writeOK(bulk.execute()); - -function debug(x) { - // printjson( x ); -} - -/** @return the op id for the running index build, or -1 if there is no current index build. */ -function getIndexBuildOpId() { - inprog = db.currentOp().inprog; - debug(inprog); - indexBuildOpId = -1; - inprog.forEach(function(op) { - // Identify the index build as the createIndex command - // It is assumed that no other clients are concurrently - // accessing the 'test' database. - if ((op.op == 'query' || op.op == 'command') && 'createIndexes' in op.query) { - debug(op.opid); - indexBuildOpId = op.opid; - } - }); - return indexBuildOpId; -} - -/** Test that building an index with @param 'options' can be aborted using killop. */ -function testAbortIndexBuild(options) { - var createIdx = startParallelShell('var coll = db.jstests_slownightly_index_killop;' + - 'assert.commandWorked(coll.createIndex({ a: 1 }, ' + - tojson(options) + '));'); - - // When the index build starts, find its op id. - assert.soon(function() { - return (opId = getIndexBuildOpId()) != -1; - }); - // Kill the index build. - db.killOp(opId); - - // Wait for the index build to stop. - assert.soon(function() { - return getIndexBuildOpId() == -1; - }); - - var exitCode = createIdx({checkExitSuccess: false}); - assert.neq( - 0, exitCode, 'expected shell to exit abnormally due to index build being terminated'); - - // Check that no new index has been created. This verifies that the index build was aborted - // rather than successfully completed. - assert.eq([{_id: 1}], t.getIndexKeys()); -} - -testAbortIndexBuild({background: false}); -testAbortIndexBuild({background: true}); diff --git a/src/mongo/db/catalog/index_create.cpp b/src/mongo/db/catalog/index_create.cpp index 4527e6cf2dc..823dacff550 100644 --- a/src/mongo/db/catalog/index_create.cpp +++ b/src/mongo/db/catalog/index_create.cpp @@ -329,12 +329,18 @@ Status MultiIndexBlock::insertAllDocumentsInCollection(std::set<RecordId>* dupsO WorkingSetCommon::toStatusString(objToIndex.value()), state == PlanExecutor::IS_EOF); - // Need the index build to hang before the progress meter is marked as finished so we can - // reliably check that the index build has actually started in js tests. - while (MONGO_FAIL_POINT(hangAfterStartingIndexBuild)) { - log() << "Hanging index build due to 'hangAfterStartingIndexBuild' failpoint"; - sleepmillis(1000); + if (MONGO_FAIL_POINT(hangAfterStartingIndexBuild)) { + // Need the index build to hang before the progress meter is marked as finished so we can + // reliably check that the index build has actually started in js tests. + while (MONGO_FAIL_POINT(hangAfterStartingIndexBuild)) { + log() << "Hanging index build due to 'hangAfterStartingIndexBuild' failpoint"; + sleepmillis(1000); + } + + // Check for interrupt to allow for killop prior to index build completion. + _txn->checkForInterrupt(); } + if (MONGO_FAIL_POINT(hangAfterStartingIndexBuildUnlocked)) { // Unlock before hanging so replication recognizes we've completed. Locker::LockSnapshot lockInfo; |