1616
1717#pragma once
1818
19+ #include " mongo/db/parsed_query.h"
1920#include " mongo/db/query/canonical_query.h"
2021#include " mongo/db/query/plan_cache.h"
22+ #include " mongo/db/query/plan_executor.h"
2123#include " mongo/db/query/runner.h"
22- #include " mongo/db/query/simple_plan_runner.h"
2324#include " mongo/db/query/stage_builder.h"
2425
2526namespace mongo {
@@ -40,53 +41,80 @@ namespace mongo {
4041 CachedPlanRunner (CanonicalQuery* canonicalQuery, CachedSolution* cached,
4142 PlanStage* root, WorkingSet* ws)
4243 : _canonicalQuery(canonicalQuery), _cachedQuery(cached),
43- _runner (new SimplePlanRunner (ws, root)) { }
44+ _exec (new PlanExecutor (ws, root)), _killed( false ), _updatedCache( false ) { }
4445
45- bool getNext (BSONObj* objOut) {
46- // Use the underlying runner until it's exhausted.
47- if (_runner->getNext (objOut)) {
48- return true ;
49- }
46+ Runner::RunnerState getNext (BSONObj* objOut) {
47+ if (_killed) { return Runner::RUNNER_DEAD; }
48+
49+ Runner::RunnerState state = _exec->getNext (objOut);
5050
51- // We're done. Update the cache.
52- PlanCache* cache = PlanCache::get (_canonicalQuery->ns ());
51+ if (Runner::RUNNER_EOF == state && !_updatedCache) {
52+ // We're done. Update the cache.
53+ PlanCache* cache = PlanCache::get (_canonicalQuery->ns ());
5354
54- // TODO: is this a verify ?
55- if (NULL == cache) { return false ; }
55+ // TODO: Is this an error ?
56+ if (NULL == cache) { return Runner::RUNNER_EOF ; }
5657
57- // TODO: How do we decide this?
58- bool shouldRemovePlan = false ;
58+ // TODO: How do we decide this?
59+ bool shouldRemovePlan = false ;
5960
60- if (shouldRemovePlan) {
61- if (!cache->remove (*_canonicalQuery, *_cachedQuery->solution )) {
62- warning () << " Cached plan runner couldn't remove plan from cache. Maybe"
63- " somebody else did already?" ;
61+ if (shouldRemovePlan) {
62+ if (!cache->remove (*_canonicalQuery, *_cachedQuery->solution )) {
63+ warning () << " Cached plan runner couldn't remove plan from cache. Maybe"
64+ " somebody else did already?" ;
65+ }
66+ return Runner::RUNNER_EOF;
6467 }
65- return false ;
68+
69+ // We're done running. Update cache.
70+ auto_ptr<CachedSolutionFeedback> feedback (new CachedSolutionFeedback ());
71+ feedback->stats = _exec->getStats ();
72+ cache->feedback (*_canonicalQuery, *_cachedQuery->solution , feedback.release ());
6673 }
74+ return state;
75+ }
6776
68- // We're done running. Update cache.
69- auto_ptr<CachedSolutionFeedback> feedback (new CachedSolutionFeedback ());
70- feedback->stats = _runner->getStats ();
71- cache->feedback (*_canonicalQuery, *_cachedQuery->solution , feedback.release ());
72- return false ;
77+ virtual void saveState () {
78+ if (!_killed) {
79+ _exec->saveState ();
80+ }
7381 }
7482
75- virtual void saveState () { _runner->saveState (); }
76- virtual void restoreState () { _runner->restoreState (); }
83+ virtual void restoreState () {
84+ if (!_killed) {
85+ _exec->restoreState ();
86+ }
87+ }
7788
7889 virtual void invalidate (const DiskLoc& dl) {
79- _runner->invalidate (dl);
90+ if (!_killed) {
91+ _exec->invalidate (dl);
92+ }
8093 }
8194
82- virtual const CanonicalQuery& getQuery () {
83- return *_canonicalQuery;
95+ virtual const CanonicalQuery& getQuery () { return *_canonicalQuery; }
96+
97+ virtual void kill () { _killed = true ; }
98+
99+ virtual bool forceYield () {
100+ saveState ();
101+ ClientCursor::registerRunner (this );
102+ ClientCursor::staticYield (ClientCursor::suggestYieldMicros (), getQuery ().getParsed ().ns (), NULL );
103+ ClientCursor::deregisterRunner (this );
104+ if (!_killed) { restoreState (); }
105+ return !_killed;
84106 }
85107
86108 private:
87109 scoped_ptr<CanonicalQuery> _canonicalQuery;
88110 scoped_ptr<CachedSolution> _cachedQuery;
89- scoped_ptr<SimplePlanRunner> _runner;
111+ scoped_ptr<PlanExecutor> _exec;
112+
113+ // Were we killed during a yield?
114+ bool _killed;
115+
116+ // Have we updated the cache with our plan stats yet?
117+ bool _updatedCache;
90118 };
91119
92120} // namespace mongo
0 commit comments