9c665ee8aadcf325cd10e57fcd26637218d857cc
[aai/esr-gui.git] /
1 "use strict";
2
3 var MongoError = require('../error');
4
5 // Wire command operation ids
6 var OP_UPDATE = 2001;
7 var OP_INSERT = 2002;
8 var OP_DELETE = 2006;
9
10 var Insert = function(requestId, ismaster, bson, ns, documents, options) {
11   // Basic options needed to be passed in
12   if(ns == null) throw new MongoError("ns must be specified for query");
13   if(!Array.isArray(documents) || documents.length == 0) throw new MongoError("documents array must contain at least one document to insert");
14
15   // Validate that we are not passing 0x00 in the colletion name
16   if(!!~ns.indexOf("\x00")) {
17     throw new MongoError("namespace cannot contain a null character");
18   }
19
20   // Set internal
21   this.requestId = requestId;
22   this.bson = bson;
23   this.ns = ns;
24   this.documents = documents;
25   this.ismaster = ismaster;
26
27   // Ensure empty options
28   options = options || {};
29
30   // Unpack options
31   this.serializeFunctions = typeof options.serializeFunctions == 'boolean' ? options.serializeFunctions : false;
32   this.ignoreUndefined = typeof options.ignoreUndefined == 'boolean' ? options.ignoreUndefined : false;
33   this.checkKeys = typeof options.checkKeys == 'boolean' ? options.checkKeys : true;
34   this.continueOnError = typeof options.continueOnError == 'boolean' ? options.continueOnError : false;
35   // Set flags
36   this.flags = this.continueOnError ? 1 : 0;
37 }
38
39 // To Binary
40 Insert.prototype.toBin = function() {
41   // Contains all the buffers to be written
42   var buffers = [];
43
44   // Header buffer
45   var header = new Buffer(
46     4 * 4 // Header
47     + 4   // Flags
48     + Buffer.byteLength(this.ns) + 1 // namespace
49   );
50
51   // Add header to buffers
52   buffers.push(header);
53
54   // Total length of the message
55   var totalLength = header.length;
56
57   // Serialize all the documents
58   for(var i = 0; i < this.documents.length; i++) {
59     var buffer = this.bson.serialize(this.documents[i]
60       , this.checkKeys
61       , true
62       , this.serializeFunctions
63       , 0, this.ignoreUndefined);
64
65     // Document is larger than maxBsonObjectSize, terminate serialization
66     if(buffer.length > this.ismaster.maxBsonObjectSize) {
67       throw new MongoError("Document exceeds maximum allowed bson size of " + this.ismaster.maxBsonObjectSize + " bytes");
68     }
69
70     // Add to total length of wire protocol message
71     totalLength = totalLength + buffer.length;
72     // Add to buffer
73     buffers.push(buffer);
74   }
75
76   // Command is larger than maxMessageSizeBytes terminate serialization
77   if(totalLength > this.ismaster.maxMessageSizeBytes) {
78     throw new MongoError("Command exceeds maximum message size of " + this.ismaster.maxMessageSizeBytes + " bytes");
79   }
80
81   // Add all the metadata
82   var index = 0;
83
84   // Write header length
85   header[index + 3] = (totalLength >> 24) & 0xff;
86   header[index + 2] = (totalLength >> 16) & 0xff;
87   header[index + 1] = (totalLength >> 8) & 0xff;
88   header[index] = (totalLength) & 0xff;
89   index = index + 4;
90
91   // Write header requestId
92   header[index + 3] = (this.requestId >> 24) & 0xff;
93   header[index + 2] = (this.requestId >> 16) & 0xff;
94   header[index + 1] = (this.requestId >> 8) & 0xff;
95   header[index] = (this.requestId) & 0xff;
96   index = index + 4;
97
98   // No flags
99   header[index + 3] = (0 >> 24) & 0xff;
100   header[index + 2] = (0 >> 16) & 0xff;
101   header[index + 1] = (0 >> 8) & 0xff;
102   header[index] = (0) & 0xff;
103   index = index + 4;
104
105   // Operation
106   header[index + 3] = (OP_INSERT >> 24) & 0xff;
107   header[index + 2] = (OP_INSERT >> 16) & 0xff;
108   header[index + 1] = (OP_INSERT >> 8) & 0xff;
109   header[index] = (OP_INSERT) & 0xff;
110   index = index + 4;
111
112   // Flags
113   header[index + 3] = (this.flags >> 24) & 0xff;
114   header[index + 2] = (this.flags >> 16) & 0xff;
115   header[index + 1] = (this.flags >> 8) & 0xff;
116   header[index] = (this.flags) & 0xff;
117   index = index + 4;
118
119   // Write collection name
120   index = index + header.write(this.ns, index, 'utf8') + 1;
121   header[index - 1] = 0;
122
123   // Return the buffers
124   return buffers;
125 }
126
127 var Update = function(requestId, ismaster, bson, ns, update, options) {
128   // Basic options needed to be passed in
129   if(ns == null) throw new MongoError("ns must be specified for query");
130
131   // Ensure empty options
132   options = options || {};
133
134   // Set internal
135   this.requestId = requestId;
136   this.bson = bson;
137   this.ns = ns;
138   this.ismaster = ismaster;
139
140   // Unpack options
141   this.serializeFunctions = typeof options.serializeFunctions == 'boolean' ? options.serializeFunctions : false;
142   this.ignoreUndefined = typeof options.ignoreUndefined == 'boolean' ? options.ignoreUndefined : false;
143   this.checkKeys = typeof options.checkKeys == 'boolean' ? options.checkKeys : false;
144
145   // Unpack the update document
146   this.upsert = typeof update[0].upsert == 'boolean' ? update[0].upsert : false;
147   this.multi = typeof update[0].multi == 'boolean' ? update[0].multi : false;
148   this.q = update[0].q;
149   this.u = update[0].u;
150
151   // Create flag value
152   this.flags = this.upsert ? 1 : 0;
153   this.flags = this.multi ? this.flags | 2 : this.flags;
154 }
155
156 // To Binary
157 Update.prototype.toBin = function() {
158   // Contains all the buffers to be written
159   var buffers = [];
160
161   // Header buffer
162   var header = new Buffer(
163     4 * 4 // Header
164     + 4   // ZERO
165     + Buffer.byteLength(this.ns) + 1 // namespace
166     + 4   // Flags
167   );
168
169   // Add header to buffers
170   buffers.push(header);
171
172   // Total length of the message
173   var totalLength = header.length;
174
175   // Serialize the selector
176   var selector = this.bson.serialize(this.q
177     , this.checkKeys
178     , true
179     , this.serializeFunctions
180     , 0, this.ignoreUndefined);
181   buffers.push(selector);
182   totalLength = totalLength + selector.length;
183
184   // Serialize the update
185   var update = this.bson.serialize(this.u
186     , this.checkKeys
187     , true
188     , this.serializeFunctions
189     , 0, this.ignoreUndefined);
190   buffers.push(update);
191   totalLength = totalLength + update.length;
192
193   // Index in header buffer
194   var index = 0;
195
196   // Write header length
197   header[index + 3] = (totalLength >> 24) & 0xff;
198   header[index + 2] = (totalLength >> 16) & 0xff;
199   header[index + 1] = (totalLength >> 8) & 0xff;
200   header[index] = (totalLength) & 0xff;
201   index = index + 4;
202
203   // Write header requestId
204   header[index + 3] = (this.requestId >> 24) & 0xff;
205   header[index + 2] = (this.requestId >> 16) & 0xff;
206   header[index + 1] = (this.requestId >> 8) & 0xff;
207   header[index] = (this.requestId) & 0xff;
208   index = index + 4;
209
210   // No flags
211   header[index + 3] = (0 >> 24) & 0xff;
212   header[index + 2] = (0 >> 16) & 0xff;
213   header[index + 1] = (0 >> 8) & 0xff;
214   header[index] = (0) & 0xff;
215   index = index + 4;
216
217   // Operation
218   header[index + 3] = (OP_UPDATE >> 24) & 0xff;
219   header[index + 2] = (OP_UPDATE >> 16) & 0xff;
220   header[index + 1] = (OP_UPDATE >> 8) & 0xff;
221   header[index] = (OP_UPDATE) & 0xff;
222   index = index + 4;
223
224   // Write ZERO
225   header[index + 3] = (0 >> 24) & 0xff;
226   header[index + 2] = (0 >> 16) & 0xff;
227   header[index + 1] = (0 >> 8) & 0xff;
228   header[index] = (0) & 0xff;
229   index = index + 4;
230
231   // Write collection name
232   index = index + header.write(this.ns, index, 'utf8') + 1;
233   header[index - 1] = 0;
234
235   // Flags
236   header[index + 3] = (this.flags >> 24) & 0xff;
237   header[index + 2] = (this.flags >> 16) & 0xff;
238   header[index + 1] = (this.flags >> 8) & 0xff;
239   header[index] = (this.flags) & 0xff;
240   index = index + 4;
241
242   // Return the buffers
243   return buffers;
244 }
245
246 var Remove = function(requestId, ismaster, bson, ns, remove, options) {
247   // Basic options needed to be passed in
248   if(ns == null) throw new MongoError("ns must be specified for query");
249
250   // Ensure empty options
251   options = options || {};
252
253   // Set internal
254   this.requestId = requestId;
255   this.bson = bson;
256   this.ns = ns;
257   this.ismaster = ismaster;
258
259   // Unpack options
260   this.serializeFunctions = typeof options.serializeFunctions == 'boolean' ? options.serializeFunctions : false;
261   this.ignoreUndefined = typeof options.ignoreUndefined == 'boolean' ? options.ignoreUndefined : false;
262   this.checkKeys = typeof options.checkKeys == 'boolean' ? options.checkKeys : false;
263
264   // Unpack the update document
265   this.limit = typeof remove[0].limit == 'number' ? remove[0].limit : 1;
266   this.q = remove[0].q;
267
268   // Create flag value
269   this.flags = this.limit == 1 ? 1 : 0;
270 }
271
272 // To Binary
273 Remove.prototype.toBin = function() {
274   // Contains all the buffers to be written
275   var buffers = [];
276
277   // Header buffer
278   var header = new Buffer(
279     4 * 4 // Header
280     + 4   // ZERO
281     + Buffer.byteLength(this.ns) + 1 // namespace
282     + 4   // Flags
283   );
284
285   // Add header to buffers
286   buffers.push(header);
287
288   // Total length of the message
289   var totalLength = header.length;
290
291   // Serialize the selector
292   var selector = this.bson.serialize(this.q
293     , this.checkKeys
294     , true
295     , this.serializeFunctions
296     , 0, this.ignoreUndefined);
297   buffers.push(selector);
298   totalLength = totalLength + selector.length;
299
300   // Index in header buffer
301   var index = 0;
302
303   // Write header length
304   header[index + 3] = (totalLength >> 24) & 0xff;
305   header[index + 2] = (totalLength >> 16) & 0xff;
306   header[index + 1] = (totalLength >> 8) & 0xff;
307   header[index] = (totalLength) & 0xff;
308   index = index + 4;
309
310   // Write header requestId
311   header[index + 3] = (this.requestId >> 24) & 0xff;
312   header[index + 2] = (this.requestId >> 16) & 0xff;
313   header[index + 1] = (this.requestId >> 8) & 0xff;
314   header[index] = (this.requestId) & 0xff;
315   index = index + 4;
316
317   // No flags
318   header[index + 3] = (0 >> 24) & 0xff;
319   header[index + 2] = (0 >> 16) & 0xff;
320   header[index + 1] = (0 >> 8) & 0xff;
321   header[index] = (0) & 0xff;
322   index = index + 4;
323
324   // Operation
325   header[index + 3] = (OP_DELETE >> 24) & 0xff;
326   header[index + 2] = (OP_DELETE >> 16) & 0xff;
327   header[index + 1] = (OP_DELETE >> 8) & 0xff;
328   header[index] = (OP_DELETE) & 0xff;
329   index = index + 4;
330
331   // Write ZERO
332   header[index + 3] = (0 >> 24) & 0xff;
333   header[index + 2] = (0 >> 16) & 0xff;
334   header[index + 1] = (0 >> 8) & 0xff;
335   header[index] = (0) & 0xff;
336   index = index + 4;
337
338   // Write collection name
339   index = index + header.write(this.ns, index, 'utf8') + 1;
340   header[index - 1] = 0;
341
342   // Write ZERO
343   header[index + 3] = (this.flags >> 24) & 0xff;
344   header[index + 2] = (this.flags >> 16) & 0xff;
345   header[index + 1] = (this.flags >> 8) & 0xff;
346   header[index] = (this.flags) & 0xff;
347   index = index + 4;
348
349   // Return the buffers
350   return buffers;
351 }
352
353 module.exports = {
354     Insert: Insert
355   , Update: Update
356   , Remove: Remove
357 }