diff options
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(); |