|
MongoDB
2.1.1-pre-
|
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"
1.8.0