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/net/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() + b.nReturned - b.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 if( strcmp(o.firstElementFieldName(), "$err") == 0 ) {
00075 string s = "nextSafe(): " + o.toString();
00076 if( logLevel >= 5 )
00077 log() << s << endl;
00078 uasserted(13106, s);
00079 }
00080 return o;
00081 }
00082
00088 void peek(vector<BSONObj>&, int atMost);
00089
00093 bool peekError(BSONObj* error = NULL);
00094
00098 int itcount() {
00099 int c = 0;
00100 while ( more() ) {
00101 next();
00102 c++;
00103 }
00104 return c;
00105 }
00106
00112 bool isDead() const { return !this || cursorId == 0; }
00113
00114 bool tailable() const { return (opts & QueryOption_CursorTailable) != 0; }
00115
00120 bool hasResultFlag( int flag ) {
00121 _assertIfNull();
00122 return (resultFlags & flag) != 0;
00123 }
00124
00125 DBClientCursor( DBClientBase* client, const string &_ns, BSONObj _query, int _nToReturn,
00126 int _nToSkip, const BSONObj *_fieldsToReturn, int queryOptions , int bs ) :
00127 _client(client),
00128 ns(_ns),
00129 query(_query),
00130 nToReturn(_nToReturn),
00131 haveLimit( _nToReturn > 0 && !(queryOptions & QueryOption_CursorTailable)),
00132 nToSkip(_nToSkip),
00133 fieldsToReturn(_fieldsToReturn),
00134 opts(queryOptions),
00135 batchSize(bs==1?2:bs),
00136 cursorId(),
00137 _ownCursor( true ),
00138 wasError( false ) {
00139 }
00140
00141 DBClientCursor( DBClientBase* client, const string &_ns, long long _cursorId, int _nToReturn, int options ) :
00142 _client(client),
00143 ns(_ns),
00144 nToReturn( _nToReturn ),
00145 haveLimit( _nToReturn > 0 && !(options & QueryOption_CursorTailable)),
00146 opts( options ),
00147 cursorId(_cursorId),
00148 _ownCursor( true ) {
00149 }
00150
00151 virtual ~DBClientCursor();
00152
00153 long long getCursorId() const { return cursorId; }
00154
00158 void decouple() { _ownCursor = false; }
00159
00160 void attach( AScopedConnection * conn );
00161
00165 bool init();
00166
00167 void initLazy( bool isRetry = false );
00168 bool initLazyFinish( bool& retry );
00169
00170 class Batch : boost::noncopyable {
00171 friend class DBClientCursor;
00172 auto_ptr<Message> m;
00173 int nReturned;
00174 int pos;
00175 const char *data;
00176 public:
00177 Batch() : m( new Message() ), nReturned(), pos(), data() { }
00178 };
00179
00180 private:
00181 friend class DBClientBase;
00182 friend class DBClientConnection;
00183
00184 int nextBatchSize();
00185
00186 Batch b;
00187 DBClientBase* _client;
00188 string ns;
00189 BSONObj query;
00190 int nToReturn;
00191 bool haveLimit;
00192 int nToSkip;
00193 const BSONObj *fieldsToReturn;
00194 int opts;
00195 int batchSize;
00196 stack< BSONObj > _putBack;
00197 int resultFlags;
00198 long long cursorId;
00199 bool _ownCursor;
00200 string _scopedHost;
00201 string _lazyHost;
00202 bool wasError;
00203
00204 void dataReceived() { bool retry; string lazyHost; dataReceived( retry, lazyHost ); }
00205 void dataReceived( bool& retry, string& lazyHost );
00206 void requestMore();
00207 void exhaustReceiveMore();
00208
00209
00210 void _assertIfNull() const { uassert(13348, "connection died", this); }
00211
00212
00213 DBClientCursor( const DBClientCursor& );
00214 DBClientCursor& operator=( const DBClientCursor& );
00215
00216
00217 void _assembleInit( Message& toSend );
00218 };
00219
00222 class DBClientCursorBatchIterator {
00223 public:
00224 DBClientCursorBatchIterator( DBClientCursor &c ) : _c( c ), _n() {}
00225 bool moreInCurrentBatch() { return _c.moreInCurrentBatch(); }
00226 BSONObj nextSafe() {
00227 massert( 13383, "BatchIterator empty", moreInCurrentBatch() );
00228 ++_n;
00229 return _c.nextSafe();
00230 }
00231 int n() const { return _n; }
00232 private:
00233 DBClientCursor &_c;
00234 int _n;
00235 };
00236
00237 }
00238
00239 #include "undef_macros.h"