diff options
Diffstat (limited to 'src/mongo/db/cursor.h')
| -rw-r--r-- | src/mongo/db/cursor.h | 319 |
1 files changed, 0 insertions, 319 deletions
diff --git a/src/mongo/db/cursor.h b/src/mongo/db/cursor.h deleted file mode 100644 index 6d92d614b81..00000000000 --- a/src/mongo/db/cursor.h +++ /dev/null @@ -1,319 +0,0 @@ -/** -* Copyright (C) 2008 10gen 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/>. -*/ - -#pragma once - -#include "mongo/pch.h" - -#include "jsobj.h" -#include "diskloc.h" -#include "matcher.h" -#include "mongo/db/projection.h" - -namespace mongo { - - class NamespaceDetails; - class Record; - class CoveredIndexMatcher; - - /** - * Query cursors, base class. This is for our internal cursors. "ClientCursor" is a separate - * concept and is for the user's cursor. - * - * WARNING concurrency: the vfunctions below are called back from within a - * ClientCursor::ccmutex. Don't cause a deadlock, you've been warned. - * - * Two general techniques may be used to ensure a Cursor is in a consistent state after a write. - * - The Cursor may be advanced before the document at its current position is deleted. - * - The Cursor may record its position and then relocate this position. - * A particular Cursor may potentially utilize only one of the above techniques, but a client - * that is Cursor subclass agnostic must implement a pattern handling both techniques. - * - * When the document at a Cursor's current position is deleted (or moved to a new location) the - * following pattern is used: - * DiskLoc toDelete = cursor->currLoc(); - * while( cursor->ok() && cursor->currLoc() == toDelete ) { - * cursor->advance(); - * } - * cursor->prepareToTouchEarlierIterate(); - * delete( toDelete ); - * cursor->recoverFromTouchingEarlierIterate(); - * - * When a cursor yields, the following pattern is used: - * cursor->prepareToYield(); - * while( Op theOp = nextOp() ) { - * if ( theOp.type() == INSERT || theOp.type() == UPDATE_IN_PLACE ) { - * theOp.run(); - * } - * else if ( theOp.type() == DELETE ) { - * if ( cursor->refLoc() == theOp.toDelete() ) { - * cursor->recoverFromYield(); - * while ( cursor->ok() && cursor->refLoc() == theOp.toDelete() ) { - * cursor->advance(); - * } - * cursor->prepareToYield(); - * } - * theOp.run(); - * } - * } - * cursor->recoverFromYield(); - * - * The break before a getMore request is typically treated as a yield, but if a Cursor supports - * getMore but not yield the following pattern is currently used: - * cursor->noteLocation(); - * runOtherOps(); - * cursor->checkLocation(); - * - * But see SERVER-5725. - * - * A Cursor may rely on additional callbacks not listed above to relocate its position after a - * write. - */ - class Cursor : boost::noncopyable { - public: - virtual ~Cursor() {} - virtual bool ok() = 0; - bool eof() { return !ok(); } - virtual Record* _current() = 0; - virtual BSONObj current() = 0; - virtual DiskLoc currLoc() = 0; - virtual bool advance() = 0; /*true=ok*/ - virtual BSONObj currKey() const { return BSONObj(); } - - // DiskLoc the cursor requires for continued operation. Before this - // DiskLoc is deleted, the cursor must be incremented or destroyed. - virtual DiskLoc refLoc() = 0; - - /* Implement these if you want the cursor to be "tailable" */ - - /* Request that the cursor starts tailing after advancing past last record. */ - /* The implementation may or may not honor this request. */ - virtual void setTailable() {} - /* indicates if tailing is enabled. */ - virtual bool tailable() { - return false; - } - - virtual void aboutToDeleteBucket(const DiskLoc& b) { } - - /* optional to implement. if implemented, means 'this' is a prototype */ - virtual Cursor* clone() { - return 0; - } - - virtual BSONObj indexKeyPattern() { - return BSONObj(); - } - - virtual bool supportGetMore() = 0; - - /* called after every query block is iterated -- i.e. between getMore() blocks - so you can note where we are, if necessary. - */ - virtual void noteLocation() { } - - /* called before query getmore block is iterated */ - virtual void checkLocation() { } - - /** - * Called before a document pointed at by an earlier iterate of this cursor is to be - * modified. It is ok if the current iterate also points to the document to be modified. - */ - virtual void prepareToTouchEarlierIterate() { noteLocation(); } - - /** Recover from a previous call to prepareToTouchEarlierIterate(). */ - virtual void recoverFromTouchingEarlierIterate() { checkLocation(); } - - virtual bool supportYields() = 0; - - /** Called before a ClientCursor yield. */ - virtual void prepareToYield() { noteLocation(); } - - /** Called after a ClientCursor yield. Recovers from a previous call to prepareToYield(). */ - virtual void recoverFromYield() { checkLocation(); } - - virtual string toString() { return "abstract?"; } - - /* used for multikey index traversal to avoid sending back dups. see Matcher::matches(). - if a multikey index traversal: - if loc has already been sent, returns true. - otherwise, marks loc as sent. - */ - virtual bool getsetdup(DiskLoc loc) = 0; - - virtual bool isMultiKey() const = 0; - - virtual bool autoDedup() const { return true; } - - /** - * return true if the keys in the index have been modified from the main doc - * if you have { a : 1 , b : [ 1 , 2 ] } - * an index on { a : 1 } would not be modified - * an index on { b : 1 } would be since the values of the array are put in the index - * not the array - */ - virtual bool modifiedKeys() const = 0; - - virtual BSONObj prettyIndexBounds() const { return BSONArray(); } - - /** - * If true, this is an unindexed cursor over a capped collection. Currently such cursors must - * not own a delegate ClientCursor, due to the implementation of ClientCursor::aboutToDelete(). - SERVER-4563 - */ - virtual bool capped() const { return false; } - - virtual long long nscanned() = 0; - - // The implementation may return different matchers depending on the - // position of the cursor. If matcher() is nonzero at the start, - // matcher() should be checked each time advance() is called. - // Implementations which generate their own matcher should return this - // to avoid a matcher being set manually. - // Note that the return values differ subtly here - - // Used when we want fast matcher lookup - virtual CoveredIndexMatcher *matcher() const { return 0; } - - virtual bool currentMatches( MatchDetails *details = 0 ) { - return !matcher() || matcher()->matchesCurrent( this, details ); - } - - // A convenience function for setting the value of matcher() manually - // so it may be accessed later. Implementations which must generate - // their own matcher() should assert here. - virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher ) { - massert( 13285, "manual matcher config not allowed", false ); - } - - /** @return the covered index projector for the current iterate, if any. */ - virtual const Projection::KeyOnly *keyFieldsOnly() const { return 0; } - - /** - * Manually set the value of keyFieldsOnly() so it may be accessed later. Implementations - * that generate their own keyFieldsOnly() must assert. - */ - virtual void setKeyFieldsOnly( const shared_ptr<Projection::KeyOnly> &keyFieldsOnly ) { - massert( 16159, "manual keyFieldsOnly config not allowed", false ); - } - - virtual void explainDetails( BSONObjBuilder& b ) { return; } - }; - - // strategy object implementing direction of traversal. - class AdvanceStrategy { - public: - virtual ~AdvanceStrategy() { } - virtual DiskLoc next( const DiskLoc &prev ) const = 0; - }; - - const AdvanceStrategy *forward(); - const AdvanceStrategy *reverse(); - - /** - * table-scan style cursor - * - * A BasicCursor relies on advance() to ensure it is in a consistent state after a write. If - * the document at a BasicCursor's current position will be deleted or relocated, the cursor - * must first be advanced. The same is true of BasicCursor subclasses. - */ - class BasicCursor : public Cursor { - public: - BasicCursor(DiskLoc dl, const AdvanceStrategy *_s = forward()) : curr(dl), s( _s ), _nscanned() { - incNscanned(); - init(); - } - BasicCursor(const AdvanceStrategy *_s = forward()) : s( _s ), _nscanned() { - init(); - } - bool ok() { return !curr.isNull(); } - Record* _current() { - verify( ok() ); - return curr.rec(); - } - BSONObj current() { - Record *r = _current(); - return BSONObj::make(r); - } - virtual DiskLoc currLoc() { return curr; } - virtual DiskLoc refLoc() { return curr.isNull() ? last : curr; } - bool advance(); - virtual string toString() { return "BasicCursor"; } - virtual void setTailable() { - if ( !curr.isNull() || !last.isNull() ) - tailable_ = true; - } - virtual bool tailable() { return tailable_; } - virtual bool getsetdup(DiskLoc loc) { return false; } - virtual bool isMultiKey() const { return false; } - virtual bool modifiedKeys() const { return false; } - virtual bool supportGetMore() { return true; } - virtual bool supportYields() { return true; } - virtual CoveredIndexMatcher *matcher() const { return _matcher.get(); } - virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher ) { _matcher = matcher; } - virtual const Projection::KeyOnly *keyFieldsOnly() const { return _keyFieldsOnly.get(); } - virtual void setKeyFieldsOnly( const shared_ptr<Projection::KeyOnly> &keyFieldsOnly ) { - _keyFieldsOnly = keyFieldsOnly; - } - virtual long long nscanned() { return _nscanned; } - - protected: - DiskLoc curr, last; - const AdvanceStrategy *s; - void incNscanned() { if ( !curr.isNull() ) { ++_nscanned; } } - private: - bool tailable_; - shared_ptr< CoveredIndexMatcher > _matcher; - shared_ptr<Projection::KeyOnly> _keyFieldsOnly; - long long _nscanned; - void init() { tailable_ = false; } - }; - - /* used for order { $natural: -1 } */ - class ReverseCursor : public BasicCursor { - public: - ReverseCursor(DiskLoc dl) : BasicCursor( dl, reverse() ) { } - ReverseCursor() : BasicCursor( reverse() ) { } - virtual string toString() { return "ReverseCursor"; } - }; - - class ForwardCappedCursor : public BasicCursor, public AdvanceStrategy { - public: - static ForwardCappedCursor* make( NamespaceDetails* nsd = 0, - const DiskLoc& startLoc = DiskLoc() ); - virtual string toString() { - return "ForwardCappedCursor"; - } - virtual DiskLoc next( const DiskLoc &prev ) const; - virtual bool capped() const { return true; } - private: - ForwardCappedCursor( NamespaceDetails* nsd ); - void init( const DiskLoc& startLoc ); - NamespaceDetails *nsd; - }; - - class ReverseCappedCursor : public BasicCursor, public AdvanceStrategy { - public: - ReverseCappedCursor( NamespaceDetails *nsd = 0, const DiskLoc &startLoc = DiskLoc() ); - virtual string toString() { - return "ReverseCappedCursor"; - } - virtual DiskLoc next( const DiskLoc &prev ) const; - virtual bool capped() const { return true; } - private: - NamespaceDetails *nsd; - }; - -} // namespace mongo |
