Esempio n. 1
0
    void Pipeline::Optimizations::Local::coalesceAdjacent(Pipeline* pipeline) {
        SourceContainer& sources = pipeline->sources;
        if (sources.empty())
            return;

        // move all sources to a temporary list
        SourceContainer tempSources;
        sources.swap(tempSources);

        // move the first one to the final list
        sources.push_back(tempSources[0]);

        // run through the sources, coalescing them or keeping them
        for (size_t tempn = tempSources.size(), tempi = 1; tempi < tempn; ++tempi) {
            // If we can't coalesce the source with the last, then move it
            // to the final list, and make it the new last.  (If we succeeded,
            // then we're still on the same last, and there's no need to move
            // or do anything with the source -- the destruction of tempSources
            // will take care of the rest.)
            intrusive_ptr<DocumentSource> &pLastSource = sources.back();
            intrusive_ptr<DocumentSource> &pTemp = tempSources[tempi];
            verify(pTemp && pLastSource);
            if (!pLastSource->coalesce(pTemp))
                sources.push_back(pTemp);
        }
    }
Esempio n. 2
0
 void Pipeline::Optimizations::Local::optimizeEachDocumentSource(Pipeline* pipeline) {
     SourceContainer& sources = pipeline->sources;
     SourceContainer newSources;
     for (SourceContainer::iterator it(sources.begin()); it != sources.end(); ++it) {
         if (auto out = (*it)->optimize()) {
             newSources.push_back(std::move(out));
         }
     }
     pipeline->sources = std::move(newSources);
 }
Esempio n. 3
0
    static void split( const SourceContainer &from, openmp_state< typename SourceContainer::value_type > &to )
    {
        if(to.size() == 0) to.resize( omp_get_max_threads() );
        const size_t part = from.size() / to.size();
#       pragma omp parallel for schedule(dynamic)
        for(size_t i = 0 ; i < to.size() ; i++) {
            typedef typename SourceContainer::const_iterator it_t;
            const it_t begin = from.begin() + i * part;
            it_t end = begin + part;
            // for cases where from.size() % to.size() > 0
            if(i + 1 == to.size() || end > from.end()) end = from.end();
            to[i].resize(end - begin);
            std::copy(begin, end, to[i].begin());
        }
    }
Esempio n. 4
0
void push_back_right(TargetContainer& x, const SourceContainer& y) {
  // x.insert( x.end(), y.begin(), y.end() );
  int n = y.size();
  for (int i = 0; i < n; i++) {
    x.push_back(-y[i] - 1);
  }
}
Esempio n. 5
0
void Pipeline::optimizePipeline() {
    SourceContainer optimizedSources;

    SourceContainer::iterator itr = sources.begin();

    while (itr != sources.end() && std::next(itr) != sources.end()) {
        invariant((*itr).get());
        itr = (*itr).get()->optimizeAt(itr, &sources);
    }

    // Once we have reached our final number of stages, optimize each individually.
    for (auto&& source : sources) {
        if (auto out = source->optimize()) {
            optimizedSources.push_back(out);
        }
    }
    sources.swap(optimizedSources);
}
Esempio n. 6
0
TargetContainer
traits::convert(
	SourceContainer const & source )
{
	return std::move(
		to_ucs2(
			&source[0],
			&source[0] + source.size() ) );
}
Esempio n. 7
0
    intrusive_ptr<Pipeline> Pipeline::parseCommand(
        string &errmsg, BSONObj &cmdObj,
        const intrusive_ptr<ExpressionContext> &pCtx) {
        intrusive_ptr<Pipeline> pPipeline(new Pipeline(pCtx));
        vector<BSONElement> pipeline;

        /* gather the specification for the aggregation */
        for(BSONObj::iterator cmdIterator = cmdObj.begin();
                cmdIterator.more(); ) {
            BSONElement cmdElement(cmdIterator.next());
            const char *pFieldName = cmdElement.fieldName();

            // ignore top-level fields prefixed with $. They are for the command processor, not us.
            if (pFieldName[0] == '$') {
                continue;
            }

            /* look for the aggregation command */
            if (!strcmp(pFieldName, commandName)) {
                pPipeline->collectionName = cmdElement.String();
                continue;
            }

            /* check for the collection name */
            if (!strcmp(pFieldName, pipelineName)) {
                pipeline = cmdElement.Array();
                continue;
            }

            /* check for explain option */
            if (!strcmp(pFieldName, explainName)) {
                pPipeline->explain = cmdElement.Bool();
                continue;
            }

            /* if the request came from the router, we're in a shard */
            if (!strcmp(pFieldName, fromRouterName)) {
                pCtx->setInShard(cmdElement.Bool());
                continue;
            }

            /* check for debug options */
            if (!strcmp(pFieldName, splitMongodPipelineName)) {
                pPipeline->splitMongodPipeline = true;
                continue;
            }

            /* we didn't recognize a field in the command */
            ostringstream sb;
            sb <<
               "unrecognized field \"" <<
               cmdElement.fieldName();
            errmsg = sb.str();
            return intrusive_ptr<Pipeline>();
        }

        /*
          If we get here, we've harvested the fields we expect for a pipeline.

          Set up the specified document source pipeline.
        */
        SourceContainer& sources = pPipeline->sources; // shorthand

        /* iterate over the steps in the pipeline */
        const size_t nSteps = pipeline.size();
        for(size_t iStep = 0; iStep < nSteps; ++iStep) {
            /* pull out the pipeline element as an object */
            BSONElement pipeElement(pipeline[iStep]);
            uassert(15942, str::stream() << "pipeline element " <<
                    iStep << " is not an object",
                    pipeElement.type() == Object);
            BSONObj bsonObj(pipeElement.Obj());

            // Parse a pipeline stage from 'bsonObj'.
            uassert(16435, "A pipeline stage specification object must contain exactly one field.",
                    bsonObj.nFields() == 1);
            BSONElement stageSpec = bsonObj.firstElement();
            const char* stageName = stageSpec.fieldName();

            // Create a DocumentSource pipeline stage from 'stageSpec'.
            StageDesc key;
            key.pName = stageName;
            const StageDesc* pDesc = (const StageDesc*)
                    bsearch(&key, stageDesc, nStageDesc, sizeof(StageDesc),
                            stageDescCmp);

            uassert(16436,
                    str::stream() << "Unrecognized pipeline stage name: '" << stageName << "'",
                    pDesc);
            intrusive_ptr<DocumentSource> stage = (*pDesc->pFactory)(&stageSpec, pCtx);
            verify(stage);
            stage->setPipelineStep(iStep);
            sources.push_back(stage);
        }

        /* if there aren't any pipeline stages, there's nothing more to do */
        if (sources.empty())
            return pPipeline;

        /*
          Move filters up where possible.

          CW TODO -- move filter past projections where possible, and noting
          corresponding field renaming.
        */

        /*
          Wherever there is a match immediately following a sort, swap them.
          This means we sort fewer items.  Neither changes the documents in
          the stream, so this transformation shouldn't affect the result.

          We do this first, because then when we coalesce operators below,
          any adjacent matches will be combined.
         */
        for (size_t srcn = sources.size(), srci = 1; srci < srcn; ++srci) {
            intrusive_ptr<DocumentSource> &pSource = sources[srci];
            if (dynamic_cast<DocumentSourceMatch *>(pSource.get())) {
                intrusive_ptr<DocumentSource> &pPrevious = sources[srci - 1];
                if (dynamic_cast<DocumentSourceSort *>(pPrevious.get())) {
                    /* swap this item with the previous */
                    intrusive_ptr<DocumentSource> pTemp(pPrevious);
                    pPrevious = pSource;
                    pSource = pTemp;
                }
            }
        }

        /* Move limits in front of skips. This is more optimal for sharding
         * since currently, we can only split the pipeline at a single source
         * and it is better to limit the results coming from each shard
         */
        for(int i = sources.size() - 1; i >= 1 /* not looking at 0 */; i--) {
            DocumentSourceLimit* limit =
                dynamic_cast<DocumentSourceLimit*>(sources[i].get());
            DocumentSourceSkip* skip =
                dynamic_cast<DocumentSourceSkip*>(sources[i-1].get());
            if (limit && skip) {
                // Increase limit by skip since the skipped docs now pass through the $limit
                limit->setLimit(limit->getLimit() + skip->getSkip());
                swap(sources[i], sources[i-1]);

                // Start at back again. This is needed to handle cases with more than 1 $limit
                // (S means skip, L means limit)
                //
                // These two would work without second pass (assuming back to front ordering)
                // SL   -> LS
                // SSL  -> LSS
                //
                // The following cases need a second pass to handle the second limit
                // SLL  -> LLS
                // SSLL -> LLSS
                // SLSL -> LLSS
                i = sources.size(); // decremented before next pass
            }
        }

        /*
          Coalesce adjacent filters where possible.  Two adjacent filters
          are equivalent to one filter whose predicate is the conjunction of
          the two original filters' predicates.  For now, capture this by
          giving any DocumentSource the option to absorb it's successor; this
          will also allow adjacent projections to coalesce when possible.

          Run through the DocumentSources, and give each one the opportunity
          to coalesce with its successor.  If successful, remove the
          successor.

          Move all document sources to a temporary list.
        */
        SourceContainer tempSources;
        sources.swap(tempSources);

        /* move the first one to the final list */
        sources.push_back(tempSources[0]);

        /* run through the sources, coalescing them or keeping them */
        for (size_t tempn = tempSources.size(), tempi = 1; tempi < tempn; ++tempi) {
            /*
              If we can't coalesce the source with the last, then move it
              to the final list, and make it the new last.  (If we succeeded,
              then we're still on the same last, and there's no need to move
              or do anything with the source -- the destruction of tempSources
              will take care of the rest.)
            */
            intrusive_ptr<DocumentSource> &pLastSource = sources.back();
            intrusive_ptr<DocumentSource> &pTemp = tempSources[tempi];
            verify(pTemp && pLastSource);
            if (!pLastSource->coalesce(pTemp))
                sources.push_back(pTemp);
        }

        /* optimize the elements in the pipeline */
        for(SourceContainer::iterator iter(sources.begin()),
                                      listEnd(sources.end());
                                    iter != listEnd;
                                    ++iter) {
            if (!*iter) {
                errmsg = "Pipeline received empty document as argument";
                return intrusive_ptr<Pipeline>();
            }

            (*iter)->optimize();
        }

        return pPipeline;
    }
Esempio n. 8
0
void push_back( TargetContainer& x, const SourceContainer& y ){
    x.insert( x.end(), y.begin(), y.end() ) ;
}
Esempio n. 9
0
/*
* IHXBroadcastMapperResponse
*/
STDMETHODIMP
BasicSourceFinder::BroadcastTypeFound(HX_RESULT status, const char* pType)
{
    if (SF_CLOSED == m_findState)
    {
        return HXR_OK;
    }

    m_CurrentSourceType = pType;

    HX_ASSERT(m_pBroadcastMapper);
    HX_RELEASE(m_pBroadcastMapper);

    PluginHandler::BroadcastFormat* broadcast_handler;
    PluginHandler::Errors            plugin_result;
    PluginHandler::Plugin*          plugin;

    broadcast_handler =
        m_pProc->pc->plugin_handler->m_broadcast_handler;
    plugin_result = broadcast_handler->Find(pType, plugin);

    if(PluginHandler::NO_ERRORS != plugin_result)
    {
        ERRMSG(m_pProc->pc->error_handler, "No live handler for %s\n",
               pType?pType:"(null)");
        return HXR_FAIL;
    }


    /*
    * Depending on a request
    */
    HX_RESULT  theErr = HXR_FAIL;
    IHXPSourceControl* pSource = NULL;
    IHXValues* pVal = NULL;
    IHXBuffer* pBuf = NULL;

    const char* pFileName = m_pURL->name + m_pFSManager->m_mount_point_len - 1;
    UINT32     bUseSourceContainer = FALSE;
    BOOL       bUseMediaDeliveryPipeline = FALSE;

    /* XXDWL
     * For live (broadcast) sessions, the media delivery pipeline needs to be turned off.
     * This is a temporary solution until a number of issues dealing with timestamp
     * dependent media, and ASM rule handling are worked out.
     * See also: server/engine/session/player.cpp:1947

     bUseMediaDeliveryPipeline = m_pPlayerSession->m_bUseMediaDeliveryPipeline;
    */

#if NOTYET
    /* XXTDM
     * According to ghori, this was an attempt to merge the various source
     * finding code into one place.  Due to time constraints, it was never
     * finished.  Therefore, this code is currently unused and untested.
     */
    theErr = m_pRequest->GetRequestHeaders(FS_HEADERS, pVal);
    if (HXR_OK == theErr)
    {
        theErr = pVal->GetPropertyULONG32("UseSourceContainer", bUseSourceContainer);
        if (HXR_OK != theErr)
        {
            bUseSourceContainer = FALSE;
        }

        theErr = pVal->GetPropertyCString("BroadcastAlias", pBuf);
        if (HXR_OK == theErr)
        {
            pFileName = (const char*)pBuf->GetBuffer();
        }
    }
#endif /* NOTYET */

    HX_ASSERT(pFileName);
    theErr = m_pProc->pc->broadcast_manager->GetStream(pType, pFileName,
                           pSource, m_pProc, bUseMediaDeliveryPipeline,
                           m_pPlayerSession ? m_pPlayerSession->GetSessionStats()
                                            : NULL);
    if (HXR_OK == theErr)
    {
        if (bUseSourceContainer)
        {
            SourceContainer* pContainer =
                new SourceContainer(m_pProc->pc->server_context, pSource);

            if (pContainer)
            {
                pContainer->AddRef();
                FindSourceDone(HXR_OK, (IUnknown*)(IHXPSinkPackets*)pContainer);
                pContainer->Release();
            }
            else
            {
                theErr = HXR_OUTOFMEMORY;
                HX_RELEASE(pSource);
            }
        }
    }

    FindSourceDone(theErr, pSource);

    HX_RELEASE(pSource);
    HX_RELEASE(pVal);
    HX_RELEASE(pBuf);
    return HXR_OK;
}