diff options
author | Xiangyu Yao <xiangyu.yao@mongodb.com> | 2017-11-27 18:19:40 -0500 |
---|---|---|
committer | Xiangyu Yao <xiangyu.yao@mongodb.com> | 2018-09-10 18:08:08 -0400 |
commit | e013b606016ead1c82ed7c09cbe3c558d5aaa3b2 (patch) | |
tree | 3e21e5353da1536c0209cafc929597bff89dc7ff | |
parent | 3339fc9385a6ae9c77d0830e7afdfe033a3a1b53 (diff) | |
download | mongo-e013b606016ead1c82ed7c09cbe3c558d5aaa3b2.tar.gz |
SERVER-25175 listIndexes command only includes ready indexes
(cherry picked from commit 2cc9396586e771a0484a4017bf3f126098818d2b)
10 files changed, 96 insertions, 10 deletions
diff --git a/jstests/noPassthrough/indexbg1.js b/jstests/noPassthrough/indexbg1.js index 00670f3f2db..5d8e4a72847 100644 --- a/jstests/noPassthrough/indexbg1.js +++ b/jstests/noPassthrough/indexbg1.js @@ -1,6 +1,7 @@ // Test background index creation load("jstests/libs/slow_weekly_util.js"); +load("jstests/noPassthrough/libs/index_build.js"); var testServer = new SlowWeeklyMongod("indexbg1"); var db = testServer.getDB("test"); @@ -56,7 +57,7 @@ while (1) { // if indexing finishes before we can run checks, try indexing w/ m // wait for indexing to start print("wait for indexing to start"); assert.soon(function() { - return 2 === t.getIndexes().length; + return getIndexBuildOpId(db) != -1; }, "no index created", 30000, 50); print("started."); sleep(1000); // there is a race between when the index build shows up in curop and diff --git a/jstests/noPassthrough/libs/index_build.js b/jstests/noPassthrough/libs/index_build.js new file mode 100644 index 00000000000..e3564db5c41 --- /dev/null +++ b/jstests/noPassthrough/libs/index_build.js @@ -0,0 +1,13 @@ +// Returns the op id for the running index build, or -1 if there is no current index build. +function getIndexBuildOpId(db) { + const result = db.currentOp(); + assert.commandWorked(result); + let indexBuildOpId = -1; + + result.inprog.forEach(function(op) { + if (op.op == 'command' && op.query != undefined && 'createIndexes' in op.query) { + indexBuildOpId = op.opid; + } + }); + return indexBuildOpId; +} diff --git a/jstests/noPassthrough/list_indexes_only_ready_indexes.js b/jstests/noPassthrough/list_indexes_only_ready_indexes.js new file mode 100644 index 00000000000..c1748792675 --- /dev/null +++ b/jstests/noPassthrough/list_indexes_only_ready_indexes.js @@ -0,0 +1,51 @@ +// SERVER-25175: Test the listIndexes command only shows ready indexes. +(function() { + "use strict"; + + load("jstests/noPassthrough/libs/index_build.js"); + + 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()); + + function assertIndexes(coll, numIndexes, indexes) { + let res = coll.runCommand("listIndexes"); + assert.eq(numIndexes, res.cursor.firstBatch.length); + for (var i = 0; i < numIndexes; i++) { + assert.eq(indexes[i], res.cursor.firstBatch[i].name); + } + } + + let coll = testDB.list_indexes_only_ready_indexes; + coll.drop(); + assert.commandWorked(testDB.createCollection(coll.getName())); + assertIndexes(coll, 1, ["_id_"]); + assert.commandWorked(coll.createIndex({a: 1})); + assertIndexes(coll, 2, ["_id_", "a_1"]); + + assert.commandWorked( + testDB.adminCommand({configureFailPoint: 'hangAfterStartingIndexBuild', mode: 'alwaysOn'})); + const createIdx = startParallelShell( + "let coll = db.getSiblingDB('test').list_indexes_only_ready_indexes;" + + "assert.commandWorked(coll.createIndex({ b: 1 }, { background: true }));", + conn.port); + assert.soon(function() { + return getIndexBuildOpId(testDB) != -1; + }, "Index build operation not found after starting via parallelShell"); + + // Verify there is no third index. + assertIndexes(coll, 2, ["_id_", "a_1"]); + + assert.commandWorked( + testDB.adminCommand({configureFailPoint: 'hangAfterStartingIndexBuild', mode: 'off'})); + // Wait for the index build to stop. + assert.soon(function() { + return getIndexBuildOpId(testDB) == -1; + }); + const exitCode = createIdx(); + assert.eq(0, exitCode, 'expected shell to exit cleanly'); + + assertIndexes(coll, 3, ["_id_", "a_1", "b_1"]); +}()); diff --git a/jstests/noPassthroughWithMongod/indexbg_drop.js b/jstests/noPassthroughWithMongod/indexbg_drop.js index 1f4e1c1be64..244d0cca9c7 100644 --- a/jstests/noPassthroughWithMongod/indexbg_drop.js +++ b/jstests/noPassthroughWithMongod/indexbg_drop.js @@ -56,14 +56,6 @@ jsTest.log("Starting background indexing for test of: " + tojson(dc)); masterDB.getCollection(collection).ensureIndex({b: 1}); masterDB.getCollection(collection).ensureIndex({i: 1}, {background: true}); -assert.eq(3, masterDB.getCollection(collection).getIndexes().length); - -// Wait for the secondary to get the index entry -assert.soon(function() { - return 3 == secondDB.getCollection(collection).getIndexes().length; -}, "index not created on secondary (prior to drop)", 240000); - -jsTest.log("Index created and index entry exists on secondary"); // make sure the index build has started on secondary assert.soon(function() { diff --git a/src/mongo/db/catalog/collection_catalog_entry.h b/src/mongo/db/catalog/collection_catalog_entry.h index dd6a1f506f1..38e5b12d234 100644 --- a/src/mongo/db/catalog/collection_catalog_entry.h +++ b/src/mongo/db/catalog/collection_catalog_entry.h @@ -64,6 +64,8 @@ public: virtual BSONObj getIndexSpec(OperationContext* txn, StringData idxName) const = 0; + virtual void getReadyIndexes(OperationContext* txn, std::vector<std::string>* names) const = 0; + /** * Returns true if the index identified by 'indexName' is multikey, and returns false otherwise. * diff --git a/src/mongo/db/commands/list_indexes.cpp b/src/mongo/db/commands/list_indexes.cpp index 1a581074d55..5e8e47a7dfd 100644 --- a/src/mongo/db/commands/list_indexes.cpp +++ b/src/mongo/db/commands/list_indexes.cpp @@ -152,7 +152,7 @@ public: vector<string> indexNames; MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN { indexNames.clear(); - cce->getAllIndexes(txn, &indexNames); + cce->getReadyIndexes(txn, &indexNames); } MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "listIndexes", ns.ns()); diff --git a/src/mongo/db/storage/bson_collection_catalog_entry.cpp b/src/mongo/db/storage/bson_collection_catalog_entry.cpp index 7837e898b56..f0e5589a946 100644 --- a/src/mongo/db/storage/bson_collection_catalog_entry.cpp +++ b/src/mongo/db/storage/bson_collection_catalog_entry.cpp @@ -143,6 +143,16 @@ void BSONCollectionCatalogEntry::getAllIndexes(OperationContext* txn, } } +void BSONCollectionCatalogEntry::getReadyIndexes(OperationContext* txn, + std::vector<std::string>* names) const { + MetaData md = _getMetaData(txn); + + for (unsigned i = 0; i < md.indexes.size(); i++) { + if (md.indexes[i].ready) + names->push_back(md.indexes[i].spec["name"].String()); + } +} + bool BSONCollectionCatalogEntry::isIndexMultikey(OperationContext* txn, StringData indexName, MultikeyPaths* multikeyPaths) const { diff --git a/src/mongo/db/storage/bson_collection_catalog_entry.h b/src/mongo/db/storage/bson_collection_catalog_entry.h index 83c2238fc17..c42908f5f8c 100644 --- a/src/mongo/db/storage/bson_collection_catalog_entry.h +++ b/src/mongo/db/storage/bson_collection_catalog_entry.h @@ -58,6 +58,8 @@ public: virtual void getAllIndexes(OperationContext* txn, std::vector<std::string>* names) const; + virtual void getReadyIndexes(OperationContext* txn, std::vector<std::string>* names) const; + virtual bool isIndexMultikey(OperationContext* txn, StringData indexName, MultikeyPaths* multikeyPaths) const; diff --git a/src/mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.cpp b/src/mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.cpp index a2421962853..abf43946697 100644 --- a/src/mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.cpp +++ b/src/mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.cpp @@ -106,6 +106,19 @@ void NamespaceDetailsCollectionCatalogEntry::getAllIndexes(OperationContext* txn } } +void NamespaceDetailsCollectionCatalogEntry::getReadyIndexes( + OperationContext* txn, std::vector<std::string>* names) const { + NamespaceDetails::IndexIterator i = _details->ii(true); + while (i.more()) { + const IndexDetails& id = i.next(); + const BSONObj obj = _indexRecordStore->dataFor(txn, id.info.toRecordId()).toBson(); + const char* idxName = obj.getStringField("name"); + if (isIndexReady(txn, StringData(idxName))) { + names->push_back(idxName); + } + } +} + bool NamespaceDetailsCollectionCatalogEntry::isIndexMultikey(OperationContext* txn, StringData idxName, MultikeyPaths* multikeyPaths) const { diff --git a/src/mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.h b/src/mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.h index 0f8940be756..8d57825d0c3 100644 --- a/src/mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.h +++ b/src/mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.h @@ -67,6 +67,8 @@ public: BSONObj getIndexSpec(OperationContext* txn, StringData idxName) const final; + void getReadyIndexes(OperationContext* txn, std::vector<std::string>* names) const final; + bool isIndexMultikey(OperationContext* txn, StringData indexName, MultikeyPaths* multikeyPaths) const final; |