00001
00017 #pragma once
00018
00019 #include "diskloc.h"
00020 #include "jsobj.h"
00021 #include "namespace-inl.h"
00022 #include "../util/message.h"
00023 #include "../client/constants.h"
00024
00025 namespace mongo {
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 extern bool objcheck;
00038
00039 #pragma pack(1)
00040 struct QueryResult : public MsgData {
00041 long long cursorId;
00042 int startingFrom;
00043 int nReturned;
00044 const char *data() {
00045 return (char *) (((int *)&nReturned)+1);
00046 }
00047 int resultFlags() {
00048 return dataAsInt();
00049 }
00050 int& _resultFlags() {
00051 return dataAsInt();
00052 }
00053 void setResultFlagsToOk() {
00054 _resultFlags() = ResultFlag_AwaitCapable;
00055 }
00056 };
00057 #pragma pack()
00058
00059
00060
00061
00062
00063
00064 class DbMessage {
00065 public:
00066 DbMessage(const Message& _m) : m(_m) , mark(0) {
00067
00068 theEnd = _m.singleData()->_data + _m.header()->dataLen();
00069 char *r = _m.singleData()->_data;
00070 reserved = (int *) r;
00071 data = r + 4;
00072 nextjsobj = data;
00073 }
00074
00076 int& reservedField() { return *reserved; }
00077
00078 const char * getns() const {
00079 return data;
00080 }
00081 void getns(Namespace& ns) const {
00082 ns = data;
00083 }
00084
00085 const char * afterNS() const {
00086 return data + strlen( data ) + 1;
00087 }
00088
00089 int getInt( int num ) const {
00090 const int * foo = (const int*)afterNS();
00091 return foo[num];
00092 }
00093
00094 int getQueryNToReturn() const {
00095 return getInt( 1 );
00096 }
00097
00101 long long getInt64( int offsetBytes ) const {
00102 const char * x = afterNS();
00103 x += offsetBytes;
00104 const long long * ll = (const long long*)x;
00105 return ll[0];
00106 }
00107
00108 void resetPull() { nextjsobj = data; }
00109 int pullInt() const { return pullInt(); }
00110 int& pullInt() {
00111 if ( nextjsobj == data )
00112 nextjsobj += strlen(data) + 1;
00113 int& i = *((int *)nextjsobj);
00114 nextjsobj += 4;
00115 return i;
00116 }
00117 long long pullInt64() const {
00118 return pullInt64();
00119 }
00120 long long &pullInt64() {
00121 if ( nextjsobj == data )
00122 nextjsobj += strlen(data) + 1;
00123 long long &i = *((long long *)nextjsobj);
00124 nextjsobj += 8;
00125 return i;
00126 }
00127
00128 OID* getOID() const {
00129 return (OID *) (data + strlen(data) + 1);
00130 }
00131
00132 void getQueryStuff(const char *&query, int& ntoreturn) {
00133 int *i = (int *) (data + strlen(data) + 1);
00134 ntoreturn = *i;
00135 i++;
00136 query = (const char *) i;
00137 }
00138
00139
00140 bool moreJSObjs() const {
00141 return nextjsobj != 0;
00142 }
00143 BSONObj nextJsObj() {
00144 if ( nextjsobj == data ) {
00145 nextjsobj += strlen(data) + 1;
00146 massert( 13066 , "Message contains no documents", theEnd > nextjsobj );
00147 }
00148 massert( 10304 , "Client Error: Remaining data too small for BSON object", theEnd - nextjsobj > 3 );
00149 BSONObj js(nextjsobj);
00150 massert( 10305 , "Client Error: Invalid object size", js.objsize() > 3 );
00151 massert( 10306 , "Client Error: Next object larger than space left in message",
00152 js.objsize() < ( theEnd - data ) );
00153 if ( objcheck && !js.valid() ) {
00154 massert( 10307 , "Client Error: bad object in message", false);
00155 }
00156 nextjsobj += js.objsize();
00157 if ( nextjsobj >= theEnd )
00158 nextjsobj = 0;
00159 return js;
00160 }
00161
00162 const Message& msg() const { return m; }
00163
00164 void markSet() {
00165 mark = nextjsobj;
00166 }
00167
00168 void markReset() {
00169 assert( mark );
00170 nextjsobj = mark;
00171 }
00172
00173 private:
00174 const Message& m;
00175 int* reserved;
00176 const char *data;
00177 const char *nextjsobj;
00178 const char *theEnd;
00179
00180 const char * mark;
00181 };
00182
00183
00184
00185 class QueryMessage {
00186 public:
00187 const char *ns;
00188 int ntoskip;
00189 int ntoreturn;
00190 int queryOptions;
00191 BSONObj query;
00192 BSONObj fields;
00193
00194
00195 QueryMessage(DbMessage& d) {
00196 ns = d.getns();
00197 ntoskip = d.pullInt();
00198 ntoreturn = d.pullInt();
00199 query = d.nextJsObj();
00200 if ( d.moreJSObjs() ) {
00201 fields = d.nextJsObj();
00202 }
00203 queryOptions = d.msg().header()->dataAsInt();
00204 }
00205 };
00206
00207 }
00208
00209 #include "../client/dbclient.h"
00210
00211 namespace mongo {
00212
00213 inline void replyToQuery(int queryResultFlags,
00214 AbstractMessagingPort* p, Message& requestMsg,
00215 void *data, int size,
00216 int nReturned, int startingFrom = 0,
00217 long long cursorId = 0
00218 ) {
00219 BufBuilder b(32768);
00220 b.skip(sizeof(QueryResult));
00221 b.appendBuf(data, size);
00222 QueryResult *qr = (QueryResult *) b.buf();
00223 qr->_resultFlags() = queryResultFlags;
00224 qr->len = b.len();
00225 qr->setOperation(opReply);
00226 qr->cursorId = cursorId;
00227 qr->startingFrom = startingFrom;
00228 qr->nReturned = nReturned;
00229 b.decouple();
00230 Message resp(qr, true);
00231 p->reply(requestMsg, resp, requestMsg.header()->id);
00232 }
00233
00234 }
00235
00236
00237
00238 #include "instance.h"
00239
00240 namespace mongo {
00241
00242
00243 inline void replyToQuery(int queryResultFlags,
00244 AbstractMessagingPort* p, Message& requestMsg,
00245 BSONObj& responseObj) {
00246 replyToQuery(queryResultFlags,
00247 p, requestMsg,
00248 (void *) responseObj.objdata(), responseObj.objsize(), 1);
00249 }
00250
00251
00252 inline void replyToQuery(int queryResultFlags, Message &m, DbResponse &dbresponse, BSONObj obj) {
00253 BufBuilder b;
00254 b.skip(sizeof(QueryResult));
00255 b.appendBuf((void*) obj.objdata(), obj.objsize());
00256 QueryResult* msgdata = (QueryResult *) b.buf();
00257 b.decouple();
00258 QueryResult *qr = msgdata;
00259 qr->_resultFlags() = queryResultFlags;
00260 qr->len = b.len();
00261 qr->setOperation(opReply);
00262 qr->cursorId = 0;
00263 qr->startingFrom = 0;
00264 qr->nReturned = 1;
00265 Message *resp = new Message();
00266 resp->setData(msgdata, true);
00267 dbresponse.response = resp;
00268 dbresponse.responseTo = m.header()->id;
00269 }
00270
00271 string debugString( Message& m );
00272
00273 }