summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/catalog/collection.cpp1
-rw-r--r--src/mongo/db/catalog/collection.h1
-rw-r--r--src/mongo/db/catalog/collection_impl.cpp1
-rw-r--r--src/mongo/db/exec/cached_plan.cpp20
-rw-r--r--src/mongo/db/exec/cached_plan.h7
-rw-r--r--src/mongo/db/exec/collection_scan.cpp14
-rw-r--r--src/mongo/db/exec/collection_scan.h5
-rw-r--r--src/mongo/db/exec/fetch.cpp15
-rw-r--r--src/mongo/db/exec/idhack.cpp39
-rw-r--r--src/mongo/db/exec/idhack.h6
-rw-r--r--src/mongo/db/exec/multi_iterator.cpp14
-rw-r--r--src/mongo/db/exec/multi_iterator.h5
-rw-r--r--src/mongo/db/exec/multi_plan.cpp20
-rw-r--r--src/mongo/db/exec/multi_plan.h6
-rw-r--r--src/mongo/db/exec/working_set.cpp13
-rw-r--r--src/mongo/db/exec/working_set.h12
-rw-r--r--src/mongo/db/exec/working_set_common.cpp3
-rw-r--r--src/mongo/db/exec/working_set_common.h10
-rw-r--r--src/mongo/db/query/mock_yield_policies.h14
-rw-r--r--src/mongo/db/query/plan_executor.cpp42
-rw-r--r--src/mongo/db/query/plan_yield_policy.cpp19
-rw-r--r--src/mongo/db/query/plan_yield_policy.h20
-rw-r--r--src/mongo/db/query/query_yield.cpp1
-rw-r--r--src/mongo/db/query/query_yield.h1
-rw-r--r--src/mongo/db/storage/record_fetcher.h57
-rw-r--r--src/mongo/db/storage/record_store.h30
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 {};
- }
};
/**