virtual bool run(const string &db, BSONObj &cmdObj, int options, string &errmsg, BSONObjBuilder &result, bool fromRepl) { string ns = parseNs(db, cmdObj); intrusive_ptr<ExpressionContext> pCtx = new ExpressionContext(InterruptStatusMongod::status, NamespaceString(ns)); /* try to parse the command; if this fails, then we didn't run */ intrusive_ptr<Pipeline> pPipeline = Pipeline::parseCommand(errmsg, cmdObj, pCtx); if (!pPipeline.get()) return false; if (pPipeline->getSplitMongodPipeline()) { // This is only used in testing return executeSplitPipeline(result, errmsg, ns, db, pPipeline, pCtx); } #if _DEBUG // This is outside of the if block to keep the object alive until the pipeline is finished. BSONObj parsed; if (!pPipeline->isExplain() && !pCtx->inShard) { // Make sure all operations round-trip through Pipeline::toBson() // correctly by reparsing every command on DEBUG builds. This is // important because sharded aggregations rely on this ability. // Skipping when inShard because this has already been through the // transformation (and this unsets pCtx->inShard). parsed = pPipeline->serialize().toBson(); pPipeline = Pipeline::parseCommand(errmsg, parsed, pCtx); verify(pPipeline); } #endif // This does the mongod-specific stuff like creating a cursor PipelineD::prepareCursorSource(pPipeline, nsToDatabase(ns), pCtx); pPipeline->stitch(); if (isCursorCommand(cmdObj)) { CursorId id; { // Set up cursor Client::ReadContext ctx(ns); shared_ptr<Cursor> cursor(new PipelineCursor(pPipeline)); // cc will be owned by cursor manager ClientCursor* cc = new ClientCursor(0, cursor, ns, cmdObj.getOwned()); id = cc->cursorid(); } handleCursorCommand(id, cmdObj, result); } else { pPipeline->run(result); } if (DocumentSourceOut* out = dynamic_cast<DocumentSourceOut*>(pPipeline->output())) { result.append("outputNs", out->getOutputNs()); } return true; }
virtual bool run(const string &db, BSONObj &cmdObj, int options, string &errmsg, BSONObjBuilder &result, bool fromRepl) { intrusive_ptr<ExpressionContext> pCtx = ExpressionContext::create(&InterruptStatusMongod::status); /* try to parse the command; if this fails, then we didn't run */ intrusive_ptr<Pipeline> pPipeline = Pipeline::parseCommand(errmsg, cmdObj, pCtx); if (!pPipeline.get()) return false; string ns = parseNs(db, cmdObj); if (pPipeline->getSplitMongodPipeline()) { // This is only used in testing return executeSplitPipeline(result, errmsg, ns, db, pPipeline, pCtx); } #if _DEBUG // This is outside of the if block to keep the object alive until the pipeline is finished. BSONObj parsed; if (!pPipeline->isExplain() && !pCtx->getInShard()) { // Make sure all operations round-trip through Pipeline::toBson() // correctly by reparsing every command on DEBUG builds. This is // important because sharded aggregations rely on this ability. // Skipping when inShard because this has already been through the // transformation (and this unsets pCtx->inShard). BSONObjBuilder bb; pPipeline->toBson(&bb); parsed = bb.obj(); pPipeline = Pipeline::parseCommand(errmsg, parsed, pCtx); verify(pPipeline); } #endif // This does the mongod-specific stuff like creating a cursor PipelineD::prepareCursorSource(pPipeline, nsToDatabase(ns), pCtx); return pPipeline->run(result, errmsg); }