summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/clientcursor.cpp31
-rw-r--r--src/mongo/db/clientcursor.h81
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp1
-rw-r--r--src/mongo/db/commands/pipeline_command.cpp2
-rw-r--r--src/mongo/db/exec/2d.cpp2
-rw-r--r--src/mongo/db/exec/2d.h2
-rw-r--r--src/mongo/db/exec/2dnear.cpp2
-rw-r--r--src/mongo/db/exec/2dnear.h2
-rw-r--r--src/mongo/db/exec/and_hash.cpp4
-rw-r--r--src/mongo/db/exec/and_hash.h2
-rw-r--r--src/mongo/db/exec/and_sorted.cpp4
-rw-r--r--src/mongo/db/exec/and_sorted.h2
-rw-r--r--src/mongo/db/exec/collection_scan.cpp4
-rw-r--r--src/mongo/db/exec/collection_scan.h2
-rw-r--r--src/mongo/db/exec/fetch.cpp4
-rw-r--r--src/mongo/db/exec/fetch.h2
-rw-r--r--src/mongo/db/exec/index_scan.cpp2
-rw-r--r--src/mongo/db/exec/index_scan.h2
-rw-r--r--src/mongo/db/exec/limit.cpp4
-rw-r--r--src/mongo/db/exec/limit.h2
-rw-r--r--src/mongo/db/exec/merge_sort.cpp4
-rw-r--r--src/mongo/db/exec/merge_sort.h2
-rw-r--r--src/mongo/db/exec/mock_stage.h2
-rw-r--r--src/mongo/db/exec/oplogstart.cpp7
-rw-r--r--src/mongo/db/exec/oplogstart.h2
-rw-r--r--src/mongo/db/exec/or.cpp4
-rw-r--r--src/mongo/db/exec/or.h2
-rw-r--r--src/mongo/db/exec/plan_stage.h3
-rw-r--r--src/mongo/db/exec/projection.cpp4
-rw-r--r--src/mongo/db/exec/projection.h2
-rw-r--r--src/mongo/db/exec/s2near.cpp4
-rw-r--r--src/mongo/db/exec/s2near.h2
-rw-r--r--src/mongo/db/exec/shard_filter.cpp4
-rw-r--r--src/mongo/db/exec/shard_filter.h2
-rw-r--r--src/mongo/db/exec/skip.cpp4
-rw-r--r--src/mongo/db/exec/skip.h2
-rw-r--r--src/mongo/db/exec/sort.cpp4
-rw-r--r--src/mongo/db/exec/sort.h2
-rw-r--r--src/mongo/db/exec/text.cpp2
-rw-r--r--src/mongo/db/exec/text.h2
-rw-r--r--src/mongo/db/instance.cpp1
-rw-r--r--src/mongo/db/invalidation_type.h42
-rw-r--r--src/mongo/db/ops/update.cpp4
-rw-r--r--src/mongo/db/query/cached_plan_runner.cpp6
-rw-r--r--src/mongo/db/query/cached_plan_runner.h2
-rw-r--r--src/mongo/db/query/eof_runner.cpp2
-rw-r--r--src/mongo/db/query/eof_runner.h2
-rw-r--r--src/mongo/db/query/idhack_runner.cpp4
-rw-r--r--src/mongo/db/query/idhack_runner.h2
-rw-r--r--src/mongo/db/query/internal_runner.cpp4
-rw-r--r--src/mongo/db/query/internal_runner.h2
-rw-r--r--src/mongo/db/query/multi_plan_runner.cpp8
-rw-r--r--src/mongo/db/query/multi_plan_runner.h2
-rw-r--r--src/mongo/db/query/plan_executor.cpp4
-rw-r--r--src/mongo/db/query/plan_executor.h2
-rw-r--r--src/mongo/db/query/runner.h11
-rw-r--r--src/mongo/db/query/single_solution_runner.cpp4
-rw-r--r--src/mongo/db/query/single_solution_runner.h2
-rw-r--r--src/mongo/db/structure/collection.cpp9
-rw-r--r--src/mongo/dbtests/query_stage_and.cpp6
-rw-r--r--src/mongo/dbtests/query_stage_collscan.cpp4
-rw-r--r--src/mongo/dbtests/query_stage_fetch.cpp2
-rw-r--r--src/mongo/dbtests/query_stage_merge_sort.cpp2
-rw-r--r--src/mongo/dbtests/query_stage_sort.cpp4
64 files changed, 173 insertions, 175 deletions
diff --git a/src/mongo/db/clientcursor.cpp b/src/mongo/db/clientcursor.cpp
index c30a73a2ddd..643d1f4aafd 100644
--- a/src/mongo/db/clientcursor.cpp
+++ b/src/mongo/db/clientcursor.cpp
@@ -123,18 +123,6 @@ namespace mongo {
}
}
- // static
- void ClientCursor::assertNoCursors() {
- recursive_scoped_lock lock(ccmutex);
- if (clientCursorsById.size() > 0) {
- log() << "ERROR clientcursors exist but should not at this point" << endl;
- ClientCursor *cc = clientCursorsById.begin()->second;
- log() << "first one: " << cc->_cursorid << ' ' << cc->_ns << endl;
- clientCursorsById.clear();
- verify(false);
- }
- }
-
void ClientCursor::invalidate(const StringData& ns) {
Lock::assertWriteLocked(ns);
@@ -223,19 +211,16 @@ namespace mongo {
}
}
- /* must call this on a delete so we clean up the cursors. */
- void ClientCursor::aboutToDelete(const StringData& ns,
- const NamespaceDetails* nsd,
- const DiskLoc& dl) {
- // Begin cursor-only
+ void ClientCursor::invalidateDocument(const StringData& ns,
+ const NamespaceDetails* nsd,
+ const DiskLoc& dl,
+ InvalidationType type) {
+ // TODO: Do we need this pagefault thing still
NoPageFaultsAllowed npfa;
- // End cursor-only
-
recursive_scoped_lock lock(ccmutex);
Database *db = cc().database();
verify(db);
-
aboutToDeleteForSharding( ns, db, nsd, dl );
// Check our non-cached active runner list.
@@ -244,7 +229,7 @@ namespace mongo {
Runner* runner = *it;
if (0 == ns.compare(runner->ns())) {
- runner->invalidate(dl);
+ runner->invalidate(dl, type);
}
}
@@ -262,7 +247,7 @@ namespace mongo {
// We're only interested in cursors over one db.
if (cc->_db != db) { continue; }
if (NULL == cc->_runner.get()) { continue; }
- cc->_runner->invalidate(dl);
+ cc->_runner->invalidate(dl, type);
}
}
@@ -341,7 +326,7 @@ namespace mongo {
CurOp * c = cc().curop();
while ( c->parent() )
c = c->parent();
- warning() << "ClientCursor::yield can't unlock b/c of recursive lock"
+ warning() << "ClientCursor::staticYield can't unlock b/c of recursive lock"
<< " ns: " << ns
<< " top: " << c->info()
<< endl;
diff --git a/src/mongo/db/clientcursor.h b/src/mongo/db/clientcursor.h
index 02bcc9a1d91..6385d20782d 100644
--- a/src/mongo/db/clientcursor.h
+++ b/src/mongo/db/clientcursor.h
@@ -28,20 +28,15 @@
#pragma once
-#include "mongo/pch.h"
-
#include <boost/thread/recursive_mutex.hpp>
#include "mongo/db/diskloc.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/keypattern.h"
-#include "mongo/db/matcher.h"
-#include "mongo/db/projection.h"
#include "mongo/db/query/runner.h"
#include "mongo/s/collection_metadata.h"
-#include "mongo/util/net/message.h"
#include "mongo/util/background.h"
-#include "mongo/util/elapsed_tracker.h"
+#include "mongo/util/net/message.h"
namespace mongo {
@@ -67,22 +62,16 @@ namespace mongo {
~ClientCursor();
- /**
- * Assert that there are no open cursors.
- * Called from DatabaseHolder::closeAll.
- */
- static void assertNoCursors();
-
//
// Basic accessors
//
CursorId cursorid() const { return _cursorid; }
string ns() const { return _ns; }
- Database * db() const { return _db; }
+ Database* db() const { return _db; }
//
- // Invalidation of DiskLocs and dropping of namespaces
+ // Mutation/Invalidation of DiskLocs and dropping of namespaces
//
/**
@@ -92,12 +81,19 @@ namespace mongo {
static void invalidate(const StringData& ns);
/**
- * Called when the provided DiskLoc is about to change state via a deletion or an update.
- * All runners/cursors that might be using that DiskLoc must adapt.
+ * Broadcast a document invalidation to all relevant Runner(s).
+ *
+ * If the type is INVALIDATION_DELETION, invalidateDocument must called *before* the
+ * provided DiskLoc is about to be deleted.
+ *
+ * If the type is INVALIDATION_MUTATION, invalidateDocument must be called *after* the
+ * provided DiskLoc is mutated. All in-progress queries that hold that DiskLoc as state
+ * must adapt.
*/
- static void aboutToDelete(const StringData& ns,
- const NamespaceDetails* nsd,
- const DiskLoc& dl);
+ static void invalidateDocument(const StringData& ns,
+ const NamespaceDetails* nsd,
+ const DiskLoc& dl,
+ InvalidationType type);
/**
* Register a runner so that it can be notified of deletion/invalidation during yields.
@@ -116,6 +112,7 @@ namespace mongo {
//
static void staticYield(int micros, const StringData& ns, const Record* rec);
+ static int suggestYieldMicros();
//
// Static methods about all ClientCursors TODO: Document.
@@ -177,7 +174,6 @@ namespace mongo {
// Sharding-specific data. TODO: Document.
//
- // future getMore.
void setCollMetadata( CollectionMetadataPtr metadata ){ _collMetadata = metadata; }
CollectionMetadataPtr getCollMetadata(){ return _collMetadata; }
@@ -202,43 +198,6 @@ namespace mongo {
void incPos(int n) { _pos += n; }
void setPos(int n) { _pos = n; }
- //
- // Yielding that is DEPRECATED. Will be removed when we use runners and they yield
- // internally.
- //
-
- /**
- * DEPRECATED
- * @param microsToSleep -1 : ask client
- * 0 : pthread_yield or equivilant
- * >0 : sleep for that amount
- * @param recordToLoad after yielding lock, load this record with only mmutex
- * do a dbtemprelease
- * note: caller should check matcher.docMatcher().atomic() first and not yield if atomic -
- * we don't do herein as this->matcher (above) is only initialized for true queries/getmore.
- * (ie not set for remote/update)
- * @return if the cursor is still valid.
- * if false is returned, then this ClientCursor should be considered deleted -
- * in fact, the whole database could be gone.
- */
- bool yield( int microsToSleep = -1, Record * recordToLoad = 0 );
-
- enum RecordNeeds {
- DontNeed = -1 , MaybeCovered = 0 , WillNeed = 100
- };
-
- /**
- * @param needRecord whether or not the next record has to be read from disk for sure
- * if this is true, will yield of next record isn't in memory
- * @param yielded true if a yield occurred, and potentially if a yield did not occur
- * @return same as yield()
- */
- bool yieldSometimes( RecordNeeds need, bool *yielded = 0 );
- struct YieldData { CursorId _id; bool _doingDeletes; };
- bool prepareToYield( YieldData &data );
- static bool recoverFromYield( const YieldData &data );
- static int suggestYieldMicros();
-
/**
* Is this ClientCursor backed by an aggregation pipeline. Defaults to false.
*
@@ -250,9 +209,7 @@ namespace mongo {
bool isAggCursor;
private:
- friend class ClientCursorHolder;
friend class ClientCursorPin;
- friend struct ClientCursorYieldLock;
friend class CmdCursorInfo;
// A map from the CursorId to the ClientCursor behind it.
@@ -275,8 +232,7 @@ namespace mongo {
static boost::recursive_mutex& ccmutex;
/**
- * Initialization common between Cursor and Runner.
- * TODO: Remove when we're all-runner.
+ * Initialization common between both constructors for the ClientCursor.
*/
void init();
@@ -290,7 +246,6 @@ namespace mongo {
* Find the ClientCursor with the provided ID. Optionally warn if it's not found.
* Assumes ccmutex is held.
*/
-
static ClientCursor* find_inlock(CursorId id, bool warn = true);
/**
@@ -345,8 +300,6 @@ namespace mongo {
//
// The underlying execution machinery.
//
-
- // The new world: a runner.
scoped_ptr<Runner> _runner;
};
diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp
index 323bc661899..31ebceb4f3f 100644
--- a/src/mongo/db/commands/find_and_modify.cpp
+++ b/src/mongo/db/commands/find_and_modify.cpp
@@ -37,6 +37,7 @@
#include "mongo/db/dbhelpers.h"
#include "mongo/db/instance.h"
#include "mongo/db/pagefault.h"
+#include "mongo/db/projection.h"
#include "mongo/db/ops/delete.h"
#include "mongo/db/ops/update.h"
#include "mongo/db/ops/update_lifecycle_impl.h"
diff --git a/src/mongo/db/commands/pipeline_command.cpp b/src/mongo/db/commands/pipeline_command.cpp
index 7f625b0ef12..f249e2f8174 100644
--- a/src/mongo/db/commands/pipeline_command.cpp
+++ b/src/mongo/db/commands/pipeline_command.cpp
@@ -101,7 +101,7 @@ namespace {
// These are all no-ops for PipelineRunners
virtual void setYieldPolicy(YieldPolicy policy) {}
- virtual void invalidate(const DiskLoc& dl) {}
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type) {}
virtual void kill() {}
virtual void saveState() {}
virtual bool restoreState() { return true; }
diff --git a/src/mongo/db/exec/2d.cpp b/src/mongo/db/exec/2d.cpp
index 959a03f2f7f..18d16b8b631 100644
--- a/src/mongo/db/exec/2d.cpp
+++ b/src/mongo/db/exec/2d.cpp
@@ -111,7 +111,7 @@ namespace mongo {
}
}
- void TwoD::invalidate(const DiskLoc& dl) {
+ void TwoD::invalidate(const DiskLoc& dl, InvalidationType type) {
if (NULL != _browse) {
_browse->invalidate(dl);
}
diff --git a/src/mongo/db/exec/2d.h b/src/mongo/db/exec/2d.h
index 4a84f695c44..9673051b13e 100644
--- a/src/mongo/db/exec/2d.h
+++ b/src/mongo/db/exec/2d.h
@@ -52,7 +52,7 @@ namespace mongo {
virtual void prepareToYield();
virtual void recoverFromYield();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual PlanStageStats* getStats();
private:
diff --git a/src/mongo/db/exec/2dnear.cpp b/src/mongo/db/exec/2dnear.cpp
index 82bacfd771c..fa84ace673d 100644
--- a/src/mongo/db/exec/2dnear.cpp
+++ b/src/mongo/db/exec/2dnear.cpp
@@ -131,7 +131,7 @@ namespace mongo {
// Also nothing to do here.
}
- void TwoDNear::invalidate(const DiskLoc& dl) {
+ void TwoDNear::invalidate(const DiskLoc& dl, InvalidationType type) {
// XXX make sure this is ok
typedef multimap<DiskLoc, WorkingSetID>::iterator MMIT;
pair<MMIT, MMIT> range = _invalidationMap.equal_range(dl);
diff --git a/src/mongo/db/exec/2dnear.h b/src/mongo/db/exec/2dnear.h
index d7a2c271d1c..c66cb293f3d 100644
--- a/src/mongo/db/exec/2dnear.h
+++ b/src/mongo/db/exec/2dnear.h
@@ -72,7 +72,7 @@ namespace mongo {
virtual void prepareToYield();
virtual void recoverFromYield();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual PlanStageStats* getStats();
diff --git a/src/mongo/db/exec/and_hash.cpp b/src/mongo/db/exec/and_hash.cpp
index 8b96570a3f5..6c3648ff479 100644
--- a/src/mongo/db/exec/and_hash.cpp
+++ b/src/mongo/db/exec/and_hash.cpp
@@ -266,13 +266,13 @@ namespace mongo {
}
}
- void AndHashStage::invalidate(const DiskLoc& dl) {
+ void AndHashStage::invalidate(const DiskLoc& dl, InvalidationType type) {
++_commonStats.invalidates;
if (isEOF()) { return; }
for (size_t i = 0; i < _children.size(); ++i) {
- _children[i]->invalidate(dl);
+ _children[i]->invalidate(dl, type);
}
_seenMap.erase(dl);
diff --git a/src/mongo/db/exec/and_hash.h b/src/mongo/db/exec/and_hash.h
index 116db71c928..d4527ae6c8e 100644
--- a/src/mongo/db/exec/and_hash.h
+++ b/src/mongo/db/exec/and_hash.h
@@ -62,7 +62,7 @@ namespace mongo {
virtual void prepareToYield();
virtual void recoverFromYield();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual PlanStageStats* getStats();
diff --git a/src/mongo/db/exec/and_sorted.cpp b/src/mongo/db/exec/and_sorted.cpp
index cd3e4472345..8cd51398093 100644
--- a/src/mongo/db/exec/and_sorted.cpp
+++ b/src/mongo/db/exec/and_sorted.cpp
@@ -227,13 +227,13 @@ namespace mongo {
}
}
- void AndSortedStage::invalidate(const DiskLoc& dl) {
+ void AndSortedStage::invalidate(const DiskLoc& dl, InvalidationType type) {
++_commonStats.invalidates;
if (isEOF()) { return; }
for (size_t i = 0; i < _children.size(); ++i) {
- _children[i]->invalidate(dl);
+ _children[i]->invalidate(dl, type);
}
if (dl == _targetLoc) {
diff --git a/src/mongo/db/exec/and_sorted.h b/src/mongo/db/exec/and_sorted.h
index 40b2b1cc3eb..cf755228433 100644
--- a/src/mongo/db/exec/and_sorted.h
+++ b/src/mongo/db/exec/and_sorted.h
@@ -63,7 +63,7 @@ namespace mongo {
virtual void prepareToYield();
virtual void recoverFromYield();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual PlanStageStats* getStats();
diff --git a/src/mongo/db/exec/collection_scan.cpp b/src/mongo/db/exec/collection_scan.cpp
index f7785ef5423..4085fe86f81 100644
--- a/src/mongo/db/exec/collection_scan.cpp
+++ b/src/mongo/db/exec/collection_scan.cpp
@@ -116,9 +116,9 @@ namespace mongo {
return _iter->isEOF();
}
- void CollectionScan::invalidate(const DiskLoc& dl) {
+ void CollectionScan::invalidate(const DiskLoc& dl, InvalidationType type) {
++_commonStats.invalidates;
- if (NULL != _iter) {
+ if (NULL != _iter && (INVALIDATION_DELETION == type)) {
_iter->invalidate(dl);
}
}
diff --git a/src/mongo/db/exec/collection_scan.h b/src/mongo/db/exec/collection_scan.h
index 44a0300c8c1..0739f085f0e 100644
--- a/src/mongo/db/exec/collection_scan.h
+++ b/src/mongo/db/exec/collection_scan.h
@@ -53,7 +53,7 @@ namespace mongo {
virtual StageState work(WorkingSetID* out);
virtual bool isEOF();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual void prepareToYield();
virtual void recoverFromYield();
diff --git a/src/mongo/db/exec/fetch.cpp b/src/mongo/db/exec/fetch.cpp
index 4b23cbacd01..50f13291fc6 100644
--- a/src/mongo/db/exec/fetch.cpp
+++ b/src/mongo/db/exec/fetch.cpp
@@ -135,10 +135,10 @@ namespace mongo {
_child->recoverFromYield();
}
- void FetchStage::invalidate(const DiskLoc& dl) {
+ void FetchStage::invalidate(const DiskLoc& dl, InvalidationType type) {
++_commonStats.invalidates;
- _child->invalidate(dl);
+ _child->invalidate(dl, type);
// If we're holding on to an object that we're waiting for the runner to page in...
if (WorkingSet::INVALID_ID != _idBeingPagedIn) {
diff --git a/src/mongo/db/exec/fetch.h b/src/mongo/db/exec/fetch.h
index c74d688be97..0b05dc389b5 100644
--- a/src/mongo/db/exec/fetch.h
+++ b/src/mongo/db/exec/fetch.h
@@ -53,7 +53,7 @@ namespace mongo {
virtual void prepareToYield();
virtual void recoverFromYield();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
PlanStageStats* getStats();
diff --git a/src/mongo/db/exec/index_scan.cpp b/src/mongo/db/exec/index_scan.cpp
index 57366b821fd..0e3edeb1d94 100644
--- a/src/mongo/db/exec/index_scan.cpp
+++ b/src/mongo/db/exec/index_scan.cpp
@@ -248,7 +248,7 @@ namespace mongo {
}
}
- void IndexScan::invalidate(const DiskLoc& dl) {
+ void IndexScan::invalidate(const DiskLoc& dl, InvalidationType type) {
++_commonStats.invalidates;
// If we see this DiskLoc again, it may not be the same doc. it was before, so we want to
diff --git a/src/mongo/db/exec/index_scan.h b/src/mongo/db/exec/index_scan.h
index 718609a488c..787d5d2bf2a 100644
--- a/src/mongo/db/exec/index_scan.h
+++ b/src/mongo/db/exec/index_scan.h
@@ -91,7 +91,7 @@ namespace mongo {
virtual bool isEOF();
virtual void prepareToYield();
virtual void recoverFromYield();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual PlanStageStats* getStats();
diff --git a/src/mongo/db/exec/limit.cpp b/src/mongo/db/exec/limit.cpp
index 5dc1a4962c8..cd85d4e2c66 100644
--- a/src/mongo/db/exec/limit.cpp
+++ b/src/mongo/db/exec/limit.cpp
@@ -74,9 +74,9 @@ namespace mongo {
_child->recoverFromYield();
}
- void LimitStage::invalidate(const DiskLoc& dl) {
+ void LimitStage::invalidate(const DiskLoc& dl, InvalidationType type) {
++_commonStats.invalidates;
- _child->invalidate(dl);
+ _child->invalidate(dl, type);
}
PlanStageStats* LimitStage::getStats() {
diff --git a/src/mongo/db/exec/limit.h b/src/mongo/db/exec/limit.h
index 77830132c16..8742dcbb0bd 100644
--- a/src/mongo/db/exec/limit.h
+++ b/src/mongo/db/exec/limit.h
@@ -51,7 +51,7 @@ namespace mongo {
virtual void prepareToYield();
virtual void recoverFromYield();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual PlanStageStats* getStats();
diff --git a/src/mongo/db/exec/merge_sort.cpp b/src/mongo/db/exec/merge_sort.cpp
index 12fe273f014..e963a65b1bd 100644
--- a/src/mongo/db/exec/merge_sort.cpp
+++ b/src/mongo/db/exec/merge_sort.cpp
@@ -174,10 +174,10 @@ namespace mongo {
}
}
- void MergeSortStage::invalidate(const DiskLoc& dl) {
+ void MergeSortStage::invalidate(const DiskLoc& dl, InvalidationType type) {
++_commonStats.invalidates;
for (size_t i = 0; i < _children.size(); ++i) {
- _children[i]->invalidate(dl);
+ _children[i]->invalidate(dl, type);
}
// Go through our data and see if we're holding on to the invalidated loc.
diff --git a/src/mongo/db/exec/merge_sort.h b/src/mongo/db/exec/merge_sort.h
index 3f642a064b8..2c448a0bd60 100644
--- a/src/mongo/db/exec/merge_sort.h
+++ b/src/mongo/db/exec/merge_sort.h
@@ -65,7 +65,7 @@ namespace mongo {
virtual void prepareToYield();
virtual void recoverFromYield();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
PlanStageStats* getStats();
diff --git a/src/mongo/db/exec/mock_stage.h b/src/mongo/db/exec/mock_stage.h
index 939af4aab11..9476038a16a 100644
--- a/src/mongo/db/exec/mock_stage.h
+++ b/src/mongo/db/exec/mock_stage.h
@@ -60,7 +60,7 @@ namespace mongo {
// have correct yielding behavior.
virtual void prepareToYield() { }
virtual void recoverFromYield() { }
- virtual void invalidate(const DiskLoc& dl) { }
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type) { }
virtual PlanStageStats* getStats() { return NULL; }
/**
diff --git a/src/mongo/db/exec/oplogstart.cpp b/src/mongo/db/exec/oplogstart.cpp
index 28454792a31..5e94e058d7f 100644
--- a/src/mongo/db/exec/oplogstart.cpp
+++ b/src/mongo/db/exec/oplogstart.cpp
@@ -152,10 +152,13 @@ namespace mongo {
bool OplogStart::isEOF() { return _done; }
- void OplogStart::invalidate(const DiskLoc& dl) {
+ void OplogStart::invalidate(const DiskLoc& dl, InvalidationType type) {
if (_needInit) { return; }
+
+ if (INVALIDATION_DELETION != type) { return; }
+
if (_backwardsScanning) {
- _cs->invalidate(dl);
+ _cs->invalidate(dl, type);
}
else {
verify(_extentHopping);
diff --git a/src/mongo/db/exec/oplogstart.h b/src/mongo/db/exec/oplogstart.h
index a9941b203ba..159e8c82a2a 100644
--- a/src/mongo/db/exec/oplogstart.h
+++ b/src/mongo/db/exec/oplogstart.h
@@ -67,7 +67,7 @@ namespace mongo {
virtual StageState work(WorkingSetID* out);
virtual bool isEOF();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual void prepareToYield();
virtual void recoverFromYield();
diff --git a/src/mongo/db/exec/or.cpp b/src/mongo/db/exec/or.cpp
index 81a5144d1b2..861fb99fef6 100644
--- a/src/mongo/db/exec/or.cpp
+++ b/src/mongo/db/exec/or.cpp
@@ -135,13 +135,13 @@ namespace mongo {
}
}
- void OrStage::invalidate(const DiskLoc& dl) {
+ void OrStage::invalidate(const DiskLoc& dl, InvalidationType type) {
++_commonStats.invalidates;
if (isEOF()) { return; }
for (size_t i = 0; i < _children.size(); ++i) {
- _children[i]->invalidate(dl);
+ _children[i]->invalidate(dl, type);
}
// If we see DL again it is not the same record as it once was so we still want to
diff --git a/src/mongo/db/exec/or.h b/src/mongo/db/exec/or.h
index 14393e5c3da..fa765f67ea6 100644
--- a/src/mongo/db/exec/or.h
+++ b/src/mongo/db/exec/or.h
@@ -56,7 +56,7 @@ namespace mongo {
virtual void prepareToYield();
virtual void recoverFromYield();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual PlanStageStats* getStats();
diff --git a/src/mongo/db/exec/plan_stage.h b/src/mongo/db/exec/plan_stage.h
index 58ee4aed6a4..d7d8b52639c 100644
--- a/src/mongo/db/exec/plan_stage.h
+++ b/src/mongo/db/exec/plan_stage.h
@@ -30,6 +30,7 @@
#include "mongo/db/exec/plan_stats.h"
#include "mongo/db/exec/working_set.h"
+#include "mongo/db/invalidation_type.h"
namespace mongo {
@@ -207,7 +208,7 @@ namespace mongo {
*
* Can only be called after a prepareToYield but before a recoverFromYield.
*/
- virtual void invalidate(const DiskLoc& dl) = 0;
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type) = 0;
/**
* Returns a tree of stats. See plan_stats.h for the details of this structure. If the
diff --git a/src/mongo/db/exec/projection.cpp b/src/mongo/db/exec/projection.cpp
index 3431be77d77..2983524707d 100644
--- a/src/mongo/db/exec/projection.cpp
+++ b/src/mongo/db/exec/projection.cpp
@@ -86,9 +86,9 @@ namespace mongo {
_child->recoverFromYield();
}
- void ProjectionStage::invalidate(const DiskLoc& dl) {
+ void ProjectionStage::invalidate(const DiskLoc& dl, InvalidationType type) {
++_commonStats.invalidates;
- _child->invalidate(dl);
+ _child->invalidate(dl, type);
}
PlanStageStats* ProjectionStage::getStats() {
diff --git a/src/mongo/db/exec/projection.h b/src/mongo/db/exec/projection.h
index fbca9ed0923..c558b8e434a 100644
--- a/src/mongo/db/exec/projection.h
+++ b/src/mongo/db/exec/projection.h
@@ -53,7 +53,7 @@ namespace mongo {
virtual void prepareToYield();
virtual void recoverFromYield();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
PlanStageStats* getStats();
diff --git a/src/mongo/db/exec/s2near.cpp b/src/mongo/db/exec/s2near.cpp
index eabb4c3d550..5a87b0c64cb 100644
--- a/src/mongo/db/exec/s2near.cpp
+++ b/src/mongo/db/exec/s2near.cpp
@@ -304,9 +304,9 @@ namespace mongo {
}
}
- void S2NearStage::invalidate(const DiskLoc& dl) {
+ void S2NearStage::invalidate(const DiskLoc& dl, InvalidationType type) {
if (NULL != _child.get()) {
- _child->invalidate(dl);
+ _child->invalidate(dl, type);
}
unordered_map<DiskLoc, WorkingSetID, DiskLoc::Hasher>::iterator it
diff --git a/src/mongo/db/exec/s2near.h b/src/mongo/db/exec/s2near.h
index 87613908f6f..3391590b862 100644
--- a/src/mongo/db/exec/s2near.h
+++ b/src/mongo/db/exec/s2near.h
@@ -71,7 +71,7 @@ namespace mongo {
void prepareToYield();
void recoverFromYield();
- void invalidate(const DiskLoc& dl);
+ void invalidate(const DiskLoc& dl, InvalidationType type);
PlanStageStats* getStats();
diff --git a/src/mongo/db/exec/shard_filter.cpp b/src/mongo/db/exec/shard_filter.cpp
index a67155cf87f..c3b6aa50ec5 100644
--- a/src/mongo/db/exec/shard_filter.cpp
+++ b/src/mongo/db/exec/shard_filter.cpp
@@ -90,9 +90,9 @@ namespace mongo {
_child->recoverFromYield();
}
- void ShardFilterStage::invalidate(const DiskLoc& dl) {
+ void ShardFilterStage::invalidate(const DiskLoc& dl, InvalidationType type) {
++_commonStats.invalidates;
- _child->invalidate(dl);
+ _child->invalidate(dl, type);
}
PlanStageStats* ShardFilterStage::getStats() {
diff --git a/src/mongo/db/exec/shard_filter.h b/src/mongo/db/exec/shard_filter.h
index 6dc238e0539..2f799476d44 100644
--- a/src/mongo/db/exec/shard_filter.h
+++ b/src/mongo/db/exec/shard_filter.h
@@ -82,7 +82,7 @@ namespace mongo {
virtual void prepareToYield();
virtual void recoverFromYield();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual PlanStageStats* getStats();
diff --git a/src/mongo/db/exec/skip.cpp b/src/mongo/db/exec/skip.cpp
index ca22798a143..0858967d168 100644
--- a/src/mongo/db/exec/skip.cpp
+++ b/src/mongo/db/exec/skip.cpp
@@ -82,9 +82,9 @@ namespace mongo {
_child->recoverFromYield();
}
- void SkipStage::invalidate(const DiskLoc& dl) {
+ void SkipStage::invalidate(const DiskLoc& dl, InvalidationType type) {
++_commonStats.invalidates;
- _child->invalidate(dl);
+ _child->invalidate(dl, type);
}
PlanStageStats* SkipStage::getStats() {
diff --git a/src/mongo/db/exec/skip.h b/src/mongo/db/exec/skip.h
index 29e8c51c71d..9c907ac8bb0 100644
--- a/src/mongo/db/exec/skip.h
+++ b/src/mongo/db/exec/skip.h
@@ -50,7 +50,7 @@ namespace mongo {
virtual void prepareToYield();
virtual void recoverFromYield();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual PlanStageStats* getStats();
diff --git a/src/mongo/db/exec/sort.cpp b/src/mongo/db/exec/sort.cpp
index 33fb68aadb0..6618dec6a62 100644
--- a/src/mongo/db/exec/sort.cpp
+++ b/src/mongo/db/exec/sort.cpp
@@ -401,9 +401,9 @@ namespace mongo {
_child->recoverFromYield();
}
- void SortStage::invalidate(const DiskLoc& dl) {
+ void SortStage::invalidate(const DiskLoc& dl, InvalidationType type) {
++_commonStats.invalidates;
- _child->invalidate(dl);
+ _child->invalidate(dl, type);
// _data contains indices into the WorkingSet, not actual data. If a WorkingSetMember in
// the WorkingSet needs to change state as a result of a DiskLoc invalidation, it will still
diff --git a/src/mongo/db/exec/sort.h b/src/mongo/db/exec/sort.h
index 99612980c99..9d688b150e6 100644
--- a/src/mongo/db/exec/sort.h
+++ b/src/mongo/db/exec/sort.h
@@ -141,7 +141,7 @@ namespace mongo {
virtual void prepareToYield();
virtual void recoverFromYield();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
PlanStageStats* getStats();
diff --git a/src/mongo/db/exec/text.cpp b/src/mongo/db/exec/text.cpp
index f5a41245f43..a4b73a1e035 100644
--- a/src/mongo/db/exec/text.cpp
+++ b/src/mongo/db/exec/text.cpp
@@ -94,7 +94,7 @@ namespace mongo {
// TODO: When we incrementally read results, tell our sub-runners to unyield.
}
- void TextStage::invalidate(const DiskLoc& dl) {
+ void TextStage::invalidate(const DiskLoc& dl, InvalidationType type) {
++_commonStats.invalidates;
// TODO: This is much slower than it should be.
for (size_t i = 0; i < _results.size(); ++i) {
diff --git a/src/mongo/db/exec/text.h b/src/mongo/db/exec/text.h
index 9b0acc5475a..ec680246526 100644
--- a/src/mongo/db/exec/text.h
+++ b/src/mongo/db/exec/text.h
@@ -88,7 +88,7 @@ namespace mongo {
virtual void prepareToYield();
virtual void recoverFromYield();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
PlanStageStats* getStats();
diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp
index 3f2b529d352..af361a73408 100644
--- a/src/mongo/db/instance.cpp
+++ b/src/mongo/db/instance.cpp
@@ -60,6 +60,7 @@
#include "mongo/db/json.h"
#include "mongo/db/kill_current_op.h"
#include "mongo/db/lasterror.h"
+#include "mongo/db/matcher.h"
#include "mongo/db/mongod_options.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/ops/count.h"
diff --git a/src/mongo/db/invalidation_type.h b/src/mongo/db/invalidation_type.h
new file mode 100644
index 00000000000..1c502d8d8a4
--- /dev/null
+++ b/src/mongo/db/invalidation_type.h
@@ -0,0 +1,42 @@
+/**
+ * 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 {
+
+ enum InvalidationType {
+ // The DiskLoc is about to be deleted. The receiver of this invalidate call cannot use
+ // the DiskLoc after it returns from the invalidate.
+ INVALIDATION_DELETION,
+
+ // The DiskLoc's contents have changed.
+ INVALIDATION_MUTATION,
+ };
+
+} // namespace mongo
diff --git a/src/mongo/db/ops/update.cpp b/src/mongo/db/ops/update.cpp
index 7345388089b..5bfff0b801c 100644
--- a/src/mongo/db/ops/update.cpp
+++ b/src/mongo/db/ops/update.cpp
@@ -684,6 +684,10 @@ namespace mongo {
opDebug->fastmod = true;
}
newObj = oldObj;
+
+ // Broadcast the mutation so that query results stay correct.
+ ClientCursor::invalidateDocument(nsString.ns(), collection->details(), loc,
+ INVALIDATION_MUTATION);
}
else {
diff --git a/src/mongo/db/query/cached_plan_runner.cpp b/src/mongo/db/query/cached_plan_runner.cpp
index 0b779e888c9..6b2e4ec1d7b 100644
--- a/src/mongo/db/query/cached_plan_runner.cpp
+++ b/src/mongo/db/query/cached_plan_runner.cpp
@@ -96,10 +96,10 @@ namespace mongo {
return _exec->restoreState();
}
- void CachedPlanRunner::invalidate(const DiskLoc& dl) {
- _exec->invalidate(dl);
+ void CachedPlanRunner::invalidate(const DiskLoc& dl, InvalidationType type) {
+ _exec->invalidate(dl, type);
if (NULL != _backupPlan.get()) {
- _backupPlan->invalidate(dl);
+ _backupPlan->invalidate(dl, type);
}
}
diff --git a/src/mongo/db/query/cached_plan_runner.h b/src/mongo/db/query/cached_plan_runner.h
index fec77b2ef21..cbc1340184b 100644
--- a/src/mongo/db/query/cached_plan_runner.h
+++ b/src/mongo/db/query/cached_plan_runner.h
@@ -71,7 +71,7 @@ namespace mongo {
virtual bool restoreState();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual void setYieldPolicy(Runner::YieldPolicy policy);
diff --git a/src/mongo/db/query/eof_runner.cpp b/src/mongo/db/query/eof_runner.cpp
index c26564c168f..8ea9fbb1402 100644
--- a/src/mongo/db/query/eof_runner.cpp
+++ b/src/mongo/db/query/eof_runner.cpp
@@ -60,7 +60,7 @@ namespace mongo {
void EOFRunner::setYieldPolicy(Runner::YieldPolicy policy) {
}
- void EOFRunner::invalidate(const DiskLoc& dl) {
+ void EOFRunner::invalidate(const DiskLoc& dl, InvalidationType type) {
}
const std::string& EOFRunner::ns() {
diff --git a/src/mongo/db/query/eof_runner.h b/src/mongo/db/query/eof_runner.h
index bffeb4f59a8..e155b174293 100644
--- a/src/mongo/db/query/eof_runner.h
+++ b/src/mongo/db/query/eof_runner.h
@@ -63,7 +63,7 @@ namespace mongo {
virtual void setYieldPolicy(Runner::YieldPolicy policy);
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual const std::string& ns();
diff --git a/src/mongo/db/query/idhack_runner.cpp b/src/mongo/db/query/idhack_runner.cpp
index c7b97d336f7..0d3e3fa5425 100644
--- a/src/mongo/db/query/idhack_runner.cpp
+++ b/src/mongo/db/query/idhack_runner.cpp
@@ -147,9 +147,9 @@ namespace mongo {
}
// Nothing to do here, holding no state.
- void IDHackRunner::invalidate(const DiskLoc& dl) {
+ void IDHackRunner::invalidate(const DiskLoc& dl, InvalidationType type) {
if (_done || _killed) { return; }
- if (_locFetching == dl) {
+ if (_locFetching == dl && (type == INVALIDATION_DELETION)) {
_locFetching = DiskLoc();
_killed = true;
}
diff --git a/src/mongo/db/query/idhack_runner.h b/src/mongo/db/query/idhack_runner.h
index def27173c94..8df1ce70f12 100644
--- a/src/mongo/db/query/idhack_runner.h
+++ b/src/mongo/db/query/idhack_runner.h
@@ -64,7 +64,7 @@ namespace mongo {
virtual void setYieldPolicy(Runner::YieldPolicy policy);
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual const std::string& ns();
diff --git a/src/mongo/db/query/internal_runner.cpp b/src/mongo/db/query/internal_runner.cpp
index 372ce4829bc..f5d1b392830 100644
--- a/src/mongo/db/query/internal_runner.cpp
+++ b/src/mongo/db/query/internal_runner.cpp
@@ -70,8 +70,8 @@ namespace mongo {
return _ns;
}
- void InternalRunner::invalidate(const DiskLoc& dl) {
- _exec->invalidate(dl);
+ void InternalRunner::invalidate(const DiskLoc& dl, InvalidationType type) {
+ _exec->invalidate(dl, type);
}
void InternalRunner::setYieldPolicy(Runner::YieldPolicy policy) {
diff --git a/src/mongo/db/query/internal_runner.h b/src/mongo/db/query/internal_runner.h
index 21a474aaf33..699814e1a2a 100644
--- a/src/mongo/db/query/internal_runner.h
+++ b/src/mongo/db/query/internal_runner.h
@@ -71,7 +71,7 @@ namespace mongo {
virtual const std::string& ns();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual void setYieldPolicy(Runner::YieldPolicy policy);
diff --git a/src/mongo/db/query/multi_plan_runner.cpp b/src/mongo/db/query/multi_plan_runner.cpp
index b2cd1ccc7ba..a4f5b3de6ed 100644
--- a/src/mongo/db/query/multi_plan_runner.cpp
+++ b/src/mongo/db/query/multi_plan_runner.cpp
@@ -132,11 +132,11 @@ namespace mongo {
}
}
- void MultiPlanRunner::invalidate(const DiskLoc& dl) {
+ void MultiPlanRunner::invalidate(const DiskLoc& dl, InvalidationType type) {
if (_failure || _killed) { return; }
if (NULL != _bestPlan) {
- _bestPlan->invalidate(dl);
+ _bestPlan->invalidate(dl, type);
for (list<WorkingSetID>::iterator it = _alreadyProduced.begin();
it != _alreadyProduced.end();) {
WorkingSetMember* member = _bestPlan->getWorkingSet()->get(*it);
@@ -153,7 +153,7 @@ namespace mongo {
}
}
if (NULL != _backupPlan) {
- _backupPlan->invalidate(dl);
+ _backupPlan->invalidate(dl, type);
for (list<WorkingSetID>::iterator it = _backupAlreadyProduced.begin();
it != _backupAlreadyProduced.end();) {
WorkingSetMember* member = _backupPlan->getWorkingSet()->get(*it);
@@ -173,7 +173,7 @@ namespace mongo {
}
else {
for (size_t i = 0; i < _candidates.size(); ++i) {
- _candidates[i].root->invalidate(dl);
+ _candidates[i].root->invalidate(dl, type);
for (list<WorkingSetID>::iterator it = _candidates[i].results.begin();
it != _candidates[i].results.end();) {
WorkingSetMember* member = _candidates[i].ws->get(*it);
diff --git a/src/mongo/db/query/multi_plan_runner.h b/src/mongo/db/query/multi_plan_runner.h
index db643d3ac55..ca4910e1f6f 100644
--- a/src/mongo/db/query/multi_plan_runner.h
+++ b/src/mongo/db/query/multi_plan_runner.h
@@ -85,7 +85,7 @@ namespace mongo {
virtual void saveState();
virtual bool restoreState();
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual void setYieldPolicy(Runner::YieldPolicy policy);
diff --git a/src/mongo/db/query/plan_executor.cpp b/src/mongo/db/query/plan_executor.cpp
index c1bf5b51957..87f433f4a8b 100644
--- a/src/mongo/db/query/plan_executor.cpp
+++ b/src/mongo/db/query/plan_executor.cpp
@@ -62,8 +62,8 @@ namespace mongo {
return !_killed;
}
- void PlanExecutor::invalidate(const DiskLoc& dl) {
- if (!_killed) { _root->invalidate(dl); }
+ void PlanExecutor::invalidate(const DiskLoc& dl, InvalidationType type) {
+ if (!_killed) { _root->invalidate(dl, type); }
}
void PlanExecutor::setYieldPolicy(Runner::YieldPolicy policy) {
diff --git a/src/mongo/db/query/plan_executor.h b/src/mongo/db/query/plan_executor.h
index b753bade782..06214d7cdc2 100644
--- a/src/mongo/db/query/plan_executor.h
+++ b/src/mongo/db/query/plan_executor.h
@@ -76,7 +76,7 @@ namespace mongo {
bool restoreState();
/** TODO document me */
- void invalidate(const DiskLoc& dl);
+ void invalidate(const DiskLoc& dl, InvalidationType type);
//
// Running Support
diff --git a/src/mongo/db/query/runner.h b/src/mongo/db/query/runner.h
index 74551a53804..7590cb12ff5 100644
--- a/src/mongo/db/query/runner.h
+++ b/src/mongo/db/query/runner.h
@@ -30,6 +30,7 @@
#include "mongo/base/status.h"
#include "mongo/db/query/canonical_query.h"
+#include "mongo/db/invalidation_type.h"
namespace mongo {
@@ -152,13 +153,15 @@ namespace mongo {
virtual bool isEOF() = 0;
/**
- * Inform the runner that the provided DiskLoc is about to disappear (or change entirely).
- * The runner then takes any actions required to continue operating correctly, including
+ * Inform the runner about changes to DiskLoc(s) that occur while the runner is yielded.
+ * The runner must take any actions required to continue operating correctly, including
* broadcasting the invalidation request to the PlanStage tree being run.
*
- * Called from ClientCursor::aboutToDelete.
+ * Called from ClientCursor::invalidateDocument.
+ *
+ * See db/invalidation_type.h for InvalidationType.
*/
- virtual void invalidate(const DiskLoc& dl) = 0;
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type) = 0;
/**
* Mark the Runner as no longer valid. Can happen when a runner yields and the underlying
diff --git a/src/mongo/db/query/single_solution_runner.cpp b/src/mongo/db/query/single_solution_runner.cpp
index 513b9473da6..3196fc831b9 100644
--- a/src/mongo/db/query/single_solution_runner.cpp
+++ b/src/mongo/db/query/single_solution_runner.cpp
@@ -74,8 +74,8 @@ namespace mongo {
_exec->setYieldPolicy(policy);
}
- void SingleSolutionRunner::invalidate(const DiskLoc& dl) {
- _exec->invalidate(dl);
+ void SingleSolutionRunner::invalidate(const DiskLoc& dl, InvalidationType type) {
+ _exec->invalidate(dl, type);
}
const std::string& SingleSolutionRunner::ns() {
diff --git a/src/mongo/db/query/single_solution_runner.h b/src/mongo/db/query/single_solution_runner.h
index bb7dde78906..7062a70c153 100644
--- a/src/mongo/db/query/single_solution_runner.h
+++ b/src/mongo/db/query/single_solution_runner.h
@@ -68,7 +68,7 @@ namespace mongo {
virtual void setYieldPolicy(Runner::YieldPolicy policy);
- virtual void invalidate(const DiskLoc& dl);
+ virtual void invalidate(const DiskLoc& dl, InvalidationType type);
virtual const std::string& ns();
diff --git a/src/mongo/db/structure/collection.cpp b/src/mongo/db/structure/collection.cpp
index 88281dd8569..42785388099 100644
--- a/src/mongo/db/structure/collection.cpp
+++ b/src/mongo/db/structure/collection.cpp
@@ -232,7 +232,7 @@ namespace mongo {
}
/* check if any cursors point to us. if so, advance them. */
- ClientCursor::aboutToDelete(_ns.ns(), _details, loc);
+ ClientCursor::invalidateDocument(_ns.ns(), _details, loc, INVALIDATION_DELETION);
_indexCatalog.unindexRecord( doc, loc, noWarn);
@@ -304,7 +304,8 @@ namespace mongo {
// unindex old record, don't delete
// this way, if inserting new doc fails, we can re-index this one
- ClientCursor::aboutToDelete(_ns.ns(), _details, oldLocation);
+ ClientCursor::invalidateDocument(_ns.ns(), _details, oldLocation,
+ INVALIDATION_DELETION);
_indexCatalog.unindexRecord( objOld, oldLocation, true );
if ( debug ) {
@@ -351,6 +352,10 @@ namespace mongo {
// update in place
int sz = objNew.objsize();
memcpy(getDur().writingPtr(oldRecord->data(), sz), objNew.objdata(), sz);
+
+ // Broadcast the mutation so that query results stay correct.
+ ClientCursor::invalidateDocument(_ns.ns(), _details, oldLocation, INVALIDATION_MUTATION);
+
return StatusWith<DiskLoc>( oldLocation );
}
diff --git a/src/mongo/dbtests/query_stage_and.cpp b/src/mongo/dbtests/query_stage_and.cpp
index 5cb6f2e3c5f..be2d7ff24bc 100644
--- a/src/mongo/dbtests/query_stage_and.cpp
+++ b/src/mongo/dbtests/query_stage_and.cpp
@@ -164,7 +164,7 @@ namespace QueryStageAnd {
getLocs(&data, coll);
for (set<DiskLoc>::const_iterator it = data.begin(); it != data.end(); ++it) {
if (it->obj()["foo"].numberInt() == 15) {
- ah->invalidate(*it);
+ ah->invalidate(*it, INVALIDATION_DELETION);
remove(it->obj());
break;
}
@@ -456,7 +456,7 @@ namespace QueryStageAnd {
// very first insert, which should be the very first thing in data. Let's invalidate it
// and make sure it shows up in the flagged results.
ah->prepareToYield();
- ah->invalidate(*data.begin());
+ ah->invalidate(*data.begin(), INVALIDATION_DELETION);
remove(data.begin()->obj());
ah->recoverFromYield();
@@ -495,7 +495,7 @@ namespace QueryStageAnd {
// Remove a result that's coming up. It's not the 'target' result of the AND so it's
// not flagged.
ah->prepareToYield();
- ah->invalidate(*it);
+ ah->invalidate(*it, INVALIDATION_DELETION);
remove(it->obj());
ah->recoverFromYield();
diff --git a/src/mongo/dbtests/query_stage_collscan.cpp b/src/mongo/dbtests/query_stage_collscan.cpp
index bf328592264..e3232bebf38 100644
--- a/src/mongo/dbtests/query_stage_collscan.cpp
+++ b/src/mongo/dbtests/query_stage_collscan.cpp
@@ -507,7 +507,7 @@ namespace QueryStageCollectionScan {
// Remove locs[count].
scan->prepareToYield();
- scan->invalidate(locs[count]);
+ scan->invalidate(locs[count], INVALIDATION_DELETION);
remove(locs[count].obj());
scan->recoverFromYield();
@@ -567,7 +567,7 @@ namespace QueryStageCollectionScan {
// Remove locs[count].
scan->prepareToYield();
- scan->invalidate(locs[count]);
+ scan->invalidate(locs[count], INVALIDATION_DELETION);
remove(locs[count].obj());
scan->recoverFromYield();
diff --git a/src/mongo/dbtests/query_stage_fetch.cpp b/src/mongo/dbtests/query_stage_fetch.cpp
index 23e6f7f0d0e..a312af3fdc6 100644
--- a/src/mongo/dbtests/query_stage_fetch.cpp
+++ b/src/mongo/dbtests/query_stage_fetch.cpp
@@ -271,7 +271,7 @@ namespace QueryStageFetch {
WorkingSetMember* member = ws.get(id);
// Invalidate the DL.
- fetchStage->invalidate(member->loc);
+ fetchStage->invalidate(member->loc, INVALIDATION_DELETION);
bool fetchReturnsInvalidated = false;
if (fetchReturnsInvalidated) {
diff --git a/src/mongo/dbtests/query_stage_merge_sort.cpp b/src/mongo/dbtests/query_stage_merge_sort.cpp
index 4fcc91de3fe..8bf6710aea5 100644
--- a/src/mongo/dbtests/query_stage_merge_sort.cpp
+++ b/src/mongo/dbtests/query_stage_merge_sort.cpp
@@ -532,7 +532,7 @@ namespace QueryStageMergeSortTests {
// Invalidate locs[11]. Should force a fetch. We don't get it back.
ms->prepareToYield();
- ms->invalidate(*it);
+ ms->invalidate(*it, INVALIDATION_DELETION);
ms->recoverFromYield();
// Make sure locs[11] was fetched for us.
diff --git a/src/mongo/dbtests/query_stage_sort.cpp b/src/mongo/dbtests/query_stage_sort.cpp
index 3320b7ed2cd..8f5f48fe35d 100644
--- a/src/mongo/dbtests/query_stage_sort.cpp
+++ b/src/mongo/dbtests/query_stage_sort.cpp
@@ -275,7 +275,7 @@ namespace QueryStageSortTests {
// We should have read in the first 'firstRead' locs. Invalidate the first.
ss->prepareToYield();
set<DiskLoc>::iterator it = locs.begin();
- ss->invalidate(*it++);
+ ss->invalidate(*it++, INVALIDATION_DELETION);
ss->recoverFromYield();
// Read the rest of the data from the mock stage.
@@ -290,7 +290,7 @@ namespace QueryStageSortTests {
// Let's just invalidate everything now.
ss->prepareToYield();
while (it != locs.end()) {
- ss->invalidate(*it++);
+ ss->invalidate(*it++, INVALIDATION_DELETION);
}
ss->recoverFromYield();