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.
- package/HISTORY.md +574 -429
- package/Makefile +2 -5
- package/README.md +108 -15
- package/conf.json +17 -13
- package/index.js +13 -2
- package/lib/admin.js +113 -47
- package/lib/aggregation_cursor.js +56 -28
- package/lib/apm.js +608 -0
- package/lib/bulk/common.js +7 -7
- package/lib/bulk/ordered.js +56 -17
- package/lib/bulk/unordered.js +52 -14
- package/lib/collection.js +671 -212
- package/lib/command_cursor.js +60 -32
- package/lib/cursor.js +313 -115
- package/lib/db.js +264 -105
- package/lib/gridfs/chunk.js +26 -29
- package/lib/gridfs/grid_store.js +150 -64
- package/lib/gridfs-stream/download.js +310 -0
- package/lib/gridfs-stream/index.js +335 -0
- package/lib/gridfs-stream/upload.js +450 -0
- package/lib/metadata.js +64 -0
- package/lib/mongo_client.js +69 -39
- package/lib/mongos.js +65 -20
- package/lib/replset.js +69 -34
- package/lib/server.js +35 -1
- package/lib/topology_base.js +22 -10
- package/lib/url_parser.js +111 -13
- package/lib/utils.js +9 -8
- package/mongolabs.js +427 -0
- package/package.json +8 -6
- package/t.js +68 -51
- package/test.js +12 -0
- package/test_boot/boot.sh +3 -0
- package/test_boot/ca.pem +49 -0
- package/test_boot/client.pem +48 -0
- package/test_boot/client_password.pem +51 -0
- package/test_boot/connect.js +29 -0
- package/test_boot/data/WiredTiger +2 -0
- package/test_boot/data/WiredTiger.lock +1 -0
- package/test_boot/data/WiredTiger.turtle +6 -0
- package/test_boot/data/WiredTiger.wt +0 -0
- package/test_boot/data/WiredTigerLAS.wt +0 -0
- package/test_boot/data/_mdb_catalog.wt +0 -0
- package/test_boot/data/collection-0-757073248613337118.wt +0 -0
- package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-44-37Z-00000 +0 -0
- package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-45-15Z-00000 +0 -0
- package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-46-31Z-00000 +0 -0
- package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-47-25Z-00000 +0 -0
- package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-49-07Z-00000 +0 -0
- package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-50-41Z-00000 +0 -0
- package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-50-53Z-00000 +0 -0
- package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-52-31Z-00000 +0 -0
- package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-54-53Z-00000 +0 -0
- package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-55-09Z-00000 +0 -0
- package/test_boot/data/diagnostic.data/metrics.2015-10-07T14-55-38Z-00000 +0 -0
- package/test_boot/data/index-1-757073248613337118.wt +0 -0
- package/test_boot/data/mongod.lock +0 -0
- package/test_boot/data/sizeStorer.wt +0 -0
- package/test_boot/data/storage.bson +0 -0
- package/test_boot/server_password.pem +51 -0
- package/.travis.yml +0 -10
- package/t1.js +0 -59
- package/wercker.yml +0 -19
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
var core = require('mongodb-core');
|
|
2
|
+
var crypto = require('crypto');
|
|
3
|
+
var shallowClone = require('../utils').shallowClone;
|
|
4
|
+
var stream = require('stream');
|
|
5
|
+
var util = require('util');
|
|
6
|
+
|
|
7
|
+
var ERROR_NAMESPACE_NOT_FOUND = 26;
|
|
8
|
+
|
|
9
|
+
module.exports = GridFSBucketWriteStream;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A writable stream that enables you to write buffers to GridFS.
|
|
13
|
+
*
|
|
14
|
+
* Do not instantiate this class directly. Use `openUploadStream()` instead.
|
|
15
|
+
*
|
|
16
|
+
* @class
|
|
17
|
+
* @param {GridFSBucket} bucket Handle for this stream's corresponding bucket
|
|
18
|
+
* @param {string} filename The value of the 'filename' key in the files doc
|
|
19
|
+
* @param {object} [options=null] Optional settings.
|
|
20
|
+
* @param {number} [options.chunkSizeBytes=null] The chunk size to use, in bytes
|
|
21
|
+
* @param {number} [options.w=null] The write concern
|
|
22
|
+
* @param {number} [options.wtimeout=null] The write concern timeout
|
|
23
|
+
* @param {number} [options.j=null] The journal write concern
|
|
24
|
+
* @fires GridFSBucketWriteStream#error
|
|
25
|
+
* @fires GridFSBucketWriteStream#finish
|
|
26
|
+
* @return {GridFSBucketWriteStream} a GridFSBucketWriteStream instance.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
function GridFSBucketWriteStream(bucket, filename, options) {
|
|
30
|
+
this.bucket = bucket;
|
|
31
|
+
this.chunks = bucket.s._chunksCollection;
|
|
32
|
+
this.filename = filename;
|
|
33
|
+
this.files = bucket.s._filesCollection;
|
|
34
|
+
this.options = options;
|
|
35
|
+
|
|
36
|
+
this.id = core.BSON.ObjectId();
|
|
37
|
+
this.chunkSizeBytes = this.options.chunkSizeBytes;
|
|
38
|
+
this.bufToStore = new Buffer(this.chunkSizeBytes);
|
|
39
|
+
this.length = 0;
|
|
40
|
+
this.md5 = crypto.createHash('md5');
|
|
41
|
+
this.n = 0;
|
|
42
|
+
this.pos = 0;
|
|
43
|
+
this.state = {
|
|
44
|
+
streamEnd: false,
|
|
45
|
+
outstandingRequests: 0,
|
|
46
|
+
errored: false
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
if (!this.bucket.s.calledOpenUploadStream) {
|
|
50
|
+
this.bucket.s.calledOpenUploadStream = true;
|
|
51
|
+
|
|
52
|
+
var _this = this;
|
|
53
|
+
checkIndexes(this, function() {
|
|
54
|
+
_this.bucket.s.checkedIndexes = true;
|
|
55
|
+
_this.bucket.emit('index');
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
util.inherits(GridFSBucketWriteStream, stream.Writable);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* An error occurred
|
|
64
|
+
*
|
|
65
|
+
* @event GridFSBucketWriteStream#error
|
|
66
|
+
* @type {Error}
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* end() was called and the write stream successfully wrote all chunks to
|
|
71
|
+
* MongoDB.
|
|
72
|
+
*
|
|
73
|
+
* @event GridFSBucketWriteStream#finish
|
|
74
|
+
* @type {object}
|
|
75
|
+
*/
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Write a buffer to the stream.
|
|
79
|
+
*
|
|
80
|
+
* @method
|
|
81
|
+
* @param {Buffer} chunk Buffer to write
|
|
82
|
+
* @param {String} encoding Optional encoding for the buffer
|
|
83
|
+
* @param {Function} callback Function to call when the chunk was added to the buffer, or if the entire chunk was persisted to MongoDB if this chunk caused a flush.
|
|
84
|
+
* @return {Boolean} False if this write required flushing a chunk to MongoDB. True otherwise.
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
GridFSBucketWriteStream.prototype.write = function(chunk, encoding, callback) {
|
|
88
|
+
var _this = this;
|
|
89
|
+
return waitForIndexes(this, function() {
|
|
90
|
+
return doWrite(_this, chunk, encoding, callback);
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Tells the stream that no more data will be coming in. The stream will
|
|
96
|
+
* persist the remaining data to MongoDB, write the files document, and
|
|
97
|
+
* then emit a 'finish' event.
|
|
98
|
+
*
|
|
99
|
+
* @method
|
|
100
|
+
* @param {Buffer} chunk Buffer to write
|
|
101
|
+
* @param {String} encoding Optional encoding for the buffer
|
|
102
|
+
* @param {Function} callback Function to call when all files and chunks have been persisted to MongoDB
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
GridFSBucketWriteStream.prototype.end = function(chunk, encoding, callback) {
|
|
106
|
+
var _this = this;
|
|
107
|
+
this.state.streamEnd = true;
|
|
108
|
+
|
|
109
|
+
if (callback) {
|
|
110
|
+
this.once('finish', callback);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!chunk) {
|
|
114
|
+
waitForIndexes(this, function() {
|
|
115
|
+
writeRemnant(_this);
|
|
116
|
+
});
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
var _this = this;
|
|
121
|
+
var inputBuf = (Buffer.isBuffer(chunk)) ?
|
|
122
|
+
chunk : new Buffer(chunk, encoding);
|
|
123
|
+
|
|
124
|
+
this.write(chunk, encoding, function() {
|
|
125
|
+
writeRemnant(_this);
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @ignore
|
|
131
|
+
*/
|
|
132
|
+
|
|
133
|
+
function __handleError(_this, error, callback) {
|
|
134
|
+
if (_this.state.errored) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
_this.state.errored = true;
|
|
138
|
+
if (callback) {
|
|
139
|
+
return callback(error);
|
|
140
|
+
}
|
|
141
|
+
_this.emit('error', error);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @ignore
|
|
146
|
+
*/
|
|
147
|
+
|
|
148
|
+
function createChunkDoc(filesId, n, data) {
|
|
149
|
+
return {
|
|
150
|
+
_id: core.BSON.ObjectId(),
|
|
151
|
+
files_id: filesId,
|
|
152
|
+
n: n,
|
|
153
|
+
data: data
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* @ignore
|
|
159
|
+
*/
|
|
160
|
+
|
|
161
|
+
function checkChunksIndex(_this, callback) {
|
|
162
|
+
_this.chunks.listIndexes().toArray(function(error, indexes) {
|
|
163
|
+
if (error) {
|
|
164
|
+
// Collection doesn't exist so create index
|
|
165
|
+
if (error.code === ERROR_NAMESPACE_NOT_FOUND) {
|
|
166
|
+
var index = { files_id: 1, n: 1 };
|
|
167
|
+
_this.chunks.createIndex(index, { background: false }, function(error) {
|
|
168
|
+
if (error) {
|
|
169
|
+
return callback(error);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
callback();
|
|
173
|
+
});
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
return callback(error);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
var hasChunksIndex = false;
|
|
180
|
+
indexes.forEach(function(index) {
|
|
181
|
+
if (index.key) {
|
|
182
|
+
var keys = Object.keys(index.key);
|
|
183
|
+
if (keys.length === 2 && index.key.files_id === 1 &&
|
|
184
|
+
index.key.n === 1) {
|
|
185
|
+
hasChunksIndex = true;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
if (hasChunksIndex) {
|
|
191
|
+
callback();
|
|
192
|
+
} else {
|
|
193
|
+
var index = { files_id: 1, n: 1 };
|
|
194
|
+
var indexOptions = getWriteOptions(_this);
|
|
195
|
+
|
|
196
|
+
indexOptions.background = false;
|
|
197
|
+
indexOptions.unique = true;
|
|
198
|
+
|
|
199
|
+
_this.chunks.createIndex(index, indexOptions, function(error) {
|
|
200
|
+
if (error) {
|
|
201
|
+
return callback(error);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
callback();
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @ignore
|
|
212
|
+
*/
|
|
213
|
+
|
|
214
|
+
function checkDone(_this, callback) {
|
|
215
|
+
if (_this.state.streamEnd &&
|
|
216
|
+
_this.state.outstandingRequests === 0 &&
|
|
217
|
+
!_this.state.errored) {
|
|
218
|
+
var filesDoc = createFilesDoc(_this.id, _this.length, _this.chunkSizeBytes,
|
|
219
|
+
_this.md5.digest('hex'), _this.filename, _this.options.contentType,
|
|
220
|
+
_this.options.aliases, _this.options.metadata);
|
|
221
|
+
|
|
222
|
+
_this.files.insert(filesDoc, getWriteOptions(_this), function(error) {
|
|
223
|
+
if (error) {
|
|
224
|
+
return __handleError(_this, error, callback);
|
|
225
|
+
}
|
|
226
|
+
_this.emit('finish', filesDoc);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* @ignore
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
function checkIndexes(_this, callback) {
|
|
240
|
+
_this.files.findOne({}, { _id: 1 }, function(error, doc) {
|
|
241
|
+
if (error) {
|
|
242
|
+
return callback(error);
|
|
243
|
+
}
|
|
244
|
+
if (doc) {
|
|
245
|
+
return callback();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
_this.files.listIndexes().toArray(function(error, indexes) {
|
|
249
|
+
if (error) {
|
|
250
|
+
// Collection doesn't exist so create index
|
|
251
|
+
if (error.code === ERROR_NAMESPACE_NOT_FOUND) {
|
|
252
|
+
var index = { filename: 1, uploadDate: 1 };
|
|
253
|
+
_this.files.createIndex(index, { background: false }, function(error) {
|
|
254
|
+
if (error) {
|
|
255
|
+
return callback(error);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
checkChunksIndex(_this, callback);
|
|
259
|
+
});
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
return callback(error);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
var hasFileIndex = false;
|
|
266
|
+
indexes.forEach(function(index) {
|
|
267
|
+
var keys = Object.keys(index.key);
|
|
268
|
+
if (keys.length === 2 && index.key.filename === 1 &&
|
|
269
|
+
index.key.uploadDate === 1) {
|
|
270
|
+
hasFileIndex = true;
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
if (hasFileIndex) {
|
|
275
|
+
checkChunksIndex(_this, callback);
|
|
276
|
+
} else {
|
|
277
|
+
var index = { filename: 1, uploadDate: 1 };
|
|
278
|
+
|
|
279
|
+
var indexOptions = getWriteOptions(_this);
|
|
280
|
+
|
|
281
|
+
indexOptions.background = false;
|
|
282
|
+
|
|
283
|
+
_this.files.createIndex(index, indexOptions, function(error) {
|
|
284
|
+
if (error) {
|
|
285
|
+
return callback(error);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
checkChunksIndex(_this, callback);
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* @ignore
|
|
297
|
+
*/
|
|
298
|
+
|
|
299
|
+
function createFilesDoc(_id, length, chunkSize, md5, filename, contentType,
|
|
300
|
+
aliases, metadata) {
|
|
301
|
+
var ret = {
|
|
302
|
+
_id: _id,
|
|
303
|
+
length: length,
|
|
304
|
+
chunkSize: chunkSize,
|
|
305
|
+
uploadDate: new Date(),
|
|
306
|
+
md5: md5,
|
|
307
|
+
filename: filename
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
if (contentType) {
|
|
311
|
+
ret.contentType = contentType;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
if (aliases) {
|
|
315
|
+
ret.aliases = aliases;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (metadata) {
|
|
319
|
+
ret.metadata = metadata;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return ret;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* @ignore
|
|
327
|
+
*/
|
|
328
|
+
|
|
329
|
+
function doWrite(_this, chunk, encoding, callback) {
|
|
330
|
+
|
|
331
|
+
var inputBuf = (Buffer.isBuffer(chunk)) ?
|
|
332
|
+
chunk : new Buffer(chunk, encoding);
|
|
333
|
+
|
|
334
|
+
_this.length += inputBuf.length;
|
|
335
|
+
|
|
336
|
+
// Input is small enough to fit in our buffer
|
|
337
|
+
if (_this.pos + inputBuf.length < _this.chunkSizeBytes) {
|
|
338
|
+
inputBuf.copy(_this.bufToStore, _this.pos);
|
|
339
|
+
_this.pos += inputBuf.length;
|
|
340
|
+
|
|
341
|
+
callback && callback();
|
|
342
|
+
|
|
343
|
+
// Note that we reverse the typical semantics of write's return value
|
|
344
|
+
// to be compatible with node's `.pipe()` function.
|
|
345
|
+
// True means client can keep writing.
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Otherwise, buffer is too big for current chunk, so we need to flush
|
|
350
|
+
// to MongoDB.
|
|
351
|
+
var inputBufRemaining = inputBuf.length;
|
|
352
|
+
var spaceRemaining = _this.chunkSizeBytes - _this.pos;
|
|
353
|
+
var numToCopy = Math.min(spaceRemaining, inputBuf.length);
|
|
354
|
+
var outstandingRequests = 0;
|
|
355
|
+
while (inputBufRemaining > 0) {
|
|
356
|
+
var inputBufPos = inputBuf.length - inputBufRemaining;
|
|
357
|
+
inputBuf.copy(_this.bufToStore, _this.pos,
|
|
358
|
+
inputBufPos, inputBufPos + numToCopy);
|
|
359
|
+
_this.pos += numToCopy;
|
|
360
|
+
spaceRemaining -= numToCopy;
|
|
361
|
+
if (spaceRemaining === 0) {
|
|
362
|
+
_this.md5.update(_this.bufToStore);
|
|
363
|
+
var doc = createChunkDoc(_this.id, _this.n, _this.bufToStore);
|
|
364
|
+
++_this.state.outstandingRequests;
|
|
365
|
+
++outstandingRequests;
|
|
366
|
+
|
|
367
|
+
_this.chunks.insert(doc, getWriteOptions(_this), function(error) {
|
|
368
|
+
if (error) {
|
|
369
|
+
return __handleError(_this, error);
|
|
370
|
+
}
|
|
371
|
+
--_this.state.outstandingRequests;
|
|
372
|
+
--outstandingRequests;
|
|
373
|
+
if (!outstandingRequests) {
|
|
374
|
+
_this.emit('drain', doc);
|
|
375
|
+
callback && callback();
|
|
376
|
+
checkDone(_this);
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
spaceRemaining = _this.chunkSizeBytes;
|
|
381
|
+
_this.pos = 0;
|
|
382
|
+
++_this.n;
|
|
383
|
+
}
|
|
384
|
+
inputBufRemaining -= numToCopy;
|
|
385
|
+
numToCopy = Math.min(spaceRemaining, inputBufRemaining);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Note that we reverse the typical semantics of write's return value
|
|
389
|
+
// to be compatible with node's `.pipe()` function.
|
|
390
|
+
// False means the client should wait for the 'drain' event.
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* @ignore
|
|
396
|
+
*/
|
|
397
|
+
|
|
398
|
+
function getWriteOptions(_this) {
|
|
399
|
+
var obj = {};
|
|
400
|
+
if (_this.options.writeConcern) {
|
|
401
|
+
obj.w = concern.w;
|
|
402
|
+
obj.wtimeout = concern.wtimeout;
|
|
403
|
+
obj.j = concern.j;
|
|
404
|
+
}
|
|
405
|
+
return obj;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* @ignore
|
|
410
|
+
*/
|
|
411
|
+
|
|
412
|
+
function waitForIndexes(_this, callback) {
|
|
413
|
+
if (_this.bucket.s.checkedIndexes) {
|
|
414
|
+
callback(false);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
_this.bucket.once('index', function() {
|
|
418
|
+
callback(true);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
return true;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* @ignore
|
|
426
|
+
*/
|
|
427
|
+
|
|
428
|
+
function writeRemnant(_this, callback) {
|
|
429
|
+
// Buffer is empty, so don't bother to insert
|
|
430
|
+
if (_this.pos === 0) {
|
|
431
|
+
return checkDone(_this, callback);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
++_this.state.outstandingRequests;
|
|
435
|
+
|
|
436
|
+
// Create a new buffer to make sure the buffer isn't bigger than it needs
|
|
437
|
+
// to be.
|
|
438
|
+
var remnant = new Buffer(_this.pos);
|
|
439
|
+
_this.bufToStore.copy(remnant, 0, 0, _this.pos);
|
|
440
|
+
_this.md5.update(remnant);
|
|
441
|
+
var doc = createChunkDoc(_this.id, _this.n, remnant);
|
|
442
|
+
|
|
443
|
+
_this.chunks.insert(doc, getWriteOptions(_this), function(error) {
|
|
444
|
+
if (error) {
|
|
445
|
+
return __handleError(_this, error);
|
|
446
|
+
}
|
|
447
|
+
--_this.state.outstandingRequests;
|
|
448
|
+
checkDone(_this);
|
|
449
|
+
});
|
|
450
|
+
}
|
package/lib/metadata.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
var f = require('util').format;
|
|
2
|
+
|
|
3
|
+
var Define = function(name, object, stream) {
|
|
4
|
+
this.name = name;
|
|
5
|
+
this.object = object;
|
|
6
|
+
this.stream = typeof stream == 'boolean' ? stream : false;
|
|
7
|
+
this.instrumentations = {};
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
Define.prototype.classMethod = function(name, options) {
|
|
11
|
+
var keys = Object.keys(options).sort();
|
|
12
|
+
var key = generateKey(keys, options);
|
|
13
|
+
|
|
14
|
+
// Add a list of instrumentations
|
|
15
|
+
if(this.instrumentations[key] == null) {
|
|
16
|
+
this.instrumentations[key] = {
|
|
17
|
+
methods: [], options: options
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Push to list of method for this instrumentation
|
|
22
|
+
this.instrumentations[key].methods.push(name);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
var generateKey = function(keys, options) {
|
|
26
|
+
var parts = [];
|
|
27
|
+
for(var i = 0; i < keys.length; i++) {
|
|
28
|
+
parts.push(f('%s=%s', keys[i], options[keys[i]]));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return parts.join();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
Define.prototype.staticMethod = function(name, options) {
|
|
35
|
+
options.static = true;
|
|
36
|
+
var keys = Object.keys(options).sort();
|
|
37
|
+
var key = generateKey(keys, options);
|
|
38
|
+
|
|
39
|
+
// Add a list of instrumentations
|
|
40
|
+
if(this.instrumentations[key] == null) {
|
|
41
|
+
this.instrumentations[key] = {
|
|
42
|
+
methods: [], options: options
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Push to list of method for this instrumentation
|
|
47
|
+
this.instrumentations[key].methods.push(name);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
Define.prototype.generate = function(keys, options) {
|
|
51
|
+
// Generate the return object
|
|
52
|
+
var object = {
|
|
53
|
+
name: this.name, obj: this.object, stream: this.stream,
|
|
54
|
+
instrumentations: []
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
for(var name in this.instrumentations) {
|
|
58
|
+
object.instrumentations.push(this.instrumentations[name]);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return object;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = Define;
|