Exemplo n.º 1
0
    Runner::RunnerState SubplanRunner::getNext(BSONObj* objOut, DiskLoc* dlOut) {
        if (_killed) {
            return Runner::RUNNER_DEAD;
        }

        if (isEOF()) { return Runner::RUNNER_EOF; }

        if (SubplanRunner::PLANNING == _state) {
            // Try to run as sub-plans.
            if (runSubplans()) {
                // If runSubplans returns true we expect something here.
                invariant(_underlyingRunner.get());
            }
            else if (!_killed) {
                // Couldn't run as subplans so we'll just call normal getRunner.

                Runner* runner;
                Status status = getRunnerAlwaysPlan(
                    _txn, _collection, _query.release(), _plannerParams, &runner
                );

                if (!status.isOK()) {
                    // We utterly failed.
                    _killed = true;

                    // Propagate the error to the user wrapped in a BSONObj
                    if (NULL != objOut) {
                        BSONObjBuilder bob;
                        bob.append("ok", status.isOK() ? 1.0 : 0.0);
                        bob.append("code", status.code());
                        bob.append("errmsg", status.reason());
                        *objOut = bob.obj();
                    }
                    return Runner::RUNNER_ERROR;
                }
                else {
                    _underlyingRunner.reset(runner);
                }
            }

            // We can change state when we're either killed or we have an underlying runner.
            invariant(_killed || NULL != _underlyingRunner.get());
            _state = SubplanRunner::RUNNING;
        }

        if (_killed) {
            return Runner::RUNNER_DEAD;
        }

        if (isEOF()) {
            return Runner::RUNNER_EOF;
        }

        // If we're here we should have planned already.
        invariant(SubplanRunner::RUNNING == _state);
        invariant(_underlyingRunner.get());
        return _underlyingRunner->getNext(objOut, dlOut);
    }
Exemplo n.º 2
0
    PlanStage::StageState SubplanStage::work(WorkingSetID* out) {
        ++_commonStats.works;

        // Adds the amount of time taken by work() to executionTimeMillis.
        ScopedTimer timer(&_commonStats.executionTimeMillis);

        if (_killed) {
            return PlanStage::DEAD;
        }

        if (isEOF()) { return PlanStage::IS_EOF; }

        if (SubplanStage::PLANNING == _state) {
            // Try to run as sub-plans.
            if (runSubplans()) {
                // If runSubplans returns true we expect something here.
                invariant(_child.get());
            }
            else if (!_killed) {
                // Couldn't run as subplans so we'll just call normal getExecutor.
                PlanExecutor* exec;
                Status status = getExecutorAlwaysPlan(_collection, _query, _plannerParams, &exec);

                if (!status.isOK()) {
                    // We utterly failed.
                    _killed = true;

                    // Propagate the error to the user wrapped in a BSONObj
                    WorkingSetID id = _ws->allocate();
                    WorkingSetMember* member = _ws->get(id);
                    member->state = WorkingSetMember::OWNED_OBJ;
                    member->keyData.clear();
                    member->loc = DiskLoc();

                    BSONObjBuilder bob;
                    bob.append("ok", status.isOK() ? 1.0 : 0.0);
                    bob.append("code", status.code());
                    bob.append("errmsg", status.reason());
                    member->obj = bob.obj();

                    *out = id;
                    return PlanStage::FAILURE;
                }
                else {
                    scoped_ptr<PlanExecutor> cleanupExec(exec);
                    _child.reset(exec->releaseStages());
                }
            }

            // We can change state when we're either killed or we have an underlying runner.
            invariant(_killed || NULL != _child.get());
            _state = SubplanStage::RUNNING;
        }

        if (_killed) {
            return PlanStage::DEAD;
        }

        if (isEOF()) {
            return PlanStage::IS_EOF;
        }

        // If we're here we should have planned already.
        invariant(SubplanStage::RUNNING == _state);
        invariant(_child.get());
        return _child->work(out);
    }