コード例 #1
0
ファイル: multi_plan.cpp プロジェクト: TylerBrock/mongo
    PlanStage::StageState MultiPlanStage::work(WorkingSetID* out) {
        // Adds the amount of time taken by work() to executionTimeMillis.
        ScopedTimer timer(&_commonStats.executionTimeMillis);

        if (_failure) {
            *out = _statusMemberId;
            return PlanStage::FAILURE;
        }

        CandidatePlan& bestPlan = _candidates[_bestPlanIdx];

        // Look for an already produced result that provides the data the caller wants.
        if (!bestPlan.results.empty()) {
            *out = bestPlan.results.front();
            bestPlan.results.pop_front();
            _commonStats.advanced++;
            return PlanStage::ADVANCED;
        }

        // best plan had no (or has no more) cached results

        StageState state = bestPlan.root->work(out);

        if (PlanStage::FAILURE == state && hasBackupPlan()) {
            QLOG() << "Best plan errored out switching to backup\n";
            // Uncache the bad solution if we fall back
            // on the backup solution.
            //
            // XXX: Instead of uncaching we should find a way for the
            // cached plan runner to fall back on a different solution
            // if the best solution fails. Alternatively we could try to
            // defer cache insertion to be after the first produced result.

            _collection->infoCache()->getPlanCache()->remove(*_query);

            _bestPlanIdx = _backupPlanIdx;
            _backupPlanIdx = kNoSuchPlan;

            return _candidates[_bestPlanIdx].root->work(out);
        }

        if (hasBackupPlan() && PlanStage::ADVANCED == state) {
            QLOG() << "Best plan had a blocking stage, became unblocked\n";
            _backupPlanIdx = kNoSuchPlan;
        }

        // Increment stats.
        if (PlanStage::ADVANCED == state) {
            _commonStats.advanced++;
        }
        else if (PlanStage::NEED_TIME == state) {
            _commonStats.needTime++;
        }

        return state;
    }
コード例 #2
0
ファイル: plan_ranking.cpp プロジェクト: 504com/mongo
        void run() {
            // 'a' is very selective, 'b' is not.
            for (int i = 0; i < N; ++i) {
                insert(BSON("a" << i << "b" << 1));
            }

            // Add indices on 'a' and 'b'.
            addIndex(BSON("a" << 1));
            addIndex(BSON("b" << 1));

            // Run the query {a:1, b:{$gt:1}.
            CanonicalQuery* cq;
            verify(CanonicalQuery::canonicalize(ns, BSON("a" << 1 << "b" << BSON("$gt" << 1)),
                                                &cq).isOK());
            ASSERT(NULL != cq);

            // Turn on the "force intersect" option.
            // This will be reverted by PlanRankingTestBase's destructor when the test completes.
            internalQueryForceIntersectionPlans = true;

            // Takes ownership of cq.
            QuerySolution* soln = pickBestPlan(cq);
            ASSERT(QueryPlannerTestLib::solutionMatches(
                             "{fetch: {filter: null, node: {andHash: {nodes: ["
                                     "{ixscan: {filter: null, pattern: {a:1}}},"
                                     "{ixscan: {filter: null, pattern: {b:1}}}]}}}}",
                             soln->root.get()));

            // Confirm that a backup plan is available.
            ASSERT(hasBackupPlan());
        }
コード例 #3
0
ファイル: multi_plan.cpp プロジェクト: baiyanghese/mongo
    MultiPlanStage::~MultiPlanStage() {
        if (bestPlanChosen()) {
            delete _candidates[_bestPlanIdx].root;

            // for now, the runner that executes this multi-plan-stage wants to own
            // the query solution for the best plan.  So we won't delete it here.
            // eventually, plan stages may own their query solutions.
            // 
            // delete _candidates[_bestPlanIdx].solution; // (owned by containing runner)

            if (hasBackupPlan()) {
                delete _candidates[_backupPlanIdx].solution;
                delete _candidates[_backupPlanIdx].root;
            }

            // Clean up the losing candidates.
            clearCandidates();
        }
        else {
            for (size_t ix = 0; ix < _candidates.size(); ++ix) {
                delete _candidates[ix].solution;
                delete _candidates[ix].root;
            }
        }

        for (vector<PlanStageStats*>::iterator it = _candidateStats.begin();
             it != _candidateStats.end();
             ++it) {
            delete *it;
        }
    }
コード例 #4
0
ファイル: multi_plan.cpp プロジェクト: baiyanghese/mongo
    PlanStageStats* MultiPlanStage::getStats() {
        if (bestPlanChosen()) {
            return _candidates[_bestPlanIdx].root->getStats();
        }
        if (hasBackupPlan()) {
            return _candidates[_backupPlanIdx].root->getStats();
        }
        _commonStats.isEOF = isEOF();

        auto_ptr<PlanStageStats> ret(new PlanStageStats(_commonStats, STAGE_MULTI_PLAN));

        return ret.release();
    }
コード例 #5
0
ファイル: multi_plan.cpp プロジェクト: baiyanghese/mongo
    void MultiPlanStage::recoverFromYield() {
        if (_failure) return;

        // this logic is from multi_plan_runner
        // but does it really make sense to operate on
        // the _bestPlan if we've switched to the backup?

        if (bestPlanChosen()) {
            _candidates[_bestPlanIdx].root->recoverFromYield();
            if (hasBackupPlan()) {
                _candidates[_backupPlanIdx].root->recoverFromYield();
            }
        }
        else {
            allPlansRestoreState();
        }
    }
コード例 #6
0
ファイル: multi_plan.cpp プロジェクト: baiyanghese/mongo
    void MultiPlanStage::invalidate(const DiskLoc& dl, InvalidationType type) {
        if (_failure) { return; }

        if (bestPlanChosen()) {
            CandidatePlan& bestPlan = _candidates[_bestPlanIdx];
            bestPlan.root->invalidate(dl, type);
            invalidateHelper(bestPlan.ws, dl, &bestPlan.results, _collection);
            if (hasBackupPlan()) {
                CandidatePlan& backupPlan = _candidates[_backupPlanIdx];
                backupPlan.root->invalidate(dl, type);
                invalidateHelper(backupPlan.ws, dl, &backupPlan.results, _collection);
            }
        }
        else {
            for (size_t ix = 0; ix < _candidates.size(); ++ix) {
                _candidates[ix].root->invalidate(dl, type);
                invalidateHelper(_candidates[ix].ws, dl, &_candidates[ix].results, _collection);
            }
        }
    }