MongoDB C++ Driver  legacy-1.1.2
dbmessage.h
1 // dbmessage.h
2 
3 /* Copyright 2014 MongoDB Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #pragma once
19 
20 #include "mongo/bson/bson_validate.h"
21 #include "mongo/client/constants.h"
22 #include "mongo/db/jsobj.h"
23 #include "mongo/util/net/message.h"
24 #include "mongo/util/net/message_port.h"
25 
26 namespace mongo {
27 
28 /* db response format
29 
30  Query or GetMore: // see struct QueryResult
31  int resultFlags;
32  int64 cursorID;
33  int startingFrom;
34  int nReturned;
35  list of marshalled JSObjects;
36 */
37 
38 /* db request message format
39 
40  unsigned opid; // arbitary; will be echoed back
41  byte operation;
42  int options;
43 
44  then for:
45 
46  dbInsert:
47  string collection;
48  a series of JSObjects
49  dbDelete:
50  string collection;
51  int flags=0; // 1=DeleteSingle
52  JSObject query;
53  dbUpdate:
54  string collection;
55  int flags; // 1=upsert
56  JSObject query;
57  JSObject objectToUpdate;
58  objectToUpdate may include { $inc: <field> } or { $set: ... }, see struct Mod.
59  dbQuery:
60  string collection;
61  int nToSkip;
62  int nToReturn; // how many you want back as the beginning of the cursor data (0=no limit)
63  // greater than zero is simply a hint on how many objects to send back per
64  // "cursor batch". a negative number indicates a hard limit.
65  JSObject query;
66  [JSObject fieldsToReturn]
67  dbGetMore:
68  string collection; // redundant, might use for security.
69  int nToReturn;
70  int64 cursorID;
71  dbKillCursors=2007:
72  int n;
73  int64 cursorIDs[n];
74 
75  Note that on Update, there is only one object, which is different
76  from insert where you can pass a list of objects to insert in the db.
77  Note that the update field layout is very similar layout to Query.
78 */
79 
80 namespace QueryResult {
81 #pragma pack(1)
82 /* see http://dochub.mongodb.org/core/mongowireprotocol
83 */
84 struct Layout {
85  MsgData::Layout msgdata;
86  int64_t cursorId;
87  int32_t startingFrom;
88  int32_t nReturned;
89 };
90 #pragma pack()
91 
92 class ConstView {
93 public:
94  ConstView(const char* storage) : _storage(storage) {}
95 
96  const char* view2ptr() const {
97  return storage().view();
98  }
99 
100  MsgData::ConstView msgdata() const {
101  return storage().view(offsetof(Layout, msgdata));
102  }
103 
104  int64_t getCursorId() const {
105  return storage().readLE<int64_t>(offsetof(Layout, cursorId));
106  }
107 
108  int32_t getStartingFrom() const {
109  return storage().readLE<int32_t>(offsetof(Layout, startingFrom));
110  }
111 
112  int32_t getNReturned() const {
113  return storage().readLE<int32_t>(offsetof(Layout, nReturned));
114  }
115 
116  const char* data() const {
117  return storage().view(sizeof(Layout));
118  }
119 
120 protected:
121  const ConstDataView& storage() const {
122  return _storage;
123  }
124 
125 private:
126  ConstDataView _storage;
127 };
128 
129 class View : public ConstView {
130 public:
131  View(char* data) : ConstView(data) {}
132 
133  using ConstView::view2ptr;
134  char* view2ptr() {
135  return storage().view();
136  }
137 
138  using ConstView::msgdata;
139  MsgData::View msgdata() {
140  return storage().view(offsetof(Layout, msgdata));
141  }
142 
143  void setCursorId(int64_t value) {
144  storage().writeLE(value, offsetof(Layout, cursorId));
145  }
146 
147  void setStartingFrom(int32_t value) {
148  storage().writeLE(value, offsetof(Layout, startingFrom));
149  }
150 
151  void setNReturned(int32_t value) {
152  storage().writeLE(value, offsetof(Layout, nReturned));
153  }
154 
155  int32_t getResultFlags() {
156  return DataView(msgdata().data()).readLE<int32_t>();
157  }
158 
159  void setResultFlags(int32_t value) {
160  DataView(msgdata().data()).writeLE(value);
161  }
162 
163  void setResultFlagsToOk() {
164  setResultFlags(ResultFlag_AwaitCapable);
165  }
166 
167  void initializeResultFlags() {
168  setResultFlags(0);
169  }
170 
171 private:
172  DataView storage() const {
173  return const_cast<char*>(ConstView::view2ptr());
174  }
175 };
176 
177 class Value : public EncodedValueStorage<Layout, ConstView, View> {
178 public:
179  Value() {
180  BOOST_STATIC_ASSERT(sizeof(Value) == sizeof(Layout));
181  }
182 
184 };
185 
186 } // namespace QueryResult
187 
188 /* For the database/server protocol, these objects and functions encapsulate
189  the various messages transmitted over the connection.
190 
191  See http://dochub.mongodb.org/core/mongowireprotocol
192 */
193 class DbMessage {
194  // Assume sizeof(int) == 4 bytes
195  BOOST_STATIC_ASSERT(sizeof(int) == 4);
196 
197 public:
198  // Note: DbMessage constructor reads the first 4 bytes and stores it in reserved
199  DbMessage(const Message& msg);
200 
201  // Indicates whether this message is expected to have a ns
202  // or in the case of dbMsg, a string in the same place as ns
203  bool messageShouldHaveNs() const {
204  return (_msg.operation() >= dbMsg) & (_msg.operation() <= dbDelete);
205  }
206 
212  int reservedField() const {
213  return _reserved;
214  }
215 
216  const char* getns() const;
217  int getQueryNToReturn() const;
218 
219  int pullInt();
220  long long pullInt64();
221  const char* getArray(size_t count) const;
222 
223  /* for insert and update msgs */
224  bool moreJSObjs() const {
225  return _nextjsobj != 0;
226  }
227 
228  BSONObj nextJsObj();
229 
230  const Message& msg() const {
231  return _msg;
232  }
233 
234  const char* markGet() const {
235  return _nextjsobj;
236  }
237 
238  void markSet() {
239  _mark = _nextjsobj;
240  }
241 
242  void markReset(const char* toMark);
243 
244 private:
245  // Check if we have enough data to read
246  template <typename T>
247  void checkRead(const char* start, size_t count = 0) const;
248 
249  // Read some type without advancing our position
250  template <typename T>
251  T read() const;
252 
253  // Read some type, and advance our position
254  template <typename T>
255  T readAndAdvance();
256 
257  const Message& _msg;
258  int _reserved; // flags or zero depending on packet, starts the packet
259 
260  const char* _nsStart; // start of namespace string, +4 from message start
261  const char* _nextjsobj; // current position reading packet
262  const char* _theEnd; // end of packet
263 
264  const char* _mark;
265 
266  unsigned int _nsLen;
267 };
268 
269 
270 /* a request to run a query, received from the database */
272 public:
273  const char* ns;
274  int ntoskip;
275  int ntoreturn;
276  int queryOptions;
277  BSONObj query;
278  BSONObj fields;
279 
285  ns = d.getns();
286  ntoskip = d.pullInt();
287  ntoreturn = d.pullInt();
288  query = d.nextJsObj();
289  if (d.moreJSObjs()) {
290  fields = d.nextJsObj();
291  }
292  queryOptions = DataView(d.msg().header().data()).readLE<int32_t>();
293  }
294 };
295 
299 struct DbResponse {
300  Message* response;
301  MSGID responseTo;
302  std::string exhaustNS; /* points to ns if exhaust mode. 0=normal mode*/
303  DbResponse(Message* r, MSGID rt) : response(r), responseTo(rt) {}
304  DbResponse() {
305  response = 0;
306  }
307  ~DbResponse() {
308  delete response;
309  }
310 };
311 
312 void replyToQuery(int queryResultFlags,
314  Message& requestMsg,
315  void* data,
316  int size,
317  int nReturned,
318  int startingFrom = 0,
319  long long cursorId = 0);
320 
321 
322 /* object reply helper. */
323 void replyToQuery(int queryResultFlags,
325  Message& requestMsg,
326  const BSONObj& responseObj);
327 
328 /* helper to do a reply using a DbResponse object */
329 void replyToQuery(int queryResultFlags, Message& m, DbResponse& dbresponse, BSONObj obj);
330 
339 void replyToQuery(int queryResultFlags, Message& response, const BSONObj& resultObj);
340 } // namespace mongo
Definition: message_port.h:34
Definition: message.h:305
Utility functions for parsing numbers from strings.
Definition: compare_numbers.h:20
Definition: dbmessage.h:84
Definition: message.h:193
BSON classes.
Definition: data_view.h:30
Definition: dbmessage.h:177
Definition: dbmessage.h:193
Definition: dbmessage.h:271
Definition: encoded_value_storage.h:24
Definition: dbmessage.h:129
Definition: dbmessage.h:92
Definition: message.h:250
A response to a DbMessage.
Definition: dbmessage.h:299
QueryMessage(DbMessage &d)
parses the message into the above fields Warning: constructor mutates DbMessage.
Definition: dbmessage.h:284
Definition: message.h:187
Definition: encoded_value_storage.h:31
Definition: data_view.h:71
C++ representation of a "BSON" object – that is, an extended JSON-style object in a binary represent...
Definition: bsonobj.h:78
int reservedField() const
the 32 bit field before the ns track all bit usage here as its cross op 0: InsertOption_ContinueOnErr...
Definition: dbmessage.h:212