mongodb 2.1.0-alpha → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/HISTORY.md +574 -429
  2. package/Makefile +2 -5
  3. package/README.md +108 -15
  4. package/conf.json +17 -13
  5. package/index.js +13 -2
  6. package/lib/admin.js +113 -47
  7. package/lib/aggregation_cursor.js +56 -28
  8. package/lib/apm.js +608 -0
  9. package/lib/bulk/common.js +7 -7
  10. package/lib/bulk/ordered.js +56 -17
  11. package/lib/bulk/unordered.js +52 -14
  12. package/lib/collection.js +671 -212
  13. package/lib/command_cursor.js +60 -32
  14. package/lib/cursor.js +313 -115
  15. package/lib/db.js +264 -105
  16. package/lib/gridfs/chunk.js +26 -29
  17. package/lib/gridfs/grid_store.js +150 -64
  18. package/lib/gridfs-stream/download.js +310 -0
  19. package/lib/gridfs-stream/index.js +335 -0
  20. package/lib/gridfs-stream/upload.js +450 -0
  21. package/lib/metadata.js +64 -0
  22. package/lib/mongo_client.js +69 -39
  23. package/lib/mongos.js +65 -20
  24. package/lib/replset.js +69 -34
  25. package/lib/server.js +35 -1
  26. package/lib/topology_base.js +22 -10
  27. package/lib/url_parser.js +111 -13
  28. package/lib/utils.js +9 -8
  29. package/mongolabs.js +427 -0
  30. package/package.json +8 -6
  31. package/t.js +68 -51
  32. package/test.js +12 -0
  33. package/test_boot/boot.sh +3 -0
  34. package/test_boot/ca.pem +49 -0
  35. package/test_boot/client.pem +48 -0
  36. package/test_boot/client_password.pem +51 -0
  37. package/test_boot/connect.js +29 -0
  38. package/test_boot/data/WiredTiger +2 -0
  39. package/test_boot/data/WiredTiger.lock +1 -0
  40. package/test_boot/data/WiredTiger.turtle +6 -0
  41. package/test_boot/data/WiredTiger.wt +0 -0
  42. package/test_boot/data/WiredTigerLAS.wt +0 -0
  43. package/test_boot/data/_mdb_catalog.wt +0 -0
  44. package/test_boot/data/collection-0-757073248613337118.wt +0 -0
  45. package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-44-37Z-00000 +0 -0
  46. package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-45-15Z-00000 +0 -0
  47. package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-46-31Z-00000 +0 -0
  48. package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-47-25Z-00000 +0 -0
  49. package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-49-07Z-00000 +0 -0
  50. package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-50-41Z-00000 +0 -0
  51. package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-50-53Z-00000 +0 -0
  52. package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-52-31Z-00000 +0 -0
  53. package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-54-53Z-00000 +0 -0
  54. package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-55-09Z-00000 +0 -0
  55. package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-55-38Z-00000 +0 -0
  56. package/test_boot/data/index-1-757073248613337118.wt +0 -0
  57. package/test_boot/data/mongod.lock +0 -0
  58. package/test_boot/data/sizeStorer.wt +0 -0
  59. package/test_boot/data/storage.bson +0 -0
  60. package/test_boot/server_password.pem +51 -0
  61. package/.travis.yml +0 -10
  62. package/t1.js +0 -59
  63. package/wercker.yml +0 -19
package/lib/apm.js ADDED
@@ -0,0 +1,608 @@
1
+ var EventEmitter = require('events').EventEmitter,
2
+ inherits = require('util').inherits;
3
+
4
+ // Get prototypes
5
+ var AggregationCursor = require('./aggregation_cursor'),
6
+ CommandCursor = require('./command_cursor'),
7
+ OrderedBulkOperation = require('./bulk/ordered').OrderedBulkOperation,
8
+ UnorderedBulkOperation = require('./bulk/unordered').UnorderedBulkOperation,
9
+ GridStore = require('./gridfs/grid_store'),
10
+ Server = require('./server'),
11
+ ReplSet = require('./replset'),
12
+ Mongos = require('./mongos'),
13
+ Cursor = require('./cursor'),
14
+ Collection = require('./collection'),
15
+ Db = require('./db'),
16
+ Admin = require('./admin');
17
+
18
+ var basicOperationIdGenerator = {
19
+ operationId: 1,
20
+
21
+ next: function() {
22
+ return this.operationId++;
23
+ }
24
+ }
25
+
26
+ var basicTimestampGenerator = {
27
+ current: function() {
28
+ return new Date().getTime();
29
+ },
30
+
31
+ duration: function(start, end) {
32
+ return end - start;
33
+ }
34
+ }
35
+
36
+ var senstiveCommands = ['authenticate', 'saslStart', 'saslContinue', 'getnonce',
37
+ 'createUser', 'updateUser', 'copydbgetnonce', 'copydbsaslstart', 'copydb'];
38
+
39
+ var Instrumentation = function(core, options, callback) {
40
+ options = options || {};
41
+
42
+ // Optional id generators
43
+ var operationIdGenerator = options.operationIdGenerator || basicOperationIdGenerator;
44
+ // Optional timestamp generator
45
+ var timestampGenerator = options.timestampGenerator || basicTimestampGenerator;
46
+ // Extend with event emitter functionality
47
+ EventEmitter.call(this);
48
+
49
+ // Contains all the instrumentation overloads
50
+ this.overloads = [];
51
+
52
+ // ---------------------------------------------------------
53
+ //
54
+ // Instrument prototype
55
+ //
56
+ // ---------------------------------------------------------
57
+
58
+ var instrumentPrototype = function(callback) {
59
+ var instrumentations = []
60
+
61
+ // Classes to support
62
+ var classes = [GridStore, OrderedBulkOperation, UnorderedBulkOperation,
63
+ CommandCursor, AggregationCursor, Cursor, Collection, Db];
64
+
65
+ // Add instrumentations to the available list
66
+ for(var i = 0; i < classes.length; i++) {
67
+ if(classes[i].define) {
68
+ instrumentations.push(classes[i].define.generate());
69
+ }
70
+ }
71
+
72
+ // Return the list of instrumentation points
73
+ callback(null, instrumentations);
74
+ }
75
+
76
+ // Did the user want to instrument the prototype
77
+ if(typeof callback == 'function') {
78
+ instrumentPrototype(callback);
79
+ }
80
+
81
+ // ---------------------------------------------------------
82
+ //
83
+ // Server
84
+ //
85
+ // ---------------------------------------------------------
86
+
87
+ // Reference
88
+ var self = this;
89
+ // Names of methods we need to wrap
90
+ var methods = ['command', 'insert', 'update', 'remove'];
91
+ // Prototype
92
+ var proto = core.Server.prototype;
93
+ // Core server method we are going to wrap
94
+ methods.forEach(function(x) {
95
+ var func = proto[x];
96
+
97
+ // Add to overloaded methods
98
+ self.overloads.push({proto: proto, name:x, func:func});
99
+
100
+ // The actual prototype
101
+ proto[x] = function() {
102
+ var requestId = core.Query.nextRequestId();
103
+ // Get the aruments
104
+ var args = Array.prototype.slice.call(arguments, 0);
105
+ var ns = args[0];
106
+ var commandObj = args[1];
107
+ var options = args[2] || {};
108
+ var keys = Object.keys(commandObj);
109
+ var commandName = keys[0];
110
+ var db = ns.split('.')[0];
111
+
112
+ // Do we have a legacy insert/update/remove command
113
+ if(x == 'insert' && !this.lastIsMaster().maxWireVersion) {
114
+ commandName = 'insert';
115
+ // Get the collection
116
+ var col = ns.split('.');
117
+ col.shift();
118
+ col = col.join('.');
119
+
120
+ // Re-write the command
121
+ commandObj = {
122
+ insert: col, documents: commandObj
123
+ }
124
+
125
+ if(options.writeConcern && Object.keys(options.writeConcern).length > 0) {
126
+ commandObj.writeConcern = options.writeConcern;
127
+ }
128
+
129
+ commandObj.ordered = options.ordered != undefined ? options.ordered : true;
130
+ } else if(x == 'update' && !this.lastIsMaster().maxWireVersion) {
131
+ commandName = 'update';
132
+
133
+ // Get the collection
134
+ var col = ns.split('.');
135
+ col.shift();
136
+ col = col.join('.');
137
+
138
+ // Re-write the command
139
+ commandObj = {
140
+ update: col, updates: commandObj
141
+ }
142
+
143
+ if(options.writeConcern && Object.keys(options.writeConcern).length > 0) {
144
+ commandObj.writeConcern = options.writeConcern;
145
+ }
146
+
147
+ commandObj.ordered = options.ordered != undefined ? options.ordered : true;
148
+ } else if(x == 'remove' && !this.lastIsMaster().maxWireVersion) {
149
+ commandName = 'delete';
150
+
151
+ // Get the collection
152
+ var col = ns.split('.');
153
+ col.shift();
154
+ col = col.join('.');
155
+
156
+ // Re-write the command
157
+ commandObj = {
158
+ delete: col, deletes: commandObj
159
+ }
160
+
161
+ if(options.writeConcern && Object.keys(options.writeConcern).length > 0) {
162
+ commandObj.writeConcern = options.writeConcern;
163
+ }
164
+
165
+ commandObj.ordered = options.ordered != undefined ? options.ordered : true;
166
+ } else if(x == 'insert' || x == 'update' || x == 'remove' && this.lastIsMaster().maxWireVersion >= 2) {
167
+ // Skip the insert/update/remove commands as they are executed as actual write commands in 2.6 or higher
168
+ return func.apply(this, args);
169
+ }
170
+
171
+ // Get the callback
172
+ var callback = args.pop();
173
+ // Set current callback operation id from the current context or create
174
+ // a new one
175
+ var ourOpId = callback.operationId || operationIdGenerator.next();
176
+
177
+ // Get a connection reference for this server instance
178
+ var connection = this.s.pool.get()
179
+
180
+ // Emit the start event for the command
181
+ var command = {
182
+ // Returns the command.
183
+ command: commandObj,
184
+ // Returns the database name.
185
+ databaseName: db,
186
+ // Returns the command name.
187
+ commandName: commandName,
188
+ // Returns the driver generated request id.
189
+ requestId: requestId,
190
+ // Returns the driver generated operation id.
191
+ // This is used to link events together such as bulk write operations. OPTIONAL.
192
+ operationId: ourOpId,
193
+ // Returns the connection id for the command. For languages that do not have this,
194
+ // this MUST return the driver equivalent which MUST include the server address and port.
195
+ // The name of this field is flexible to match the object that is returned from the driver.
196
+ connectionId: connection
197
+ };
198
+
199
+ // Filter out any sensitive commands
200
+ if(senstiveCommands.indexOf(commandName.toLowerCase())) {
201
+ command.commandObj = {};
202
+ command.commandObj[commandName] = true;
203
+ }
204
+
205
+ // Emit the started event
206
+ self.emit('started', command)
207
+
208
+ // Start time
209
+ var startTime = timestampGenerator.current();
210
+
211
+ // Push our handler callback
212
+ args.push(function(err, r) {
213
+ var endTime = timestampGenerator.current();
214
+ var command = {
215
+ duration: timestampGenerator.duration(startTime, endTime),
216
+ commandName: commandName,
217
+ requestId: requestId,
218
+ operationId: ourOpId,
219
+ connectionId: connection
220
+ };
221
+
222
+ // If we have an error
223
+ if(err || (r && r.result && r.result.ok == 0)) {
224
+ command.failure = err || r.result.writeErrors || r.result;
225
+
226
+ // Filter out any sensitive commands
227
+ if(senstiveCommands.indexOf(commandName.toLowerCase())) {
228
+ command.failure = {};
229
+ }
230
+
231
+ self.emit('failed', command);
232
+ } else if(commandObj && commandObj.writeConcern
233
+ && commandObj.writeConcern.w == 0) {
234
+ // If we have write concern 0
235
+ command.reply = {ok:1};
236
+ self.emit('succeeded', command);
237
+ } else {
238
+ command.reply = r && r.result ? r.result : r;
239
+
240
+ // Filter out any sensitive commands
241
+ if(senstiveCommands.indexOf(commandName.toLowerCase()) != -1) {
242
+ command.reply = {};
243
+ }
244
+
245
+ self.emit('succeeded', command);
246
+ }
247
+
248
+ // Return to caller
249
+ callback(err, r);
250
+ });
251
+
252
+ // Apply the call
253
+ func.apply(this, args);
254
+ }
255
+ });
256
+
257
+ // ---------------------------------------------------------
258
+ //
259
+ // Bulk Operations
260
+ //
261
+ // ---------------------------------------------------------
262
+
263
+ // Inject ourselves into the Bulk methods
264
+ var methods = ['execute'];
265
+ var prototypes = [
266
+ require('./bulk/ordered').Bulk.prototype,
267
+ require('./bulk/unordered').Bulk.prototype
268
+ ]
269
+
270
+ prototypes.forEach(function(proto) {
271
+ // Core server method we are going to wrap
272
+ methods.forEach(function(x) {
273
+ var func = proto[x];
274
+
275
+ // Add to overloaded methods
276
+ self.overloads.push({proto: proto, name:x, func:func});
277
+
278
+ // The actual prototype
279
+ proto[x] = function() {
280
+ var bulk = this;
281
+ // Get the aruments
282
+ var args = Array.prototype.slice.call(arguments, 0);
283
+ // Set an operation Id on the bulk object
284
+ this.operationId = operationIdGenerator.next();
285
+
286
+ // Get the callback
287
+ var callback = args.pop();
288
+ // If we have a callback use this
289
+ if(typeof callback == 'function') {
290
+ args.push(function(err, r) {
291
+ // Return to caller
292
+ callback(err, r);
293
+ });
294
+
295
+ // Apply the call
296
+ func.apply(this, args);
297
+ } else {
298
+ return func.apply(this, args);
299
+ }
300
+ }
301
+ });
302
+ });
303
+
304
+ // ---------------------------------------------------------
305
+ //
306
+ // Cursor
307
+ //
308
+ // ---------------------------------------------------------
309
+
310
+ // Inject ourselves into the Cursor methods
311
+ var methods = ['_find', '_getmore', '_killcursor'];
312
+ var prototypes = [
313
+ require('./cursor').prototype,
314
+ require('./command_cursor').prototype,
315
+ require('./aggregation_cursor').prototype
316
+ ]
317
+
318
+ // Command name translation
319
+ var commandTranslation = {
320
+ '_find': 'find', '_getmore': 'getMore', '_killcursor': 'killCursors', '_explain': 'explain'
321
+ }
322
+
323
+ prototypes.forEach(function(proto) {
324
+
325
+ // Core server method we are going to wrap
326
+ methods.forEach(function(x) {
327
+ var func = proto[x];
328
+
329
+ // Add to overloaded methods
330
+ self.overloads.push({proto: proto, name:x, func:func});
331
+
332
+ // The actual prototype
333
+ proto[x] = function() {
334
+ var cursor = this;
335
+ var requestId = core.Query.nextRequestId();
336
+ var ourOpId = operationIdGenerator.next();
337
+ var parts = this.ns.split('.');
338
+ var db = parts[0];
339
+
340
+ // Get the collection
341
+ parts.shift();
342
+ var collection = parts.join('.');
343
+
344
+ // Set the command
345
+ var command = this.query;
346
+ var cmd = this.s.cmd;
347
+
348
+ // If we have a find method, set the operationId on the cursor
349
+ if(x == '_find') {
350
+ cursor.operationId = ourOpId;
351
+ }
352
+
353
+ // Do we have a find command rewrite it
354
+ if(x == '_getmore') {
355
+ command = {
356
+ getMore: this.cursorState.cursorId,
357
+ collection: collection,
358
+ batchSize: cmd.batchSize
359
+ }
360
+
361
+ if(cmd.maxTimeMS) command.maxTimeMS = cmd.maxTimeMS;
362
+ } else if(x == '_killcursors') {
363
+ command = {
364
+ killCursors: collection,
365
+ cursors: [this.cursorState.cursorId]
366
+ }
367
+ } else if(cmd.find) {
368
+ command = {
369
+ find: collection, filter: cmd.query
370
+ }
371
+
372
+ if(cmd.sort) command.sort = cmd.sort;
373
+ if(cmd.fields) command.projection = cmd.fields;
374
+ if(cmd.limit && cmd.limit < 0) {
375
+ command.limit = Math.abs(cmd.limit);
376
+ command.singleBatch = true;
377
+ } else if(cmd.limit) {
378
+ command.limit = Math.abs(cmd.limit);
379
+ }
380
+
381
+ // Options
382
+ if(cmd.skip) command.skip = cmd.skip;
383
+ if(cmd.hint) command.hint = cmd.hint;
384
+ if(cmd.batchSize) command.batchSize = cmd.batchSize;
385
+ if(typeof cmd.returnKey == 'boolean') command.returnKey = cmd.returnKey;
386
+ if(cmd.comment) command.comment = cmd.comment;
387
+ if(cmd.min) command.min = cmd.min;
388
+ if(cmd.max) command.max = cmd.max;
389
+ if(cmd.maxScan) command.maxScan = cmd.maxScan;
390
+ if(cmd.maxTimeMS) command.maxTimeMS = cmd.maxTimeMS;
391
+
392
+ // Flags
393
+ if(typeof cmd.awaitData == 'boolean') command.awaitData = cmd.awaitData;
394
+ if(typeof cmd.snapshot == 'boolean') command.snapshot = cmd.snapshot;
395
+ if(typeof cmd.tailable == 'boolean') command.tailable = cmd.tailable;
396
+ if(typeof cmd.oplogReplay == 'boolean') command.oplogReplay = cmd.oplogReplay;
397
+ if(typeof cmd.noCursorTimeout == 'boolean') command.noCursorTimeout = cmd.noCursorTimeout;
398
+ if(typeof cmd.partial == 'boolean') command.partial = cmd.partial;
399
+ if(typeof cmd.showDiskLoc == 'boolean') command.showRecordId = cmd.showDiskLoc;
400
+
401
+ // Read Concern
402
+ if(cmd.readConcern) command.readConcern = cmd.readConcern;
403
+
404
+ // Override method
405
+ if(cmd.explain) command.explain = cmd.explain;
406
+ if(cmd.exhaust) command.exhaust = cmd.exhaust;
407
+
408
+ // If we have a explain flag
409
+ if(cmd.explain) {
410
+ // Create fake explain command
411
+ command = {
412
+ explain: command,
413
+ verbosity: 'allPlansExecution'
414
+ }
415
+
416
+ // Set readConcern on the command if available
417
+ if(cmd.readConcern) command.readConcern = cmd.readConcern
418
+
419
+ // Set up the _explain name for the command
420
+ x = '_explain';
421
+ }
422
+ } else {
423
+ command = cmd;
424
+ }
425
+
426
+ // Set up the connection
427
+ var connectionId = null;
428
+
429
+ // Set local connection
430
+ if(this.connection) connectionId = this.connection;
431
+ if(!connectionId && this.server && this.server.getConnection) connectionId = this.server.getConnection();
432
+
433
+ // Get the command Name
434
+ var commandName = x == '_find' ? Object.keys(command)[0] : commandTranslation[x];
435
+
436
+ // Emit the start event for the command
437
+ var command = {
438
+ // Returns the command.
439
+ command: command,
440
+ // Returns the database name.
441
+ databaseName: db,
442
+ // Returns the command name.
443
+ commandName: commandName,
444
+ // Returns the driver generated request id.
445
+ requestId: requestId,
446
+ // Returns the driver generated operation id.
447
+ // This is used to link events together such as bulk write operations. OPTIONAL.
448
+ operationId: this.operationId,
449
+ // Returns the connection id for the command. For languages that do not have this,
450
+ // this MUST return the driver equivalent which MUST include the server address and port.
451
+ // The name of this field is flexible to match the object that is returned from the driver.
452
+ connectionId: connectionId
453
+ };
454
+
455
+ // Get the aruments
456
+ var args = Array.prototype.slice.call(arguments, 0);
457
+
458
+ // Get the callback
459
+ var callback = args.pop();
460
+
461
+ // We do not have a callback but a Promise
462
+ if(typeof callback == 'function' || command.commandName == 'killCursors') {
463
+ var startTime = timestampGenerator.current();
464
+ // Emit the started event
465
+ self.emit('started', command)
466
+
467
+ // Emit succeeded event with killcursor if we have a legacy protocol
468
+ if(command.commandName == 'killCursors'
469
+ && this.server.lastIsMaster()
470
+ && this.server.lastIsMaster().maxWireVersion < 4) {
471
+ // Emit the succeeded command
472
+ var command = {
473
+ duration: timestampGenerator.duration(startTime, timestampGenerator.current()),
474
+ commandName: commandName,
475
+ requestId: requestId,
476
+ operationId: cursor.operationId,
477
+ connectionId: cursor.server.getConnection(),
478
+ reply: [{ok:1}]
479
+ };
480
+
481
+ // Emit the command
482
+ return self.emit('succeeded', command)
483
+ }
484
+
485
+ // Add our callback handler
486
+ args.push(function(err, r) {
487
+ if(err) {
488
+ // Command
489
+ var command = {
490
+ duration: timestampGenerator.duration(startTime, timestampGenerator.current()),
491
+ commandName: commandName,
492
+ requestId: requestId,
493
+ operationId: ourOpId,
494
+ connectionId: cursor.server.getConnection(),
495
+ failure: err };
496
+
497
+ // Emit the command
498
+ self.emit('failed', command)
499
+ } else {
500
+
501
+ // Do we have a getMore
502
+ if(commandName.toLowerCase() == 'getmore' && r == null) {
503
+ r = {
504
+ cursor: {
505
+ id: cursor.cursorState.cursorId,
506
+ ns: cursor.ns,
507
+ nextBatch: cursor.cursorState.documents
508
+ }, ok:1
509
+ }
510
+ } else if(commandName.toLowerCase() == 'find' && r == null) {
511
+ r = {
512
+ cursor: {
513
+ id: cursor.cursorState.cursorId,
514
+ ns: cursor.ns,
515
+ firstBatch: cursor.cursorState.documents
516
+ }, ok:1
517
+ }
518
+ } else if(commandName.toLowerCase() == 'killcursors' && r == null) {
519
+ r = {
520
+ cursorsUnknown:[cursor.cursorState.lastCursorId],
521
+ ok:1
522
+ }
523
+ }
524
+
525
+ // cursor id is zero, we can issue success command
526
+ var command = {
527
+ duration: timestampGenerator.duration(startTime, timestampGenerator.current()),
528
+ commandName: commandName,
529
+ requestId: requestId,
530
+ operationId: cursor.operationId,
531
+ connectionId: cursor.server.getConnection(),
532
+ reply: r && r.result ? r.result : r
533
+ };
534
+
535
+ // Emit the command
536
+ self.emit('succeeded', command)
537
+ }
538
+
539
+ // Return
540
+ if(!callback) return;
541
+
542
+ // Return to caller
543
+ callback(err, r);
544
+ });
545
+
546
+ // Apply the call
547
+ func.apply(this, args);
548
+ } else {
549
+ // Assume promise, push back the missing value
550
+ args.push(callback);
551
+ // Get the promise
552
+ var promise = func.apply(this, args);
553
+ // Return a new promise
554
+ return new cursor.s.promiseLibrary(function(resolve, reject) {
555
+ var startTime = timestampGenerator.current();
556
+ // Emit the started event
557
+ self.emit('started', command)
558
+ // Execute the function
559
+ promise.then(function(r) {
560
+ // cursor id is zero, we can issue success command
561
+ var command = {
562
+ duration: timestampGenerator.duration(startTime, timestampGenerator.current()),
563
+ commandName: commandName,
564
+ requestId: requestId,
565
+ operationId: cursor.operationId,
566
+ connectionId: cursor.server.getConnection(),
567
+ reply: cursor.cursorState.documents
568
+ };
569
+
570
+ // Emit the command
571
+ self.emit('succeeded', command)
572
+ }).catch(function(err) {
573
+ // Command
574
+ var command = {
575
+ duration: timestampGenerator.duration(startTime, timestampGenerator.current()),
576
+ commandName: commandName,
577
+ requestId: requestId,
578
+ operationId: ourOpId,
579
+ connectionId: cursor.server.getConnection(),
580
+ failure: err };
581
+
582
+ // Emit the command
583
+ self.emit('failed', command)
584
+ // reject the promise
585
+ reject(err);
586
+ });
587
+ });
588
+ }
589
+ }
590
+ });
591
+ });
592
+ }
593
+
594
+ inherits(Instrumentation, EventEmitter);
595
+
596
+ Instrumentation.prototype.uninstrument = function() {
597
+ for(var i = 0; i < this.overloads.length; i++) {
598
+ var obj = this.overloads[i];
599
+ obj.proto[obj.name] = obj.func;
600
+ }
601
+
602
+ // Remove all listeners
603
+ this.removeAllListeners('started');
604
+ this.removeAllListeners('succeeded');
605
+ this.removeAllListeners('failed');
606
+ }
607
+
608
+ module.exports = Instrumentation;
@@ -18,7 +18,7 @@ var REMOVE = 3
18
18
  var writeConcern = function(target, col, options) {
19
19
  if(options.w != null || options.j != null || options.fsync != null) {
20
20
  target.writeConcern = options;
21
- } else if(col.writeConcern.w != null || col.writeConcern.j != null || col.writeConcern.fsync != null) {
21
+ } else if(col.writeConcern.w != null || col.writeConcern.j != null || col.writeConcern.fsync != null) {
22
22
  target.writeConcern = col.writeConcern;
23
23
  }
24
24
 
@@ -43,7 +43,7 @@ var defineReadOnlyProperty = function(self, name, value) {
43
43
  * correctly after command execution
44
44
  * @ignore
45
45
  */
46
- var Batch = function(batchType, originalZeroIndex) {
46
+ var Batch = function(batchType, originalZeroIndex) {
47
47
  this.originalZeroIndex = originalZeroIndex;
48
48
  this.currentIndex = 0;
49
49
  this.originalIndexes = [];
@@ -108,7 +108,7 @@ var BulkWriteResult = function(bulkResult) {
108
108
  * @return {object}
109
109
  */
110
110
  this.getUpsertedIdAt = function(index) {
111
- return bulkResult.upserted[index];
111
+ return bulkResult.upserted[index];
112
112
  }
113
113
 
114
114
  /**
@@ -186,7 +186,7 @@ var BulkWriteResult = function(bulkResult) {
186
186
  for(var i = 0; i < bulkResult.writeConcernErrors.length; i++) {
187
187
  var err = bulkResult.writeConcernErrors[i];
188
188
  errmsg = errmsg + err.errmsg;
189
-
189
+
190
190
  // TODO: Something better
191
191
  if(i == 0) errmsg = errmsg + " and ";
192
192
  }
@@ -289,7 +289,7 @@ var mergeBatchResults = function(ordered, batch, bulkResult, err, result) {
289
289
  , op: batch.operations[0]
290
290
  };
291
291
 
292
- bulkResult.writeErrors.push(new WriteError(writeError));
292
+ bulkResult.writeErrors.push(new WriteError(writeError));
293
293
  return;
294
294
  } else if(result.ok == 0 && bulkResult.ok == 0) {
295
295
  return;
@@ -337,7 +337,7 @@ var mergeBatchResults = function(ordered, batch, bulkResult, err, result) {
337
337
  var nModified = result.nModified;
338
338
  bulkResult.nUpserted = bulkResult.nUpserted + nUpserted;
339
339
  bulkResult.nMatched = bulkResult.nMatched + (result.n - nUpserted);
340
-
340
+
341
341
  if(typeof nModified == 'number') {
342
342
  bulkResult.nModified = bulkResult.nModified + nModified;
343
343
  } else {
@@ -390,4 +390,4 @@ exports.MULTIPLE_ERROR = MULTIPLE_ERROR;
390
390
  exports.UNKNOWN_ERROR = UNKNOWN_ERROR;
391
391
  exports.INSERT = INSERT;
392
392
  exports.UPDATE = UPDATE;
393
- exports.REMOVE = REMOVE;
393
+ exports.REMOVE = REMOVE;