diff options
author | Waley Chen <waleycz@gmail.com> | 2016-05-17 14:05:13 -0400 |
---|---|---|
committer | Waley Chen <waleycz@gmail.com> | 2016-05-17 17:27:12 -0400 |
commit | 51ee6f1952addc650b1c719cce51fcf460e6e9e8 (patch) | |
tree | 426840377be5d2b698678f009f8328e57a89d40c /src | |
parent | 44abb8db32a6fad705854793e397961dfc72d09e (diff) | |
download | mongo-51ee6f1952addc650b1c719cce51fcf460e6e9e8.tar.gz |
SERVER-23243 Replace Listener::getElapsedTimeMillis() in scoped_timer.cpp
Diffstat (limited to 'src')
20 files changed, 327 insertions, 238 deletions
diff --git a/src/mongo/db/exec/SConscript b/src/mongo/db/exec/SConscript index 931ea2abbd1..e54f69b82d7 100644 --- a/src/mongo/db/exec/SConscript +++ b/src/mongo/db/exec/SConscript @@ -112,6 +112,7 @@ env.CppUnitTest( "exec", "$BUILD_DIR/mongo/db/serveronly", "$BUILD_DIR/mongo/dbtests/mocklib", + "$BUILD_DIR/mongo/util/clock_source_mock", "$BUILD_DIR/mongo/util/ntservice_mock", ], NO_CRUTCH = True, @@ -127,6 +128,7 @@ env.CppUnitTest( "$BUILD_DIR/mongo/db/serveronly", "$BUILD_DIR/mongo/dbtests/mocklib", "$BUILD_DIR/mongo/db/query/collation/collator_interface_mock", + "$BUILD_DIR/mongo/util/clock_source_mock", "$BUILD_DIR/mongo/util/ntservice_mock", ], NO_CRUTCH = True, diff --git a/src/mongo/db/exec/cached_plan.cpp b/src/mongo/db/exec/cached_plan.cpp index 7604d5ce465..3425a2562b5 100644 --- a/src/mongo/db/exec/cached_plan.cpp +++ b/src/mongo/db/exec/cached_plan.cpp @@ -74,7 +74,7 @@ Status CachedPlanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) { // Adds the amount of time taken by pickBestPlan() to executionTimeMillis. There's lots of // execution work that happens here, so this is needed for the time accounting to // make sense. - ScopedTimer timer(&_commonStats.executionTimeMillis); + ScopedTimer timer(getClock(), &_commonStats.executionTimeMillis); // If we work this many times during the trial period, then we will replan the // query from scratch. diff --git a/src/mongo/db/exec/multi_plan.cpp b/src/mongo/db/exec/multi_plan.cpp index 95c70b47ce0..c57e0a5f02f 100644 --- a/src/mongo/db/exec/multi_plan.cpp +++ b/src/mongo/db/exec/multi_plan.cpp @@ -203,7 +203,7 @@ Status MultiPlanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) { // Adds the amount of time taken by pickBestPlan() to executionTimeMillis. There's lots of // execution work that happens here, so this is needed for the time accounting to // make sense. - ScopedTimer timer(&_commonStats.executionTimeMillis); + ScopedTimer timer(getClock(), &_commonStats.executionTimeMillis); size_t numWorks = getTrialPeriodWorks(getOpCtx(), _collection); size_t numResults = getTrialPeriodNumToReturn(*_query); diff --git a/src/mongo/db/exec/plan_stage.cpp b/src/mongo/db/exec/plan_stage.cpp index c81679bd8cb..13062fa919f 100644 --- a/src/mongo/db/exec/plan_stage.cpp +++ b/src/mongo/db/exec/plan_stage.cpp @@ -33,11 +33,14 @@ #include "mongo/db/exec/plan_stage.h" #include "mongo/db/exec/scoped_timer.h" +#include "mongo/db/operation_context.h" +#include "mongo/db/service_context.h" namespace mongo { PlanStage::StageState PlanStage::work(WorkingSetID* out) { - ScopedTimer timer(&_commonStats.executionTimeMillis); + invariant(_opCtx); + ScopedTimer timer(getClock(), &_commonStats.executionTimeMillis); ++_commonStats.works; StageState workResult = doWork(out); @@ -102,4 +105,8 @@ void PlanStage::reattachToOperationContext(OperationContext* opCtx) { doReattachToOperationContext(); } +ClockSource* PlanStage::getClock() const { + return _opCtx->getServiceContext()->getFastClockSource(); +} + } // namespace mongo diff --git a/src/mongo/db/exec/plan_stage.h b/src/mongo/db/exec/plan_stage.h index 3ad007c8430..c0afd992e72 100644 --- a/src/mongo/db/exec/plan_stage.h +++ b/src/mongo/db/exec/plan_stage.h @@ -37,9 +37,10 @@ namespace mongo { +class ClockSource; class Collection; -class RecordId; class OperationContext; +class RecordId; /** * A PlanStage ("stage") is the basic building block of a "Query Execution Plan." A stage is @@ -357,6 +358,8 @@ protected: */ virtual void doInvalidate(OperationContext* txn, const RecordId& dl, InvalidationType type) {} + ClockSource* getClock() const; + OperationContext* getOpCtx() const { return _opCtx; } diff --git a/src/mongo/db/exec/queued_data_stage_test.cpp b/src/mongo/db/exec/queued_data_stage_test.cpp index e26d303a833..26f41ca4c8c 100644 --- a/src/mongo/db/exec/queued_data_stage_test.cpp +++ b/src/mongo/db/exec/queued_data_stage_test.cpp @@ -32,8 +32,12 @@ #include "mongo/db/exec/queued_data_stage.h" #include "mongo/db/exec/working_set.h" +#include "mongo/db/operation_context_noop.h" +#include "mongo/db/service_context.h" +#include "mongo/db/service_context_noop.h" #include "mongo/stdx/memory.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/clock_source_mock.h" using namespace mongo; @@ -42,12 +46,38 @@ namespace { using std::unique_ptr; using stdx::make_unique; +class QueuedDataStageTest : public unittest::Test { +public: + QueuedDataStageTest() { + _service = stdx::make_unique<ServiceContextNoop>(); + _client = _service.get()->makeClient("test"); + _opCtxNoop.reset(new OperationContextNoop(_client.get(), 0)); + _opCtx = _opCtxNoop.get(); + } + +protected: + OperationContext* getOpCtx() { + return _opCtx; + } + +private: + OperationContext* _opCtx; + std::unique_ptr<OperationContextNoop> _opCtxNoop; + + std::unique_ptr<ServiceContextNoop> _service; + + // UniqueClient is declared after ServiceContextNoop because + // members of a class are destroyed in reverse order of declaration and + // UniqueClient must be destroyed before the ServiceContextNoop is destroyed. + ServiceContext::UniqueClient _client; +}; + // // Basic test that we get out valid stats objects. // -TEST(QueuedDataStageTest, getValidStats) { +TEST_F(QueuedDataStageTest, getValidStats) { WorkingSet ws; - auto mock = make_unique<QueuedDataStage>(nullptr, &ws); + auto mock = make_unique<QueuedDataStage>(getOpCtx(), &ws); const CommonStats* commonStats = mock->getCommonStats(); ASSERT_EQUALS(commonStats->works, static_cast<size_t>(0)); const SpecificStats* specificStats = mock->getSpecificStats(); @@ -59,10 +89,10 @@ TEST(QueuedDataStageTest, getValidStats) { // // Test that our stats are updated as we perform operations. // -TEST(QueuedDataStageTest, validateStats) { +TEST_F(QueuedDataStageTest, validateStats) { WorkingSet ws; WorkingSetID wsID; - auto mock = make_unique<QueuedDataStage>(nullptr, &ws); + auto mock = make_unique<QueuedDataStage>(getOpCtx(), &ws); // make sure that we're at all zero const CommonStats* stats = mock->getCommonStats(); diff --git a/src/mongo/db/exec/scoped_timer.cpp b/src/mongo/db/exec/scoped_timer.cpp index e1db4a44ff8..8493db68116 100644 --- a/src/mongo/db/exec/scoped_timer.cpp +++ b/src/mongo/db/exec/scoped_timer.cpp @@ -29,16 +29,15 @@ #include "mongo/platform/basic.h" #include "mongo/db/exec/scoped_timer.h" - -#include "mongo/util/net/listen.h" +#include "mongo/util/clock_source.h" namespace mongo { -ScopedTimer::ScopedTimer(long long* counter) - : _counter(counter), _start(Listener::getElapsedTimeMillis()) {} +ScopedTimer::ScopedTimer(ClockSource* cs, long long* counter) + : _clock(cs), _counter(counter), _start(cs->now()) {} ScopedTimer::~ScopedTimer() { - long long elapsed = Listener::getElapsedTimeMillis() - _start; + long long elapsed = durationCount<Milliseconds>(_clock->now() - _start); *_counter += elapsed; } diff --git a/src/mongo/db/exec/scoped_timer.h b/src/mongo/db/exec/scoped_timer.h index 3e1c29fe719..da0a484fabf 100644 --- a/src/mongo/db/exec/scoped_timer.h +++ b/src/mongo/db/exec/scoped_timer.h @@ -30,8 +30,12 @@ #include "mongo/base/disallow_copying.h" +#include "mongo/util/time_support.h" + namespace mongo { +class ClockSource; + /** * This class increments a counter by a rough estimate of the time elapsed since its * construction when it goes out of scope. @@ -40,19 +44,17 @@ class ScopedTimer { MONGO_DISALLOW_COPYING(ScopedTimer); public: - ScopedTimer(long long* counter); + ScopedTimer(ClockSource* cs, long long* counter); ~ScopedTimer(); private: - // Default constructor disallowed. - ScopedTimer(); - + ClockSource* const _clock; // Reference to the counter that we are incrementing with the elapsed time. long long* _counter; // Time at which the timer was constructed. - long long _start; + const Date_t _start; }; } // namespace mongo diff --git a/src/mongo/db/exec/sort_test.cpp b/src/mongo/db/exec/sort_test.cpp index 6a45fa27022..f0cc0d01062 100644 --- a/src/mongo/db/exec/sort_test.cpp +++ b/src/mongo/db/exec/sort_test.cpp @@ -34,23 +34,145 @@ #include "mongo/db/exec/queued_data_stage.h" #include "mongo/db/json.h" +#include "mongo/db/operation_context_noop.h" #include "mongo/db/query/collation/collator_interface_mock.h" +#include "mongo/db/service_context.h" +#include "mongo/db/service_context_noop.h" #include "mongo/stdx/memory.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/clock_source_mock.h" using namespace mongo; namespace { -TEST(SortStageTest, SortEmptyWorkingSet) { +class SortStageTest : public unittest::Test { +public: + SortStageTest() { + _service = stdx::make_unique<ServiceContextNoop>(); + _client = _service.get()->makeClient("test"); + _opCtxNoop.reset(new OperationContextNoop(_client.get(), 0)); + _opCtx = _opCtxNoop.get(); + } + + /** + * Test function to verify sort stage. + * SortStageParams will be initialized using patternStr, collator, queryStr and limit. + * inputStr represents the input data set in a BSONObj. + * {input: [doc1, doc2, doc3, ...]} + * expectedStr represents the expected sorted data set. + * {output: [docA, docB, docC, ...]} + */ + void testWork(const char* patternStr, + CollatorInterface* collator, + const char* queryStr, + int limit, + const char* inputStr, + const char* expectedStr) { + // WorkingSet is not owned by stages + // so it's fine to declare + WorkingSet ws; + + // QueuedDataStage will be owned by SortStage. + auto queuedDataStage = stdx::make_unique<QueuedDataStage>(getOpCtx(), &ws); + BSONObj inputObj = fromjson(inputStr); + BSONElement inputElt = inputObj.getField("input"); + ASSERT(inputElt.isABSONObj()); + BSONObjIterator inputIt(inputElt.embeddedObject()); + while (inputIt.more()) { + BSONElement elt = inputIt.next(); + ASSERT(elt.isABSONObj()); + BSONObj obj = elt.embeddedObject().getOwned(); + + // Insert obj from input array into working set. + WorkingSetID id = ws.allocate(); + WorkingSetMember* wsm = ws.get(id); + wsm->obj = Snapshotted<BSONObj>(SnapshotId(), obj); + wsm->transitionToOwnedObj(); + queuedDataStage->pushBack(id); + } + + // Initialize SortStageParams + // Setting limit to 0 means no limit + SortStageParams params; + params.pattern = fromjson(patternStr); + params.collator = collator; + params.limit = limit; + + auto sortKeyGen = stdx::make_unique<SortKeyGeneratorStage>( + getOpCtx(), queuedDataStage.release(), &ws, params.pattern, fromjson(queryStr)); + + SortStage sort(getOpCtx(), params, &ws, sortKeyGen.release()); + + WorkingSetID id = WorkingSet::INVALID_ID; + PlanStage::StageState state = PlanStage::NEED_TIME; + + // Keep working sort stage until data is available. + while (state == PlanStage::NEED_TIME) { + state = sort.work(&id); + } + + // QueuedDataStage's state should be EOF when sort is ready to advance. + ASSERT_TRUE(sort.child()->child()->isEOF()); + + // While there's data to be retrieved, state should be equal to ADVANCED. + // Insert documents into BSON document in this format: + // {output: [docA, docB, docC, ...]} + BSONObjBuilder bob; + BSONArrayBuilder arr(bob.subarrayStart("output")); + while (state == PlanStage::ADVANCED) { + WorkingSetMember* member = ws.get(id); + const BSONObj& obj = member->obj.value(); + arr.append(obj); + state = sort.work(&id); + } + arr.doneFast(); + BSONObj outputObj = bob.obj(); + + // Sort stage should be EOF after data is retrieved. + ASSERT_EQUALS(state, PlanStage::IS_EOF); + ASSERT_TRUE(sort.isEOF()); + + // Finally, we get to compare the sorted results against what we expect. + BSONObj expectedObj = fromjson(expectedStr); + if (outputObj != expectedObj) { + mongoutils::str::stream ss; + // Even though we have the original string representation of the expected output, + // we invoke BSONObj::toString() to get a format consistent with outputObj. + ss << "Unexpected sort result with query=" << queryStr << "; pattern=" << patternStr + << "; limit=" << limit << ":\n" + << "Expected: " << expectedObj.toString() << "\n" + << "Actual: " << outputObj.toString() << "\n"; + FAIL(ss); + } + } + +protected: + OperationContext* getOpCtx() { + return _opCtx; + } + +private: + OperationContext* _opCtx; + std::unique_ptr<OperationContextNoop> _opCtxNoop; + + std::unique_ptr<ServiceContextNoop> _service; + + // UniqueClient is declared after ServiceContextNoop because + // members of a class are destroyed in reverse order of declaration and + // UniqueClient must be destroyed before the ServiceContextNoop is destroyed. + ServiceContext::UniqueClient _client; +}; + +TEST_F(SortStageTest, SortEmptyWorkingSet) { WorkingSet ws; // QueuedDataStage will be owned by SortStage. - auto queuedDataStage = stdx::make_unique<QueuedDataStage>(nullptr, &ws); + auto queuedDataStage = stdx::make_unique<QueuedDataStage>(getOpCtx(), &ws); auto sortKeyGen = stdx::make_unique<SortKeyGeneratorStage>( - nullptr, queuedDataStage.release(), &ws, BSONObj(), BSONObj()); + getOpCtx(), queuedDataStage.release(), &ws, BSONObj(), BSONObj()); SortStageParams params; - SortStage sort(nullptr, params, &ws, sortKeyGen.release()); + SortStage sort(getOpCtx(), params, &ws, sortKeyGen.release()); // Check initial EOF state. ASSERT_FALSE(sort.isEOF()); @@ -71,98 +193,6 @@ TEST(SortStageTest, SortEmptyWorkingSet) { ASSERT_TRUE(sort.isEOF()); } -/** - * Test function to verify sort stage. - * SortStageParams will be initialized using patternStr, collator, queryStr and limit. - * inputStr represents the input data set in a BSONObj. - * {input: [doc1, doc2, doc3, ...]} - * expectedStr represents the expected sorted data set. - * {output: [docA, docB, docC, ...]} - */ -void testWork(const char* patternStr, - CollatorInterface* collator, - const char* queryStr, - int limit, - const char* inputStr, - const char* expectedStr) { - // WorkingSet is not owned by stages - // so it's fine to declare - WorkingSet ws; - - // QueuedDataStage will be owned by SortStage. - auto queuedDataStage = stdx::make_unique<QueuedDataStage>(nullptr, &ws); - BSONObj inputObj = fromjson(inputStr); - BSONElement inputElt = inputObj.getField("input"); - ASSERT(inputElt.isABSONObj()); - BSONObjIterator inputIt(inputElt.embeddedObject()); - while (inputIt.more()) { - BSONElement elt = inputIt.next(); - ASSERT(elt.isABSONObj()); - BSONObj obj = elt.embeddedObject().getOwned(); - - // Insert obj from input array into working set. - WorkingSetID id = ws.allocate(); - WorkingSetMember* wsm = ws.get(id); - wsm->obj = Snapshotted<BSONObj>(SnapshotId(), obj); - wsm->transitionToOwnedObj(); - queuedDataStage->pushBack(id); - } - - // Initialize SortStageParams - // Setting limit to 0 means no limit - SortStageParams params; - params.pattern = fromjson(patternStr); - params.collator = collator; - params.limit = limit; - - auto sortKeyGen = stdx::make_unique<SortKeyGeneratorStage>( - nullptr, queuedDataStage.release(), &ws, params.pattern, fromjson(queryStr)); - - SortStage sort(nullptr, params, &ws, sortKeyGen.release()); - - WorkingSetID id = WorkingSet::INVALID_ID; - PlanStage::StageState state = PlanStage::NEED_TIME; - - // Keep working sort stage until data is available. - while (state == PlanStage::NEED_TIME) { - state = sort.work(&id); - } - - // QueuedDataStage's state should be EOF when sort is ready to advance. - ASSERT_TRUE(sort.child()->child()->isEOF()); - - // While there's data to be retrieved, state should be equal to ADVANCED. - // Insert documents into BSON document in this format: - // {output: [docA, docB, docC, ...]} - BSONObjBuilder bob; - BSONArrayBuilder arr(bob.subarrayStart("output")); - while (state == PlanStage::ADVANCED) { - WorkingSetMember* member = ws.get(id); - const BSONObj& obj = member->obj.value(); - arr.append(obj); - state = sort.work(&id); - } - arr.doneFast(); - BSONObj outputObj = bob.obj(); - - // Sort stage should be EOF after data is retrieved. - ASSERT_EQUALS(state, PlanStage::IS_EOF); - ASSERT_TRUE(sort.isEOF()); - - // Finally, we get to compare the sorted results against what we expect. - BSONObj expectedObj = fromjson(expectedStr); - if (outputObj != expectedObj) { - mongoutils::str::stream ss; - // Even though we have the original string representation of the expected output, - // we invoke BSONObj::toString() to get a format consistent with outputObj. - ss << "Unexpected sort result with query=" << queryStr << "; pattern=" << patternStr - << "; limit=" << limit << ":\n" - << "Expected: " << expectedObj.toString() << "\n" - << "Actual: " << outputObj.toString() << "\n"; - FAIL(ss); - } -} - // // Limit values // The server interprets limit values from the user as follows: @@ -176,7 +206,7 @@ void testWork(const char* patternStr, // Implementation should keep all items fetched from child. // -TEST(SortStageTest, SortAscending) { +TEST_F(SortStageTest, SortAscending) { testWork("{a: 1}", nullptr, "{}", @@ -185,7 +215,7 @@ TEST(SortStageTest, SortAscending) { "{output: [{a: 1}, {a: 2}, {a: 3}]}"); } -TEST(SortStageTest, SortDescending) { +TEST_F(SortStageTest, SortDescending) { testWork("{a: -1}", nullptr, "{}", @@ -194,7 +224,7 @@ TEST(SortStageTest, SortDescending) { "{output: [{a: 3}, {a: 2}, {a: 1}]}"); } -TEST(SortStageTest, SortIrrelevantSortKey) { +TEST_F(SortStageTest, SortIrrelevantSortKey) { testWork("{b: 1}", nullptr, "{}", @@ -209,7 +239,7 @@ TEST(SortStageTest, SortIrrelevantSortKey) { // and discard the rest. // -TEST(SortStageTest, SortAscendingWithLimit) { +TEST_F(SortStageTest, SortAscendingWithLimit) { testWork("{a: 1}", nullptr, "{}", @@ -218,7 +248,7 @@ TEST(SortStageTest, SortAscendingWithLimit) { "{output: [{a: 1}, {a: 2}]}"); } -TEST(SortStageTest, SortDescendingWithLimit) { +TEST_F(SortStageTest, SortDescendingWithLimit) { testWork("{a: -1}", nullptr, "{}", @@ -233,7 +263,7 @@ TEST(SortStageTest, SortDescendingWithLimit) { // and discard the rest. // -TEST(SortStageTest, SortAscendingWithLimitGreaterThanInputSize) { +TEST_F(SortStageTest, SortAscendingWithLimitGreaterThanInputSize) { testWork("{a: 1}", nullptr, "{}", @@ -242,7 +272,7 @@ TEST(SortStageTest, SortAscendingWithLimitGreaterThanInputSize) { "{output: [{a: 1}, {a: 2}, {a: 3}]}"); } -TEST(SortStageTest, SortDescendingWithLimitGreaterThanInputSize) { +TEST_F(SortStageTest, SortDescendingWithLimitGreaterThanInputSize) { testWork("{a: -1}", nullptr, "{}", @@ -256,16 +286,16 @@ TEST(SortStageTest, SortDescendingWithLimitGreaterThanInputSize) { // Implementation should optimize this into a running maximum. // -TEST(SortStageTest, SortAscendingWithLimitOfOne) { +TEST_F(SortStageTest, SortAscendingWithLimitOfOne) { testWork("{a: 1}", nullptr, "{}", 1, "{input: [{a: 2}, {a: 1}, {a: 3}]}", "{output: [{a: 1}]}"); } -TEST(SortStageTest, SortDescendingWithLimitOfOne) { +TEST_F(SortStageTest, SortDescendingWithLimitOfOne) { testWork( "{a: -1}", nullptr, "{}", 1, "{input: [{a: 2}, {a: 1}, {a: 3}]}", "{output: [{a: 3}]}"); } -TEST(SortStageTest, SortAscendingWithCollation) { +TEST_F(SortStageTest, SortAscendingWithCollation) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); testWork("{a: 1}", &collator, @@ -275,7 +305,7 @@ TEST(SortStageTest, SortAscendingWithCollation) { "{output: [{a: 'aa'}, {a: 'ba'}, {a: 'ab'}]}"); } -TEST(SortStageTest, SortDescendingWithCollation) { +TEST_F(SortStageTest, SortDescendingWithCollation) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); testWork("{a: -1}", &collator, diff --git a/src/mongo/db/exec/subplan.cpp b/src/mongo/db/exec/subplan.cpp index b694a4cc902..8be5da178dc 100644 --- a/src/mongo/db/exec/subplan.cpp +++ b/src/mongo/db/exec/subplan.cpp @@ -494,7 +494,7 @@ Status SubplanStage::choosePlanWholeQuery(PlanYieldPolicy* yieldPolicy) { Status SubplanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) { // Adds the amount of time taken by pickBestPlan() to executionTimeMillis. There's lots of // work that happens here, so this is needed for the time accounting to make sense. - ScopedTimer timer(&_commonStats.executionTimeMillis); + ScopedTimer timer(getClock(), &_commonStats.executionTimeMillis); // Plan each branch of the $or. Status subplanningStatus = planSubqueries(); diff --git a/src/mongo/db/pipeline/document_source_test.cpp b/src/mongo/db/pipeline/document_source_test.cpp index 80423154a8d..b8f96fd1f60 100644 --- a/src/mongo/db/pipeline/document_source_test.cpp +++ b/src/mongo/db/pipeline/document_source_test.cpp @@ -37,9 +37,9 @@ #include "mongo/db/pipeline/pipeline.h" #include "mongo/db/service_context.h" #include "mongo/db/service_context_noop.h" -#include "mongo/stdx/memory.h" #include "mongo/db/storage/storage_options.h" #include "mongo/dbtests/dbtests.h" +#include "mongo/stdx/memory.h" #include "mongo/util/clock_source_mock.h" #include "mongo/unittest/temp_dir.h" diff --git a/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp b/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp index 79517b5b193..542c61dc8ce 100644 --- a/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp +++ b/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp @@ -88,8 +88,8 @@ BSONObj createRecvChunkCommitRequest(const NamespaceString& nss, */ class DeleteNotificationStage final : public PlanStage { public: - DeleteNotificationStage(MigrationChunkClonerSourceLegacy* cloner) - : PlanStage("SHARDING_NOTIFY_DELETE", nullptr), _cloner(cloner) {} + DeleteNotificationStage(MigrationChunkClonerSourceLegacy* cloner, OperationContext* txn) + : PlanStage("SHARDING_NOTIFY_DELETE", txn), _cloner(cloner) {} void doInvalidate(OperationContext* txn, const RecordId& dl, InvalidationType type) override { if (type == INVALIDATION_DELETION) { @@ -527,7 +527,7 @@ Status MigrationChunkClonerSourceLegacy::_storeCurrentLocs(OperationContext* txn auto statusWithPlanExecutor = PlanExecutor::make(txn, stdx::make_unique<WorkingSet>(), - stdx::make_unique<DeleteNotificationStage>(this), + stdx::make_unique<DeleteNotificationStage>(this, txn), collection, PlanExecutor::YIELD_MANUAL); invariant(statusWithPlanExecutor.isOK()); diff --git a/src/mongo/db/storage/mmap_v1/dur_journal.cpp b/src/mongo/db/storage/mmap_v1/dur_journal.cpp index ea3b02d9476..524085a87e9 100644 --- a/src/mongo/db/storage/mmap_v1/dur_journal.cpp +++ b/src/mongo/db/storage/mmap_v1/dur_journal.cpp @@ -58,7 +58,6 @@ #include "mongo/util/hex.h" #include "mongo/util/log.h" #include "mongo/util/mongoutils/str.h" -#include "mongo/util/net/listen.h" // getelapsedtimemillis #include "mongo/util/progress_meter.h" #include "mongo/util/timer.h" diff --git a/src/mongo/dbtests/plan_ranking.cpp b/src/mongo/dbtests/plan_ranking.cpp index 8871e17a5bf..970f7d02ac9 100644 --- a/src/mongo/dbtests/plan_ranking.cpp +++ b/src/mongo/dbtests/plan_ranking.cpp @@ -51,12 +51,9 @@ #include "mongo/db/query/stage_builder.h" #include "mongo/dbtests/dbtests.h" #include "mongo/stdx/memory.h" -#include "mongo/util/clock_source_mock.h" namespace mongo { -const std::unique_ptr<ClockSource> clockSource = stdx::make_unique<ClockSourceMock>(); - // How we access the external setParameter testing bool. extern std::atomic<bool> internalQueryForceIntersectionPlans; // NOLINT @@ -132,7 +129,8 @@ public: _mps->addPlan(solutions[i], root, ws.get()); } // This is what sets a backup plan, should we test for it. - PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get()); + PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, + _txn.getServiceContext()->getFastClockSource()); _mps->pickBestPlan(&yieldPolicy); ASSERT(_mps->bestPlanChosen()); diff --git a/src/mongo/dbtests/query_stage_cached_plan.cpp b/src/mongo/dbtests/query_stage_cached_plan.cpp index 1d41db88d93..f090e61f8c4 100644 --- a/src/mongo/dbtests/query_stage_cached_plan.cpp +++ b/src/mongo/dbtests/query_stage_cached_plan.cpp @@ -47,11 +47,9 @@ #include "mongo/db/query/query_planner_params.h" #include "mongo/dbtests/dbtests.h" #include "mongo/stdx/memory.h" -#include "mongo/util/clock_source_mock.h" namespace QueryStageCachedPlan { -const std::unique_ptr<ClockSource> clockSource = stdx::make_unique<ClockSourceMock>(); static const NamespaceString nss("unittests.QueryStageCachedPlan"); class QueryStageCachedPlanBase { @@ -149,7 +147,8 @@ public: &_txn, collection, &_ws, cq.get(), plannerParams, decisionWorks, mockChild.release()); // This should succeed after triggering a replan. - PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get()); + PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, + _txn.getServiceContext()->getFastClockSource()); ASSERT_OK(cachedPlanStage.pickBestPlan(&yieldPolicy)); // Make sure that we get 2 legit results back. @@ -220,7 +219,8 @@ public: &_txn, collection, &_ws, cq.get(), plannerParams, decisionWorks, mockChild.release()); // This should succeed after triggering a replan. - PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get()); + PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, + _txn.getServiceContext()->getFastClockSource()); ASSERT_OK(cachedPlanStage.pickBestPlan(&yieldPolicy)); // Make sure that we get 2 legit results back. diff --git a/src/mongo/dbtests/query_stage_ensure_sorted.cpp b/src/mongo/dbtests/query_stage_ensure_sorted.cpp index 8ba3b552eeb..f89bbd42ea5 100644 --- a/src/mongo/dbtests/query_stage_ensure_sorted.cpp +++ b/src/mongo/dbtests/query_stage_ensure_sorted.cpp @@ -28,6 +28,7 @@ #include "mongo/platform/basic.h" +#include "mongo/db/client.h" #include "mongo/db/exec/ensure_sorted.h" #include "mongo/db/exec/sort_key_generator.h" #include "mongo/db/exec/queued_data_stage.h" @@ -40,12 +41,81 @@ namespace mongo { namespace { -TEST(QueryStageEnsureSorted, EnsureSortedEmptyWorkingSet) { +class QueryStageEnsureSortedTest : public unittest::Test { +public: + /** + * Test function to verify the EnsureSortedStage. + * patternStr is the JSON representation of the sort pattern BSONObj. + * inputStr represents the input data set in a BSONObj. + * {input: [doc1, doc2, doc3, ...]} + * expectedStr represents the expected output data set. + * {output: [docA, docB, docC, ...]} + * collator is passed to EnsureSortedStage() for string comparisons. + */ + void testWork(const char* patternStr, + const char* inputStr, + const char* expectedStr, + CollatorInterface* collator = nullptr) { + WorkingSet ws; + auto queuedDataStage = stdx::make_unique<QueuedDataStage>(_opCtx, &ws); + BSONObj inputObj = fromjson(inputStr); + BSONElement inputElt = inputObj["input"]; + ASSERT(inputElt.isABSONObj()); + + for (auto&& elt : inputElt.embeddedObject()) { + ASSERT(elt.isABSONObj()); + BSONObj obj = elt.embeddedObject().getOwned(); + + // Insert obj from input array into working set. + WorkingSetID id = ws.allocate(); + WorkingSetMember* wsm = ws.get(id); + wsm->obj = Snapshotted<BSONObj>(SnapshotId(), obj); + wsm->transitionToOwnedObj(); + queuedDataStage->pushBack(id); + } + + // Initialization. + BSONObj pattern = fromjson(patternStr); + auto sortKeyGen = stdx::make_unique<SortKeyGeneratorStage>( + _opCtx, queuedDataStage.release(), &ws, pattern, BSONObj()); + EnsureSortedStage ess(_opCtx, pattern, collator, &ws, sortKeyGen.release()); + WorkingSetID id = WorkingSet::INVALID_ID; + PlanStage::StageState state = PlanStage::NEED_TIME; + + // Documents are inserted into BSON document in this format: + // {output: [docA, docB, docC, ...]} + BSONObjBuilder bob; + BSONArrayBuilder arr(bob.subarrayStart("output")); + while (state != PlanStage::IS_EOF) { + state = ess.work(&id); + ASSERT_NE(state, PlanStage::DEAD); + ASSERT_NE(state, PlanStage::FAILURE); + if (state == PlanStage::ADVANCED) { + WorkingSetMember* member = ws.get(id); + const BSONObj& obj = member->obj.value(); + arr.append(obj); + } + } + ASSERT_TRUE(ess.isEOF()); + arr.doneFast(); + BSONObj outputObj = bob.obj(); + + // Compare the results against what we expect. + BSONObj expectedObj = fromjson(expectedStr); + ASSERT_EQ(outputObj, expectedObj); + } + +protected: + const ServiceContext::UniqueOperationContext _uniqOpCtx = cc().makeOperationContext(); + OperationContext* const _opCtx = _uniqOpCtx.get(); +}; + +TEST_F(QueryStageEnsureSortedTest, EnsureSortedEmptyWorkingSet) { WorkingSet ws; - auto queuedDataStage = stdx::make_unique<QueuedDataStage>(nullptr, &ws); + auto queuedDataStage = stdx::make_unique<QueuedDataStage>(_opCtx, &ws); auto sortKeyGen = stdx::make_unique<SortKeyGeneratorStage>( - nullptr, queuedDataStage.release(), &ws, BSONObj(), BSONObj()); - EnsureSortedStage ess(nullptr, BSONObj(), nullptr, &ws, sortKeyGen.release()); + _opCtx, queuedDataStage.release(), &ws, BSONObj(), BSONObj()); + EnsureSortedStage ess(_opCtx, BSONObj(), nullptr, &ws, sortKeyGen.release()); WorkingSetID id = WorkingSet::INVALID_ID; PlanStage::StageState state = PlanStage::NEED_TIME; @@ -56,81 +126,19 @@ TEST(QueryStageEnsureSorted, EnsureSortedEmptyWorkingSet) { ASSERT_EQ(state, PlanStage::IS_EOF); } -/** - * Test function to verify the EnsureSortedStage. - * patternStr is the JSON representation of the sort pattern BSONObj. - * inputStr represents the input data set in a BSONObj. - * {input: [doc1, doc2, doc3, ...]} - * expectedStr represents the expected output data set. - * {output: [docA, docB, docC, ...]} - * collator is passed to EnsureSortedStage() for string comparisons. - */ -void testWork(const char* patternStr, - const char* inputStr, - const char* expectedStr, - const CollatorInterface* collator = nullptr) { - WorkingSet ws; - auto queuedDataStage = stdx::make_unique<QueuedDataStage>(nullptr, &ws); - BSONObj inputObj = fromjson(inputStr); - BSONElement inputElt = inputObj["input"]; - ASSERT(inputElt.isABSONObj()); - - for (auto&& elt : inputElt.embeddedObject()) { - ASSERT(elt.isABSONObj()); - BSONObj obj = elt.embeddedObject().getOwned(); - - // Insert obj from input array into working set. - WorkingSetID id = ws.allocate(); - WorkingSetMember* wsm = ws.get(id); - wsm->obj = Snapshotted<BSONObj>(SnapshotId(), obj); - wsm->transitionToOwnedObj(); - queuedDataStage->pushBack(id); - } - - // Initialization. - BSONObj pattern = fromjson(patternStr); - auto sortKeyGen = stdx::make_unique<SortKeyGeneratorStage>( - nullptr, queuedDataStage.release(), &ws, pattern, BSONObj()); - EnsureSortedStage ess(nullptr, pattern, collator, &ws, sortKeyGen.release()); - WorkingSetID id = WorkingSet::INVALID_ID; - PlanStage::StageState state = PlanStage::NEED_TIME; - - // Documents are inserted into BSON document in this format: - // {output: [docA, docB, docC, ...]} - BSONObjBuilder bob; - BSONArrayBuilder arr(bob.subarrayStart("output")); - while (state != PlanStage::IS_EOF) { - state = ess.work(&id); - ASSERT_NE(state, PlanStage::DEAD); - ASSERT_NE(state, PlanStage::FAILURE); - if (state == PlanStage::ADVANCED) { - WorkingSetMember* member = ws.get(id); - const BSONObj& obj = member->obj.value(); - arr.append(obj); - } - } - ASSERT_TRUE(ess.isEOF()); - arr.doneFast(); - BSONObj outputObj = bob.obj(); - - // Compare the results against what we expect. - BSONObj expectedObj = fromjson(expectedStr); - ASSERT_EQ(outputObj, expectedObj); -} - // // EnsureSorted on already sorted order should make no change. // -TEST(QueryStageEnsureSorted, EnsureAlreadySortedAscending) { +TEST_F(QueryStageEnsureSortedTest, EnsureAlreadySortedAscending) { testWork("{a: 1}", "{input: [{a: 1}, {a: 2}, {a: 3}]}", "{output: [{a: 1}, {a: 2}, {a: 3}]}"); } -TEST(QueryStageEnsureSorted, EnsureAlreadySortedDescending) { +TEST_F(QueryStageEnsureSortedTest, EnsureAlreadySortedDescending) { testWork("{a: -1}", "{input: [{a: 3}, {a: 2}, {a: 1}]}", "{output: [{a: 3}, {a: 2}, {a: 1}]}"); } -TEST(QueryStageEnsureSorted, EnsureIrrelevantSortKey) { +TEST_F(QueryStageEnsureSortedTest, EnsureIrrelevantSortKey) { testWork("{b: 1}", "{input: [{a: 2}, {a: 1}, {a: 3}]}", "{output: [{a: 2}, {a: 1}, {a: 3}]}"); } @@ -138,33 +146,29 @@ TEST(QueryStageEnsureSorted, EnsureIrrelevantSortKey) { // EnsureSorted should drop unsorted results. // -TEST(QueryStageEnsureSorted, EnsureSortedOnAscending) { +TEST_F(QueryStageEnsureSortedTest, EnsureSortedOnAscending) { testWork("{a: 1}", "{input: [{a: 1}, {a: 2}, {a: 0}, {a: 4}, {a: 6}]}", "{output: [{a: 1}, {a: 2}, {a: 4}, {a: 6}]}"); } -TEST(QueryStageEnsureSorted, EnsureSortedOnDescending) { +TEST_F(QueryStageEnsureSortedTest, EnsureSortedOnDescending) { testWork("{a: -1}", "{input: [{a: 6}, {a: 4}, {a: 3}, {a: 9}, {a: 8}]}", "{output: [{a: 6}, {a: 4}, {a: 3}]}"); } -TEST(QueryStageEnsureSorted, EnsureSortedCompoundKey) { +TEST_F(QueryStageEnsureSortedTest, EnsureSortedCompoundKey) { testWork("{a: -1, b: 1}", "{input: [{a: 6, b: 10}, {a: 6, b: 8}, {a: 6, b: 12}, {a: 9, b: 13}, {a: 5, b: 1}]}", "{output: [{a: 6, b: 10}, {a: 6, b: 12}, {a: 5, b: 1}]}"); } -TEST(QueryStageEnsureSorted, EnsureSortedStringsNullCollator) { - const CollatorInterface* collator = nullptr; - testWork("{a: 1}", - "{input: [{a: 'abc'}, {a: 'cba'}]}", - "{output: [{a: 'abc'}, {a: 'cba'}]}", - collator); +TEST_F(QueryStageEnsureSortedTest, EnsureSortedStringsNullCollator) { + testWork("{a: 1}", "{input: [{a: 'abc'}, {a: 'cba'}]}", "{output: [{a: 'abc'}, {a: 'cba'}]}"); } -TEST(QueryStageEnsureSorted, EnsureSortedStringsCollator) { +TEST_F(QueryStageEnsureSortedTest, EnsureSortedStringsCollator) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); testWork("{a: 1}", "{input: [{a: 'abc'}, {a: 'cba'}]}", "{output: [{a: 'abc'}]}", &collator); } diff --git a/src/mongo/dbtests/query_stage_limit_skip.cpp b/src/mongo/dbtests/query_stage_limit_skip.cpp index 2bb8e3b1faf..0009f32ea8c 100644 --- a/src/mongo/dbtests/query_stage_limit_skip.cpp +++ b/src/mongo/dbtests/query_stage_limit_skip.cpp @@ -34,6 +34,7 @@ #include "mongo/platform/basic.h" #include "mongo/client/dbclientcursor.h" +#include "mongo/db/client.h" #include "mongo/db/exec/limit.h" #include "mongo/db/exec/plan_stage.h" #include "mongo/db/exec/queued_data_stage.h" @@ -55,8 +56,8 @@ using stdx::make_unique; static const int N = 50; /* Populate a QueuedDataStage and return it. Caller owns it. */ -QueuedDataStage* getMS(WorkingSet* ws) { - auto ms = make_unique<QueuedDataStage>(nullptr, ws); +QueuedDataStage* getMS(OperationContext* opCtx, WorkingSet* ws) { + auto ms = make_unique<QueuedDataStage>(opCtx, ws); // Put N ADVANCED results into the mock stage, and some other stalling results (YIELD/TIME). for (int i = 0; i < N; ++i) { @@ -96,13 +97,18 @@ public: for (int i = 0; i < 2 * N; ++i) { WorkingSet ws; - unique_ptr<PlanStage> skip = make_unique<SkipStage>(nullptr, i, &ws, getMS(&ws)); + unique_ptr<PlanStage> skip = make_unique<SkipStage>(_opCtx, i, &ws, getMS(_opCtx, &ws)); ASSERT_EQUALS(max(0, N - i), countResults(skip.get())); - unique_ptr<PlanStage> limit = make_unique<LimitStage>(nullptr, i, &ws, getMS(&ws)); + unique_ptr<PlanStage> limit = + make_unique<LimitStage>(_opCtx, i, &ws, getMS(_opCtx, &ws)); ASSERT_EQUALS(min(N, i), countResults(limit.get())); } } + +protected: + const ServiceContext::UniqueOperationContext _uniqOpCtx = cc().makeOperationContext(); + OperationContext* const _opCtx = _uniqOpCtx.get(); }; class All : public Suite { diff --git a/src/mongo/dbtests/query_stage_multiplan.cpp b/src/mongo/dbtests/query_stage_multiplan.cpp index 1ea517f1253..a76bfbe22c1 100644 --- a/src/mongo/dbtests/query_stage_multiplan.cpp +++ b/src/mongo/dbtests/query_stage_multiplan.cpp @@ -114,6 +114,8 @@ public: protected: const ServiceContext::UniqueOperationContext _txnPtr = cc().makeOperationContext(); OperationContext& _txn = *_txnPtr; + ClockSource* const _clock = _txn.getServiceContext()->getFastClockSource(); + DBDirectClient _client; }; @@ -180,7 +182,7 @@ public: mps->addPlan(createQuerySolution(), secondRoot.release(), sharedWs.get()); // Plan 0 aka the first plan aka the index scan should be the best. - PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get()); + PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock); mps->pickBestPlan(&yieldPolicy); ASSERT(mps->bestPlanChosen()); ASSERT_EQUALS(0, mps->bestPlanIdx()); @@ -264,7 +266,7 @@ public: } // This sets a backup plan. - PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get()); + PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock); mps->pickBestPlan(&yieldPolicy); ASSERT(mps->bestPlanChosen()); ASSERT(mps->hasBackupPlan()); diff --git a/src/mongo/dbtests/query_stage_near.cpp b/src/mongo/dbtests/query_stage_near.cpp index 58833e6a2bf..d973779e7ed 100644 --- a/src/mongo/dbtests/query_stage_near.cpp +++ b/src/mongo/dbtests/query_stage_near.cpp @@ -34,6 +34,7 @@ #include "mongo/platform/basic.h" #include "mongo/base/owned_pointer_vector.h" +#include "mongo/db/client.h" #include "mongo/db/exec/near.h" #include "mongo/db/exec/queued_data_stage.h" #include "mongo/db/exec/working_set_common.h" @@ -48,6 +49,12 @@ using std::unique_ptr; using std::vector; using stdx::make_unique; +class QueryStageNearTest : public unittest::Test { +protected: + const ServiceContext::UniqueOperationContext _uniqOpCtx = cc().makeOperationContext(); + OperationContext* const _opCtx = _uniqOpCtx.get(); +}; + /** * Stage which implements a basic distance search, and interprets the "distance" field of * fetched documents as the distance. @@ -63,8 +70,9 @@ public: double max; }; - MockNearStage(WorkingSet* workingSet) - : NearStage(NULL, "MOCK_DISTANCE_SEARCH_STAGE", STAGE_UNKNOWN, workingSet, NULL), _pos(0) {} + MockNearStage(OperationContext* opCtx, WorkingSet* workingSet) + : NearStage(opCtx, "MOCK_DISTANCE_SEARCH_STAGE", STAGE_UNKNOWN, workingSet, NULL), + _pos(0) {} void addInterval(vector<BSONObj> data, double min, double max) { _intervals.mutableVector().push_back(new MockInterval(data, min, max)); @@ -139,11 +147,11 @@ static void assertAscendingAndValid(const vector<BSONObj>& results) { } } -TEST(query_stage_near, Basic) { +TEST_F(QueryStageNearTest, Basic) { vector<BSONObj> mockData; WorkingSet workingSet; - MockNearStage nearStage(&workingSet); + MockNearStage nearStage(_opCtx, &workingSet); // First set of results mockData.clear(); @@ -174,11 +182,11 @@ TEST(query_stage_near, Basic) { assertAscendingAndValid(results); } -TEST(query_stage_near, EmptyResults) { +TEST_F(QueryStageNearTest, EmptyResults) { vector<BSONObj> mockData; WorkingSet workingSet; - MockNearStage nearStage(&workingSet); + MockNearStage nearStage(_opCtx, &workingSet); // Empty set of results mockData.clear(); diff --git a/src/mongo/dbtests/query_stage_subplan.cpp b/src/mongo/dbtests/query_stage_subplan.cpp index 419cd04d08d..825152c4007 100644 --- a/src/mongo/dbtests/query_stage_subplan.cpp +++ b/src/mongo/dbtests/query_stage_subplan.cpp @@ -43,11 +43,9 @@ #include "mongo/db/query/canonical_query.h" #include "mongo/db/query/get_executor.h" #include "mongo/dbtests/dbtests.h" -#include "mongo/util/clock_source_mock.h" namespace QueryStageSubplan { -const std::unique_ptr<ClockSource> clockSource = stdx::make_unique<ClockSourceMock>(); static const NamespaceString nss("unittests.QueryStageSubplan"); class QueryStageSubplanBase { @@ -89,6 +87,7 @@ protected: const ServiceContext::UniqueOperationContext _txnPtr = cc().makeOperationContext(); OperationContext& _txn = *_txnPtr; + ClockSource* _clock = _txn.getServiceContext()->getFastClockSource(); private: DBDirectClient _client; @@ -132,7 +131,7 @@ public: new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); // Plan selection should succeed due to falling back on regular planning. - PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get()); + PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); } }; @@ -175,7 +174,7 @@ public: std::unique_ptr<SubplanStage> subplan( new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); - PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get()); + PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); // Nothing is in the cache yet, so neither branch should have been planned from @@ -233,7 +232,7 @@ public: std::unique_ptr<SubplanStage> subplan( new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); - PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get()); + PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); // Nothing is in the cache yet, so neither branch should have been planned from @@ -292,7 +291,7 @@ public: std::unique_ptr<SubplanStage> subplan( new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); - PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get()); + PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); // Nothing is in the cache yet, so neither branch should have been planned from @@ -549,7 +548,7 @@ public: new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); // Plan selection should succeed due to falling back on regular planning. - PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get()); + PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); // Work the stage until it produces all results. @@ -607,7 +606,7 @@ public: std::unique_ptr<SubplanStage> subplan( new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); - PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get()); + PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); size_t numResults = 0; |