diff options
author | Eric Milkie <milkie@10gen.com> | 2015-06-05 17:44:36 -0400 |
---|---|---|
committer | Eric Milkie <milkie@10gen.com> | 2015-06-05 17:48:23 -0400 |
commit | b1d6f667a771fb5768978e89ae32cc862b74904f (patch) | |
tree | d3c08f1823f83134e448e738675076e59d7f71f0 | |
parent | bfdf548bc4c882ab944e0cf2f1e6015752fc05c2 (diff) | |
download | mongo-b1d6f667a771fb5768978e89ae32cc862b74904f.tar.gz |
SERVER-17923 prohibit database/collection actions when bg index is running
-rw-r--r-- | src/mongo/db/catalog/index_create.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_create.h | 16 | ||||
-rw-r--r-- | src/mongo/db/commands.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/commands.h | 5 | ||||
-rw-r--r-- | src/mongo/db/commands/collection_to_capped.cpp | 15 | ||||
-rw-r--r-- | src/mongo/db/commands/compact.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/commands/drop_indexes.cpp | 47 | ||||
-rw-r--r-- | src/mongo/db/commands/rename_collection.cpp | 34 | ||||
-rw-r--r-- | src/mongo/db/commands/test_commands.cpp | 15 | ||||
-rw-r--r-- | src/mongo/db/dbcommands.cpp | 66 | ||||
-rw-r--r-- | src/mongo/db/index_builder.cpp | 23 | ||||
-rw-r--r-- | src/mongo/db/index_builder.h | 16 | ||||
-rw-r--r-- | src/mongo/db/repl/oplog.cpp | 2 |
13 files changed, 12 insertions, 261 deletions
diff --git a/src/mongo/db/catalog/index_create.cpp b/src/mongo/db/catalog/index_create.cpp index a4e59139b83..2ce91435224 100644 --- a/src/mongo/db/catalog/index_create.cpp +++ b/src/mongo/db/catalog/index_create.cpp @@ -223,20 +223,6 @@ namespace mongo { return Status::OK(); } - IndexDescriptor* MultiIndexBlock::registerIndexBuild() { - // Register background index build so that it can be found and killed when necessary - invariant(_collection); - invariant(_indexes.size() == 1); - invariant(_buildInBackground); - IndexDescriptor* descriptor = _indexes[0].block->getEntry()->descriptor(); - _collection->getIndexCatalog()->registerIndexBuild(descriptor, _txn->getCurOp()->opNum()); - return descriptor; - } - - void MultiIndexBlock::unregisterIndexBuild(IndexDescriptor* descriptor) { - _collection->getIndexCatalog()->unregisterIndexBuild(descriptor); - } - Status MultiIndexBlock::insertAllDocumentsInCollection(std::set<RecordId>* dupsOut) { const char* curopMessage = _buildInBackground ? "Index Build (background)" : "Index Build"; ProgressMeterHolder progress(*_txn->setMessage(curopMessage, diff --git a/src/mongo/db/catalog/index_create.h b/src/mongo/db/catalog/index_create.h index c4c3badd901..e6cdd4aeb0a 100644 --- a/src/mongo/db/catalog/index_create.h +++ b/src/mongo/db/catalog/index_create.h @@ -112,22 +112,6 @@ namespace mongo { } /** - * Manages in-progress background index builds. - * Call registerIndexBuild() after calling init() to record this build in the catalog's - * in-progress map. - * The build must be a background build and it must be a single index build (the size of - * _indexes must be 1). - * registerIndexBuild() returns the descriptor for the index build. You must subsequently - * call unregisterIndexBuild() with that same descriptor before this MultiIndexBlock goes - * out of scope. - * These functions are only intended to be used by the replication system. No internal - * concurrency control is performed; it is expected that the code has already taken steps - * to ensure calls to these functions are serialized, for a particular IndexCatalog. - */ - IndexDescriptor* registerIndexBuild(); - void unregisterIndexBuild(IndexDescriptor* descriptor); - - /** * Inserts all documents in the Collection into the indexes and logs with timing info. * * This is a simplified replacement for insert and doneInserting. Do not call this if you diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp index 7fcfeebf3e1..e8ec4ea2245 100644 --- a/src/mongo/db/commands.cpp +++ b/src/mongo/db/commands.cpp @@ -226,12 +226,6 @@ namespace mongo { help << "no help defined"; } - std::vector<BSONObj> Command::stopIndexBuilds(OperationContext* opCtx, - Database* db, - const BSONObj& cmdObj) { - return std::vector<BSONObj>(); - } - Command* Command::findCommand( const StringData& name ) { CommandMap::const_iterator i = _commands->find( name ); if ( i == _commands->end() ) diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h index 56a64cbc89c..c75200ea3c0 100644 --- a/src/mongo/db/commands.h +++ b/src/mongo/db/commands.h @@ -242,11 +242,6 @@ namespace mutablebson { ServerStatusMetricField<Counter64> _commandsFailedMetric; public: - // Stops all index builds required to run this command and returns index builds killed. - virtual std::vector<BSONObj> stopIndexBuilds(OperationContext* opCtx, - Database* db, - const BSONObj& cmdObj); - static const CommandMap* commandsByBestName() { return _commandsByBestName; } static const CommandMap* webCommands() { return _webCommands; } diff --git a/src/mongo/db/commands/collection_to_capped.cpp b/src/mongo/db/commands/collection_to_capped.cpp index 14e817840fa..3f217d7eaa9 100644 --- a/src/mongo/db/commands/collection_to_capped.cpp +++ b/src/mongo/db/commands/collection_to_capped.cpp @@ -217,20 +217,6 @@ namespace { out->push_back(Privilege(parseResourcePattern(dbname, cmdObj), actions)); } - virtual std::vector<BSONObj> stopIndexBuilds(OperationContext* opCtx, - Database* db, - const BSONObj& cmdObj) { - const std::string ns = parseNsCollectionRequired(db->name(), cmdObj); - - IndexCatalog::IndexKillCriteria criteria; - criteria.ns = ns; - Collection* coll = db->getCollection(ns); - if (coll) { - return IndexBuilder::killMatchingIndexBuilds(coll, criteria); - } - return std::vector<BSONObj>(); - } - bool run(OperationContext* txn, const string& dbname, BSONObj& jsobj, @@ -259,7 +245,6 @@ namespace { << dbname << " does not exist")); } - stopIndexBuilds(txn, db, jsobj); BackgroundOperation::assertNoBgOpInProgForDb(dbname.c_str()); string shortSource = jsobj.getStringField( "convertToCapped" ); diff --git a/src/mongo/db/commands/compact.cpp b/src/mongo/db/commands/compact.cpp index ef60369eaeb..ae248528761 100644 --- a/src/mongo/db/commands/compact.cpp +++ b/src/mongo/db/commands/compact.cpp @@ -76,16 +76,6 @@ namespace mongo { } CompactCmd() : Command("compact") { } - virtual std::vector<BSONObj> stopIndexBuilds(OperationContext* opCtx, - Database* db, - const BSONObj& cmdObj) { - const std::string ns = parseNsCollectionRequired(db->name(), cmdObj); - - IndexCatalog::IndexKillCriteria criteria; - criteria.ns = ns; - return IndexBuilder::killMatchingIndexBuilds(db->getCollection(ns), criteria); - } - virtual bool run(OperationContext* txn, const string& db, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { const std::string nsToCompact = parseNsCollectionRequired(db, cmdObj); @@ -163,8 +153,6 @@ namespace mongo { log() << "compact " << ns << " begin, options: " << compactOptions.toString(); - std::vector<BSONObj> indexesInProg = stopIndexBuilds(txn, collDB, cmdObj); - StatusWith<CompactStats> status = collection->compact( txn, &compactOptions ); if ( !status.isOK() ) return appendCommandStatus( result, status.getStatus() ); @@ -174,8 +162,6 @@ namespace mongo { log() << "compact " << ns << " end"; - IndexBuilder::restoreIndexes(txn, indexesInProg); - return true; } }; diff --git a/src/mongo/db/commands/drop_indexes.cpp b/src/mongo/db/commands/drop_indexes.cpp index c2c2f05d6c1..1b3798b98ae 100644 --- a/src/mongo/db/commands/drop_indexes.cpp +++ b/src/mongo/db/commands/drop_indexes.cpp @@ -79,37 +79,6 @@ namespace mongo { out->push_back(Privilege(parseResourcePattern(dbname, cmdObj), actions)); } - virtual std::vector<BSONObj> stopIndexBuilds(OperationContext* opCtx, - Database* db, - const BSONObj& cmdObj) { - const std::string toDeleteNs = parseNsCollectionRequired(db->name(), cmdObj); - Collection* collection = db->getCollection(toDeleteNs); - IndexCatalog::IndexKillCriteria criteria; - - // Get index name to drop - BSONElement toDrop = cmdObj.getField("index"); - - if (toDrop.type() == String) { - // Kill all in-progress indexes - if (strcmp("*", toDrop.valuestr()) == 0) { - criteria.ns = toDeleteNs; - return IndexBuilder::killMatchingIndexBuilds(collection, criteria); - } - // Kill an in-progress index by name - else { - criteria.name = toDrop.valuestr(); - return IndexBuilder::killMatchingIndexBuilds(collection, criteria); - } - } - // Kill an in-progress index build by index key - else if (toDrop.type() == Object) { - criteria.key = toDrop.Obj(); - return IndexBuilder::killMatchingIndexBuilds(collection, criteria); - } - - return std::vector<BSONObj>(); - } - CmdDropIndexes() : Command("dropIndexes", false, "deleteIndexes") { } bool run(OperationContext* txn, const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { @@ -156,8 +125,8 @@ namespace mongo { } Client::Context ctx(txn, toDeleteNs); - stopIndexBuilds(txn, db, jsobj); - + BackgroundOperation::assertNoBgOpInProgForNs(toDeleteNs); + IndexCatalog* indexCatalog = collection->getIndexCatalog(); anObjBuilder.appendNumber("nIndexesWas", indexCatalog->numIndexesTotal(txn) ); @@ -243,15 +212,6 @@ namespace mongo { } CmdReIndex() : Command("reIndex") { } - virtual std::vector<BSONObj> stopIndexBuilds(OperationContext* opCtx, - Database* db, - const BSONObj& cmdObj) { - const std::string ns = parseNsCollectionRequired(db->name(), cmdObj); - IndexCatalog::IndexKillCriteria criteria; - criteria.ns = ns; - return IndexBuilder::killMatchingIndexBuilds(db->getCollection(ns), criteria); - } - bool run(OperationContext* txn, const string& dbname , BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool /*fromRepl*/) { DBDirectClient db(txn); @@ -272,8 +232,6 @@ namespace mongo { BackgroundOperation::assertNoBgOpInProgForNs( toDeleteNs ); - std::vector<BSONObj> indexesInProg = stopIndexBuilds(txn, ctx.db(), jsobj); - vector<BSONObj> all; { vector<string> indexNames; @@ -326,7 +284,6 @@ namespace mongo { result.append( "nIndexes", (int)all.size() ); result.append( "indexes", all ); - IndexBuilder::restoreIndexes(txn, indexesInProg); return true; } } cmdReIndex; diff --git a/src/mongo/db/commands/rename_collection.cpp b/src/mongo/db/commands/rename_collection.cpp index fdbf6ce220e..b68d290c556 100644 --- a/src/mongo/db/commands/rename_collection.cpp +++ b/src/mongo/db/commands/rename_collection.cpp @@ -29,6 +29,7 @@ */ #include "mongo/client/dbclientcursor.h" +#include "mongo/db/background.h" #include "mongo/db/catalog/collection.h" #include "mongo/db/catalog/collection_catalog_entry.h" #include "mongo/db/catalog/database_holder.h" @@ -72,31 +73,6 @@ namespace mongo { help << " example: { renameCollection: foo.a, to: bar.b }"; } - virtual std::vector<BSONObj> stopIndexBuilds(OperationContext* opCtx, - Database* db, - const BSONObj& cmdObj) { - string source = cmdObj.getStringField( name.c_str() ); - string target = cmdObj.getStringField( "to" ); - - IndexCatalog::IndexKillCriteria criteria; - criteria.ns = source; - std::vector<BSONObj> prelim = - IndexBuilder::killMatchingIndexBuilds(db->getCollection(source), criteria); - - std::vector<BSONObj> indexes; - - for (int i = 0; i < static_cast<int>(prelim.size()); i++) { - // Change the ns - BSONObj stripped = prelim[i].removeField("ns"); - BSONObjBuilder builder; - builder.appendElements(stripped); - builder.append("ns", target); - indexes.push_back(builder.obj()); - } - - return indexes; - } - static void dropCollection(OperationContext* txn, Database* db, StringData collName) { WriteUnitOfWork wunit(txn); if (db->dropCollection(txn, collName).isOK()) { @@ -207,11 +183,7 @@ namespace mongo { } } - const std::vector<BSONObj> indexesInProg = stopIndexBuilds(txn, sourceDB, cmdObj); - // Dismissed on success - ScopeGuard indexBuildRestorer = MakeGuard(IndexBuilder::restoreIndexes, - txn, - indexesInProg); + BackgroundOperation::assertNoBgOpInProgForNs(source); Database* const targetDB = dbHolder().openDb(txn, nsToDatabase(target)); @@ -249,7 +221,6 @@ namespace mongo { } wunit.commit(); - indexBuildRestorer.Dismiss(); return true; } @@ -350,7 +321,6 @@ namespace mongo { wunit.commit(); } - indexBuildRestorer.Dismiss(); targetCollectionDropper.Dismiss(); return true; } diff --git a/src/mongo/db/commands/test_commands.cpp b/src/mongo/db/commands/test_commands.cpp index d29f7f7f18b..434fb694435 100644 --- a/src/mongo/db/commands/test_commands.cpp +++ b/src/mongo/db/commands/test_commands.cpp @@ -34,6 +34,7 @@ #include "mongo/base/init.h" #include "mongo/base/initializer_context.h" +#include "mongo/db/background.h" #include "mongo/db/client.h" #include "mongo/db/commands.h" #include "mongo/db/index_builder.h" @@ -192,16 +193,6 @@ namespace mongo { const BSONObj& cmdObj, std::vector<Privilege>* out) {} - virtual std::vector<BSONObj> stopIndexBuilds(OperationContext* opCtx, - Database* db, - const BSONObj& cmdObj) { - const std::string ns = parseNsCollectionRequired(db->name(), cmdObj); - - IndexCatalog::IndexKillCriteria criteria; - criteria.ns = ns; - return IndexBuilder::killMatchingIndexBuilds(db->getCollection(ns), criteria); - } - virtual bool run(OperationContext* txn, const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { const std::string ns = parseNsCollectionRequired(dbname, cmdObj); @@ -220,7 +211,7 @@ namespace mongo { Collection* collection = db->getCollection(ns); massert(28584, "no such collection", collection); - std::vector<BSONObj> indexes = stopIndexBuilds(txn, db, cmdObj); + BackgroundOperation::assertNoBgOpInProgForNs(ns); WriteUnitOfWork wuow(txn); @@ -229,8 +220,6 @@ namespace mongo { return appendCommandStatus(result, status); } - IndexBuilder::restoreIndexes(txn, indexes); - if (!fromRepl) { repl::logOp(txn, "c", (dbname + ".$cmd").c_str(), cmdObj); } diff --git a/src/mongo/db/dbcommands.cpp b/src/mongo/db/dbcommands.cpp index a9cb7c6e88b..1c7c280f9c7 100644 --- a/src/mongo/db/dbcommands.cpp +++ b/src/mongo/db/dbcommands.cpp @@ -146,30 +146,6 @@ namespace mongo { virtual bool isWriteCommandForConfigServer() const { return true; } - virtual std::vector<BSONObj> stopIndexBuilds(OperationContext* opCtx, - Database* db, - const BSONObj& cmdObj) { - invariant(db); - std::list<std::string> collections; - db->getDatabaseCatalogEntry()->getCollectionNamespaces(&collections); - - std::vector<BSONObj> allKilledIndexes; - for (std::list<std::string>::iterator it = collections.begin(); - it != collections.end(); - ++it) { - std::string ns = *it; - - IndexCatalog::IndexKillCriteria criteria; - criteria.ns = ns; - std::vector<BSONObj> killedIndexes = - IndexBuilder::killMatchingIndexBuilds(db->getCollection(ns), criteria); - allKilledIndexes.insert(allKilledIndexes.end(), - killedIndexes.begin(), - killedIndexes.end()); - } - return allKilledIndexes; - } - CmdDropDatabase() : Command("dropDatabase") {} bool run(OperationContext* txn, const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { @@ -210,7 +186,7 @@ namespace mongo { log() << "dropDatabase " << dbname << " starting" << endl; - stopIndexBuilds(txn, db, cmdObj); + BackgroundOperation::assertNoBgOpInProgForDb(dbname); dropDatabase(txn, db); log() << "dropDatabase " << dbname << " finished"; @@ -254,30 +230,6 @@ namespace mongo { } - virtual std::vector<BSONObj> stopIndexBuilds(OperationContext* opCtx, - Database* db, - const BSONObj& cmdObj) { - invariant(db); - std::list<std::string> collections; - db->getDatabaseCatalogEntry()->getCollectionNamespaces(&collections); - - std::vector<BSONObj> allKilledIndexes; - for (std::list<std::string>::iterator it = collections.begin(); - it != collections.end(); - ++it) { - std::string ns = *it; - - IndexCatalog::IndexKillCriteria criteria; - criteria.ns = ns; - std::vector<BSONObj> killedIndexes = - IndexBuilder::killMatchingIndexBuilds(db->getCollection(ns), criteria); - allKilledIndexes.insert(allKilledIndexes.end(), - killedIndexes.begin(), - killedIndexes.end()); - } - return allKilledIndexes; - } - bool run(OperationContext* txn, const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { BSONElement e = cmdObj.firstElement(); if ( e.numberInt() != 1 ) { @@ -291,7 +243,7 @@ namespace mongo { Client::Context context(txn, dbname ); log() << "repairDatabase " << dbname; - std::vector<BSONObj> indexesInProg = stopIndexBuilds(txn, context.db(), cmdObj); + BackgroundOperation::assertNoBgOpInProgForDb(dbname); e = cmdObj.getField( "preserveClonedFilesOnFailure" ); bool preserveClonedFilesOnFailure = e.isBoolean() && e.boolean(); @@ -302,8 +254,6 @@ namespace mongo { Status status = repairDatabase(txn, engine, dbname, preserveClonedFilesOnFailure, backupOriginalFiles ); - IndexBuilder::restoreIndexes(txn, indexesInProg); - // Open database before returning dbHolder().openDb(txn, dbname); return appendCommandStatus( result, status ); @@ -465,16 +415,6 @@ namespace mongo { virtual bool isWriteCommandForConfigServer() const { return true; } - virtual std::vector<BSONObj> stopIndexBuilds(OperationContext* opCtx, - Database* db, - const BSONObj& cmdObj) { - const std::string nsToDrop = parseNsCollectionRequired(db->name(), cmdObj); - - IndexCatalog::IndexKillCriteria criteria; - criteria.ns = nsToDrop; - return IndexBuilder::killMatchingIndexBuilds(db->getCollection(nsToDrop), criteria); - } - virtual bool run(OperationContext* txn, const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { const std::string nsToDrop = parseNsCollectionRequired(dbname, cmdObj); @@ -515,7 +455,7 @@ namespace mongo { int numIndexes = coll->getIndexCatalog()->numIndexesTotal( txn ); - stopIndexBuilds(txn, db, cmdObj); + BackgroundOperation::assertNoBgOpInProgForNs(nsToDrop); result.append( "ns", nsToDrop ); result.append( "nIndexesWas", numIndexes ); diff --git a/src/mongo/db/index_builder.cpp b/src/mongo/db/index_builder.cpp index dca08c69de0..6a1e778b6ba 100644 --- a/src/mongo/db/index_builder.cpp +++ b/src/mongo/db/index_builder.cpp @@ -156,7 +156,6 @@ namespace { indexer.allowBackgroundBuilding(); - IndexDescriptor* descriptor(NULL); try { status = indexer.init(_index); if ( status.code() == ErrorCodes::IndexAlreadyExists ) { @@ -169,7 +168,6 @@ namespace { if (status.isOK()) { if (allowBackgroundBuilding) { - descriptor = indexer.registerIndexBuild(); if (!haveSetBgIndexStarting) { _setBgIndexStarting(); haveSetBgIndexStarting = true; @@ -200,7 +198,6 @@ namespace { Database* reloadDb = dbHolder().get(txn, ns.db()); fassert(28553, reloadDb); fassert(28554, reloadDb->getCollection(ns.ns())); - indexer.unregisterIndexBuild(descriptor); } if (status.code() == ErrorCodes::InterruptedAtShutdown) { @@ -220,22 +217,4 @@ namespace { txn->recoveryUnit()->commitAndRestart(); } } - - std::vector<BSONObj> - IndexBuilder::killMatchingIndexBuilds(Collection* collection, - const IndexCatalog::IndexKillCriteria& criteria) { - invariant(collection); - return collection->getIndexCatalog()->killMatchingIndexBuilds(criteria); - } - - void IndexBuilder::restoreIndexes(OperationContext* txn, const std::vector<BSONObj>& indexes) { - log() << "restarting " << indexes.size() << " background index build(s)" << endl; - for (int i = 0; i < static_cast<int>(indexes.size()); i++) { - IndexBuilder* indexBuilder = new IndexBuilder(indexes[i]); - // This looks like a memory leak, but indexBuilder deletes itself when it finishes - indexBuilder->go(); - Lock::TempRelease release(txn->lockState()); - IndexBuilder::waitForBgIndexStarting(); - } - } -} +} // namespace mongo diff --git a/src/mongo/db/index_builder.h b/src/mongo/db/index_builder.h index b32c6b5d988..dabfe92bae2 100644 --- a/src/mongo/db/index_builder.h +++ b/src/mongo/db/index_builder.h @@ -75,22 +75,6 @@ namespace mongo { Status buildInForeground(OperationContext* txn, Database* db) const; /** - * Kill all in-progress indexes matching criteria, if non-empty: - * index ns, index name, and/or index key spec. - * Returns a vector of the indexes that were killed. - */ - static std::vector<BSONObj> - killMatchingIndexBuilds(Collection* collection, - const IndexCatalog::IndexKillCriteria& criteria); - - /** - * Retry all index builds in the list. Builds each index in a separate thread. If ns does - * not match the ns field in the indexes list, the BSONObj's ns field is changed before the - * index is built (to handle rename). - */ - static void restoreIndexes(OperationContext* txn, const std::vector<BSONObj>& indexes); - - /** * Waits for a background index build to register itself. This function must be called * after starting a background index build via a BackgroundJob and before starting a * subsequent one. diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index 38fafeffa55..84883cc5286 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -745,6 +745,7 @@ namespace { Lock::TempRelease release(txn->lockState()); BackgroundOperation::awaitNoBgOpInProgForDb(nsToDatabaseSubstring(ns)); + txn->recoveryUnit()->commitAndRestart(); break; } case ErrorCodes::BackgroundOperationInProgressForNamespace: { @@ -753,6 +754,7 @@ namespace { Command* cmd = Command::findCommand(o.firstElement().fieldName()); invariant(cmd); BackgroundOperation::awaitNoBgOpInProgForNs(cmd->parseNs(nsToDatabase(ns), o)); + txn->recoveryUnit()->commitAndRestart(); break; } default: |