Esempio n. 1
0
        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>();
        }
Esempio n. 2
0
        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;
        }
Esempio n. 3
0
    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);
        }