コード例 #1
0
ファイル: pipeline.cpp プロジェクト: Xyand/mongo
    intrusive_ptr<Pipeline> Pipeline::splitForSharded() {
        /* create an initialize the shard spec we'll return */
        intrusive_ptr<Pipeline> pShardPipeline(new Pipeline(pCtx));
        pShardPipeline->collectionName = collectionName;
        pShardPipeline->explain = explain;

        // We will be removing from the front so reverse for now. undone later
        // TODO: maybe sourceVector should be a deque
        reverse(sourceVector.begin(), sourceVector.end());

        /*
          Run through the pipeline, looking for points to split it into
          shard pipelines, and the rest.
         */
        while(!sourceVector.empty()) {
            // pop the first source
            intrusive_ptr<DocumentSource> pSource = sourceVector.back();
            sourceVector.pop_back();

            // Check if this source is splittable
            SplittableDocumentSource* splittable=
                dynamic_cast<SplittableDocumentSource *>(pSource.get());

            if (!splittable){
                // move the source from the router sourceVector to the shard sourceVector
                pShardPipeline->sourceVector.push_back(pSource);
            }
            else {
                // split into Router and Shard sources
                intrusive_ptr<DocumentSource> shardSource  = splittable->getShardSource();
                intrusive_ptr<DocumentSource> routerSource = splittable->getRouterSource();
                if (shardSource) pShardPipeline->sourceVector.push_back(shardSource);
                if (routerSource)          this->sourceVector.push_back(routerSource);

                // put the sourceVector back in the correct order and exit the loop
                reverse(sourceVector.begin(), sourceVector.end());
                break;
            }
        }

        return pShardPipeline;
    }
コード例 #2
0
ファイル: pipeline.cpp プロジェクト: cwestin/mongo
    intrusive_ptr<Pipeline> Pipeline::splitForSharded() {
        /* create an initialize the shard spec we'll return */
        intrusive_ptr<Pipeline> pShardPipeline(new Pipeline(pCtx));
        pShardPipeline->collectionName = collectionName;
        pShardPipeline->explain = explain;

        /* put the source list aside */
        SourceVector tempVector(sourceVector);
        sourceVector.clear();

        /*
          Run through the pipeline, looking for points to split it into
          shard pipelines, and the rest.
         */
        while(!tempVector.empty()) {
            intrusive_ptr<DocumentSource> &pSource = tempVector.front();

            /* hang on to this in advance, in case it is a group */
            DocumentSourceGroup *pGroup =
                dynamic_cast<DocumentSourceGroup *>(pSource.get());

            /* move the source from the tempVector to the shard sourceVector */
            pShardPipeline->sourceVector.push_back(pSource);
            tempVector.erase(tempVector.begin());

            /*
              If we found a group, that's a split point.
             */
            if (pGroup) {
                /* start this pipeline with the group merger */
                sourceVector.push_back(pGroup->createMerger());

                /* and then add everything that remains and quit */
                for(size_t tempn = tempVector.size(), tempi = 0;
                    tempi < tempn; ++tempi)
                    sourceVector.push_back(tempVector[tempi]);
                break;
            }
        }

        return pShardPipeline;
    }
コード例 #3
0
ファイル: pipeline.cpp プロジェクト: darkiri/mongo
    intrusive_ptr<Pipeline> Pipeline::splitForSharded() {
        /* create an initialize the shard spec we'll return */
        intrusive_ptr<Pipeline> pShardPipeline(new Pipeline(pCtx));
        pShardPipeline->collectionName = collectionName;
        pShardPipeline->explain = explain;

        /*
          Run through the pipeline, looking for points to split it into
          shard pipelines, and the rest.
         */
        while (!sources.empty()) {
            // pop the first source
            intrusive_ptr<DocumentSource> pSource = sources.front();
            sources.pop_front();

            // Check if this source is splittable
            SplittableDocumentSource* splittable=
                dynamic_cast<SplittableDocumentSource *>(pSource.get());

            if (!splittable){
                // move the source from the router sources to the shard sources
                pShardPipeline->sources.push_back(pSource);
            }
            else {
                // split into Router and Shard sources
                intrusive_ptr<DocumentSource> shardSource  = splittable->getShardSource();
                intrusive_ptr<DocumentSource> routerSource = splittable->getRouterSource();
                if (shardSource) pShardPipeline->sources.push_back(shardSource);
                if (routerSource)          this->sources.push_front(routerSource);

                break;
            }
        }

        return pShardPipeline;
    }
コード例 #4
0
ファイル: pipeline_command.cpp プロジェクト: JKO/mongo
    bool PipelineCommand::executePipeline(
        BSONObjBuilder &result, string &errmsg, const string &ns,
        intrusive_ptr<Pipeline> &pPipeline,
        intrusive_ptr<DocumentSourceCursor> &pSource,
        intrusive_ptr<ExpressionContext> &pCtx) {

        /* this is the normal non-debug path */
        if (!pPipeline->getSplitMongodPipeline())
            return pPipeline->run(result, errmsg, pSource);

        /* setup as if we're in the router */
        pCtx->setInRouter(true);

        /*
          Here, we'll split the pipeline in the same way we would for sharding,
          for testing purposes.

          Run the shard pipeline first, then feed the results into the remains
          of the existing pipeline.

          Start by splitting the pipeline.
         */
        intrusive_ptr<Pipeline> pShardSplit(
            pPipeline->splitForSharded());

        /*
          Write the split pipeline as we would in order to transmit it to
          the shard servers.
        */
        BSONObjBuilder shardBuilder;
        pShardSplit->toBson(&shardBuilder);
        BSONObj shardBson(shardBuilder.done());

        DEV (log() << "\n---- shardBson\n" <<
             shardBson.jsonString(Strict, 1) << "\n----\n").flush();

        /* for debugging purposes, show what the pipeline now looks like */
        DEV {
            BSONObjBuilder pipelineBuilder;
            pPipeline->toBson(&pipelineBuilder);
            BSONObj pipelineBson(pipelineBuilder.done());
            (log() << "\n---- pipelineBson\n" <<
             pipelineBson.jsonString(Strict, 1) << "\n----\n").flush();
        }

        /* on the shard servers, create the local pipeline */
        intrusive_ptr<ExpressionContext> pShardCtx(
            ExpressionContext::create(&InterruptStatusMongod::status));
        intrusive_ptr<Pipeline> pShardPipeline(
            Pipeline::parseCommand(errmsg, shardBson, pShardCtx));
        if (!pShardPipeline.get()) {
            return false;
        }

        /* run the shard pipeline */
        BSONObjBuilder shardResultBuilder;
        string shardErrmsg;
        pShardPipeline->run(shardResultBuilder, shardErrmsg, pSource);
        BSONObj shardResult(shardResultBuilder.done());

        /* pick out the shard result, and prepare to read it */
        intrusive_ptr<DocumentSourceBsonArray> pShardSource;
        BSONObjIterator shardIter(shardResult);
        while(shardIter.more()) {
            BSONElement shardElement(shardIter.next());
            const char *pFieldName = shardElement.fieldName();

            if ((strcmp(pFieldName, "result") == 0) ||
                (strcmp(pFieldName, "serverPipeline") == 0)) {
                pShardSource = DocumentSourceBsonArray::create(
                    &shardElement, pCtx);

                /*
                  Connect the output of the shard pipeline with the mongos
                  pipeline that will merge the results.
                */
                return pPipeline->run(result, errmsg, pShardSource);
            }
        }

        /* NOTREACHED */
        verify(false);
        return false;
    }
コード例 #5
0
ファイル: pipeline_command.cpp プロジェクト: Axv2/mongo
        /*
          Execute the pipeline for the explain.  This is common to both the
          locked and unlocked code path.  However, the results are different.
          For an explain, with no lock, it really outputs the pipeline
          chain rather than fetching the data.
         */
        bool executeSplitPipeline(BSONObjBuilder& result, string& errmsg,
                                  const string& ns, const string& db,
                                  intrusive_ptr<Pipeline>& pPipeline,
                                  intrusive_ptr<ExpressionContext>& pCtx) {
            /* setup as if we're in the router */
            pCtx->inRouter = true;

            /*
            Here, we'll split the pipeline in the same way we would for sharding,
            for testing purposes.

            Run the shard pipeline first, then feed the results into the remains
            of the existing pipeline.

            Start by splitting the pipeline.
            */
            intrusive_ptr<Pipeline> pShardSplit = pPipeline->splitForSharded();

            // Write the split pipeline as we would in order to transmit it to the shard servers.
            Document shardCmd = pShardSplit->serialize();

            DEV log() << "\n---- shardDescription\n" << shardCmd.toString() << "\n----\n";

            // for debugging purposes, show what the pipeline now looks like
            DEV log() << "\n---- pipelineDescription\n" << pPipeline->serialize() << "\n----\n";

            /* on the shard servers, create the local pipeline */
            intrusive_ptr<ExpressionContext> pShardCtx =
                new ExpressionContext(InterruptStatusMongod::status, NamespaceString(ns));
            BSONObj shardObj = shardCmd.toBson();
            intrusive_ptr<Pipeline> pShardPipeline(
                Pipeline::parseCommand(errmsg, shardObj, pShardCtx));
            if (!pShardPipeline.get()) {
                return false;
            }

            PipelineD::prepareCursorSource(pShardPipeline, nsToDatabase(ns), pCtx);

            /* run the shard pipeline */
            BSONObjBuilder shardResultBuilder;
            string shardErrmsg;
            pShardPipeline->stitch();
            pShardPipeline->run(shardResultBuilder);
            BSONObj shardResult(shardResultBuilder.done());

            /* pick out the shard result, and prepare to read it */
            intrusive_ptr<DocumentSourceBsonArray> pShardSource;
            BSONObjIterator shardIter(shardResult);
            while(shardIter.more()) {
                BSONElement shardElement(shardIter.next());
                const char *pFieldName = shardElement.fieldName();

                if ((strcmp(pFieldName, "result") == 0) ||
                    (strcmp(pFieldName, "serverPipeline") == 0)) {
                    pPipeline->addInitialSource(DocumentSourceBsonArray::create(&shardElement, pCtx));
                    pPipeline->stitch();

                    /*
                    Connect the output of the shard pipeline with the mongos
                    pipeline that will merge the results.
                    */
                    pPipeline->run(result);
                    return true;
                }
            }

            /* NOTREACHED */
            verify(false);
            return false;
        }