Exemplo n.º 1
0
    UpdateResult update(OperationContext* txn,
                        Database* db,
                        const UpdateRequest& request,
                        OpDebug* opDebug) {
        invariant(db);

        // Explain should never use this helper.
        invariant(!request.isExplain());

        const NamespaceString& nsString = request.getNamespaceString();
        Collection* collection = db->getCollection(nsString.ns());

        // The update stage does not create its own collection.  As such, if the update is
        // an upsert, create the collection that the update stage inserts into beforehand.
        if (!collection && request.isUpsert()) {
            // We have to have an exclusive lock on the db to be allowed to create the collection.
            // Callers should either get an X or create the collection.
            const Locker* locker = txn->lockState();
            invariant(locker->isW() ||
                      locker->isLockHeldForMode(ResourceId(RESOURCE_DATABASE, nsString.db()),
                                                MODE_X));

            ScopedTransaction transaction(txn, MODE_IX);
            Lock::DBLock lk(txn->lockState(), nsString.db(), MODE_X);

            bool userInitiatedWritesAndNotPrimary = txn->writesAreReplicated() &&
                !repl::getGlobalReplicationCoordinator()->canAcceptWritesForDatabase(nsString.db());

            if (userInitiatedWritesAndNotPrimary) {
                uassertStatusOK(Status(ErrorCodes::NotMaster, str::stream()
                    << "Not primary while creating collection " << nsString.ns()
                    << " during upsert"));
            }

            WriteUnitOfWork wuow(txn);
            collection = db->createCollection(txn, nsString.ns(), CollectionOptions());
            invariant(collection);

            wuow.commit();
        }

        // Parse the update, get an executor for it, run the executor, get stats out.
        ParsedUpdate parsedUpdate(txn, &request);
        uassertStatusOK(parsedUpdate.parseRequest());

        PlanExecutor* rawExec;
        uassertStatusOK(getExecutorUpdate(txn, collection, &parsedUpdate, opDebug, &rawExec));
        boost::scoped_ptr<PlanExecutor> exec(rawExec);

        uassertStatusOK(exec->executePlan());
        return UpdateStage::makeUpdateResult(exec.get(), opDebug);
    }
Exemplo n.º 2
0
Arquivo: update.cpp Projeto: 3rf/mongo
    UpdateResult update(OperationContext* txn,
                        Database* db,
                        const UpdateRequest& request,
                        OpDebug* opDebug) {
        invariant(db);

        // Explain should never use this helper.
        invariant(!request.isExplain());

        const NamespaceString& nsString = request.getNamespaceString();
        Collection* collection = db->getCollection(txn, nsString.ns());

        // The update stage does not create its own collection.  As such, if the update is
        // an upsert, create the collection that the update stage inserts into beforehand.
        if (!collection && request.isUpsert()) {
            // We have to have an exclusive lock on the db to be allowed to create the collection.
            // Callers should either get an X or create the collection.
            const Locker* locker = txn->lockState();
            invariant(locker->isW() ||
                      locker->isLockHeldForMode(ResourceId(RESOURCE_DATABASE, nsString.db()),
                                                MODE_X));

            ScopedTransaction transaction(txn, MODE_IX);
            Lock::DBLock lk(txn->lockState(), nsString.db(), MODE_X);

            WriteUnitOfWork wuow(txn);
            collection = db->createCollection(txn, nsString.ns());
            invariant(collection);

            if (!request.isFromReplication()) {
                repl::logOp(txn,
                            "c",
                            (db->name() + ".$cmd").c_str(),
                            BSON("create" << (nsString.coll())));
            }
            wuow.commit();
        }

        // Parse the update, get an executor for it, run the executor, get stats out.
        ParsedUpdate parsedUpdate(txn, &request);
        uassertStatusOK(parsedUpdate.parseRequest());

        PlanExecutor* rawExec;
        uassertStatusOK(getExecutorUpdate(txn, collection, &parsedUpdate, opDebug, &rawExec));
        boost::scoped_ptr<PlanExecutor> exec(rawExec);

        uassertStatusOK(exec->executePlan());
        return UpdateStage::makeUpdateResult(exec.get(), opDebug);
    }