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>(); }
bool run(OperationContext* txn, const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { const std::string ns = parseNsCollectionRequired(dbname, jsobj); MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN { ScopedTransaction transaction(txn, MODE_IX); AutoGetDb autoDb(txn, dbname, MODE_X); if (!fromRepl && !repl::getGlobalReplicationCoordinator()->canAcceptWritesForDatabase(dbname)) { return appendCommandStatus(result, Status(ErrorCodes::NotMaster, str::stream() << "Not primary while dropping indexes in " << ns)); } WriteUnitOfWork wunit(txn); bool ok = wrappedRun(txn, dbname, ns, autoDb.getDb(), jsobj, errmsg, result); if (!ok) { return false; } if (!fromRepl) { getGlobalEnvironment()->getOpObserver()->onDropIndex(txn, dbname + ".$cmd", jsobj); } wunit.commit(); } MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "dropIndexes", dbname); return true; }
virtual bool run(OperationContext* txn, const string& dbname, BSONObj& cmdObj, int options, string& errmsg, BSONObjBuilder& result, bool fromRepl) { const std::string ns = parseNsCollectionRequired(dbname, cmdObj); Status allowedWriteStatus = userAllowedWriteNS(ns); if (!allowedWriteStatus.isOK()) { return appendCommandStatus(result, allowedWriteStatus); } const BSONObj query = cmdObj.getObjectField("query"); const BSONObj fields = cmdObj.getObjectField("fields"); const BSONObj update = cmdObj.getObjectField("update"); const BSONObj sort = cmdObj.getObjectField("sort"); bool upsert = cmdObj["upsert"].trueValue(); bool returnNew = cmdObj["new"].trueValue(); bool remove = cmdObj["remove"].trueValue(); if (remove) { if (upsert) { errmsg = "remove and upsert can't co-exist"; return false; } if (!update.isEmpty()) { errmsg = "remove and update can't co-exist"; return false; } if (returnNew) { errmsg = "remove and returnNew can't co-exist"; return false; } } else if (!cmdObj.hasField("update")) { errmsg = "need remove or update"; return false; } bool ok = false; MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN { errmsg = ""; // We can always retry because we only ever modify one document ok = runImpl(txn, dbname, ns, query, fields, update, sort, upsert, returnNew, remove, result, errmsg); } MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "findAndModify", ns); if (!ok && errmsg == "no-collection") { // Take X lock so we can create collection, then re-run operation. ScopedTransaction transaction(txn, MODE_IX); Lock::DBLock lk(txn->lockState(), dbname, MODE_X); Client::Context ctx(txn, ns, false /* don't check version */); if (!fromRepl && !repl::getGlobalReplicationCoordinator()->canAcceptWritesForDatabase(dbname)) { return appendCommandStatus(result, Status(ErrorCodes::NotMaster, str::stream() << "Not primary while creating collection " << ns << " during findAndModify")); } Database* db = ctx.db(); if (db->getCollection(ns)) { // someone else beat us to it, that's ok // we might race while we unlock if someone drops // but that's ok, we'll just do nothing and error out } else { MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN { WriteUnitOfWork wuow(txn); uassertStatusOK(userCreateNS(txn, db, ns, BSONObj(), !fromRepl)); wuow.commit(); } MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "findAndModify", ns); } errmsg = ""; ok = runImpl(txn, dbname, ns, query, fields, update, sort, upsert, returnNew, remove, result, errmsg); }