summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec/fetch.cpp
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2014-10-29 18:56:51 -0400
committerDavid Storch <david.storch@10gen.com>2014-11-04 14:24:14 -0500
commitc8012ebc991cd4db85e63c4c61883aef3b793498 (patch)
tree9a0b3fbd3f1b4049b103b95690caaf3db2a9dc0d /src/mongo/db/exec/fetch.cpp
parentd5f6eb21a94a39bd39c3c7a7b0ac107aca33a7e4 (diff)
downloadmongo-c8012ebc991cd4db85e63c4c61883aef3b793498.tar.gz
SERVER-15665 MMAP v1 requests yields during page faults via NEED_FETCH
Diffstat (limited to 'src/mongo/db/exec/fetch.cpp')
-rw-r--r--src/mongo/db/exec/fetch.cpp67
1 files changed, 58 insertions, 9 deletions
diff --git a/src/mongo/db/exec/fetch.cpp b/src/mongo/db/exec/fetch.cpp
index de7e5b2000b..b1bde6dafc4 100644
--- a/src/mongo/db/exec/fetch.cpp
+++ b/src/mongo/db/exec/fetch.cpp
@@ -32,6 +32,7 @@
#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/util/fail_point_service.h"
#include "mongo/util/mongoutils/str.h"
@@ -50,11 +51,18 @@ namespace mongo {
_ws(ws),
_child(child),
_filter(filter),
+ _idBeingPagedIn(WorkingSet::INVALID_ID),
_commonStats(kStageType) { }
FetchStage::~FetchStage() { }
bool FetchStage::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 _child->isEOF();
}
@@ -66,6 +74,17 @@ namespace mongo {
if (isEOF()) { return PlanStage::IS_EOF; }
+ // We might have a fetched result to return.
+ if (WorkingSet::INVALID_ID != _idBeingPagedIn) {
+ WorkingSetID id = _idBeingPagedIn;
+ _idBeingPagedIn = WorkingSet::INVALID_ID;
+ WorkingSetMember* member = _ws->get(id);
+
+ WorkingSetCommon::completeFetch(_txn, member, _collection);
+
+ return returnIfMatches(member, id, out);
+ }
+
// If we're here, we're not waiting for a DiskLoc to be fetched. Get another to-be-fetched
// result from our child.
WorkingSetID id = WorkingSet::INVALID_ID;
@@ -83,14 +102,29 @@ namespace mongo {
verify(WorkingSetMember::LOC_AND_IDX == member->state);
verify(member->hasLoc());
- // Don't need index data anymore as we have an obj.
- member->keyData.clear();
+ // We might need to retrieve 'nextLoc' from secondary storage, in which case we send
+ // a NEED_FETCH request up to the PlanExecutor.
+ if (!member->loc.isNull()) {
+ std::auto_ptr<RecordFetcher> fetcher(
+ _collection->documentNeedsFetch(_txn, member->loc));
+ if (NULL != fetcher.get()) {
+ // 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;
+ _commonStats.needFetch++;
+ return NEED_FETCH;
+ }
+ }
+
+ // The doc is already in memory, so go ahead and grab it. Now we have a DiskLoc
+ // as well as an unowned object
member->obj = _collection->docFor(_txn, member->loc);
+ member->keyData.clear();
member->state = WorkingSetMember::LOC_AND_UNOWNED_OBJ;
}
- ++_specificStats.docsExamined;
-
return returnIfMatches(member, id, out);
}
else if (PlanStage::FAILURE == status) {
@@ -106,12 +140,15 @@ namespace mongo {
}
return status;
}
- else {
- if (PlanStage::NEED_TIME == status) {
- ++_commonStats.needTime;
- }
- return status;
+ else if (PlanStage::NEED_TIME == status) {
+ ++_commonStats.needTime;
+ }
+ else if (PlanStage::NEED_FETCH == status) {
+ ++_commonStats.needFetch;
+ *out = id;
}
+
+ return status;
}
void FetchStage::saveState() {
@@ -129,11 +166,23 @@ namespace mongo {
++_commonStats.invalidates;
_child->invalidate(dl, type);
+
+ // It's possible that the loc getting invalidated is the one we're about to
+ // fetch. In this case we do a "forced fetch" and put the WSM in owned object state.
+ if (WorkingSet::INVALID_ID != _idBeingPagedIn) {
+ WorkingSetMember* member = _ws->get(_idBeingPagedIn);
+ if (member->hasLoc() && (member->loc == dl)) {
+ // Fetch it now and kill the diskloc.
+ WorkingSetCommon::fetchAndInvalidateLoc(_txn, member, _collection);
+ }
+ }
}
PlanStage::StageState FetchStage::returnIfMatches(WorkingSetMember* member,
WorkingSetID memberID,
WorkingSetID* out) {
+ ++_specificStats.docsExamined;
+
if (Filter::passes(member, _filter)) {
if (NULL != _filter) {
++_specificStats.matchTested;