diff options
Diffstat (limited to 'src/mongo/db')
26 files changed, 40 insertions, 336 deletions
diff --git a/src/mongo/db/catalog/collection.cpp b/src/mongo/db/catalog/collection.cpp index d5a05ec5e02..474992997a9 100644 --- a/src/mongo/db/catalog/collection.cpp +++ b/src/mongo/db/catalog/collection.cpp @@ -56,7 +56,6 @@ #include "mongo/db/server_parameters.h" #include "mongo/db/service_context.h" #include "mongo/db/storage/key_string.h" -#include "mongo/db/storage/record_fetcher.h" #include "mongo/db/storage/record_store.h" #include "mongo/db/update/update_driver.h" diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h index fce9ba050d7..ce77483315c 100644 --- a/src/mongo/db/catalog/collection.h +++ b/src/mongo/db/catalog/collection.h @@ -68,7 +68,6 @@ class MultiIndexBlock; class OpDebug; class OperationContext; class RecordCursor; -class RecordFetcher; class UpdateDriver; class UpdateRequest; diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp index 0a961beecb1..4389b6b7641 100644 --- a/src/mongo/db/catalog/collection_impl.cpp +++ b/src/mongo/db/catalog/collection_impl.cpp @@ -64,7 +64,6 @@ #include "mongo/db/server_parameters.h" #include "mongo/db/service_context.h" #include "mongo/db/storage/key_string.h" -#include "mongo/db/storage/record_fetcher.h" #include "mongo/db/storage/record_store.h" #include "mongo/db/update/update_driver.h" diff --git a/src/mongo/db/exec/cached_plan.cpp b/src/mongo/db/exec/cached_plan.cpp index 01ca4bd2e37..d6ca70095b9 100644 --- a/src/mongo/db/exec/cached_plan.cpp +++ b/src/mongo/db/exec/cached_plan.cpp @@ -114,15 +114,9 @@ Status CachedPlanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) { updatePlanCache(); return Status::OK(); } else if (PlanStage::NEED_YIELD == state) { - if (id == WorkingSet::INVALID_ID) { - if (!yieldPolicy->canAutoYield()) { - throw WriteConflictException(); - } - } else { - WorkingSetMember* member = _ws->get(id); - invariant(member->hasFetcher()); - // Transfer ownership of the fetcher and yield. - _fetcher.reset(member->releaseFetcher()); + invariant(id == WorkingSet::INVALID_ID); + if (!yieldPolicy->canAutoYield()) { + throw WriteConflictException(); } if (yieldPolicy->canAutoYield()) { @@ -177,18 +171,14 @@ Status CachedPlanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) { Status CachedPlanStage::tryYield(PlanYieldPolicy* yieldPolicy) { // These are the conditions which can cause us to yield: // 1) The yield policy's timer elapsed, or - // 2) some stage requested a yield due to a document fetch, or + // 2) some stage requested a yield, or // 3) we need to yield and retry due to a WriteConflictException. // In all cases, the actual yielding happens here. if (yieldPolicy->shouldYieldOrInterrupt()) { // Here's where we yield. - return yieldPolicy->yieldOrInterrupt(_fetcher.get()); + return yieldPolicy->yieldOrInterrupt(); } - // We're done using the fetcher, so it should be freed. We don't want to - // use the same RecordFetcher twice. - _fetcher.reset(); - return Status::OK(); } diff --git a/src/mongo/db/exec/cached_plan.h b/src/mongo/db/exec/cached_plan.h index e8de18d7bca..3b1f76f4f05 100644 --- a/src/mongo/db/exec/cached_plan.h +++ b/src/mongo/db/exec/cached_plan.h @@ -38,7 +38,6 @@ #include "mongo/db/query/query_planner_params.h" #include "mongo/db/query/query_solution.h" #include "mongo/db/record_id.h" -#include "mongo/db/storage/record_fetcher.h" namespace mongo { @@ -136,12 +135,6 @@ private: // Any results produced during trial period execution are kept here. std::queue<WorkingSetID> _results; - // When a stage requests a yield for document fetch, it gives us back a RecordFetcher* - // to use to pull the record into memory. We take ownership of the RecordFetcher here, - // deleting it after we've had a chance to do the fetch. For timing-based yields, we - // just pass a NULL fetcher. - std::unique_ptr<RecordFetcher> _fetcher; - // Stats CachedPlanStats _specificStats; }; diff --git a/src/mongo/db/exec/collection_scan.cpp b/src/mongo/db/exec/collection_scan.cpp index e2c51ea7304..07d8803d211 100644 --- a/src/mongo/db/exec/collection_scan.cpp +++ b/src/mongo/db/exec/collection_scan.cpp @@ -39,7 +39,6 @@ #include "mongo/db/exec/working_set.h" #include "mongo/db/exec/working_set_common.h" #include "mongo/db/repl/optime.h" -#include "mongo/db/storage/record_fetcher.h" #include "mongo/stdx/memory.h" #include "mongo/util/fail_point_service.h" #include "mongo/util/log.h" @@ -63,8 +62,7 @@ CollectionScan::CollectionScan(OperationContext* opCtx, _workingSet(workingSet), _filter(filter), _params(params), - _isDead(false), - _wsidForFetch(_workingSet->allocate()) { + _isDead(false) { // Explain reports the direction of the collection scan. _specificStats.direction = params.direction; _specificStats.maxTs = params.maxTs; @@ -145,16 +143,6 @@ PlanStage::StageState CollectionScan::doWork(WorkingSetID* out) { if (_lastSeenId.isNull() && !_params.start.isNull()) { record = _cursor->seekExact(_params.start); } else { - // See if the record we're about to access is in memory. If not, pass a fetch - // request up. - if (auto fetcher = _cursor->fetcherForNext()) { - // Pass the RecordFetcher up. - WorkingSetMember* member = _workingSet->get(_wsidForFetch); - member->setFetcher(fetcher.release()); - *out = _wsidForFetch; - return PlanStage::NEED_YIELD; - } - record = _cursor->next(); } } catch (const WriteConflictException&) { diff --git a/src/mongo/db/exec/collection_scan.h b/src/mongo/db/exec/collection_scan.h index 1a997a01ac1..8a41cf77003 100644 --- a/src/mongo/db/exec/collection_scan.h +++ b/src/mongo/db/exec/collection_scan.h @@ -110,11 +110,6 @@ private: RecordId _lastSeenId; // Null if nothing has been returned from _cursor yet. - // We allocate a working set member with this id on construction of the stage. It gets used for - // all fetch requests. This should only be used for passing up the Fetcher for a NEED_YIELD, and - // should remain in the INVALID state. - const WorkingSetID _wsidForFetch; - // If _params.shouldTrackLatestOplogTimestamp is set and the collection is the oplog, the latest // timestamp seen in the collection. Otherwise, this is a null timestamp. Timestamp _latestOplogEntryTimestamp; diff --git a/src/mongo/db/exec/fetch.cpp b/src/mongo/db/exec/fetch.cpp index 001e7010c54..9dacdadcb0a 100644 --- a/src/mongo/db/exec/fetch.cpp +++ b/src/mongo/db/exec/fetch.cpp @@ -35,7 +35,6 @@ #include "mongo/db/exec/filter.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/exec/working_set_common.h" -#include "mongo/db/storage/record_fetcher.h" #include "mongo/stdx/memory.h" #include "mongo/util/fail_point_service.h" #include "mongo/util/mongoutils/str.h" @@ -66,8 +65,7 @@ FetchStage::~FetchStage() {} bool FetchStage::isEOF() { if (WorkingSet::INVALID_ID != _idRetrying) { - // We asked the parent for a page-in, but still haven't had a chance to return the - // paged in document + // We have a working set member that we need to retry. return false; } @@ -105,17 +103,6 @@ PlanStage::StageState FetchStage::doWork(WorkingSetID* out) { if (!_cursor) _cursor = _collection->getCursor(getOpCtx()); - if (auto fetcher = _cursor->fetcherForId(member->recordId)) { - // There's something to fetch. Hand the fetcher off to the WSM, and pass up - // a fetch request. - _idRetrying = id; - member->setFetcher(fetcher.release()); - *out = id; - return NEED_YIELD; - } - - // The doc is already in memory, so go ahead and grab it. Now we have a RecordId - // as well as an unowned object if (!WorkingSetCommon::fetch(getOpCtx(), _ws, id, _cursor)) { _ws->free(id); return NEED_TIME; diff --git a/src/mongo/db/exec/idhack.cpp b/src/mongo/db/exec/idhack.cpp index 366d9f7ca56..6390e109ffc 100644 --- a/src/mongo/db/exec/idhack.cpp +++ b/src/mongo/db/exec/idhack.cpp @@ -37,7 +37,6 @@ #include "mongo/db/exec/working_set_common.h" #include "mongo/db/exec/working_set_computed_data.h" #include "mongo/db/index/btree_access_method.h" -#include "mongo/db/storage/record_fetcher.h" #include "mongo/stdx/memory.h" namespace mongo { @@ -58,8 +57,7 @@ IDHackStage::IDHackStage(OperationContext* opCtx, _collection(collection), _workingSet(ws), _key(query->getQueryObj()["_id"].wrap()), - _done(false), - _idBeingPagedIn(WorkingSet::INVALID_ID) { + _done(false) { const IndexCatalog* catalog = _collection->getIndexCatalog(); _specificStats.indexName = descriptor->indexName(); _accessMethod = catalog->getIndex(descriptor); @@ -81,8 +79,7 @@ IDHackStage::IDHackStage(OperationContext* opCtx, _workingSet(ws), _key(key), _done(false), - _addKeyMetadata(false), - _idBeingPagedIn(WorkingSet::INVALID_ID) { + _addKeyMetadata(false) { const IndexCatalog* catalog = _collection->getIndexCatalog(); _specificStats.indexName = descriptor->indexName(); _accessMethod = catalog->getIndex(descriptor); @@ -91,12 +88,6 @@ IDHackStage::IDHackStage(OperationContext* opCtx, IDHackStage::~IDHackStage() {} bool IDHackStage::isEOF() { - if (WorkingSet::INVALID_ID != _idBeingPagedIn) { - // We asked the parent for a page-in, but still haven't had a chance to return the - // paged in document - return false; - } - return _done; } @@ -105,17 +96,6 @@ PlanStage::StageState IDHackStage::doWork(WorkingSetID* out) { return PlanStage::IS_EOF; } - if (WorkingSet::INVALID_ID != _idBeingPagedIn) { - invariant(_recordCursor); - WorkingSetID id = _idBeingPagedIn; - _idBeingPagedIn = WorkingSet::INVALID_ID; - - invariant(WorkingSetCommon::fetchIfUnfetched(getOpCtx(), _workingSet, id, _recordCursor)); - - WorkingSetMember* member = _workingSet->get(id); - return advance(id, member, out); - } - WorkingSetID id = WorkingSet::INVALID_ID; try { // Look up the key by going directly to the index. @@ -139,20 +119,9 @@ PlanStage::StageState IDHackStage::doWork(WorkingSetID* out) { if (!_recordCursor) _recordCursor = _collection->getCursor(getOpCtx()); - // We may need to request a yield while we fetch the document. - if (auto fetcher = _recordCursor->fetcherForId(recordId)) { - // There's something to fetch. Hand the fetcher off to the WSM, and pass up a - // fetch request. - _idBeingPagedIn = id; - member->setFetcher(fetcher.release()); - *out = id; - return NEED_YIELD; - } - - // The doc was already in memory, so we go ahead and return it. + // Find the document associated with 'id' in the collection's record store. if (!WorkingSetCommon::fetch(getOpCtx(), _workingSet, id, _recordCursor)) { - // _id is immutable so the index would return the only record that could - // possibly match the query. + // We didn't find a document with RecordId 'id'. _workingSet->free(id); _commonStats.isEOF = true; _done = true; diff --git a/src/mongo/db/exec/idhack.h b/src/mongo/db/exec/idhack.h index 16a7982860f..62a2155afc9 100644 --- a/src/mongo/db/exec/idhack.h +++ b/src/mongo/db/exec/idhack.h @@ -113,12 +113,6 @@ private: // Do we need to add index key metadata for returnKey? bool _addKeyMetadata; - // If we want to return a RecordId and it points to something that's not in memory, - // we return a "please page this in" result. We add a RecordFetcher given back to us by the - // storage engine to the WSM. The RecordFetcher is used by the PlanExecutor when it handles - // the fetch request. - WorkingSetID _idBeingPagedIn; - IDHackStats _specificStats; }; diff --git a/src/mongo/db/exec/multi_iterator.cpp b/src/mongo/db/exec/multi_iterator.cpp index 64056ff9c67..2291c11ec82 100644 --- a/src/mongo/db/exec/multi_iterator.cpp +++ b/src/mongo/db/exec/multi_iterator.cpp @@ -32,7 +32,6 @@ #include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/exec/working_set_common.h" -#include "mongo/db/storage/record_fetcher.h" #include "mongo/stdx/memory.h" namespace mongo { @@ -46,10 +45,7 @@ const char* MultiIteratorStage::kStageType = "MULTI_ITERATOR"; MultiIteratorStage::MultiIteratorStage(OperationContext* opCtx, WorkingSet* ws, Collection* collection) - : PlanStage(kStageType, opCtx), - _collection(collection), - _ws(ws), - _wsidForFetch(_ws->allocate()) {} + : PlanStage(kStageType, opCtx), _collection(collection), _ws(ws) {} void MultiIteratorStage::addIterator(unique_ptr<RecordCursor> it) { _iterators.push_back(std::move(it)); @@ -65,14 +61,6 @@ PlanStage::StageState MultiIteratorStage::doWork(WorkingSetID* out) { boost::optional<Record> record; try { while (!_iterators.empty()) { - if (auto fetcher = _iterators.back()->fetcherForNext()) { - // Pass the RecordFetcher off up. - WorkingSetMember* member = _ws->get(_wsidForFetch); - member->setFetcher(fetcher.release()); - *out = _wsidForFetch; - return NEED_YIELD; - } - record = _iterators.back()->next(); if (record) break; diff --git a/src/mongo/db/exec/multi_iterator.h b/src/mongo/db/exec/multi_iterator.h index 78909adc72d..eebcee34972 100644 --- a/src/mongo/db/exec/multi_iterator.h +++ b/src/mongo/db/exec/multi_iterator.h @@ -83,11 +83,6 @@ private: // Not owned by us. WorkingSet* _ws; - - // We allocate a working set member with this id on construction of the stage. It gets used for - // all fetch requests. This should only be used for passing up the Fetcher for a NEED_YIELD, and - // should remain in the INVALID state. - const WorkingSetID _wsidForFetch; }; } // namespace mongo diff --git a/src/mongo/db/exec/multi_plan.cpp b/src/mongo/db/exec/multi_plan.cpp index 4b2d60269f7..fc6834925ea 100644 --- a/src/mongo/db/exec/multi_plan.cpp +++ b/src/mongo/db/exec/multi_plan.cpp @@ -45,7 +45,6 @@ #include "mongo/db/query/explain.h" #include "mongo/db/query/plan_cache.h" #include "mongo/db/query/plan_ranker.h" -#include "mongo/db/storage/record_fetcher.h" #include "mongo/stdx/memory.h" #include "mongo/util/log.h" #include "mongo/util/mongoutils/str.h" @@ -148,11 +147,11 @@ PlanStage::StageState MultiPlanStage::doWork(WorkingSetID* out) { Status MultiPlanStage::tryYield(PlanYieldPolicy* yieldPolicy) { // These are the conditions which can cause us to yield: // 1) The yield policy's timer elapsed, or - // 2) some stage requested a yield due to a document fetch, or + // 2) some stage requested a yield, or // 3) we need to yield and retry due to a WriteConflictException. // In all cases, the actual yielding happens here. if (yieldPolicy->shouldYieldOrInterrupt()) { - auto yieldStatus = yieldPolicy->yieldOrInterrupt(_fetcher.get()); + auto yieldStatus = yieldPolicy->yieldOrInterrupt(); if (!yieldStatus.isOK()) { _failure = true; @@ -162,10 +161,6 @@ Status MultiPlanStage::tryYield(PlanYieldPolicy* yieldPolicy) { } } - // We're done using the fetcher, so it should be freed. We don't want to - // use the same RecordFetcher twice. - _fetcher.reset(); - return Status::OK(); } @@ -371,14 +366,9 @@ bool MultiPlanStage::workAllPlans(size_t numResults, PlanYieldPolicy* yieldPolic // Assumes that the ranking will pick this plan. doneWorking = true; } else if (PlanStage::NEED_YIELD == state) { - if (id == WorkingSet::INVALID_ID) { - if (!yieldPolicy->canAutoYield()) - throw WriteConflictException(); - } else { - WorkingSetMember* member = candidate.ws->get(id); - invariant(member->hasFetcher()); - // Transfer ownership of the fetcher and yield. - _fetcher.reset(member->releaseFetcher()); + invariant(id == WorkingSet::INVALID_ID); + if (!yieldPolicy->canAutoYield()) { + throw WriteConflictException(); } if (yieldPolicy->canAutoYield()) { diff --git a/src/mongo/db/exec/multi_plan.h b/src/mongo/db/exec/multi_plan.h index 5b118653d9a..30c20599332 100644 --- a/src/mongo/db/exec/multi_plan.h +++ b/src/mongo/db/exec/multi_plan.h @@ -220,12 +220,6 @@ private: // returned by ::work() WorkingSetID _statusMemberId; - // When a stage requests a yield for document fetch, it gives us back a RecordFetcher* - // to use to pull the record into memory. We take ownership of the RecordFetcher here, - // deleting it after we've had a chance to do the fetch. For timing-based yields, we - // just pass a NULL fetcher. - std::unique_ptr<RecordFetcher> _fetcher; - // Stats MultiPlanStats _specificStats; }; diff --git a/src/mongo/db/exec/working_set.cpp b/src/mongo/db/exec/working_set.cpp index 0882328c285..e26f194c9be 100644 --- a/src/mongo/db/exec/working_set.cpp +++ b/src/mongo/db/exec/working_set.cpp @@ -31,7 +31,6 @@ #include "mongo/db/bson/dotted_path_support.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/service_context.h" -#include "mongo/db/storage/record_fetcher.h" namespace mongo { @@ -177,18 +176,6 @@ void WorkingSetMember::addComputed(WorkingSetComputedData* data) { _computed[data->type()].reset(data); } -void WorkingSetMember::setFetcher(RecordFetcher* fetcher) { - _fetcher.reset(fetcher); -} - -RecordFetcher* WorkingSetMember::releaseFetcher() { - return _fetcher.release(); -} - -bool WorkingSetMember::hasFetcher() const { - return NULL != _fetcher.get(); -} - bool WorkingSetMember::getFieldDotted(const string& field, BSONElement* out) const { // If our state is such that we have an object, use it. if (hasObj()) { diff --git a/src/mongo/db/exec/working_set.h b/src/mongo/db/exec/working_set.h index 9cc70750638..8efb1e748b8 100644 --- a/src/mongo/db/exec/working_set.h +++ b/src/mongo/db/exec/working_set.h @@ -39,7 +39,6 @@ namespace mongo { class IndexAccessMethod; -class RecordFetcher; class WorkingSetMember; typedef size_t WorkingSetID; @@ -279,15 +278,6 @@ public: const WorkingSetComputedData* getComputed(const WorkingSetComputedDataType type) const; void addComputed(WorkingSetComputedData* data); - // - // Fetching - // - - void setFetcher(RecordFetcher* fetcher); - // Transfers ownership to the caller. - RecordFetcher* releaseFetcher(); - bool hasFetcher() const; - /** * getFieldDotted uses its state (obj or index data) to produce the field with the provided * name. @@ -310,8 +300,6 @@ private: MemberState _state = WorkingSetMember::INVALID; std::unique_ptr<WorkingSetComputedData> _computed[WSM_COMPUTED_NUM_TYPES]; - - std::unique_ptr<RecordFetcher> _fetcher; }; } // namespace mongo diff --git a/src/mongo/db/exec/working_set_common.cpp b/src/mongo/db/exec/working_set_common.cpp index 4439af31ba8..1636e3a631d 100644 --- a/src/mongo/db/exec/working_set_common.cpp +++ b/src/mongo/db/exec/working_set_common.cpp @@ -60,9 +60,6 @@ bool WorkingSetCommon::fetch(OperationContext* opCtx, unowned_ptr<SeekableRecordCursor> cursor) { WorkingSetMember* member = workingSet->get(id); - // The RecordFetcher should already have been transferred out of the WSM and used. - invariant(!member->hasFetcher()); - // We should have a RecordId but need to retrieve the obj. Get the obj now and reset all WSM // state appropriately. invariant(member->hasRecordId()); diff --git a/src/mongo/db/exec/working_set_common.h b/src/mongo/db/exec/working_set_common.h index 5f35dffb878..f233fb88d30 100644 --- a/src/mongo/db/exec/working_set_common.h +++ b/src/mongo/db/exec/working_set_common.h @@ -66,16 +66,6 @@ public: WorkingSetID id, unowned_ptr<SeekableRecordCursor> cursor); - static bool fetchIfUnfetched(OperationContext* opCtx, - WorkingSet* workingSet, - WorkingSetID id, - unowned_ptr<SeekableRecordCursor> cursor) { - WorkingSetMember* member = workingSet->get(id); - if (member->hasObj()) - return true; - return fetch(opCtx, workingSet, id, cursor); - } - /** * Build a BSONObj which represents a Status to return in a WorkingSet. */ diff --git a/src/mongo/db/query/mock_yield_policies.h b/src/mongo/db/query/mock_yield_policies.h index dc3f5c1ef26..b1f03e316c8 100644 --- a/src/mongo/db/query/mock_yield_policies.h +++ b/src/mongo/db/query/mock_yield_policies.h @@ -49,12 +49,7 @@ public: return true; } - Status yieldOrInterrupt(RecordFetcher* recordFetcher) override { - return {ErrorCodes::ExceededTimeLimit, "Using AlwaysTimeOutYieldPolicy"}; - } - - Status yieldOrInterrupt(stdx::function<void()> beforeYieldingFn, - stdx::function<void()> whileYieldingFn) override { + Status yieldOrInterrupt(stdx::function<void()> whileYieldingFn) override { return {ErrorCodes::ExceededTimeLimit, "Using AlwaysTimeOutYieldPolicy"}; } }; @@ -75,12 +70,7 @@ public: return true; } - Status yieldOrInterrupt(RecordFetcher* recordFetcher) override { - return {ErrorCodes::QueryPlanKilled, "Using AlwaysPlanKilledYieldPolicy"}; - } - - Status yieldOrInterrupt(stdx::function<void()> beforeYieldingFn, - stdx::function<void()> whileYieldingFn) override { + Status yieldOrInterrupt(stdx::function<void()> whileYieldingFn) override { return {ErrorCodes::QueryPlanKilled, "Using AlwaysPlanKilledYieldPolicy"}; } }; diff --git a/src/mongo/db/query/plan_executor.cpp b/src/mongo/db/query/plan_executor.cpp index 046b6e67256..98b2254ee1d 100644 --- a/src/mongo/db/query/plan_executor.cpp +++ b/src/mongo/db/query/plan_executor.cpp @@ -52,7 +52,6 @@ #include "mongo/db/query/plan_yield_policy.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/service_context.h" -#include "mongo/db/storage/record_fetcher.h" #include "mongo/stdx/memory.h" #include "mongo/util/fail_point_service.h" #include "mongo/util/log.h" @@ -471,7 +470,7 @@ PlanExecutor::ExecState PlanExecutor::waitForInserts(CappedInsertNotifierData* n ON_BLOCK_EXIT([curOp] { curOp->resumeTimer(); }); auto opCtx = _opCtx; uint64_t currentNotifierVersion = notifierData->notifier->getVersion(); - auto yieldResult = _yieldPolicy->yieldOrInterrupt(nullptr, [opCtx, notifierData] { + auto yieldResult = _yieldPolicy->yieldOrInterrupt([opCtx, notifierData] { const auto deadline = awaitDataState(opCtx).waitForInsertsDeadline; notifierData->notifier->waitUntil(notifierData->lastEOFVersion, deadline); }); @@ -515,12 +514,6 @@ PlanExecutor::ExecState PlanExecutor::getNextImpl(Snapshotted<BSONObj>* objOut, return PlanExecutor::ADVANCED; } - // When a stage requests a yield for document fetch, it gives us back a RecordFetcher* - // to use to pull the record into memory. We take ownership of the RecordFetcher here, - // deleting it after we've had a chance to do the fetch. For timing-based yields, we - // just pass a NULL fetcher. - unique_ptr<RecordFetcher> fetcher; - // Incremented on every writeConflict, reset to 0 on any successful call to _root->work. size_t writeConflictsInARow = 0; @@ -535,11 +528,11 @@ PlanExecutor::ExecState PlanExecutor::getNextImpl(Snapshotted<BSONObj>* objOut, for (;;) { // These are the conditions which can cause us to yield: // 1) The yield policy's timer elapsed, or - // 2) some stage requested a yield due to a document fetch, or + // 2) some stage requested a yield, or // 3) we need to yield and retry due to a WriteConflictException. // In all cases, the actual yielding happens here. if (_yieldPolicy->shouldYieldOrInterrupt()) { - auto yieldStatus = _yieldPolicy->yieldOrInterrupt(fetcher.get()); + auto yieldStatus = _yieldPolicy->yieldOrInterrupt(); if (!yieldStatus.isOK()) { if (objOut) { *objOut = Snapshotted<BSONObj>( @@ -549,10 +542,6 @@ PlanExecutor::ExecState PlanExecutor::getNextImpl(Snapshotted<BSONObj>* objOut, } } - // We're done using the fetcher, so it should be freed. We don't want to - // use the same RecordFetcher twice. - fetcher.reset(); - WorkingSetID id = WorkingSet::INVALID_ID; PlanStage::StageState code = _root->work(&id); @@ -596,25 +585,20 @@ PlanExecutor::ExecState PlanExecutor::getNextImpl(Snapshotted<BSONObj>* objOut, } // This result didn't have the data the caller wanted, try again. } else if (PlanStage::NEED_YIELD == code) { - if (id == WorkingSet::INVALID_ID) { - if (!_yieldPolicy->canAutoYield()) - throw WriteConflictException(); - CurOp::get(_opCtx)->debug().additiveMetrics.incrementWriteConflicts(1); - writeConflictsInARow++; - WriteConflictException::logAndBackoff( - writeConflictsInARow, "plan execution", _nss.ns()); - - } else { - WorkingSetMember* member = _workingSet->get(id); - invariant(member->hasFetcher()); - // Transfer ownership of the fetcher. Next time around the loop a yield will - // happen. - fetcher.reset(member->releaseFetcher()); + invariant(id == WorkingSet::INVALID_ID); + if (!_yieldPolicy->canAutoYield()) { + throw WriteConflictException(); } + CurOp::get(_opCtx)->debug().additiveMetrics.incrementWriteConflicts(1); + writeConflictsInARow++; + WriteConflictException::logAndBackoff( + writeConflictsInARow, "plan execution", _nss.ns()); + // If we're allowed to, we will yield next time through the loop. - if (_yieldPolicy->canAutoYield()) + if (_yieldPolicy->canAutoYield()) { _yieldPolicy->forceYield(); + } } else if (PlanStage::NEED_TIME == code) { // Fall through to yield check at end of large conditional. } else if (PlanStage::IS_EOF == code) { diff --git a/src/mongo/db/query/plan_yield_policy.cpp b/src/mongo/db/query/plan_yield_policy.cpp index 6d493d40e4d..ef66ad9f4f4 100644 --- a/src/mongo/db/query/plan_yield_policy.cpp +++ b/src/mongo/db/query/plan_yield_policy.cpp @@ -85,19 +85,9 @@ void PlanYieldPolicy::resetTimer() { _elapsedTracker.resetLastTime(); } -Status PlanYieldPolicy::yieldOrInterrupt(RecordFetcher* recordFetcher) { +Status PlanYieldPolicy::yieldOrInterrupt(stdx::function<void()> whileYieldingFn) { invariant(_planYielding); - if (recordFetcher) { - OperationContext* opCtx = _planYielding->getOpCtx(); - return yieldOrInterrupt([recordFetcher, opCtx] { recordFetcher->setup(opCtx); }, - [recordFetcher] { recordFetcher->fetch(); }); - } else { - return yieldOrInterrupt(nullptr, nullptr); - } -} -Status PlanYieldPolicy::yieldOrInterrupt(stdx::function<void()> beforeYieldingFn, - stdx::function<void()> whileYieldingFn) { if (_policy == PlanExecutor::INTERRUPT_ONLY) { ON_BLOCK_EXIT([this]() { resetTimer(); }); OperationContext* opCtx = _planYielding->getOpCtx(); @@ -114,11 +104,10 @@ Status PlanYieldPolicy::yieldOrInterrupt(stdx::function<void()> beforeYieldingFn return opCtx->checkForInterruptNoAssert(); } - return yield(beforeYieldingFn, whileYieldingFn); + return yield(whileYieldingFn); } -Status PlanYieldPolicy::yield(stdx::function<void()> beforeYieldingFn, - stdx::function<void()> whileYieldingFn) { +Status PlanYieldPolicy::yield(stdx::function<void()> whileYieldingFn) { invariant(_planYielding); invariant(canAutoYield()); @@ -157,8 +146,6 @@ Status PlanYieldPolicy::yield(stdx::function<void()> beforeYieldingFn, opCtx->recoveryUnit()->abandonSnapshot(); } else { // Release and reacquire locks. - if (beforeYieldingFn) - beforeYieldingFn(); QueryYield::yieldAllLocks(opCtx, whileYieldingFn, _planYielding->nss()); } diff --git a/src/mongo/db/query/plan_yield_policy.h b/src/mongo/db/query/plan_yield_policy.h index 80be6e11095..1f311cb803c 100644 --- a/src/mongo/db/query/plan_yield_policy.h +++ b/src/mongo/db/query/plan_yield_policy.h @@ -36,7 +36,6 @@ namespace mongo { class ClockSource; -class RecordFetcher; class PlanYieldPolicy { public: @@ -69,23 +68,14 @@ public: * plans). The PlanExecutor must *not* be in saved state. Handles calls to save/restore state * internally. * - * If 'fetcher' is non-NULL, then we are yielding because the storage engine told us - * that we will page fault on this record. We use 'fetcher' to retrieve the record - * after we give up our locks. - * * Returns Status::OK() if the executor was restored successfully and is still alive. Returns * ErrorCodes::QueryPlanKilled if the executor got killed during yield, and * ErrorCodes::ExceededTimeLimit if the operation has exceeded the time limit. + * + * Calls 'whileYieldingFn' after relinquishing locks and before reacquiring the locks that have + * been relinquished. */ - virtual Status yieldOrInterrupt(RecordFetcher* fetcher = nullptr); - - /** - * More generic version of yieldOrInterrupt() above. This version calls 'beforeYieldingFn' - * immediately before locks are yielded (if they are), and 'whileYieldingFn' before locks are - * restored. - */ - virtual Status yieldOrInterrupt(stdx::function<void()> beforeYieldingFn, - stdx::function<void()> whileYieldingFn); + virtual Status yieldOrInterrupt(stdx::function<void()> whileYieldingFn = nullptr); /** * All calls to shouldYieldOrInterrupt() will return true until the next call to @@ -157,7 +147,7 @@ private: bool shouldYield(); // Releases locks or storage engine state. - Status yield(stdx::function<void()> beforeYieldingFn, stdx::function<void()> whileYieldingFn); + Status yield(stdx::function<void()> whileYieldingFn); }; } // namespace mongo diff --git a/src/mongo/db/query/query_yield.cpp b/src/mongo/db/query/query_yield.cpp index 66397c409ca..b14e8c3b5b2 100644 --- a/src/mongo/db/query/query_yield.cpp +++ b/src/mongo/db/query/query_yield.cpp @@ -32,7 +32,6 @@ #include "mongo/bson/bsonobj.h" #include "mongo/db/curop.h" #include "mongo/db/operation_context.h" -#include "mongo/db/storage/record_fetcher.h" #include "mongo/util/fail_point_service.h" #include "mongo/util/time_support.h" diff --git a/src/mongo/db/query/query_yield.h b/src/mongo/db/query/query_yield.h index a4fbba72fe7..6e318fb962a 100644 --- a/src/mongo/db/query/query_yield.h +++ b/src/mongo/db/query/query_yield.h @@ -34,7 +34,6 @@ namespace mongo { class OperationContext; -class RecordFetcher; /** * See the documentation for yieldAllLocks(...). diff --git a/src/mongo/db/storage/record_fetcher.h b/src/mongo/db/storage/record_fetcher.h deleted file mode 100644 index 0c8d5f18080..00000000000 --- a/src/mongo/db/storage/record_fetcher.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (C) 2014 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#pragma once - -namespace mongo { - -class OperationContext; - -/** - * Used for yielding while data is fetched from disk. - * - * @see RecordStore::recordNeedsFetch - */ -class RecordFetcher { -public: - virtual ~RecordFetcher() {} - - /** - * Performs any setup which is needed prior to yielding locks. - */ - virtual void setup(OperationContext* opCtx) = 0; - - /** - * Called after locks are yielded in order to bring data into memory. - * - * Should not be called more than once. - */ - virtual void fetch() = 0; -}; - -} // namespace mongo diff --git a/src/mongo/db/storage/record_store.h b/src/mongo/db/storage/record_store.h index 178574f43ab..308bab5992f 100644 --- a/src/mongo/db/storage/record_store.h +++ b/src/mongo/db/storage/record_store.h @@ -37,7 +37,6 @@ #include "mongo/db/exec/collection_scan_common.h" #include "mongo/db/record_id.h" #include "mongo/db/storage/record_data.h" -#include "mongo/db/storage/record_fetcher.h" namespace mongo { @@ -48,7 +47,6 @@ struct CompactStats; class MAdvise; class NamespaceDetails; class OperationContext; -class RecordFetcher; class RecordStoreCompactAdaptor; class RecordStore; @@ -183,27 +181,6 @@ public: * "saved" state, so callers must still call restoreState to use this object. */ virtual void reattachToOperationContext(OperationContext* opCtx) = 0; - - // - // RecordFetchers - // - // Storage engines which do not support document-level locking hold locks at collection or - // database granularity. As an optimization, these locks can be yielded when a record needs - // to be fetched from secondary storage. If this method returns non-NULL, then it indicates - // that the query system layer should yield its locks, following the protocol defined by the - // RecordFetcher class, so that a potential page fault is triggered out of the lock. - // - // Storage engines which support document-level locking need not implement this. - // - // TODO see if these can be replaced by WriteConflictException. - // - - /** - * Returns a RecordFetcher if needed for a call to next() or none if unneeded. - */ - virtual std::unique_ptr<RecordFetcher> fetcherForNext() const { - return {}; - } }; /** @@ -238,13 +215,6 @@ public: virtual void saveUnpositioned() { save(); } - - /** - * Returns a RecordFetcher if needed to fetch the provided Record or none if unneeded. - */ - virtual std::unique_ptr<RecordFetcher> fetcherForId(const RecordId& id) const { - return {}; - } }; /** |