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); }
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); }