00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #pragma once
00019
00020 #include "../pch.h"
00021 #include "../util/message.h"
00022 #include "../db/jsobj.h"
00023 #include "../db/json.h"
00024 #include <stack>
00025
00026 namespace mongo {
00027
00028 class AScopedConnection;
00029
00031 class DBClientCursorInterface {
00032 public:
00033 virtual ~DBClientCursorInterface() {}
00034
00035 virtual bool more() = 0;
00036 virtual BSONObj next() = 0;
00037
00038
00039
00040 protected:
00041 DBClientCursorInterface() {}
00042 };
00043
00045 class DBClientCursor : public DBClientCursorInterface {
00046 public:
00048 bool more();
00049
00055 int objsLeftInBatch() const { _assertIfNull(); return _putBack.size() + nReturned - pos; }
00056 bool moreInCurrentBatch() { return objsLeftInBatch() > 0; }
00057
00064 BSONObj next();
00065
00069 void putBack( const BSONObj &o ) { _putBack.push( o.getOwned() ); }
00070
00072 BSONObj nextSafe() {
00073 BSONObj o = next();
00074 BSONElement e = o.firstElement();
00075 if( strcmp(e.fieldName(), "$err") == 0 ) {
00076 if( logLevel >= 5 )
00077 log() << "nextSafe() error " << o.toString() << endl;
00078 uassert(13106, "nextSafe(): " + o.toString(), false);
00079 }
00080 return o;
00081 }
00082
00088 void peek(vector<BSONObj>&, int atMost);
00089
00093 int itcount() {
00094 int c = 0;
00095 while ( more() ) {
00096 next();
00097 c++;
00098 }
00099 return c;
00100 }
00101
00107 bool isDead() const {
00108 return !this || cursorId == 0;
00109 }
00110
00111 bool tailable() const {
00112 return (opts & QueryOption_CursorTailable) != 0;
00113 }
00114
00119 bool hasResultFlag( int flag ) {
00120 _assertIfNull();
00121 return (resultFlags & flag) != 0;
00122 }
00123
00124 DBClientCursor( DBClientBase* client, const string &_ns, BSONObj _query, int _nToReturn,
00125 int _nToSkip, const BSONObj *_fieldsToReturn, int queryOptions , int bs ) :
00126 _client(client),
00127 ns(_ns),
00128 query(_query),
00129 nToReturn(_nToReturn),
00130 haveLimit( _nToReturn > 0 && !(queryOptions & QueryOption_CursorTailable)),
00131 nToSkip(_nToSkip),
00132 fieldsToReturn(_fieldsToReturn),
00133 opts(queryOptions),
00134 batchSize(bs==1?2:bs),
00135 m(new Message()),
00136 cursorId(),
00137 nReturned(),
00138 pos(),
00139 data(),
00140 _ownCursor( true ) {
00141 }
00142
00143 DBClientCursor( DBClientBase* client, const string &_ns, long long _cursorId, int _nToReturn, int options ) :
00144 _client(client),
00145 ns(_ns),
00146 nToReturn( _nToReturn ),
00147 haveLimit( _nToReturn > 0 && !(options & QueryOption_CursorTailable)),
00148 opts( options ),
00149 m(new Message()),
00150 cursorId( _cursorId ),
00151 nReturned(),
00152 pos(),
00153 data(),
00154 _ownCursor( true ) {
00155 }
00156
00157 virtual ~DBClientCursor();
00158
00159 long long getCursorId() const { return cursorId; }
00160
00164 void decouple() { _ownCursor = false; }
00165
00166 void attach( AScopedConnection * conn );
00167
00168 private:
00169 friend class DBClientBase;
00170 friend class DBClientConnection;
00171 bool init();
00172 int nextBatchSize();
00173 DBClientBase* _client;
00174 string ns;
00175 BSONObj query;
00176 int nToReturn;
00177 bool haveLimit;
00178 int nToSkip;
00179 const BSONObj *fieldsToReturn;
00180 int opts;
00181 int batchSize;
00182 auto_ptr<Message> m;
00183 stack< BSONObj > _putBack;
00184 int resultFlags;
00185 long long cursorId;
00186 int nReturned;
00187 int pos;
00188 const char *data;
00189 void dataReceived();
00190 void requestMore();
00191 void exhaustReceiveMore();
00192 bool _ownCursor;
00193 string _scopedHost;
00194
00195
00196 void _assertIfNull() const { uassert(13348, "connection died", this); }
00197
00198
00199 DBClientCursor( const DBClientCursor& );
00200 DBClientCursor& operator=( const DBClientCursor& );
00201 };
00202
00205 class DBClientCursorBatchIterator {
00206 public:
00207 DBClientCursorBatchIterator( DBClientCursor &c ) : _c( c ), _n() {}
00208 bool moreInCurrentBatch() { return _c.moreInCurrentBatch(); }
00209 BSONObj nextSafe() {
00210 massert( 13383, "BatchIterator empty", moreInCurrentBatch() );
00211 ++_n;
00212 return _c.nextSafe();
00213 }
00214 int n() const { return _n; }
00215 private:
00216 DBClientCursor &_c;
00217 int _n;
00218 };
00219
00220 }
00221
00222 #include "undef_macros.h"