diff options
author | Eliot Horowitz <eliot@10gen.com> | 2011-12-24 15:33:26 -0500 |
---|---|---|
committer | Eliot Horowitz <eliot@10gen.com> | 2011-12-24 15:33:45 -0500 |
commit | ae1ecd9c786911f9f1f0242f0f7d702b3e5dfeba (patch) | |
tree | 92f8e1649e6f080b251ff5f1763679a72eb59b34 /src/mongo/db/dbmessage.h | |
parent | dfa4cd7e2cf109b072440155fabc08a93c8045a0 (diff) | |
download | mongo-ae1ecd9c786911f9f1f0242f0f7d702b3e5dfeba.tar.gz |
bulk move of code to src/ SERVER-4551
Diffstat (limited to 'src/mongo/db/dbmessage.h')
-rw-r--r-- | src/mongo/db/dbmessage.h | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/src/mongo/db/dbmessage.h b/src/mongo/db/dbmessage.h new file mode 100644 index 00000000000..a789bff849c --- /dev/null +++ b/src/mongo/db/dbmessage.h @@ -0,0 +1,282 @@ +// dbmessage.h + +/** +* Copyright (C) 2008 10gen Inc. +* +* 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. +* +* 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. +* +* 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/>. +*/ + +#pragma once + +#include "diskloc.h" +#include "jsobj.h" +#include "namespace-inl.h" +#include "../util/net/message.h" +#include "../client/constants.h" +#include "instance.h" + +namespace mongo { + + /* db response format + + Query or GetMore: // see struct QueryResult + int resultFlags; + int64 cursorID; + int startingFrom; + int nReturned; + list of marshalled JSObjects; + */ + +/* db request message format + + unsigned opid; // arbitary; will be echoed back + byte operation; + int options; + + then for: + + dbInsert: + string collection; + a series of JSObjects + dbDelete: + string collection; + int flags=0; // 1=DeleteSingle + JSObject query; + dbUpdate: + string collection; + int flags; // 1=upsert + JSObject query; + JSObject objectToUpdate; + objectToUpdate may include { $inc: <field> } or { $set: ... }, see struct Mod. + dbQuery: + string collection; + int nToSkip; + int nToReturn; // how many you want back as the beginning of the cursor data (0=no limit) + // greater than zero is simply a hint on how many objects to send back per "cursor batch". + // a negative number indicates a hard limit. + JSObject query; + [JSObject fieldsToReturn] + dbGetMore: + string collection; // redundant, might use for security. + int nToReturn; + int64 cursorID; + dbKillCursors=2007: + int n; + int64 cursorIDs[n]; + + Note that on Update, there is only one object, which is different + from insert where you can pass a list of objects to insert in the db. + Note that the update field layout is very similar layout to Query. +*/ + + +#pragma pack(1) + struct QueryResult : public MsgData { + long long cursorId; + int startingFrom; + int nReturned; + const char *data() { + return (char *) (((int *)&nReturned)+1); + } + int resultFlags() { + return dataAsInt(); + } + int& _resultFlags() { + return dataAsInt(); + } + void setResultFlagsToOk() { + _resultFlags() = ResultFlag_AwaitCapable; + } + void initializeResultFlags() { + _resultFlags() = 0; + } + }; + +#pragma pack() + + /* For the database/server protocol, these objects and functions encapsulate + the various messages transmitted over the connection. + + See http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol + */ + class DbMessage { + public: + DbMessage(const Message& _m) : m(_m) , mark(0) { + // for received messages, Message has only one buffer + theEnd = _m.singleData()->_data + _m.header()->dataLen(); + char *r = _m.singleData()->_data; + reserved = (int *) r; + data = r + 4; + nextjsobj = data; + } + + /** the 32 bit field before the ns + * track all bit usage here as its cross op + * 0: InsertOption_ContinueOnError + * 1: fromWriteback + */ + 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; + } + + int getInt( int num ) const { + const int * foo = (const int*)afterNS(); + return foo[num]; + } + + int getQueryNToReturn() const { + return getInt( 1 ); + } + + /** + * get an int64 at specified offsetBytes after ns + */ + long long getInt64( int offsetBytes ) const { + const char * x = afterNS(); + x += offsetBytes; + const long long * ll = (const long long*)x; + return ll[0]; + } + + void resetPull() { nextjsobj = data; } + int pullInt() const { return pullInt(); } + int& pullInt() { + if ( nextjsobj == data ) + nextjsobj += strlen(data) + 1; // skip namespace + int& i = *((int *)nextjsobj); + nextjsobj += 4; + return i; + } + long long pullInt64() const { + return pullInt64(); + } + long long &pullInt64() { + if ( nextjsobj == data ) + nextjsobj += strlen(data) + 1; // skip namespace + long long &i = *((long long *)nextjsobj); + nextjsobj += 8; + return i; + } + + OID* getOID() const { + return (OID *) (data + strlen(data) + 1); // skip namespace + } + + void getQueryStuff(const char *&query, int& ntoreturn) { + int *i = (int *) (data + strlen(data) + 1); + ntoreturn = *i; + i++; + query = (const char *) i; + } + + /* 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 ); + } + massert( 10304 , "Client Error: Remaining data too small for BSON object", theEnd - nextjsobj > 3 ); + BSONObj js(nextjsobj); + massert( 10305 , "Client Error: Invalid object size", js.objsize() > 3 ); + massert( 10306 , "Client Error: Next object larger than space left in message", + js.objsize() < ( theEnd - data ) ); + if ( cmdLine.objcheck && !js.valid() ) { + massert( 10307 , "Client Error: bad object in message", false); + } + nextjsobj += js.objsize(); + if ( nextjsobj >= theEnd ) + nextjsobj = 0; + return js; + } + + const Message& msg() const { return m; } + + void markSet() { + mark = nextjsobj; + } + + void markReset() { + assert( mark ); + nextjsobj = mark; + } + + private: + const Message& m; + int* reserved; + const char *data; + const char *nextjsobj; + const char *theEnd; + + const char * mark; + + public: + enum ReservedOptions { + Reserved_InsertOption_ContinueOnError = 1 << 0 , + Reserved_FromWriteback = 1 << 1 + }; + }; + + + /* 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(); + } + queryOptions = d.msg().header()->dataAsInt(); + } + }; + + void replyToQuery(int queryResultFlags, + AbstractMessagingPort* p, Message& requestMsg, + void *data, int size, + int nReturned, int startingFrom = 0, + long long cursorId = 0 + ); + + + /* object reply helper. */ + void replyToQuery(int queryResultFlags, + AbstractMessagingPort* p, Message& requestMsg, + BSONObj& responseObj); + + /* helper to do a reply using a DbResponse object */ + void replyToQuery(int queryResultFlags, Message &m, DbResponse &dbresponse, BSONObj obj); + + +} // namespace mongo |