MongoDB  2.1.1-pre-
dbclientcursor.h
00001 // file dbclientcursor.h
00002 
00003 /*    Copyright 2009 10gen Inc.
00004  *
00005  *    Licensed under the Apache License, Version 2.0 (the "License");
00006  *    you may not use this file except in compliance with the License.
00007  *    You may obtain a copy of the License at
00008  *
00009  *    http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  *    Unless required by applicable law or agreed to in writing, software
00012  *    distributed under the License is distributed on an "AS IS" BASIS,
00013  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  *    See the License for the specific language governing permissions and
00015  *    limitations under the License.
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 
00033     class DBClientCursorInterface : boost::noncopyable {
00034     public:
00035         virtual ~DBClientCursorInterface() {}
00036         virtual bool more() = 0;
00037         virtual BSONObj next() = 0;
00038         // TODO bring more of the DBClientCursor interface to here
00039     protected:
00040         DBClientCursorInterface() {}
00041     };
00042 
00044     class DBClientCursor : public DBClientCursorInterface {
00045     public:
00047         bool more();
00048 
00054         int objsLeftInBatch() const { _assertIfNull(); return _putBack.size() + batch.nReturned - batch.pos; }
00055         bool moreInCurrentBatch() { return objsLeftInBatch() > 0; }
00056 
00063         BSONObj next();
00064 
00068         void putBack( const BSONObj &o ) { _putBack.push( o.getOwned() ); }
00069 
00071         BSONObj nextSafe() {
00072             BSONObj o = next();
00073             if( strcmp(o.firstElementFieldName(), "$err") == 0 ) {
00074                 string s = "nextSafe(): " + o.toString();
00075                 if( logLevel >= 5 )
00076                     log() << s << endl;
00077                 uasserted(13106, s);
00078             }
00079             return o;
00080         }
00081 
00087         void peek(vector<BSONObj>&, int atMost);
00088 
00089         // Peeks at first element, if exists
00090         BSONObj peekFirst();
00091 
00095         bool peekError(BSONObj* error = NULL);
00096 
00100         int itcount() {
00101             int c = 0;
00102             while ( more() ) {
00103                 next();
00104                 c++;
00105             }
00106             return c;
00107         }
00108 
00114         bool isDead() const { return  !this || cursorId == 0; }
00115 
00116         bool tailable() const { return (opts & QueryOption_CursorTailable) != 0; }
00117 
00122         bool hasResultFlag( int flag ) {
00123             _assertIfNull();
00124             return (resultFlags & flag) != 0;
00125         }
00126 
00127         DBClientCursor( DBClientBase* client, const string &_ns, BSONObj _query, int _nToReturn,
00128                         int _nToSkip, const BSONObj *_fieldsToReturn, int queryOptions , int bs ) :
00129             _client(client),
00130             ns(_ns),
00131             query(_query),
00132             nToReturn(_nToReturn),
00133             haveLimit( _nToReturn > 0 && !(queryOptions & QueryOption_CursorTailable)),
00134             nToSkip(_nToSkip),
00135             fieldsToReturn(_fieldsToReturn),
00136             opts(queryOptions),
00137             batchSize(bs==1?2:bs),
00138             cursorId(),
00139             _ownCursor( true ),
00140             wasError( false ) {
00141             _finishConsInit();
00142         }
00143 
00144         DBClientCursor( DBClientBase* client, const string &_ns, long long _cursorId, int _nToReturn, int options ) :
00145             _client(client),
00146             ns(_ns),
00147             nToReturn( _nToReturn ),
00148             haveLimit( _nToReturn > 0 && !(options & QueryOption_CursorTailable)),
00149             opts( options ),
00150             cursorId(_cursorId),
00151             _ownCursor( true ) {
00152             _finishConsInit();
00153         }
00154 
00155         virtual ~DBClientCursor();
00156 
00157         long long getCursorId() const { return cursorId; }
00158 
00162         void decouple() { _ownCursor = false; }
00163 
00164         void attach( AScopedConnection * conn );
00165 
00166         string originalHost() const { return _originalHost; }
00167 
00168         Message* getMessage(){ return batch.m.get(); }
00169 
00173         bool init();
00174 
00175         void initLazy( bool isRetry = false );
00176         bool initLazyFinish( bool& retry );
00177 
00178         class Batch : boost::noncopyable { 
00179             friend class DBClientCursor;
00180             auto_ptr<Message> m;
00181             int nReturned;
00182             int pos;
00183             const char *data;
00184         public:
00185             Batch() : m( new Message() ), nReturned(), pos(), data() { }
00186         };
00187 
00188     private:
00189         friend class DBClientBase;
00190         friend class DBClientConnection;
00191 
00192         int nextBatchSize();
00193         void _finishConsInit();
00194         
00195         Batch batch;
00196         DBClientBase* _client;
00197         string _originalHost;
00198         string ns;
00199         BSONObj query;
00200         int nToReturn;
00201         bool haveLimit;
00202         int nToSkip;
00203         const BSONObj *fieldsToReturn;
00204         int opts;
00205         int batchSize;
00206         stack< BSONObj > _putBack;
00207         int resultFlags;
00208         long long cursorId;
00209         bool _ownCursor; // see decouple()
00210         string _scopedHost;
00211         string _lazyHost;
00212         bool wasError;
00213 
00214         void dataReceived() { bool retry; string lazyHost; dataReceived( retry, lazyHost ); }
00215         void dataReceived( bool& retry, string& lazyHost );
00216         void requestMore();
00217         void exhaustReceiveMore(); // for exhaust
00218 
00219         // Don't call from a virtual function
00220         void _assertIfNull() const { uassert(13348, "connection died", this); }
00221 
00222         // non-copyable , non-assignable
00223         DBClientCursor( const DBClientCursor& );
00224         DBClientCursor& operator=( const DBClientCursor& );
00225 
00226         // init pieces
00227         void _assembleInit( Message& toSend );
00228     };
00229 
00232     class DBClientCursorBatchIterator {
00233     public:
00234         DBClientCursorBatchIterator( DBClientCursor &c ) : _c( c ), _n() {}
00235         bool moreInCurrentBatch() { return _c.moreInCurrentBatch(); }
00236         BSONObj nextSafe() {
00237             massert( 13383, "BatchIterator empty", moreInCurrentBatch() );
00238             ++_n;
00239             return _c.nextSafe();
00240         }
00241         int n() const { return _n; }
00242     private:
00243         DBClientCursor &_c;
00244         int _n;
00245     };
00246 
00247 } // namespace mongo
00248 
00249 #include "undef_macros.h"