summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2016-02-24 15:44:48 -0500
committerDavid Storch <david.storch@10gen.com>2016-02-25 16:54:00 -0500
commit5149712212bd52eec0d511779427fd95781d7838 (patch)
treead5669c6e0b10e44b254b7e1ae0e7589d1632853
parent28c90fe01b494a3920a591096a0377706a6707bf (diff)
downloadmongo-5149712212bd52eec0d511779427fd95781d7838.tar.gz
SERVER-22793 clear buffered WorkingSetIDs on storage engines without document-level concurrency
This ensures that the set of WorkingSetIDs does not grow without bound on MMAPv1. (cherry picked from commit aaa5074a59327cdd2d0a462bb27c98f1c1c3ec6a)
-rw-r--r--src/mongo/db/exec/delete.cpp6
-rw-r--r--src/mongo/db/exec/update.cpp6
-rw-r--r--src/mongo/db/exec/working_set_common.cpp8
-rw-r--r--src/mongo/db/query/plan_executor.cpp5
4 files changed, 10 insertions, 15 deletions
diff --git a/src/mongo/db/exec/delete.cpp b/src/mongo/db/exec/delete.cpp
index 9db64a9ea20..d0dad6e0db2 100644
--- a/src/mongo/db/exec/delete.cpp
+++ b/src/mongo/db/exec/delete.cpp
@@ -197,11 +197,7 @@ PlanStage::StageState DeleteStage::work(WorkingSetID* out) {
// saving/restoring state repeatedly?
try {
- if (supportsDocLocking()) {
- // Doc-locking engines require this before saveState() since they don't use
- // invalidations.
- WorkingSetCommon::prepareForSnapshotChange(_ws);
- }
+ WorkingSetCommon::prepareForSnapshotChange(_ws);
child()->saveState();
} catch (const WriteConflictException& wce) {
std::terminate();
diff --git a/src/mongo/db/exec/update.cpp b/src/mongo/db/exec/update.cpp
index 0e768074d80..65af0e1a24d 100644
--- a/src/mongo/db/exec/update.cpp
+++ b/src/mongo/db/exec/update.cpp
@@ -877,11 +877,7 @@ PlanStage::StageState UpdateStage::work(WorkingSetID* out) {
// Save state before making changes
try {
- if (supportsDocLocking()) {
- // Doc-locking engines require this before saveState() since they don't use
- // invalidations.
- WorkingSetCommon::prepareForSnapshotChange(_ws);
- }
+ WorkingSetCommon::prepareForSnapshotChange(_ws);
child()->saveState();
} catch (const WriteConflictException& wce) {
std::terminate();
diff --git a/src/mongo/db/exec/working_set_common.cpp b/src/mongo/db/exec/working_set_common.cpp
index db5ed4aa8ba..5a0fbf115f2 100644
--- a/src/mongo/db/exec/working_set_common.cpp
+++ b/src/mongo/db/exec/working_set_common.cpp
@@ -63,7 +63,13 @@ bool WorkingSetCommon::fetchAndInvalidateLoc(OperationContext* txn,
}
void WorkingSetCommon::prepareForSnapshotChange(WorkingSet* workingSet) {
- dassert(supportsDocLocking());
+ if (!supportsDocLocking()) {
+ // Non doc-locking storage engines use invalidations, so we don't need to examine the
+ // buffered working set ids. But we do need to clear the set of ids in order to keep our
+ // memory utilization in check.
+ workingSet->getAndClearYieldSensitiveIds();
+ return;
+ }
for (auto id : workingSet->getAndClearYieldSensitiveIds()) {
if (workingSet->isFree(id)) {
diff --git a/src/mongo/db/query/plan_executor.cpp b/src/mongo/db/query/plan_executor.cpp
index 78f9dad20ce..c477fad2a02 100644
--- a/src/mongo/db/query/plan_executor.cpp
+++ b/src/mongo/db/query/plan_executor.cpp
@@ -254,13 +254,10 @@ OperationContext* PlanExecutor::getOpCtx() const {
void PlanExecutor::saveState() {
invariant(_currentState == kUsable || _currentState == kSaved);
- // Doc-locking storage engines drop their transactional context after saving state.
// The query stages inside this stage tree might buffer record ids (e.g. text, geoNear,
// mergeSort, sort) which are no longer protected by the storage engine's transactional
// boundaries.
- if (supportsDocLocking()) {
- WorkingSetCommon::prepareForSnapshotChange(_workingSet.get());
- }
+ WorkingSetCommon::prepareForSnapshotChange(_workingSet.get());
if (!killed()) {
_root->saveState();