summaryrefslogtreecommitdiff
path: root/db/cursor.h
diff options
context:
space:
mode:
Diffstat (limited to 'db/cursor.h')
-rw-r--r--db/cursor.h249
1 files changed, 139 insertions, 110 deletions
diff --git a/db/cursor.h b/db/cursor.h
index ecd417ed433..32aa5a3b4ad 100644
--- a/db/cursor.h
+++ b/db/cursor.h
@@ -1,15 +1,15 @@
/**
* 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/>.
*/
@@ -18,130 +18,159 @@
#include "../stdafx.h"
-/* Query cursors, base class. This is for our internal cursors. "ClientCursor" is a separate
+/* Query cursors, base class. This is for our internal cursors. "ClientCursor" is a separate
concept and is for the user's cursor.
*/
class Cursor {
public:
- 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*/
-
- /* Implement these if you want the cursor to be "tailable" */
- /* tailable(): if true, cursor has tailable capability AND
- the user requested use of those semantics. */
- virtual bool tailable() { return false; }
- /* indicates we should mark where we are and go into tail mode. */
- virtual void setAtTail() { assert(false); }
- /* you must call tailResume before reusing the cursor */
- virtual void tailResume() { }
- /* indicates ifi we are actively tailing. once it goes active,
- this should return treu even after tailResume(). */
- virtual bool tailing() { 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(); }
-
- /* 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() { }
-
- virtual string toString() { return "abstract?"; }
-
- /* used for multikey index traversal to avoid sending back dups. see JSMatcher::matches() */
- set<DiskLoc> dups;
- bool getsetdup(DiskLoc loc) {
- /* to save mem only call this when there is risk of dups (e.g. when 'deep'/multikey) */
- if( dups.count(loc) > 0 )
- return true;
- dups.insert(loc);
- return false;
- }
+ 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*/
+
+ /* Implement these if you want the cursor to be "tailable" */
+ /* tailable(): if true, cursor has tailable capability AND
+ the user requested use of those semantics. */
+ virtual bool tailable() {
+ return false;
+ }
+ /* indicates we should mark where we are and go into tail mode. */
+ virtual void setAtTail() {
+ assert(false);
+ }
+ /* you must call tailResume before reusing the cursor */
+ virtual void tailResume() { }
+ /* indicates ifi we are actively tailing. once it goes active,
+ this should return treu even after tailResume(). */
+ virtual bool tailing() {
+ 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();
+ }
+
+ /* 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() { }
+
+ virtual string toString() {
+ return "abstract?";
+ }
+
+ /* used for multikey index traversal to avoid sending back dups. see JSMatcher::matches() */
+ set<DiskLoc> dups;
+ bool getsetdup(DiskLoc loc) {
+ /* to save mem only call this when there is risk of dups (e.g. when 'deep'/multikey) */
+ if ( dups.count(loc) > 0 )
+ return true;
+ dups.insert(loc);
+ return false;
+ }
};
/* table-scan style cursor */
class BasicCursor : public Cursor {
protected:
- DiskLoc curr, last;
+ DiskLoc curr, last;
private:
- // for tailing:
- enum State { Normal, TailPoint, TailResumed } state;
- void init() { state = Normal; }
+ // for tailing:
+ enum State { Normal, TailPoint, TailResumed } state;
+ void init() {
+ state = Normal;
+ }
public:
- bool ok() { return !curr.isNull(); }
- Record* _current() {
- assert( ok() );
- return curr.rec();
- }
- BSONObj current() {
- Record *r = _current();
- BSONObj j(r);
- return j;
- }
- virtual DiskLoc currLoc() { return curr; }
-
- bool advance() {
- if( eof() )
- return false;
- Record *r = _current();
- last = curr;
- curr = r->getNext(curr);
- return ok();
- }
-
- BasicCursor(DiskLoc dl) : curr(dl) { init(); }
- BasicCursor() { init(); }
- virtual string toString() { return "BasicCursor"; }
-
- virtual void tailResume() {
- if( state == TailPoint ) {
- state = TailResumed;
- advance();
- }
- }
- virtual void setAtTail() {
- assert( state != TailPoint );
- assert( curr.isNull() );
- assert( !last.isNull() );
- curr = last; last.Null();
- state = TailPoint;
- }
- virtual bool tailable() {
- // to go into tail mode we need a non-null point of reference for resumption
- return !last.isNull();
- }
- virtual bool tailing() {
- return state != Normal;
- }
+ bool ok() {
+ return !curr.isNull();
+ }
+ Record* _current() {
+ assert( ok() );
+ return curr.rec();
+ }
+ BSONObj current() {
+ Record *r = _current();
+ BSONObj j(r);
+ return j;
+ }
+ virtual DiskLoc currLoc() {
+ return curr;
+ }
+
+ bool advance() {
+ if ( eof() )
+ return false;
+ Record *r = _current();
+ last = curr;
+ curr = r->getNext(curr);
+ return ok();
+ }
+
+ BasicCursor(DiskLoc dl) : curr(dl) {
+ init();
+ }
+ BasicCursor() {
+ init();
+ }
+ virtual string toString() {
+ return "BasicCursor";
+ }
+
+ virtual void tailResume() {
+ if ( state == TailPoint ) {
+ state = TailResumed;
+ advance();
+ }
+ }
+ virtual void setAtTail() {
+ assert( state != TailPoint );
+ assert( curr.isNull() );
+ assert( !last.isNull() );
+ curr = last;
+ last.Null();
+ state = TailPoint;
+ }
+ virtual bool tailable() {
+ // to go into tail mode we need a non-null point of reference for resumption
+ return !last.isNull();
+ }
+ virtual bool tailing() {
+ return state != Normal;
+ }
};
/* used for order { $natural: -1 } */
class ReverseCursor : public BasicCursor {
public:
- bool advance() {
- if( eof() )
- return false;
- Record *r = _current();
- last = curr;
- curr = r->getPrev(curr);
- return ok();
- }
-
- ReverseCursor(DiskLoc dl) : BasicCursor(dl) { }
- ReverseCursor() { }
- virtual string toString() { return "ReverseCursor"; }
+ bool advance() {
+ if ( eof() )
+ return false;
+ Record *r = _current();
+ last = curr;
+ curr = r->getPrev(curr);
+ return ok();
+ }
+
+ ReverseCursor(DiskLoc dl) : BasicCursor(dl) { }
+ ReverseCursor() { }
+ virtual string toString() {
+ return "ReverseCursor";
+ }
};