0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00
mongodb/db/dbmessage.h

265 lines
7.8 KiB
C
Raw Normal View History

2008-09-30 00:00:53 +02:00
/**
* Copyright (C) 2008 10gen Inc.
2008-12-29 02:28:49 +01:00
*
2008-09-30 00:00:53 +02:00
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
2008-12-29 02:28:49 +01:00
*
2008-09-30 00:00:53 +02:00
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
2008-12-29 02:28:49 +01:00
*
2008-09-30 00:00:53 +02:00
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2009-02-06 20:11:02 +01:00
#pragma once
2010-02-05 00:06:04 +01:00
#include "diskloc.h"
2008-09-30 00:00:53 +02:00
#include "jsobj.h"
2010-11-04 14:07:28 +01:00
#include "namespace-inl.h"
#include "../util/message.h"
2010-07-18 19:34:16 +02:00
#include "../client/constants.h"
2008-09-30 00:00:53 +02:00
2009-01-14 23:09:51 +01:00
namespace mongo {
2009-02-14 02:04:13 +01:00
/* db response format
Query or GetMore: // see struct QueryResult
int resultFlags;
int64 cursorID;
int startingFrom;
int nReturned;
list of marshalled JSObjects;
*/
extern bool objcheck;
2009-02-14 02:04:13 +01:00
#pragma pack(1)
struct QueryResult : public MsgData {
long long cursorId;
int startingFrom;
int nReturned;
const char *data() {
return (char *) (((int *)&nReturned)+1);
}
int resultFlags() {
2009-02-14 02:04:13 +01:00
return dataAsInt();
}
int& _resultFlags() {
return dataAsInt();
}
void setResultFlagsToOk() {
_resultFlags() = ResultFlag_AwaitCapable;
}
2009-02-14 02:04:13 +01:00
};
#pragma pack()
/* For the database/server protocol, these objects and functions encapsulate
the various messages transmitted over the connection.
2010-06-06 21:46:55 +02:00
See http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol
*/
class DbMessage {
public:
2010-06-06 21:46:55 +02:00
DbMessage(const Message& _m) : m(_m)
{
2010-05-13 00:26:00 +02:00
// for received messages, Message has only one buffer
theEnd = _m.singleData()->_data + _m.header()->dataLen();
2010-06-06 21:46:55 +02:00
char *r = _m.singleData()->_data;
reserved = (int *) r;
data = r + 4;
nextjsobj = data;
}
2008-12-29 02:28:49 +01:00
2010-06-06 21:46:55 +02:00
/** the 32 bit field before the ns */
int& reservedField() { return *reserved; }
const char * getns() const {
return data;
}
void getns(Namespace& ns) const {
ns = data;
}
const char * afterNS() const {
return data + strlen( data ) + 1;
}
2009-02-19 17:33:15 +01:00
int getInt( int num ) const {
const int * foo = (const int*)afterNS();
return foo[num];
}
int getQueryNToReturn() const {
return getInt( 1 );
}
2010-06-06 21:46:55 +02:00
void resetPull(){ nextjsobj = data; }
int pullInt() const { return pullInt(); }
int& pullInt() {
if ( nextjsobj == data )
nextjsobj += strlen(data) + 1; // skip namespace
2010-06-06 21:46:55 +02:00
int& i = *((int *)nextjsobj);
nextjsobj += 4;
return i;
}
2009-03-10 20:06:47 +01:00
long long pullInt64() const {
return pullInt64();
}
long long &pullInt64() {
if ( nextjsobj == data )
nextjsobj += strlen(data) + 1; // skip namespace
2009-03-10 20:06:47 +01:00
long long &i = *((long long *)nextjsobj);
nextjsobj += 8;
return i;
}
2008-12-29 02:28:49 +01:00
OID* getOID() const {
return (OID *) (data + strlen(data) + 1); // skip namespace
}
2008-12-29 02:28:49 +01:00
void getQueryStuff(const char *&query, int& ntoreturn) {
int *i = (int *) (data + strlen(data) + 1);
ntoreturn = *i;
i++;
query = (const char *) i;
}
2008-12-29 02:28:49 +01:00
/* for insert and update msgs */
bool moreJSObjs() const {
return nextjsobj != 0;
}
BSONObj nextJsObj() {
if ( nextjsobj == data ) {
nextjsobj += strlen(data) + 1; // skip namespace
massert( 13066 , "Message contains no documents", theEnd > nextjsobj );
}
2010-06-03 22:50:51 +02:00
massert( 10304 , "Client Error: Remaining data too small for BSON object", theEnd - nextjsobj > 3 );
BSONObj js(nextjsobj);
2010-06-03 22:50:51 +02:00
massert( 10305 , "Client Error: Invalid object size", js.objsize() > 3 );
massert( 10306 , "Client Error: Next object larger than space left in message",
2009-01-21 17:14:35 +01:00
js.objsize() < ( theEnd - data ) );
if ( objcheck && !js.valid() ) {
2010-06-03 22:50:51 +02:00
massert( 10307 , "Client Error: bad object in message", false);
}
2009-01-21 17:14:35 +01:00
nextjsobj += js.objsize();
if ( nextjsobj >= theEnd )
nextjsobj = 0;
return js;
2008-12-29 02:28:49 +01:00
}
2010-06-06 21:46:55 +02:00
const Message& msg() const { return m; }
2008-10-21 22:13:48 +02:00
void markSet(){
mark = nextjsobj;
}
void markReset(){
nextjsobj = mark;
}
private:
const Message& m;
2010-06-06 21:46:55 +02:00
int* reserved;
const char *data;
const char *nextjsobj;
const char *theEnd;
const char * mark;
};
/* a request to run a query, received from the database */
class QueryMessage {
public:
const char *ns;
int ntoskip;
int ntoreturn;
int queryOptions;
BSONObj query;
BSONObj fields;
/* parses the message into the above fields */
QueryMessage(DbMessage& d) {
ns = d.getns();
ntoskip = d.pullInt();
ntoreturn = d.pullInt();
query = d.nextJsObj();
if ( d.moreJSObjs() ) {
fields = d.nextJsObj();
}
2010-05-13 00:26:00 +02:00
queryOptions = d.msg().header()->dataAsInt();
2008-10-21 22:13:48 +02:00
}
};
2009-01-14 23:09:51 +01:00
} // namespace mongo
2008-12-29 02:28:49 +01:00
#include "../client/dbclient.h"
2009-01-14 23:09:51 +01:00
namespace mongo {
inline void replyToQuery(int queryResultFlags,
2009-03-02 05:43:00 +01:00
AbstractMessagingPort* p, Message& requestMsg,
void *data, int size,
int nReturned, int startingFrom = 0,
long long cursorId = 0
) {
BufBuilder b(32768);
b.skip(sizeof(QueryResult));
b.appendBuf(data, size);
QueryResult *qr = (QueryResult *) b.buf();
qr->_resultFlags() = queryResultFlags;
qr->len = b.len();
qr->setOperation(opReply);
qr->cursorId = cursorId;
qr->startingFrom = startingFrom;
2009-02-23 23:08:34 +01:00
qr->nReturned = nReturned;
b.decouple();
Message resp(qr, true);
2010-05-13 00:26:00 +02:00
p->reply(requestMsg, resp, requestMsg.header()->id);
}
2009-01-14 23:09:51 +01:00
} // namespace mongo
//#include "bsonobj.h"
2010-06-26 19:06:03 +02:00
2009-01-29 00:08:02 +01:00
#include "instance.h"
2009-01-14 23:09:51 +01:00
namespace mongo {
2009-01-29 00:08:02 +01:00
/* object reply helper. */
inline void replyToQuery(int queryResultFlags,
2009-03-02 05:43:00 +01:00
AbstractMessagingPort* p, Message& requestMsg,
BSONObj& responseObj)
{
replyToQuery(queryResultFlags,
p, requestMsg,
(void *) responseObj.objdata(), responseObj.objsize(), 1);
}
2009-01-14 23:09:51 +01:00
2009-01-29 00:08:02 +01:00
/* helper to do a reply using a DbResponse object */
inline void replyToQuery(int queryResultFlags, Message &m, DbResponse &dbresponse, BSONObj obj) {
BufBuilder b;
b.skip(sizeof(QueryResult));
b.appendBuf((void*) obj.objdata(), obj.objsize());
2009-01-29 00:08:02 +01:00
QueryResult* msgdata = (QueryResult *) b.buf();
b.decouple();
QueryResult *qr = msgdata;
qr->_resultFlags() = queryResultFlags;
2009-01-29 00:08:02 +01:00
qr->len = b.len();
qr->setOperation(opReply);
qr->cursorId = 0;
qr->startingFrom = 0;
qr->nReturned = 1;
Message *resp = new Message();
resp->setData(msgdata, true); // transport will free
dbresponse.response = resp;
2010-05-13 00:26:00 +02:00
dbresponse.responseTo = m.header()->id;
2009-01-29 00:08:02 +01:00
}
2010-07-23 22:06:06 +02:00
string debugString( Message& m );
2009-01-14 23:09:51 +01:00
} // namespace mongo