mirror of
https://github.com/sstent/node_app.git
synced 2026-03-23 05:15:58 +00:00
removing ned for second mongo
This commit is contained in:
14
node_modules/mongoskin/History.md
generated
vendored
14
node_modules/mongoskin/History.md
generated
vendored
@@ -1,3 +1,17 @@
|
||||
|
||||
0.5.0 / 2012-12-29
|
||||
==================
|
||||
|
||||
* fixed unsafe mode warnning log
|
||||
* Merge pull request #84 from kingpearl/master
|
||||
* MongoDB 1.2.x support
|
||||
* Merge pull request #73 from jockster/master
|
||||
* Merge pull request #75 from voke/patch-1
|
||||
* Fix typo
|
||||
* fixed bind() test cases;
|
||||
* Minor error in readme. Now updated
|
||||
* Updated readme according to issue #72
|
||||
|
||||
0.3.4 / 2011-03-24
|
||||
* fix global leaks
|
||||
|
||||
|
||||
40
node_modules/mongoskin/Readme.md
generated
vendored
40
node_modules/mongoskin/Readme.md
generated
vendored
@@ -1,6 +1,6 @@
|
||||
# mongoskin
|
||||
# mongoskin [](http://travis-ci.org/kissjs/node-mongoskin)
|
||||
|
||||
[](http://travis-ci.org/kissjs/node-mongoskin)
|
||||

|
||||
|
||||
This project is a wrapper of [node-mongodb-native](https://github.com/mongodb/node-mongodb-native).
|
||||
The api is same to node-mongodb-native, please see the [document](http://mongodb.github.com/node-mongodb-native/) first.
|
||||
@@ -14,11 +14,12 @@ The api is same to node-mongodb-native, please see the [document](http://mongodb
|
||||
|
||||
* <del>>= 0.9.8 < 1.0.0</del>: mongodb have bug, it will throw a `TypeError: object is not a function`
|
||||
when connection open error.
|
||||
* 1.0.x
|
||||
* 1.1.x
|
||||
* <del>1.0.x</del>
|
||||
* <del>1.1.x</del>
|
||||
* 1.2.x
|
||||
|
||||
```bash
|
||||
$ make test-version
|
||||
$ make test
|
||||
```
|
||||
|
||||
<a name='index'>
|
||||
@@ -129,7 +130,7 @@ mongo.db('localhost:27017/testdb').collection('blog').find().toArray(function (e
|
||||
Server options and BSON options
|
||||
--------
|
||||
You can also set `auto_reconnect` options querystring.
|
||||
And native_parser options will automatically set if native_parser is avariable.
|
||||
And native_parser options will automatically set if native_parser is available.
|
||||
|
||||
```js
|
||||
var mongo = require('mongoskin');
|
||||
@@ -172,6 +173,10 @@ It is very useful if you want to use MVC patterns with nodejs and mongodb.
|
||||
You can also invoke collection by properties after bind,
|
||||
it could simplfy your `require`.
|
||||
|
||||
To keep your code in line with DRY principles, it's possible to create your own
|
||||
data layer by for example, setting up your own validators and/or default values
|
||||
inside the MVC methods as shown below in the config example
|
||||
|
||||
```js
|
||||
db.bind('posts', {
|
||||
findTop10 : function (fn) {
|
||||
@@ -180,8 +185,26 @@ db.bind('posts', {
|
||||
removeTagWith : function (tag, fn) {
|
||||
this.remove({tags:tag},fn);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
db.bind('settings', {
|
||||
|
||||
getAll: function(user, fn) {
|
||||
|
||||
this.find({user: user}).toArray(function(err, settings) {
|
||||
|
||||
// We want to set a default currency from within our app instead of storing it
|
||||
// for every user
|
||||
settings.currency = (typeof settings.currency !== "undefined") ? settings.currency : 'USD';
|
||||
|
||||
fn(err, settings);
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
db.bind('comments');
|
||||
|
||||
db.collection('posts').removeTagWith('delete', function (err, replies) {
|
||||
@@ -245,7 +268,8 @@ var db = mongoskin.db([
|
||||
'192.168.0.2:27017/?auto_reconnect=true',
|
||||
'192.168.0.3:27017/?auto_reconnect=true'
|
||||
], {
|
||||
database: 'testdb'
|
||||
database: 'testdb',
|
||||
safe: true
|
||||
}, {
|
||||
connectArbiter: false,
|
||||
socketOptions: {
|
||||
@@ -587,6 +611,8 @@ collection.group([], {}, {"count":0}, "function (obj, prev) { prev.count++; }",
|
||||
Options:
|
||||
upsert - true/false (perform upsert operation)
|
||||
multi - true/false (update all documents matching spec)
|
||||
strict - true/false (perform check if the operation failed, required extra call to db)
|
||||
Deprecated Options:
|
||||
safe - true/false (perform check if the operation failed, required extra call to db)
|
||||
**/
|
||||
```
|
||||
|
||||
2
node_modules/mongoskin/examples/update.js
generated
vendored
2
node_modules/mongoskin/examples/update.js
generated
vendored
@@ -3,7 +3,7 @@ var articles = db.collection('articles');
|
||||
articles.insert({foo: 'bar', val: 'val1'}, function(err, result) {
|
||||
|
||||
console.log(result);
|
||||
articles.update({foo:'bar'}, {foo: 'bar', val:'val2'}, {safe: true}, function(err, result) {
|
||||
articles.update({foo:'bar'}, {foo: 'bar', val:'val2'}, {strict: true}, function(err, result) {
|
||||
|
||||
console.log(result);
|
||||
articles.find({foo: 'bar'}).toArray(function(err, docs){
|
||||
|
||||
0
node_modules/mongoskin/node_modules/mongodb/index.js
generated
vendored
Normal file → Executable file
0
node_modules/mongoskin/node_modules/mongodb/index.js
generated
vendored
Normal file → Executable file
34
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/admin.js
generated
vendored
34
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/admin.js
generated
vendored
@@ -21,7 +21,7 @@ function Admin(db) {
|
||||
* Retrieve the server information for the current
|
||||
* instance of the db client
|
||||
*
|
||||
* @param {Function} callback Callback function of format `function(err, result) {}`.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from buildInfo or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
@@ -33,7 +33,7 @@ Admin.prototype.buildInfo = function(callback) {
|
||||
* Retrieve the server information for the current
|
||||
* instance of the db client
|
||||
*
|
||||
* @param {Function} callback Callback function of format `function(err, result) {}`.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from serverInfo or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api private
|
||||
*/
|
||||
@@ -47,7 +47,7 @@ Admin.prototype.serverInfo = function(callback) {
|
||||
/**
|
||||
* Retrieve this db's server status.
|
||||
*
|
||||
* @param {Function} callback returns the server status.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from serverStatus or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -67,7 +67,7 @@ Admin.prototype.serverStatus = function(callback) {
|
||||
/**
|
||||
* Retrieve the current profiling Level for MongoDB
|
||||
*
|
||||
* @param {Function} callback Callback function of format `function(err, result) {}`.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from profilingLevel or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
@@ -92,7 +92,7 @@ Admin.prototype.profilingLevel = function(callback) {
|
||||
/**
|
||||
* Ping the MongoDB server and retrieve results
|
||||
*
|
||||
* @param {Function} callback Callback function of format `function(err, result) {}`.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from ping or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
@@ -109,7 +109,7 @@ Admin.prototype.ping = function(options, callback) {
|
||||
*
|
||||
* @param {String} username The user name for the authentication.
|
||||
* @param {String} password The password for the authentication.
|
||||
* @param {Function} callback Callback function of format `function(err, result) {}`.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from authenticate or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
@@ -123,7 +123,7 @@ Admin.prototype.authenticate = function(username, password, callback) {
|
||||
* Logout current authenticated user
|
||||
*
|
||||
* @param {Object} [options] Optional parameters to the command.
|
||||
* @param {Function} callback Callback function of format `function(err, result) {}`.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from logout or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
@@ -143,7 +143,7 @@ Admin.prototype.logout = function(callback) {
|
||||
* @param {String} username The user name for the authentication.
|
||||
* @param {String} password The password for the authentication.
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @param {Function} callback Callback function of format `function(err, result) {}`.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from addUser or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
@@ -167,7 +167,7 @@ Admin.prototype.addUser = function(username, password, options, callback) {
|
||||
*
|
||||
* @param {String} username The user name for the authentication.
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @param {Function} callback Callback function of format `function(err, result) {}`.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from removeUser or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
@@ -187,7 +187,7 @@ Admin.prototype.removeUser = function(username, options, callback) {
|
||||
* Set the current profiling level of MongoDB
|
||||
*
|
||||
* @param {String} level The new profiling level (off, slow_only, all)
|
||||
* @param {Function} callback Callback function of format `function(err, result) {}`.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from setProfilingLevel or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
@@ -221,15 +221,13 @@ Admin.prototype.setProfilingLevel = function(level, callback) {
|
||||
/**
|
||||
* Retrive the current profiling information for MongoDB
|
||||
*
|
||||
* @param {Function} callback Callback function of format `function(err, result) {}`.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from profilingInfo or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.profilingInfo = function(callback) {
|
||||
try {
|
||||
new Cursor(this.db, new Collection(this.db, DbCommand.SYSTEM_PROFILE_COLLECTION), {}, null, null, null
|
||||
, null, null, null, null, null, null, null, null, null, null
|
||||
, null, null, null, null, null, null, null, null, 'admin').toArray(function(err, items) {
|
||||
new Cursor(this.db, new Collection(this.db, DbCommand.SYSTEM_PROFILE_COLLECTION), {}, {}, {dbName: 'admin'}).toArray(function(err, items) {
|
||||
return callback(err, items);
|
||||
});
|
||||
} catch (err) {
|
||||
@@ -242,7 +240,7 @@ Admin.prototype.profilingInfo = function(callback) {
|
||||
*
|
||||
* @param {Object} command A command object `{ping:1}`.
|
||||
* @param {Object} [options] Optional parameters to the command.
|
||||
* @param {Function} callback Callback function of format `function(err, result) {}`.
|
||||
* @param {Function} callback this will be called after executing this method. The command always return the whole result of the command as the second parameter.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
@@ -264,7 +262,7 @@ Admin.prototype.command = function(command, options, callback) {
|
||||
*
|
||||
* @param {String} collectionName The name of the collection to validate.
|
||||
* @param {Object} [options] Optional parameters to the command.
|
||||
* @param {Function} callback Callback function of format `function(err, result) {}`.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from validateCollection or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
@@ -304,7 +302,7 @@ Admin.prototype.validateCollection = function(collectionName, options, callback)
|
||||
/**
|
||||
* List the available databases
|
||||
*
|
||||
* @param {Function} callback Callback function of format `function(err, result) {}`.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from listDatabases or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
@@ -319,7 +317,7 @@ Admin.prototype.listDatabases = function(callback) {
|
||||
/**
|
||||
* Get ReplicaSet status
|
||||
*
|
||||
* @param {Function} callback returns the replica set status (if available).
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from replSetGetStatus or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
320
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/collection.js
generated
vendored
320
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/collection.js
generated
vendored
@@ -67,13 +67,19 @@ function Collection (db, collectionName, pkFactory, options) {
|
||||
* Inserts a single document or a an array of documents into MongoDB.
|
||||
*
|
||||
* Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
|
||||
* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
|
||||
* - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
|
||||
* - **fsync**, (Boolean, default:false) write waits for fsync before returning
|
||||
* - **journal**, (Boolean, default:false) write waits for journal sync before returning
|
||||
* - **continueOnError/keepGoing** {Boolean, default:false}, keep inserting documents even if one document has an error, *mongodb 1.9.1 >*.
|
||||
* - **serializeFunctions** {Boolean, default:false}, serialize functions on the document.
|
||||
*
|
||||
* Deprecated Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
|
||||
*
|
||||
* @param {Array|Object} docs
|
||||
* @param {Object} [options] optional options for insert command
|
||||
* @param {Function} [callback] optional callback for the function, must be provided when using `safe` mode
|
||||
* @param {Function} [callback] optional callback for the function, must be provided when using a writeconcern
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -112,12 +118,18 @@ var checkCollectionName = function checkCollectionName (collectionName) {
|
||||
* Removes documents specified by `selector` from the db.
|
||||
*
|
||||
* Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
|
||||
* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
|
||||
* - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
|
||||
* - **fsync**, (Boolean, default:false) write waits for fsync before returning
|
||||
* - **journal**, (Boolean, default:false) write waits for journal sync before returning
|
||||
* - **single** {Boolean, default:false}, removes the first document found.
|
||||
*
|
||||
* Deprecated Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
|
||||
*
|
||||
* @param {Object} [selector] optional select, no selector is equivalent to removing all documents.
|
||||
* @param {Object} [options] additional options during remove.
|
||||
* @param {Function} [callback] must be provided if you performing a safe remove
|
||||
* @param {Function} [callback] must be provided if you performing a remove with a writeconcern
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -153,14 +165,9 @@ Collection.prototype.remove = function remove(selector, options, callback) {
|
||||
, flags);
|
||||
|
||||
var self = this;
|
||||
var errorOptions = options.safe != null ? options.safe : null;
|
||||
errorOptions = errorOptions == null && this.opts.safe != null ? this.opts.safe : errorOptions;
|
||||
errorOptions = errorOptions == null && this.db.safe != null ? this.db.safe : errorOptions;
|
||||
|
||||
// If we have a write concern set and no callback throw error
|
||||
if(errorOptions && errorOptions['safe'] != false && typeof callback !== 'function') throw new Error("safe cannot be used without a callback");
|
||||
var errorOptions = _getWriteConcern(self, options, callback);
|
||||
// Execute the command, do not add a callback as it's async
|
||||
if(errorOptions && errorOptions != false) {
|
||||
if(_hasWriteConcern(errorOptions) && typeof callback == 'function') {
|
||||
// Insert options
|
||||
var commandOptions = {read:false};
|
||||
// If we have safe set set async to false
|
||||
@@ -188,6 +195,8 @@ Collection.prototype.remove = function remove(selector, options, callback) {
|
||||
callback(null, error[0].n);
|
||||
}
|
||||
});
|
||||
} else if(_hasWriteConcern(errorOptions) && callback == null) {
|
||||
throw new Error("Cannot use a writeConcern without a provided callback");
|
||||
} else {
|
||||
var result = this.db._executeRemoveCommand(deleteCommand);
|
||||
// If no callback just return
|
||||
@@ -271,7 +280,7 @@ var insertAll = function insertAll (self, docs, options, callback) {
|
||||
, dbName + "." + self.collectionName, true, insertFlags);
|
||||
|
||||
// Add the documents and decorate them with id's if they have none
|
||||
for (var index = 0, len = docs.length; index < len; ++index) {
|
||||
for(var index = 0, len = docs.length; index < len; ++index) {
|
||||
var doc = docs[index];
|
||||
|
||||
// Add id to each document if it's not already defined
|
||||
@@ -283,17 +292,11 @@ var insertAll = function insertAll (self, docs, options, callback) {
|
||||
}
|
||||
|
||||
// Collect errorOptions
|
||||
var errorOptions = options.safe != null ? options.safe : null;
|
||||
errorOptions = errorOptions == null && self.opts.safe != null ? self.opts.safe : errorOptions;
|
||||
errorOptions = errorOptions == null && self.db.safe != null ? self.db.safe : errorOptions;
|
||||
|
||||
// If we have a write concern set and no callback throw error
|
||||
if(errorOptions && errorOptions['safe'] != false && typeof callback !== 'function') throw new Error("safe cannot be used without a callback");
|
||||
|
||||
var errorOptions = _getWriteConcern(self, options, callback);
|
||||
// Default command options
|
||||
var commandOptions = {};
|
||||
// If safe is defined check for error message
|
||||
if(errorOptions && errorOptions != false) {
|
||||
if(_hasWriteConcern(errorOptions) && typeof callback == 'function') {
|
||||
// Insert options
|
||||
commandOptions['read'] = false;
|
||||
// If we have safe set set async to false
|
||||
@@ -322,8 +325,11 @@ var insertAll = function insertAll (self, docs, options, callback) {
|
||||
callback(null, docs);
|
||||
}
|
||||
});
|
||||
} else if(_hasWriteConcern(errorOptions) && callback == null) {
|
||||
throw new Error("Cannot use a writeConcern without a provided callback");
|
||||
} else {
|
||||
var result = self.db._executeInsertCommand(insertCommand, commandOptions, callback);
|
||||
// Execute the call without a write concern
|
||||
var result = self.db._executeInsertCommand(insertCommand, commandOptions);
|
||||
// If no callback just return
|
||||
if(!callback) return;
|
||||
// If error return error
|
||||
@@ -340,6 +346,12 @@ var insertAll = function insertAll (self, docs, options, callback) {
|
||||
* operators and update instead for more efficient operations.
|
||||
*
|
||||
* Options
|
||||
* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
|
||||
* - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
|
||||
* - **fsync**, (Boolean, default:false) write waits for fsync before returning
|
||||
* - **journal**, (Boolean, default:false) write waits for journal sync before returning
|
||||
*
|
||||
* Deprecated Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
|
||||
*
|
||||
* @param {Object} [doc] the document to save
|
||||
@@ -352,16 +364,15 @@ Collection.prototype.save = function save(doc, options, callback) {
|
||||
if('function' === typeof options) callback = options, options = null;
|
||||
if(options == null) options = {};
|
||||
if(!('function' === typeof callback)) callback = null;
|
||||
|
||||
var errorOptions = options.safe != null ? options.safe : false;
|
||||
errorOptions = errorOptions == null && this.opts.safe != null ? this.opts.safe : errorOptions;
|
||||
// Extract the id, if we have one we need to do a update command
|
||||
var id = doc['_id'];
|
||||
var commandOptions = _getWriteConcern(this, options, callback);
|
||||
|
||||
if(id) {
|
||||
this.update({ _id: id }, doc, { upsert: true, safe: errorOptions }, callback);
|
||||
commandOptions.upsert = true;
|
||||
this.update({ _id: id }, doc, commandOptions, callback);
|
||||
} else {
|
||||
this.insert(doc, { safe: errorOptions }, callback && function (err, docs) {
|
||||
this.insert(doc, commandOptions, callback && function (err, docs) {
|
||||
if (err) return callback(err, null);
|
||||
|
||||
if (Array.isArray(docs)) {
|
||||
@@ -377,15 +388,21 @@ Collection.prototype.save = function save(doc, options, callback) {
|
||||
* Updates documents.
|
||||
*
|
||||
* Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
|
||||
* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
|
||||
* - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
|
||||
* - **fsync**, (Boolean, default:false) write waits for fsync before returning
|
||||
* - **journal**, (Boolean, default:false) write waits for journal sync before returning
|
||||
* - **upsert** {Boolean, default:false}, perform an upsert operation.
|
||||
* - **multi** {Boolean, default:false}, update all documents matching the selector.
|
||||
* - **serializeFunctions** {Boolean, default:false}, serialize functions on the document.
|
||||
*
|
||||
* Deprecated Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
|
||||
*
|
||||
* @param {Object} selector the query to select the document/documents to be updated
|
||||
* @param {Object} document the fields/vals to be updated, or in the case of an upsert operation, inserted.
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @param {Function} [callback] must be provided if you performing a safe update
|
||||
* @param {Function} [callback] must be provided if you performing an update with a writeconcern
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -418,21 +435,15 @@ Collection.prototype.update = function update(selector, document, options, callb
|
||||
|
||||
var self = this;
|
||||
// Unpack the error options if any
|
||||
var errorOptions = (options && options.safe != null) ? options.safe : null;
|
||||
errorOptions = errorOptions == null && this.opts.safe != null ? this.opts.safe : errorOptions;
|
||||
errorOptions = errorOptions == null && this.db.safe != null ? this.db.safe : errorOptions;
|
||||
|
||||
// If we have a write concern set and no callback throw error
|
||||
if(errorOptions && errorOptions['safe'] != false && typeof callback !== 'function') throw new Error("safe cannot be used without a callback");
|
||||
|
||||
// If we are executing in safe mode or safe both the update and the safe command must happen on the same line
|
||||
if(errorOptions && errorOptions != false) {
|
||||
var errorOptions = _getWriteConcern(this, options, callback);
|
||||
// If safe is defined check for error message
|
||||
if(_hasWriteConcern(errorOptions) && typeof callback == 'function') {
|
||||
// Insert options
|
||||
var commandOptions = {read:false};
|
||||
// If we have safe set set async to false
|
||||
if(errorOptions == null) commandOptions['async'] = true;
|
||||
// Set safe option
|
||||
commandOptions['safe'] = true;
|
||||
commandOptions['safe'] = errorOptions;
|
||||
// If we have an error option
|
||||
if(typeof errorOptions == 'object') {
|
||||
var keys = Object.keys(errorOptions);
|
||||
@@ -455,6 +466,8 @@ Collection.prototype.update = function update(selector, document, options, callb
|
||||
callback(null, error[0].n, error[0]);
|
||||
}
|
||||
});
|
||||
} else if(_hasWriteConcern(errorOptions) && callback == null) {
|
||||
throw new Error("Cannot use a writeConcern without a provided callback");
|
||||
} else {
|
||||
// Execute update
|
||||
var result = this.db._executeUpdateCommand(updateCommand);
|
||||
@@ -478,7 +491,7 @@ Collection.prototype.update = function update(selector, document, options, callb
|
||||
* @param {String} key key to run distinct against.
|
||||
* @param {Object} [query] option query to narrow the returned objects.
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @param {Function} callback must be provided.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from distinct or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -516,7 +529,7 @@ Collection.prototype.distinct = function distinct(key, query, options, callback)
|
||||
*
|
||||
* @param {Object} [query] query to filter by before performing count.
|
||||
* @param {Object} [options] additional options during count.
|
||||
* @param {Function} callback must be provided.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the count method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -567,7 +580,7 @@ Collection.prototype.count = function count (query, options, callback) {
|
||||
/**
|
||||
* Drop the collection
|
||||
*
|
||||
* @param {Function} [callback] provide a callback to be notified when command finished executing
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the drop method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -579,16 +592,22 @@ Collection.prototype.drop = function drop(callback) {
|
||||
* Find and update a document.
|
||||
*
|
||||
* Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
|
||||
* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
|
||||
* - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
|
||||
* - **fsync**, (Boolean, default:false) write waits for fsync before returning
|
||||
* - **journal**, (Boolean, default:false) write waits for journal sync before returning
|
||||
* - **remove** {Boolean, default:false}, set to true to remove the object before returning.
|
||||
* - **upsert** {Boolean, default:false}, perform an upsert operation.
|
||||
* - **new** {Boolean, default:false}, set to true if you want to return the modified object rather than the original. Ignored for remove.
|
||||
*
|
||||
* Deprecated Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
|
||||
*
|
||||
* @param {Object} query query object to locate the object to modify
|
||||
* @param {Array} sort - if multiple docs match, choose the first one in the specified sort order as the object to manipulate
|
||||
* @param {Object} doc - the fields/vals to be updated
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @param {Function} [callback] returns results.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findAndModify method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -627,9 +646,7 @@ Collection.prototype.findAndModify = function findAndModify (query, sort, doc, o
|
||||
}
|
||||
|
||||
// Unpack the error options if any
|
||||
var errorOptions = (options && options.safe != null) ? options.safe : null;
|
||||
errorOptions = errorOptions == null && this.opts.safe != null ? this.opts.safe : errorOptions;
|
||||
errorOptions = errorOptions == null && this.db.safe != null ? this.db.safe : errorOptions;
|
||||
var errorOptions = _getWriteConcern(this, options, callback);
|
||||
|
||||
// If we have j, w or something else do the getLast Error path
|
||||
if(errorOptions != null && typeof errorOptions == 'object') {
|
||||
@@ -676,12 +693,18 @@ Collection.prototype.findAndModify = function findAndModify (query, sort, doc, o
|
||||
* Find and remove a document
|
||||
*
|
||||
* Options
|
||||
* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
|
||||
* - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
|
||||
* - **fsync**, (Boolean, default:false) write waits for fsync before returning
|
||||
* - **journal**, (Boolean, default:false) write waits for journal sync before returning
|
||||
*
|
||||
* Deprecated Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
|
||||
*
|
||||
* @param {Object} query query object to locate the object to modify
|
||||
* @param {Array} sort - if multiple docs match, choose the first one in the specified sort order as the object to manipulate
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @param {Function} [callback] returns results.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findAndRemove method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -696,10 +719,11 @@ Collection.prototype.findAndRemove = function(query, sort, options, callback) {
|
||||
this.findAndModify(query, sort, null, options, callback);
|
||||
}
|
||||
|
||||
var testForFields = {'limit' : 1, 'sort' : 1, 'fields' : 1, 'skip' : 1, 'hint' : 1, 'explain' : 1, 'snapshot' : 1
|
||||
, 'timeout' : 1, 'tailable' : 1, 'batchSize' : 1, 'raw' : 1, 'read' : 1
|
||||
, 'returnKey' : 1, 'maxScan' : 1, 'min' : 1, 'max' : 1, 'showDiskLoc' : 1, 'comment' : 1, 'dbName' : 1, 'exhaust': 1
|
||||
, 'tailableRetryInterval': 1};
|
||||
var testForFields = {
|
||||
limit: 1, sort: 1, fields:1, skip: 1, hint: 1, explain: 1, snapshot: 1, timeout: 1, tailable: 1, tailableRetryInterval: 1
|
||||
, numberOfRetries: 1, awaitdata: 1, exhaust: 1, batchSize: 1, returnKey: 1, maxScan: 1, min: 1, max: 1, showDiskLoc: 1
|
||||
, comment: 1, raw: 1, readPreference: 1, numberOfRetries: 1, partial: 1, read: 1, dbName: 1
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a cursor for a query that can be used to iterate over results from MongoDB
|
||||
@@ -741,7 +765,7 @@ var testForFields = {'limit' : 1, 'sort' : 1, 'fields' : 1, 'skip' : 1, 'hint' :
|
||||
*
|
||||
* @param {Object} query query object to locate the object to modify
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @param {Function} [callback] optional callback for cursor.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the find method or null if an error occured.
|
||||
* @return {Cursor} returns a cursor to the query
|
||||
* @api public
|
||||
*/
|
||||
@@ -860,15 +884,9 @@ Collection.prototype.find = function find () {
|
||||
// callback for backward compatibility
|
||||
if(callback) {
|
||||
// TODO refactor Cursor args
|
||||
callback(null, new Cursor(this.db, this, selector, fields, o.skip, o.limit
|
||||
, o.sort, o.hint, o.explain, o.snapshot, o.timeout, o.tailable, o.batchSize
|
||||
, o.slaveOk, o.raw, o.read, o.returnKey, o.maxScan, o.min, o.max, o.showDiskLoc, o.comment, o.awaitdata
|
||||
, o.numberOfRetries, o.dbName, o.tailableRetryInterval, o.exhaust));
|
||||
callback(null, new Cursor(this.db, this, selector, fields, o));
|
||||
} else {
|
||||
return new Cursor(this.db, this, selector, fields, o.skip, o.limit
|
||||
, o.sort, o.hint, o.explain, o.snapshot, o.timeout, o.tailable, o.batchSize
|
||||
, o.slaveOk, o.raw, o.read, o.returnKey, o.maxScan, o.min, o.max, o.showDiskLoc, o.comment, o.awaitdata
|
||||
, o.numberOfRetries, o.dbName, o.tailableRetryInterval, o.exhaust);
|
||||
return new Cursor(this.db, this, selector, fields, o);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -941,7 +959,7 @@ var normalizeHintField = function normalizeHintField(hint) {
|
||||
*
|
||||
* @param {Object} query query object to locate the object to modify
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @param {Function} [callback] optional callback for cursor.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findOne method or null if an error occured.
|
||||
* @return {Cursor} returns a cursor to the query
|
||||
* @api public
|
||||
*/
|
||||
@@ -951,10 +969,9 @@ Collection.prototype.findOne = function findOne () {
|
||||
var callback = args.pop();
|
||||
var cursor = this.find.apply(this, args).limit(-1).batchSize(1);
|
||||
// Return the item
|
||||
cursor.toArray(function(err, items) {
|
||||
if(err != null) return callback(err instanceof Error ? err : self.db.wrap(new Error(err)), null);
|
||||
if(items.length == 1) return callback(null, items[0]);
|
||||
callback(null, null);
|
||||
cursor.nextObject(function(err, item) {
|
||||
if(err != null) return callback(err instanceof Error ? err : self.db.wrap(err), null);
|
||||
callback(null, item);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -962,7 +979,10 @@ Collection.prototype.findOne = function findOne () {
|
||||
* Creates an index on the collection.
|
||||
*
|
||||
* Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a
|
||||
* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
|
||||
* - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
|
||||
* - **fsync**, (Boolean, default:false) write waits for fsync before returning
|
||||
* - **journal**, (Boolean, default:false) write waits for journal sync before returning
|
||||
* - **unique** {Boolean, default:false}, creates an unique index.
|
||||
* - **sparse** {Boolean, default:false}, creates a sparse index.
|
||||
* - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible.
|
||||
@@ -972,10 +992,13 @@ Collection.prototype.findOne = function findOne () {
|
||||
* - **v** {Number}, specify the format version of the indexes.
|
||||
* - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher)
|
||||
* - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes)
|
||||
*
|
||||
* Deprecated Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
|
||||
*
|
||||
* @param {Object} fieldOrSpec fieldOrSpec that defines the index.
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @param {Function} callback for results.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the createIndex method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -988,13 +1011,7 @@ Collection.prototype.createIndex = function createIndex (fieldOrSpec, options, c
|
||||
options = options == null ? {} : options;
|
||||
|
||||
// Collect errorOptions
|
||||
var errorOptions = options.safe != null ? options.safe : null;
|
||||
errorOptions = errorOptions == null && this.opts.safe != null ? this.opts.safe : errorOptions;
|
||||
errorOptions = errorOptions == null && this.db.safe != null ? this.db.safe : errorOptions;
|
||||
|
||||
// If we have a write concern set and no callback throw error
|
||||
if(errorOptions != null && errorOptions != false && (typeof callback !== 'function' && typeof options !== 'function')) throw new Error("safe cannot be used without a callback");
|
||||
|
||||
var errorOptions = _getWriteConcern(this, options, callback);
|
||||
// Execute create index
|
||||
this.db.createIndex(this.collectionName, fieldOrSpec, options, callback);
|
||||
};
|
||||
@@ -1003,7 +1020,10 @@ Collection.prototype.createIndex = function createIndex (fieldOrSpec, options, c
|
||||
* Ensures that an index exists, if it does not it creates it
|
||||
*
|
||||
* Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a
|
||||
* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
|
||||
* - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
|
||||
* - **fsync**, (Boolean, default:false) write waits for fsync before returning
|
||||
* - **journal**, (Boolean, default:false) write waits for journal sync before returning
|
||||
* - **unique** {Boolean, default:false}, creates an unique index.
|
||||
* - **sparse** {Boolean, default:false}, creates a sparse index.
|
||||
* - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible.
|
||||
@@ -1013,10 +1033,13 @@ Collection.prototype.createIndex = function createIndex (fieldOrSpec, options, c
|
||||
* - **v** {Number}, specify the format version of the indexes.
|
||||
* - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher)
|
||||
* - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes)
|
||||
*
|
||||
* Deprecated Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
|
||||
*
|
||||
* @param {Object} fieldOrSpec fieldOrSpec that defines the index.
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @param {Function} callback for results.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the ensureIndex method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -1031,14 +1054,6 @@ Collection.prototype.ensureIndex = function ensureIndex (fieldOrSpec, options, c
|
||||
options = {};
|
||||
}
|
||||
|
||||
// Collect errorOptions
|
||||
var errorOptions = options.safe != null ? options.safe : null;
|
||||
errorOptions = errorOptions == null && this.opts.safe != null ? this.opts.safe : errorOptions;
|
||||
errorOptions = errorOptions == null && this.db.safe != null ? this.db.safe : errorOptions;
|
||||
|
||||
// If we have a write concern set and no callback throw error
|
||||
if(errorOptions != null && errorOptions != false && (typeof callback !== 'function' && typeof options !== 'function')) throw new Error("safe cannot be used without a callback");
|
||||
|
||||
// Execute create index
|
||||
this.db.ensureIndex(this.collectionName, fieldOrSpec, options, callback);
|
||||
};
|
||||
@@ -1050,7 +1065,7 @@ Collection.prototype.ensureIndex = function ensureIndex (fieldOrSpec, options, c
|
||||
* - **full** {Boolean, default:false}, returns the full raw index information.
|
||||
*
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @param {Function} callback returns the index information.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexInformation method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -1067,7 +1082,7 @@ Collection.prototype.indexInformation = function indexInformation (options, call
|
||||
* Drops an index from this collection.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {Function} callback returns the results.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropIndex method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -1078,7 +1093,7 @@ Collection.prototype.dropIndex = function dropIndex (name, callback) {
|
||||
/**
|
||||
* Drops all indexes from this collection.
|
||||
*
|
||||
* @param {Function} callback returns the results.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropAllIndexes method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -1098,7 +1113,7 @@ Collection.prototype.dropAllIndexes = function dropIndexes (callback) {
|
||||
* Drops all indexes from this collection.
|
||||
*
|
||||
* @deprecated
|
||||
* @param {Function} callback returns the results.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropIndexes method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api private
|
||||
*/
|
||||
@@ -1108,7 +1123,7 @@ Collection.prototype.dropIndexes = Collection.prototype.dropAllIndexes;
|
||||
* Reindex all indexes on the collection
|
||||
* Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections.
|
||||
*
|
||||
* @param {Function} callback returns the results.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the reIndex method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
**/
|
||||
@@ -1134,7 +1149,7 @@ Collection.prototype.reIndex = function(callback) {
|
||||
* @param {Function|String} map the mapping function.
|
||||
* @param {Function|String} reduce the reduce function.
|
||||
* @param {Objects} [options] options for the map reduce job.
|
||||
* @param {Function} callback returns the result of the map reduce job, (error, results, [stats])
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the mapReduce method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -1165,7 +1180,11 @@ Collection.prototype.mapReduce = function mapReduce (map, reduce, options, callb
|
||||
|
||||
// Add any other options passed in
|
||||
for (var name in options) {
|
||||
mapCommandHash[name] = options[name];
|
||||
if ('scope' == name) {
|
||||
mapCommandHash[name] = processScope(options[name]);
|
||||
} else {
|
||||
mapCommandHash[name] = options[name];
|
||||
}
|
||||
}
|
||||
|
||||
// Set read preference if we set one
|
||||
@@ -1222,6 +1241,30 @@ Collection.prototype.mapReduce = function mapReduce (map, reduce, options, callb
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Functions that are passed as scope args must
|
||||
* be converted to Code instances.
|
||||
* @ignore
|
||||
*/
|
||||
function processScope (scope) {
|
||||
if (!utils.isObject(scope)) {
|
||||
return scope;
|
||||
}
|
||||
|
||||
var keys = Object.keys(scope);
|
||||
var i = keys.length;
|
||||
var key;
|
||||
|
||||
while (i--) {
|
||||
key = keys[i];
|
||||
if ('function' == typeof scope[key]) {
|
||||
scope[key] = new Code(String(scope[key]));
|
||||
}
|
||||
}
|
||||
|
||||
return scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group function helper
|
||||
* @ignore
|
||||
@@ -1267,7 +1310,7 @@ var groupFunction = function () {
|
||||
* @param {Function|Code} finalize an optional function to be run on each item in the result set just before the item is returned.
|
||||
* @param {Boolean} command specify if you wish to run using the internal group command or using eval, default is true.
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @param {Function} callback returns the results.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the group method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -1371,7 +1414,7 @@ Collection.prototype.group = function group(keys, condition, initial, reduce, fi
|
||||
/**
|
||||
* Returns the options of the collection.
|
||||
*
|
||||
* @param {Function} callback returns option results.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the options method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -1387,7 +1430,7 @@ Collection.prototype.options = function options(callback) {
|
||||
/**
|
||||
* Returns if the collection is a capped collection
|
||||
*
|
||||
* @param {Function} callback returns if collection is capped.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the isCapped method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -1405,7 +1448,7 @@ Collection.prototype.isCapped = function isCapped(callback) {
|
||||
* Checks if one or more indexes exist on the collection
|
||||
*
|
||||
* @param {String|Array} indexNames check if one or more indexes exist on the collection.
|
||||
* @param {Function} callback returns if the indexes exist.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexExists method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -1445,7 +1488,7 @@ Collection.prototype.indexExists = function indexExists(indexes, callback) {
|
||||
* @param {Number} x point to search on the x axis, ensure the indexes are ordered in the same order.
|
||||
* @param {Number} y point to search on the y axis, ensure the indexes are ordered in the same order.
|
||||
* @param {Objects} [options] options for the map reduce job.
|
||||
* @param {Function} callback returns matching documents.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the geoNear method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -1486,7 +1529,7 @@ Collection.prototype.geoNear = function geoNear(x, y, options, callback) {
|
||||
* @param {Number} x point to search on the x axis, ensure the indexes are ordered in the same order.
|
||||
* @param {Number} y point to search on the y axis, ensure the indexes are ordered in the same order.
|
||||
* @param {Objects} [options] options for the map reduce job.
|
||||
* @param {Function} callback returns matching documents.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the geoHaystackSearch method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -1515,7 +1558,7 @@ Collection.prototype.geoHaystackSearch = function geoHaystackSearch(x, y, option
|
||||
/**
|
||||
* Retrieve all the indexes on the collection.
|
||||
*
|
||||
* @param {Function} callback returns index information.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexes method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -1532,7 +1575,7 @@ Collection.prototype.indexes = function indexes(callback) {
|
||||
*
|
||||
* @param {Array} array containing all the aggregation framework commands for the execution.
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @param {Function} callback returns matching documents.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the aggregate method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -1541,8 +1584,10 @@ Collection.prototype.aggregate = function(pipeline, options, callback) {
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
callback = args.pop();
|
||||
var self = this;
|
||||
// Get the right options
|
||||
options = args[args.length - 1].explain ? args.pop() : {}
|
||||
|
||||
// If we have any of the supported options in the options object
|
||||
var opts = args[args.length - 1];
|
||||
options = opts.readPreference || opts.explain ? args.pop() : {}
|
||||
|
||||
// Convert operations to an array
|
||||
if(!Array.isArray(args[0])) {
|
||||
@@ -1582,7 +1627,7 @@ Collection.prototype.aggregate = function(pipeline, options, callback) {
|
||||
* - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST).
|
||||
*
|
||||
* @param {Objects} [options] options for the stats command.
|
||||
* @param {Function} callback returns statistical information for the collection.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the stats method or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -1617,20 +1662,65 @@ Object.defineProperty(Collection.prototype, "hint", {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
var _hasWriteConcern = function(errorOptions) {
|
||||
return errorOptions == true
|
||||
|| errorOptions.w > 0
|
||||
|| errorOptions.w == 'majority'
|
||||
|| errorOptions.j == true
|
||||
|| errorOptions.journal == true
|
||||
|| errorOptions.fsync == true
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
var _setWriteConcernHash = function(options) {
|
||||
var finalOptions = {};
|
||||
if(options.w != null) finalOptions.w = options.w;
|
||||
if(options.journal == true) finalOptions.j = options.journal;
|
||||
if(options.j == true) finalOptions.j = options.j;
|
||||
if(options.fsync == true) finalOptions.fsync = options.fsync;
|
||||
if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout;
|
||||
return finalOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
var _getWriteConcern = function(self, options, callback) {
|
||||
// Final options
|
||||
var finalOptions = {w:1};
|
||||
// Local options verification
|
||||
if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') {
|
||||
finalOptions = _setWriteConcernHash(options);
|
||||
} else if(typeof options.safe == "boolean") {
|
||||
finalOptions = {w: (options.safe ? 1 : 0)};
|
||||
} else if(options.safe != null && typeof options.safe == 'object') {
|
||||
finalOptions = _setWriteConcernHash(options.safe);
|
||||
} else if(self.opts.w != null || typeof self.opts.j == 'boolean' || typeof self.opts.journal == 'boolean' || typeof self.opts.fsync == 'boolean') {
|
||||
finalOptions = _setWriteConcernHash(self.opts);
|
||||
} else if(typeof self.opts.safe == "boolean") {
|
||||
finalOptions = {w: (self.opts.safe ? 1 : 0)};
|
||||
} else if(self.db.safe.w != null || typeof self.db.safe.j == 'boolean' || typeof self.db.safe.journal == 'boolean' || typeof self.db.safe.fsync == 'boolean') {
|
||||
finalOptions = _setWriteConcernHash(self.db.safe);
|
||||
} else if(self.db.options.w != null || typeof self.db.options.j == 'boolean' || typeof self.db.options.journal == 'boolean' || typeof self.db.options.fsync == 'boolean') {
|
||||
finalOptions = _setWriteConcernHash(self.db.options);
|
||||
} else if(typeof self.db.safe == "boolean") {
|
||||
finalOptions = {w: (self.db.safe ? 1 : 0)};
|
||||
}
|
||||
|
||||
// Ensure we don't have an invalid combination of write concerns
|
||||
if(finalOptions.w < 1
|
||||
&& (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowlegement using w < 1 cannot be combined with journal:true or fsync:true");
|
||||
|
||||
// Return the options
|
||||
return finalOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose.
|
||||
*/
|
||||
exports.Collection = Collection;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
64
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/commands/db_command.js
generated
vendored
64
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/commands/db_command.js
generated
vendored
@@ -1,6 +1,7 @@
|
||||
var QueryCommand = require('./query_command').QueryCommand,
|
||||
InsertCommand = require('./insert_command').InsertCommand,
|
||||
inherits = require('util').inherits,
|
||||
utils = require('../utils'),
|
||||
crypto = require('crypto');
|
||||
|
||||
/**
|
||||
@@ -107,6 +108,11 @@ DbCommand.createGetLastErrorCommand = function(options, db) {
|
||||
}
|
||||
}
|
||||
|
||||
// Special case for w == 1, remove the w
|
||||
if(1 == command.w) {
|
||||
delete command.w;
|
||||
}
|
||||
|
||||
// Execute command
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command, null);
|
||||
};
|
||||
@@ -127,28 +133,36 @@ DbCommand.createCreateIndexCommand = function(db, collectionName, fieldOrSpec, o
|
||||
var keys;
|
||||
|
||||
// Get all the fields accordingly
|
||||
if (fieldOrSpec.constructor === String) { // 'type'
|
||||
if('string' == typeof fieldOrSpec) {
|
||||
// 'type'
|
||||
indexes.push(fieldOrSpec + '_' + 1);
|
||||
fieldHash[fieldOrSpec] = 1;
|
||||
} else if (fieldOrSpec.constructor === Array) { // [{location:'2d'}, ...]
|
||||
|
||||
} else if(utils.isArray(fieldOrSpec)) {
|
||||
|
||||
fieldOrSpec.forEach(function(f) {
|
||||
if (f.constructor === String) { // [{location:'2d'}, 'type']
|
||||
if('string' == typeof f) {
|
||||
// [{location:'2d'}, 'type']
|
||||
indexes.push(f + '_' + 1);
|
||||
fieldHash[f] = 1;
|
||||
} else if (f.constructor === Array) { // [['location', '2d'],['type', 1]]
|
||||
} else if(utils.isArray(f)) {
|
||||
// [['location', '2d'],['type', 1]]
|
||||
indexes.push(f[0] + '_' + (f[1] || 1));
|
||||
fieldHash[f[0]] = f[1] || 1;
|
||||
} else if (f.constructor === Object) { // [{location:'2d'}, {type:1}]
|
||||
} else if(utils.isObject(f)) {
|
||||
// [{location:'2d'}, {type:1}]
|
||||
keys = Object.keys(f);
|
||||
keys.forEach(function(k) {
|
||||
indexes.push(k + '_' + f[k]);
|
||||
fieldHash[k] = f[k];
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// undefined
|
||||
// undefined (ignore)
|
||||
}
|
||||
});
|
||||
} else if (fieldOrSpec.constructor === Object) { // {location:'2d', type:1}
|
||||
|
||||
} else if(utils.isObject(fieldOrSpec)) {
|
||||
// {location:'2d', type:1}
|
||||
keys = Object.keys(fieldOrSpec);
|
||||
keys.forEach(function(key) {
|
||||
indexes.push(key + '_' + fieldOrSpec[key]);
|
||||
@@ -157,26 +171,38 @@ DbCommand.createCreateIndexCommand = function(db, collectionName, fieldOrSpec, o
|
||||
}
|
||||
|
||||
// Generate the index name
|
||||
var indexName = typeof options.name == 'string' ? options.name : indexes.join("_");
|
||||
// Build the selector
|
||||
var selector = {'ns':(db.databaseName + "." + collectionName), 'key':fieldHash, 'name':indexName};
|
||||
var indexName = typeof options.name == 'string'
|
||||
? options.name
|
||||
: indexes.join("_");
|
||||
|
||||
var selector = {
|
||||
'ns': db.databaseName + "." + collectionName,
|
||||
'key': fieldHash,
|
||||
'name': indexName
|
||||
}
|
||||
|
||||
// Ensure we have a correct finalUnique
|
||||
var finalUnique = options == null || 'object' === typeof options ? false : options;
|
||||
var finalUnique = options == null || 'object' === typeof options
|
||||
? false
|
||||
: options;
|
||||
|
||||
// Set up options
|
||||
options = options == null || typeof options == 'boolean' ? {} : options;
|
||||
options = options == null || typeof options == 'boolean'
|
||||
? {}
|
||||
: options;
|
||||
|
||||
// Add all the options
|
||||
var keys = Object.keys(options);
|
||||
// Add all the fields to the selector
|
||||
for(var i = 0; i < keys.length; i++) {
|
||||
selector[keys[i]] = options[keys[i]];
|
||||
}
|
||||
|
||||
// If we don't have the unique property set on the selector
|
||||
if(selector['unique'] == null) selector['unique'] = finalUnique;
|
||||
// Create the insert command for the index and return the document
|
||||
return new InsertCommand(db, db.databaseName + "." + DbCommand.SYSTEM_INDEX_COLLECTION, false).add(selector);
|
||||
if(selector['unique'] == null)
|
||||
selector['unique'] = finalUnique;
|
||||
|
||||
var name = db.databaseName + "." + DbCommand.SYSTEM_INDEX_COLLECTION;
|
||||
var cmd = new InsertCommand(db, name, false);
|
||||
return cmd.add(selector);
|
||||
};
|
||||
|
||||
DbCommand.logoutCommand = function(db, command_hash, options) {
|
||||
@@ -211,4 +237,4 @@ DbCommand.createAdminDbCommandSlaveOk = function(db, command_hash) {
|
||||
|
||||
DbCommand.createDbSlaveOkCommand = function(db, command_hash, options) {
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT | QueryCommand.OPTS_SLAVE, 0, -1, command_hash, null, options);
|
||||
};
|
||||
};
|
||||
|
||||
10
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/connection/connection.js
generated
vendored
10
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/connection/connection.js
generated
vendored
@@ -89,10 +89,10 @@ Connection.prototype.start = function() {
|
||||
}
|
||||
} else {
|
||||
// Create new connection instance
|
||||
if(!this.domainSocket) {
|
||||
this.connection = net.createConnection(this.socketOptions.port, this.socketOptions.host);
|
||||
if(this.domainSocket) {
|
||||
this.connection = net.createConnection(this.socketOptions.host);
|
||||
} else {
|
||||
this.connection = net.createConnection(this.socketOptions.host);
|
||||
this.connection = net.createConnection(this.socketOptions.port, this.socketOptions.host);
|
||||
}
|
||||
if(this.logger != null && this.logger.doDebug){
|
||||
this.logger.debug("opened connection", this.socketOptions);
|
||||
@@ -139,7 +139,7 @@ Connection.prototype.write = function(command, callback) {
|
||||
if(!this.socketOptions['disableDriverBSONSizeCheck'] && binaryCommand.length > this.maxBsonSize)
|
||||
return callback(new Error("Document exceeds maximal allowed bson size of " + this.maxBsonSize + " bytes"));
|
||||
if(this.logger != null && this.logger.doDebug)
|
||||
this.logger.debug("writing command to mongodb", binaryCommand);
|
||||
this.logger.debug("writing command to mongodb", {binary: binaryCommand, json: command[i]});
|
||||
|
||||
var r = this.writeSteam.write(binaryCommand);
|
||||
}
|
||||
@@ -149,7 +149,7 @@ Connection.prototype.write = function(command, callback) {
|
||||
return callback(new Error("Document exceeds maximal allowed bson size of " + this.maxBsonSize + " bytes"));
|
||||
|
||||
if(this.logger != null && this.logger.doDebug)
|
||||
this.logger.debug("writing command to mongodb", binaryCommand);
|
||||
this.logger.debug("writing command to mongodb", {binary: binaryCommand, json: command});
|
||||
|
||||
var r = this.writeSteam.write(binaryCommand);
|
||||
}
|
||||
|
||||
20
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/connection/connection_pool.js
generated
vendored
20
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/connection/connection_pool.js
generated
vendored
@@ -7,9 +7,13 @@ var utils = require('./connection_utils'),
|
||||
Connection = require("./connection").Connection;
|
||||
|
||||
var ConnectionPool = exports.ConnectionPool = function(host, port, poolSize, bson, socketOptions) {
|
||||
if(typeof host !== 'string' || typeof port !== 'number') throw "host and port must be specified [" + host + ":" + port + "]";
|
||||
if(typeof host !== 'string') {
|
||||
throw new Error("host must be specified [" + host + "]");
|
||||
}
|
||||
|
||||
// Set up event emitter
|
||||
EventEmitter.call(this);
|
||||
|
||||
// Keep all options for the socket in a specific collection allowing the user to specify the
|
||||
// Wished upon socket connection parameters
|
||||
this.socketOptions = typeof socketOptions === 'object' ? socketOptions : {};
|
||||
@@ -22,7 +26,11 @@ var ConnectionPool = exports.ConnectionPool = function(host, port, poolSize, bso
|
||||
this.minPoolSize = Math.floor(this.poolSize / 2) + 1;
|
||||
|
||||
// Check if the host is a socket
|
||||
if(host.match(/^\//)) this.socketOptions.domainSocket = true;
|
||||
if(host.match(/^\//)) {
|
||||
this.socketOptions.domainSocket = true;
|
||||
} else if(typeof port !== 'number') {
|
||||
throw new Error("port must be specified [" + port + "]");
|
||||
}
|
||||
|
||||
// Set default settings for the socket options
|
||||
utils.setIntegerParameter(this.socketOptions, 'timeout', 0);
|
||||
@@ -96,9 +104,8 @@ var _connect = function(_self) {
|
||||
_self.emit("error", err);
|
||||
}
|
||||
|
||||
// Set disconnected
|
||||
connection.close();
|
||||
_self._poolState = 'disconnected';
|
||||
// Stop
|
||||
_self.stop();
|
||||
});
|
||||
|
||||
@@ -120,9 +127,8 @@ var _connect = function(_self) {
|
||||
if(_self._poolState !== 'disconnected' && _self.listeners("timeout").length > 0) {
|
||||
_self.emit("timeout", err);
|
||||
}
|
||||
// Set disconnected
|
||||
_self._poolState = 'disconnected';
|
||||
// Stop
|
||||
|
||||
connection.close();
|
||||
_self.stop();
|
||||
});
|
||||
|
||||
|
||||
615
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/connection/repl_set.js
generated
vendored
615
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/connection/repl_set.js
generated
vendored
@@ -1,14 +1,14 @@
|
||||
var Connection = require('./connection').Connection,
|
||||
var Connection = require('./connection').Connection,
|
||||
ReadPreference = require('./read_preference').ReadPreference,
|
||||
DbCommand = require('../commands/db_command').DbCommand,
|
||||
MongoReply = require('../responses/mongo_reply').MongoReply,
|
||||
debug = require('util').debug,
|
||||
EventEmitter = require('events').EventEmitter,
|
||||
inherits = require('util').inherits,
|
||||
inspect = require('util').inspect,
|
||||
Server = require('./server').Server,
|
||||
PingStrategy = require('./strategies/ping_strategy').PingStrategy,
|
||||
StatisticsStrategy = require('./strategies/statistics_strategy').StatisticsStrategy;
|
||||
StatisticsStrategy = require('./strategies/statistics_strategy').StatisticsStrategy,
|
||||
Base = require('./base').Base;
|
||||
|
||||
const STATE_STARTING_PHASE_1 = 0;
|
||||
const STATE_PRIMARY = 1;
|
||||
@@ -35,6 +35,7 @@ const STATE_ROLLBACK = 9;
|
||||
* - **strategy** {String, default:null}, selection strategy for reads choose between (ping and statistical, default is round-robin)
|
||||
* - **secondaryAcceptableLatencyMS** {Number, default:15}, sets the range of servers to pick when using NEAREST (lowest ping ms + the latency fence, ex: range of 1 to (1 + 15) ms)
|
||||
* - **connectArbiter** {Boolean, default:false}, sets if the driver should connect to arbiters or not.
|
||||
* - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**.
|
||||
*
|
||||
* @class Represents a Replicaset Configuration
|
||||
* @param {Array} list of server objects participating in the replicaset.
|
||||
@@ -48,7 +49,7 @@ var ReplSet = exports.ReplSet = function(servers, options) {
|
||||
return new ReplSet(servers, options);
|
||||
|
||||
// Set up event emitter
|
||||
EventEmitter.call(this);
|
||||
Base.call(this);
|
||||
|
||||
// Ensure no Mongos's
|
||||
for(var i = 0; i < servers.length; i++) {
|
||||
@@ -89,6 +90,8 @@ var ReplSet = exports.ReplSet = function(servers, options) {
|
||||
this._numberOfServersLeftToInitialize = 0;
|
||||
// Do we record server stats or not
|
||||
this.recordQueryStats = false;
|
||||
// Update health try server
|
||||
this.updateHealthServerTry = 0;
|
||||
|
||||
// Get the readPreference
|
||||
var readPreference = this.options['readPreference'];
|
||||
@@ -106,6 +109,12 @@ var ReplSet = exports.ReplSet = function(servers, options) {
|
||||
this._readPreference = null;
|
||||
}
|
||||
|
||||
// Ensure read_secondary is set correctly
|
||||
if(!this.readSecondary)
|
||||
this.readSecondary = this._readPreference == ReadPreference.PRIMARY
|
||||
|| this._readPreference == false
|
||||
|| this._readPreference == null ? false : true;
|
||||
|
||||
// Strategy for picking a secondary
|
||||
this.secondaryAcceptableLatencyMS = this.options['secondaryAcceptableLatencyMS'] == null ? 15 : this.options['secondaryAcceptableLatencyMS'];
|
||||
this.strategy = this.options['strategy'];
|
||||
@@ -115,7 +124,6 @@ var ReplSet = exports.ReplSet = function(servers, options) {
|
||||
if(this.strategy == 'ping') {
|
||||
// Create a new instance
|
||||
this.strategyInstance = new PingStrategy(this, this.secondaryAcceptableLatencyMS);
|
||||
this.strategyInstance.start();
|
||||
} else if(this.strategy == 'statistical') {
|
||||
// Set strategy as statistical
|
||||
this.strategyInstance = new StatisticsStrategy(this);
|
||||
@@ -174,8 +182,12 @@ var ReplSet = exports.ReplSet = function(servers, options) {
|
||||
// How often are we checking for new servers in the replicaset
|
||||
this.replicasetStatusCheckInterval = this.options['haInterval'] == null ? 1000 : this.options['haInterval'];
|
||||
this._replicasetTimeoutId = null;
|
||||
|
||||
// Connection timeout
|
||||
this._connectTimeoutMS = 1000;
|
||||
this._connectTimeoutMS = this.socketOptions.connectTimeoutMS
|
||||
? this.socketOptions.connectTimeoutMS
|
||||
: 1000;
|
||||
|
||||
// Current list of servers to test
|
||||
this.pingCandidateServers = [];
|
||||
|
||||
@@ -186,7 +198,7 @@ var ReplSet = exports.ReplSet = function(servers, options) {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
inherits(ReplSet, EventEmitter);
|
||||
inherits(ReplSet, Base);
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
@@ -219,8 +231,20 @@ ReplSet.prototype.isMongos = function() {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ReplSet.prototype.isConnected = function() {
|
||||
return this.primary != null && this._state.master != null && this._state.master.isConnected();
|
||||
ReplSet.prototype.isConnected = function(read) {
|
||||
if(read == null || read == ReadPreference.PRIMARY || read == false)
|
||||
return this.primary != null && this._state.master != null && this._state.master.isConnected();
|
||||
|
||||
if((read == ReadPreference.PRIMARY_PREFERRED || read == ReadPreference.SECONDARY_PREFERRED || read == ReadPreference.NEAREST)
|
||||
&& ((this.primary != null && this._state.master != null && this._state.master.isConnected())
|
||||
|| (this._state && this._state.secondaries && Object.keys(this._state.secondaries).length > 0))) {
|
||||
return true;
|
||||
} else if(read == ReadPreference.SECONDARY) {
|
||||
return this._state && this._state.secondaries && Object.keys(this._state.secondaries).length > 0;
|
||||
}
|
||||
|
||||
// No valid connection return false
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -242,25 +266,13 @@ ReplSet.prototype.isPrimary = function(config) {
|
||||
*/
|
||||
ReplSet.prototype.isReadPrimary = ReplSet.prototype.isPrimary;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
**/
|
||||
ReplSet.prototype._checkReplicaSet = function() {
|
||||
if(!this.haEnabled) return false;
|
||||
var currentTime = new Date().getTime();
|
||||
if((currentTime - this.lastReplicaSetTime) >= this.replicasetStatusCheckInterval) {
|
||||
this.lastReplicaSetTime = currentTime;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ReplSet.prototype.allServerInstances = function() {
|
||||
var self = this;
|
||||
// If no state yet return empty
|
||||
if(!self._state) return [];
|
||||
// Close all the servers (concatenate entire list of servers first for ease)
|
||||
var allServers = self._state.master != null ? [self._state.master] : [];
|
||||
|
||||
@@ -290,153 +302,274 @@ ReplSet.prototype.allServerInstances = function() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables high availability pings.
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
var __executeAllCallbacksWithError = function(dbInstance, error) {
|
||||
var keys = Object.keys(dbInstance._callBackStore._notReplied);
|
||||
// Iterate over all callbacks
|
||||
for(var i = 0; i < keys.length; i++) {
|
||||
// Delete info object
|
||||
delete dbInstance._callBackStore._notReplied[keys[i]];
|
||||
// Emit the error
|
||||
dbInstance._callBackStore.emit(keys[i], error);
|
||||
ReplSet.prototype._enableHA = function () {
|
||||
var self = this;
|
||||
return check();
|
||||
|
||||
function ping () {
|
||||
if("disconnected" == self._serverState) return;
|
||||
|
||||
if(Object.keys(self._state.addresses).length == 0) return;
|
||||
var selectedServer = self._state.addresses[Object.keys(self._state.addresses)[self.updateHealthServerTry++]];
|
||||
if(self.updateHealthServerTry >= Object.keys(self._state.addresses).length) self.updateHealthServerTry = 0;
|
||||
if(selectedServer == null) return check();
|
||||
|
||||
// If we have an active db instance
|
||||
if(self.dbInstances.length > 0) {
|
||||
var db = self.dbInstances[0];
|
||||
|
||||
// Create a new master connection
|
||||
var _server = new Server(selectedServer.host, selectedServer.port, {
|
||||
auto_reconnect: false,
|
||||
returnIsMasterResults: true,
|
||||
slaveOk: true,
|
||||
poolSize: 1,
|
||||
socketOptions: { connectTimeoutMS: self._connectTimeoutMS }
|
||||
});
|
||||
|
||||
// Connect using the new _server connection to not impact the driver
|
||||
// behavior on any errors we could possibly run into
|
||||
_server.connect(db, function(err, result, _server) {
|
||||
if(err) {
|
||||
if(_server.close) _server.close();
|
||||
return check();
|
||||
}
|
||||
|
||||
// Create is master command
|
||||
var cmd = DbCommand.createIsMasterCommand(db);
|
||||
// Execute is master command
|
||||
db._executeQueryCommand(cmd, {failFast:true, connection: _server.checkoutWriter()}, function(err, res) {
|
||||
// Close the connection used
|
||||
_server.close();
|
||||
// If error let's set perform another check
|
||||
if(err) return check();
|
||||
// Validate the replicaset
|
||||
self._validateReplicaset(res, db.auths, function() {
|
||||
check();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function check () {
|
||||
self._haTimer = setTimeout(ping, self.replicasetStatusCheckInterval);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ReplSet.prototype._validateReplicaset = function(result, auths) {
|
||||
ReplSet.prototype._validateReplicaset = function(result, auths, cb) {
|
||||
var self = this;
|
||||
// For each member we need to check if we have a new connection that needs to be established
|
||||
var members = result['documents'][0]['members'];
|
||||
// Get members
|
||||
var members = Array.isArray(result['documents'][0]['members']) ? result['documents'][0]['members'] : [];
|
||||
// The total members we check
|
||||
var serversToConnectList = {};
|
||||
var res = result.documents[0];
|
||||
|
||||
// Iterate over all the members and see if we need to reconnect
|
||||
for(var i = 0, jlen = members.length; i < jlen; i++) {
|
||||
var member = members[i];
|
||||
// manage master node changes
|
||||
if(res.primary && self._state.master && self._state.master.name != res.primary) {
|
||||
// Delete master record so we can rediscover it
|
||||
delete self._state.addresses[self._state.master.name];
|
||||
|
||||
if(member['health'] != 0
|
||||
&& null == self._state['addresses'][member['name']]
|
||||
&& null == serversToConnectList[member['name']]) {
|
||||
if (member['stateStr'] == 'ARBITER' && self.connectArbiter != true) {
|
||||
continue;
|
||||
}
|
||||
// Split the server string
|
||||
var parts = member.name.split(/:/);
|
||||
if(parts.length == 1) {
|
||||
parts = [parts[0], Connection.DEFAULT_PORT];
|
||||
}
|
||||
// TODO existing issue? this seems to only work if
|
||||
// we already have a connection to the new primary.
|
||||
|
||||
// Default empty socket options object
|
||||
var socketOptions = {host:parts[0], port:parseInt(parts[1], 10)};
|
||||
// If a socket option object exists clone it
|
||||
if(self.socketOptions != null) {
|
||||
var keys = Object.keys(self.socketOptions);
|
||||
for(var k = 0; k < keys.length;k++) socketOptions[keys[i]] = self.socketOptions[keys[i]];
|
||||
}
|
||||
// Update information on new primary
|
||||
// add as master, remove from secondary
|
||||
var newMaster = self._state.addresses[res.primary];
|
||||
newMaster.isMasterDoc.ismaster = true;
|
||||
newMaster.isMasterDoc.secondary = false;
|
||||
self._state.master = newMaster;
|
||||
delete self._state.secondaries[res.primary];
|
||||
}
|
||||
|
||||
// Create a new server instance
|
||||
var newServer = new Server(parts[0], parseInt(parts[1], 10), {auto_reconnect:false, 'socketOptions':socketOptions
|
||||
, logger:self.logger, ssl:self.ssl, poolSize:self.poolSize});
|
||||
// Set the replicaset instance
|
||||
newServer.replicasetInstance = self;
|
||||
// discover new hosts
|
||||
var hosts = [];
|
||||
|
||||
// Add handlers
|
||||
newServer.on("close", _handler("close", self));
|
||||
newServer.on("error", _handler("error", self));
|
||||
newServer.on("timeout", _handler("timeout", self));
|
||||
// Add to list of server connection target
|
||||
serversToConnectList[member['name']] = newServer;
|
||||
} else if(member['stateStr'] == 'PRIMARY' && self._state.master['name'] != member['name']) {
|
||||
// Delete master record so we can rediscover it
|
||||
delete self._state['addresses'][self._state.master['name']];
|
||||
// Update inormation on new primary
|
||||
var newMaster = self._state.addresses[member['name']];
|
||||
newMaster.isMasterDoc.ismaster = true;
|
||||
newMaster.isMasterDoc.secondary = false;
|
||||
self._state.master = newMaster;
|
||||
// Remove from secondaries
|
||||
delete self._state.secondaries[member['name']];
|
||||
newMaster = null;
|
||||
for(var i = 0; i < res.hosts.length; ++i) {
|
||||
var host = res.hosts[i];
|
||||
if (host == res.me) continue;
|
||||
if (!(self._state.addresses[host] || ~hosts.indexOf(host))) {
|
||||
// we dont already have a connection to this host and aren't
|
||||
// already planning on connecting.
|
||||
hosts.push(host);
|
||||
}
|
||||
}
|
||||
|
||||
// All servers we want to connect to
|
||||
var serverKeys = Object.keys(serversToConnectList);
|
||||
// For all remaining servers on the list connect
|
||||
while(serverKeys.length > 0) {
|
||||
var _serverKey = serverKeys.pop();
|
||||
// Fetch the server
|
||||
var _server = serversToConnectList[_serverKey];
|
||||
// Add a new server to the total number of servers that need to initialized before we are done
|
||||
//var newServerCallback = self.connectionHandler(_server);
|
||||
var newServerCallback = _connectHandler(self, null, _server)
|
||||
// Connect To the new server
|
||||
_server.connect(self.db, {returnIsMasterResults: true, eventReceiver:newServer}, function(err, result, _server) {
|
||||
if(err == null && result != null) {
|
||||
// Fetch the myState
|
||||
var document = result.documents[0];
|
||||
// Remove from list until
|
||||
if(document.ismaster || document.secondary || document.arbiterOnly) {
|
||||
process.nextTick(function() {
|
||||
// Apply any auths
|
||||
if(Array.isArray(auths) && auths.length > 0) {
|
||||
// Get number of auths we need to execute
|
||||
var numberOfAuths = auths.length;
|
||||
// Apply all auths
|
||||
for(var i = 0; i < auths.length; i++) {
|
||||
self.db.authenticate(auths[i].username, auths[i].password, {'authdb':auths[i].authdb}, function(err, authenticated) {
|
||||
numberOfAuths = numberOfAuths - 1;
|
||||
// If we have no more authentications to replay
|
||||
if(numberOfAuths == 0) {
|
||||
newServerCallback(err, result, _server);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
newServerCallback(err, result, _server);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
_server.close();
|
||||
}
|
||||
} else {
|
||||
_server.close();
|
||||
}
|
||||
});
|
||||
connectTo(hosts, auths, self, cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create connections to all `hosts` firing `cb` after
|
||||
* connections are attempted for all `hosts`.
|
||||
*
|
||||
* @param {Array} hosts
|
||||
* @param {Array} [auths]
|
||||
* @param {ReplSet} replset
|
||||
* @param {Function} cb
|
||||
* @ignore
|
||||
*/
|
||||
function connectTo (hosts, auths, replset, cb) {
|
||||
var pending = hosts.length;
|
||||
if (!pending) return cb();
|
||||
|
||||
for(var i = 0; i < hosts.length; ++i) {
|
||||
connectToHost(hosts[i], auths, replset, handle);
|
||||
}
|
||||
|
||||
function handle () {
|
||||
--pending;
|
||||
if (0 === pending) cb();
|
||||
}
|
||||
}
|
||||
|
||||
var _handler = function(event, self) {
|
||||
return function(err, server) {
|
||||
// Check if we have a secondary server
|
||||
if(self._state.master && self._state.master.name == server.name) {
|
||||
// Force close
|
||||
self.close();
|
||||
// Error out all callbacks
|
||||
__executeAllCallbacksWithError(self.db, err);
|
||||
} else if(self._state.master
|
||||
&& (self._state.secondaries[server.name] != null
|
||||
|| self._state.arbiters[server.name] != null
|
||||
|| self._state.passives[server.name] != null)) {
|
||||
/**
|
||||
* Attempts connection to `host` and authenticates with optional `auth`
|
||||
* for the given `replset` firing `cb` when finished.
|
||||
*
|
||||
* @param {String} host
|
||||
* @param {Array} auths
|
||||
* @param {ReplSet} replset
|
||||
* @param {Function} cb
|
||||
* @ignore
|
||||
*/
|
||||
function connectToHost (host, auths, replset, cb) {
|
||||
var server = createServer(host, replset);
|
||||
|
||||
delete self._state.secondaries[server.name];
|
||||
delete self._state.arbiters[server.name];
|
||||
delete self._state.passives[server.name];
|
||||
delete self._state.addresses[server.name];
|
||||
var options = {
|
||||
returnIsMasterResults: true,
|
||||
eventReceiver: server
|
||||
}
|
||||
|
||||
server.connect(replset.db, options, function(err, result) {
|
||||
var doc = result && result.documents && result.documents[0];
|
||||
|
||||
if (err || !doc) {
|
||||
server.close();
|
||||
return cb(err, result, server);
|
||||
}
|
||||
|
||||
// If it's a primary we need to close the set to reconnect
|
||||
if(self._state.master && self._state.master.host == server.host && self._state.master.port == server.port) {
|
||||
// If we have app listeners on close event
|
||||
if(self.db.listeners(event).length > 0) {
|
||||
self.db.emit(event, err);
|
||||
if(!(doc.ismaster || doc.secondary || doc.arbiterOnly)) {
|
||||
server.close();
|
||||
return cb(null, result, server);
|
||||
}
|
||||
|
||||
// if host is an arbiter, disconnect if not configured for it
|
||||
if(doc.arbiterOnly && !replset.connectArbiter) {
|
||||
server.close();
|
||||
return cb(null, result, server);
|
||||
}
|
||||
|
||||
// create handler for successful connections
|
||||
var handleConnect = _connectHandler(replset, null, server);
|
||||
function complete () {
|
||||
handleConnect(err, result);
|
||||
cb();
|
||||
}
|
||||
|
||||
// authenticate if necessary
|
||||
if(!(Array.isArray(auths) && auths.length > 0)) {
|
||||
return complete();
|
||||
}
|
||||
|
||||
var pending = auths.length;
|
||||
|
||||
var connections = server.allRawConnections();
|
||||
var pendingAuthConn = connections.length;
|
||||
for(var x = 0; x <connections.length; x++) {
|
||||
var connection = connections[x];
|
||||
var authDone = false;
|
||||
for(var i = 0; i < auths.length; i++) {
|
||||
var auth = auths[i];
|
||||
var options = { authdb: auth.authdb, connection: connection };
|
||||
var username = auth.username;
|
||||
var password = auth.password;
|
||||
replset.db.authenticate(username, password, options, function() {
|
||||
--pending;
|
||||
if(0 === pending) {
|
||||
authDone = true;
|
||||
--pendingAuthConn;
|
||||
if(0 === pendingAuthConn) {
|
||||
return complete();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new server for the `replset` based on `host`.
|
||||
*
|
||||
* @param {String} host - host:port pair (localhost:27017)
|
||||
* @param {ReplSet} replset - the ReplSet instance
|
||||
* @return {Server}
|
||||
* @ignore
|
||||
*/
|
||||
function createServer (host, replset) {
|
||||
// copy existing socket options to new server
|
||||
var socketOptions = {}
|
||||
if(replset.socketOptions) {
|
||||
var keys = Object.keys(replset.socketOptions);
|
||||
for(var k = 0; k < keys.length; k++) {
|
||||
socketOptions[keys[k]] = replset.socketOptions[keys[k]];
|
||||
}
|
||||
}
|
||||
|
||||
var parts = host.split(/:/);
|
||||
if(1 === parts.length) {
|
||||
parts[1] = Connection.DEFAULT_PORT;
|
||||
}
|
||||
|
||||
socketOptions.host = parts[0];
|
||||
socketOptions.port = parseInt(parts[1], 10);
|
||||
|
||||
var serverOptions = {
|
||||
readPreference: replset._readPreference,
|
||||
socketOptions: socketOptions,
|
||||
poolSize: replset.poolSize,
|
||||
logger: replset.logger,
|
||||
auto_reconnect: false,
|
||||
ssl: replset.ssl
|
||||
}
|
||||
|
||||
var server = new Server(socketOptions.host, socketOptions.port, serverOptions);
|
||||
server.replicasetInstance = replset;
|
||||
server.on("close", _handler("close", replset));
|
||||
server.on("error", _handler("error", replset));
|
||||
server.on("timeout", _handler("timeout", replset));
|
||||
return server;
|
||||
}
|
||||
|
||||
var _handler = function(event, self) {
|
||||
return function(err, server) {
|
||||
// console.log("============================== HANDLE EVENT :: " + event)
|
||||
// console.log("" + server.host + ":" + server.port)
|
||||
|
||||
// Remove from all lists
|
||||
delete self._state.secondaries[server.name];
|
||||
delete self._state.arbiters[server.name];
|
||||
delete self._state.passives[server.name];
|
||||
delete self._state.addresses[server.name];
|
||||
|
||||
// Execute all the callbacks with errors
|
||||
self.__executeAllCallbacksWithError(err);
|
||||
|
||||
// If we have app listeners on close event
|
||||
if(self.db.listeners(event).length > 0) {
|
||||
self.db.emit(event, err);
|
||||
}
|
||||
|
||||
// If it's the primary close all connections
|
||||
if(self._state.master
|
||||
&& self._state.master.host == server.host
|
||||
&& self._state.master.port == server.port) {
|
||||
// return self.close();
|
||||
self._state.master = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,6 +577,7 @@ var _connectHandler = function(self, candidateServers, instanceServer) {
|
||||
return function(err, result) {
|
||||
// We are disconnected stop attempting reconnect or connect
|
||||
if(self._serverState == 'disconnected') return instanceServer.close();
|
||||
|
||||
// If no error handle isMaster
|
||||
if(err == null && result.documents[0].hosts != null) {
|
||||
// Fetch the isMaster command result
|
||||
@@ -479,7 +613,10 @@ var _connectHandler = function(self, candidateServers, instanceServer) {
|
||||
if (oldServer && oldServer !== instanceServer) oldServer.close();
|
||||
delete self._state.addresses[userProvidedServerString];
|
||||
|
||||
if (self._state.addresses[me] && self._state.addresses[me] !== instanceServer) self._state.addresses[me].close();
|
||||
if (self._state.addresses[me] && self._state.addresses[me] !== instanceServer) {
|
||||
self._state.addresses[me].close();
|
||||
}
|
||||
|
||||
self._state.addresses[me] = instanceServer;
|
||||
|
||||
// Let's add the server to our list of server types
|
||||
@@ -499,6 +636,7 @@ var _connectHandler = function(self, candidateServers, instanceServer) {
|
||||
instanceServer.name = me;
|
||||
// Add tag info
|
||||
instanceServer.tags = tags;
|
||||
|
||||
// Add the handlers to the instance
|
||||
instanceServer.on("close", _handler("close", self));
|
||||
instanceServer.on("error", _handler("error", self));
|
||||
@@ -539,19 +677,25 @@ var _connectHandler = function(self, candidateServers, instanceServer) {
|
||||
// Attempt to connect to the next server
|
||||
if(Array.isArray(candidateServers) && candidateServers.length > 0) {
|
||||
var server = candidateServers.pop();
|
||||
|
||||
// Get server addresses
|
||||
var addresses = self._state.addresses;
|
||||
|
||||
// Default empty socket options object
|
||||
var socketOptions = {};
|
||||
|
||||
// Set fast connect timeout
|
||||
socketOptions['connectTimeoutMS'] = self._connectTimeoutMS;
|
||||
|
||||
// If a socket option object exists clone it
|
||||
if(self.socketOptions != null && typeof self.socketOptions === 'object') {
|
||||
var keys = Object.keys(self.socketOptions);
|
||||
for(var j = 0; j < keys.length;j++) socketOptions[keys[j]] = self.socketOptions[keys[j]];
|
||||
}
|
||||
|
||||
// If ssl is specified
|
||||
if(self.ssl) serverConnections[i].ssl = true;
|
||||
// Set fast connect timeout
|
||||
socketOptions['connectTimeoutMS'] = self._connectTimeoutMS
|
||||
if(self.ssl) server.ssl = true;
|
||||
|
||||
// Add host information to socket options
|
||||
socketOptions['host'] = server.host;
|
||||
socketOptions['port'] = server.port;
|
||||
@@ -579,6 +723,10 @@ var _connectHandler = function(self, candidateServers, instanceServer) {
|
||||
return self.emit("connectionError",
|
||||
new Error("no primary server found in set"))
|
||||
} else{
|
||||
if (self.strategyInstance) {
|
||||
self.strategyInstance.start();
|
||||
}
|
||||
|
||||
self.emit("fullsetup", null, self.db, self);
|
||||
self.emit("open", null, self.db, self);
|
||||
}
|
||||
@@ -586,6 +734,23 @@ var _connectHandler = function(self, candidateServers, instanceServer) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interval state object constructor
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
ReplSet.State = function ReplSetState () {
|
||||
this.errorMessages = [];
|
||||
this.secondaries = {};
|
||||
this.addresses = {};
|
||||
this.arbiters = {};
|
||||
this.passives = {};
|
||||
this.members = [];
|
||||
this.errors = {};
|
||||
this.setName = null;
|
||||
this.master = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@@ -597,14 +762,18 @@ ReplSet.prototype.connect = function(parent, options, callback) {
|
||||
|
||||
// Ensure it's all closed
|
||||
self.close();
|
||||
|
||||
// Set connecting status
|
||||
this.db = parent;
|
||||
this._serverState = 'connecting';
|
||||
this._callbackList = [];
|
||||
this._state = {'master':null, 'secondaries':{}, 'arbiters':{}, 'passives':{}
|
||||
, 'errors':{}, 'addresses':{}, 'setName':null, 'errorMessages':[], 'members':[]};
|
||||
|
||||
this._state = new ReplSet.State();
|
||||
|
||||
// Ensure parent can do a slave query if it's set
|
||||
parent.slaveOk = this.slaveOk ? this.slaveOk : parent.slaveOk;
|
||||
parent.slaveOk = this.slaveOk
|
||||
? this.slaveOk
|
||||
: parent.slaveOk;
|
||||
|
||||
// Remove any listeners
|
||||
this.removeAllListeners("fullsetup");
|
||||
@@ -612,11 +781,8 @@ ReplSet.prototype.connect = function(parent, options, callback) {
|
||||
|
||||
// Add primary found event handler
|
||||
this.once("fullsetup", function() {
|
||||
// Set state connected
|
||||
self._serverState = 'connected';
|
||||
// Emit the fullsetup and open event
|
||||
parent.emit("open", null, self.db, self);
|
||||
parent.emit("fullsetup", null, self.db, self);
|
||||
self._handleOnFullSetup(parent);
|
||||
|
||||
// Callback
|
||||
if(typeof callback == 'function') {
|
||||
var internalCallback = callback;
|
||||
@@ -640,31 +806,13 @@ ReplSet.prototype.connect = function(parent, options, callback) {
|
||||
// Get server addresses
|
||||
var addresses = this._state.addresses;
|
||||
|
||||
// Default empty socket options object
|
||||
var socketOptions = {};
|
||||
// If a socket option object exists clone it
|
||||
if(this.socketOptions != null && typeof this.socketOptions === 'object') {
|
||||
var keys = Object.keys(this.socketOptions);
|
||||
for(var j = 0; j < keys.length;j++) socketOptions[keys[j]] = this.socketOptions[keys[j]];
|
||||
}
|
||||
// If ssl is specified
|
||||
if(this.ssl) serverConnections[i].ssl = true;
|
||||
// Set fast connect timeout
|
||||
socketOptions['connectTimeoutMS'] = this._connectTimeoutMS
|
||||
|
||||
// De-duplicate any servers
|
||||
var server;
|
||||
var server, key;
|
||||
for(var i = 0; i < this.servers.length; i++) {
|
||||
server = this.servers[i];
|
||||
// Add host information to socket options
|
||||
socketOptions['host'] = server.host;
|
||||
socketOptions['port'] = server.port;
|
||||
server.socketOptions = socketOptions;
|
||||
server.replicasetInstance = this;
|
||||
server.enableRecordQueryStats(this.recordQueryStats);
|
||||
// If server does not exist set it
|
||||
if(addresses[server.host + ":" + server.port] == null) {
|
||||
addresses[server.host + ":" + server.port] = server;
|
||||
key = server.host + ":" + server.port;
|
||||
if(null == addresses[key]) {
|
||||
addresses[key] = server;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -672,11 +820,45 @@ ReplSet.prototype.connect = function(parent, options, callback) {
|
||||
var candidateServers = [];
|
||||
var keys = Object.keys(addresses);
|
||||
for(var i = 0; i < keys.length; i++) {
|
||||
candidateServers.push(addresses[keys[i]]);
|
||||
server = addresses[keys[i]];
|
||||
server.assignReplicaSet(this);
|
||||
candidateServers.push(server);
|
||||
}
|
||||
|
||||
// Let's connect to the first one on the list
|
||||
server = candidateServers.pop();
|
||||
server.connect(parent, {returnIsMasterResults: true, eventReceiver:server}, _connectHandler(this, candidateServers, server));
|
||||
var opts = {
|
||||
returnIsMasterResults: true,
|
||||
eventReceiver: server
|
||||
}
|
||||
server.connect(parent, opts, _connectHandler(this, candidateServers, server));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the first `fullsetup` event of this ReplSet.
|
||||
*
|
||||
* @param {Db} parent
|
||||
* @ignore
|
||||
*/
|
||||
ReplSet.prototype._handleOnFullSetup = function (parent) {
|
||||
this._serverState = 'connected';
|
||||
|
||||
// Emit the fullsetup and open event
|
||||
parent.emit("open", null, this.db, this);
|
||||
parent.emit("fullsetup", null, this.db, this);
|
||||
|
||||
if(!this.haEnabled) return;
|
||||
this._enableHA();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables high availability pings.
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
ReplSet.prototype._disableHA = function () {
|
||||
clearTimeout(this._haTimer);
|
||||
this._haTimer = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -694,26 +876,28 @@ ReplSet.prototype.checkoutWriter = function() {
|
||||
*/
|
||||
var pickFirstConnectedSecondary = function pickFirstConnectedSecondary(self, tags) {
|
||||
var keys = Object.keys(self._state.secondaries);
|
||||
var connection = null;
|
||||
var connection;
|
||||
|
||||
// Find first available reader if any
|
||||
for(var i = 0; i < keys.length; i++) {
|
||||
connection = self._state.secondaries[keys[i]].checkoutReader();
|
||||
if(connection != null) break;
|
||||
if(connection) return connection;
|
||||
}
|
||||
|
||||
// If we still have a null, read from primary if it's not secondary only
|
||||
if(self._readPreference == ReadPreference.SECONDARY_PREFERRED) {
|
||||
connection = self._state.master.checkoutReader();
|
||||
if(connection) return connection;
|
||||
}
|
||||
|
||||
if(connection == null) {
|
||||
var preferenceName = self._readPreference == ReadPreference.SECONDARY_PREFERRED ? 'secondary' : self._readPreference;
|
||||
return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags));
|
||||
}
|
||||
var preferenceName = self._readPreference == ReadPreference.SECONDARY_PREFERRED
|
||||
? 'secondary'
|
||||
: self._readPreference;
|
||||
|
||||
// Return the connection
|
||||
return connection;
|
||||
// console.log("================================================================ pickFirstConnectedSecondary :::: ")
|
||||
|
||||
return new Error("No replica set member available for query with ReadPreference "
|
||||
+ preferenceName + " and tags " + JSON.stringify(tags));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -769,6 +953,10 @@ var _pickFromTags = function(self, tags) {
|
||||
*/
|
||||
ReplSet.prototype.checkoutReader = function(readPreference, tags) {
|
||||
var connection = null;
|
||||
// console.log("============================ checkoutReader")
|
||||
// console.dir(readPreference)
|
||||
// console.log(arguments.callee.caller.toString())
|
||||
|
||||
// If we have a read preference object unpack it
|
||||
if(typeof readPreference == 'object' && readPreference['_type'] == 'ReadPreference') {
|
||||
// Validate if the object is using a valid mode
|
||||
@@ -783,6 +971,11 @@ ReplSet.prototype.checkoutReader = function(readPreference, tags) {
|
||||
// Set up our read Preference, allowing us to override the readPreference
|
||||
var finalReadPreference = readPreference != null ? readPreference : this._readPreference;
|
||||
finalReadPreference = finalReadPreference == true ? ReadPreference.SECONDARY_PREFERRED : finalReadPreference;
|
||||
finalReadPreference = finalReadPreference == null ? ReadPreference.PRIMARY : finalReadPreference;
|
||||
// finalReadPreference = 'primary';
|
||||
|
||||
// console.log("============================ finalReadPreference: " + finalReadPreference)
|
||||
// console.dir(finalReadPreference)
|
||||
|
||||
// If we are reading from a primary
|
||||
if(finalReadPreference == 'primary') {
|
||||
@@ -812,14 +1005,7 @@ ReplSet.prototype.checkoutReader = function(readPreference, tags) {
|
||||
return new Error("No replica set members available for query");
|
||||
}
|
||||
} else {
|
||||
// Pick a secondary using round robin
|
||||
var keys = Object.keys(this._state.secondaries);
|
||||
this._currentServerChoice = this._currentServerChoice % keys.length;
|
||||
var key = keys[this._currentServerChoice++];
|
||||
// Fetch a connectio
|
||||
connection = this._state.secondaries[key] != null ? this._state.secondaries[key].checkoutReader() : null;
|
||||
// If connection is null fallback to first available secondary
|
||||
connection = connection == null ? pickFirstConnectedSecondary(this, tags) : connection;
|
||||
connection = _roundRobin(this, tags);
|
||||
}
|
||||
} else if(finalReadPreference == ReadPreference.PRIMARY_PREFERRED) {
|
||||
// Check if there is a primary available and return that if possible
|
||||
@@ -835,17 +1021,11 @@ ReplSet.prototype.checkoutReader = function(readPreference, tags) {
|
||||
return new Error("No replica set members available for query");
|
||||
}
|
||||
} else {
|
||||
// Pick a secondary using round robin
|
||||
var keys = Object.keys(this._state.secondaries);
|
||||
this._currentServerChoice = this._currentServerChoice % keys.length;
|
||||
var key = keys[this._currentServerChoice++];
|
||||
// Fetch a connectio
|
||||
connection = this._state.secondaries[key] != null ? this._state.secondaries[key].checkoutReader() : null;
|
||||
// If connection is null fallback to first available secondary
|
||||
connection = connection == null ? pickFirstConnectedSecondary(this, tags) : connection;
|
||||
connection = _roundRobin(this, tags);
|
||||
}
|
||||
}
|
||||
} else if(finalReadPreference == ReadPreference.SECONDARY_PREFERRED && tags == null && Object.keys(this._state.secondaries).length == 0) {
|
||||
// console.log("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ SECONDARY_PREFERRED")
|
||||
connection = this.checkoutWriter();
|
||||
// If no connection return an error
|
||||
if(connection == null) {
|
||||
@@ -874,6 +1054,7 @@ ReplSet.prototype.checkoutReader = function(readPreference, tags) {
|
||||
} else if(finalReadPreference == ReadPreference.NEAREST && this.strategyInstance == null) {
|
||||
return new Error("A strategy for calculating nearness must be enabled such as ping or statistical");
|
||||
} else if(finalReadPreference == ReadPreference.SECONDARY && Object.keys(this._state.secondaries).length == 0) {
|
||||
// console.log("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ SECONDARY")
|
||||
if(tags != null && typeof tags == 'object') {
|
||||
var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference;
|
||||
connection = new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags));
|
||||
@@ -888,6 +1069,27 @@ ReplSet.prototype.checkoutReader = function(readPreference, tags) {
|
||||
return connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick a secondary using round robin
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
function _roundRobin (replset, tags) {
|
||||
var keys = Object.keys(replset._state.secondaries);
|
||||
var key = keys[replset._currentServerChoice++ % keys.length];
|
||||
|
||||
var conn = null != replset._state.secondaries[key]
|
||||
? replset._state.secondaries[key].checkoutReader()
|
||||
: null;
|
||||
|
||||
// If connection is null fallback to first available secondary
|
||||
if (null == conn) {
|
||||
conn = pickFirstConnectedSecondary(replset, tags);
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@@ -899,9 +1101,8 @@ ReplSet.prototype.allRawConnections = function() {
|
||||
var allMasterConnections = this._state.master.connectionPool.getAllConnections();
|
||||
// Add all connections to list
|
||||
allConnections = allConnections.concat(allMasterConnections);
|
||||
|
||||
// If we have read secondary let's add all secondary servers
|
||||
if(this.readSecondary && Object.keys(this._state.secondaries).length > 0) {
|
||||
if(Object.keys(this._state.secondaries).length > 0) {
|
||||
// Get all the keys
|
||||
var keys = Object.keys(this._state.secondaries);
|
||||
// For each of the secondaries grab the connections
|
||||
|
||||
130
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/connection/server.js
generated
vendored
130
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/connection/server.js
generated
vendored
@@ -4,6 +4,8 @@ var Connection = require('./connection').Connection,
|
||||
MongoReply = require('../responses/mongo_reply').MongoReply,
|
||||
ConnectionPool = require('./connection_pool').ConnectionPool,
|
||||
EventEmitter = require('events').EventEmitter,
|
||||
Base = require('./base').Base,
|
||||
utils = require('../utils'),
|
||||
inherits = require('util').inherits;
|
||||
|
||||
/**
|
||||
@@ -13,7 +15,7 @@ var Connection = require('./connection').Connection,
|
||||
* - **readPreference** {String, default:null}, set's the read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST)
|
||||
* - **ssl** {Boolean, default:false}, use ssl connection (needs to have a mongod server with ssl support)
|
||||
* - **slaveOk** {Boolean, default:false}, legacy option allowing reads from secondary, use **readPrefrence** instead.
|
||||
* - **poolSize** {Number, default:1}, number of connections in the connection pool, set to 1 as default for legacy reasons.
|
||||
* - **poolSize** {Number, default:5}, number of connections in the connection pool, set to 5 as default for legacy reasons.
|
||||
* - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number))
|
||||
* - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**.
|
||||
* - **auto_reconnect** {Boolean, default:false}, reconnect on error.
|
||||
@@ -25,10 +27,12 @@ var Connection = require('./connection').Connection,
|
||||
* @param {Object} [options] optional options for insert command
|
||||
*/
|
||||
function Server(host, port, options) {
|
||||
// Set up event emitter
|
||||
EventEmitter.call(this);
|
||||
// Set up Server instance
|
||||
if(!(this instanceof Server)) return new Server(host, port, options);
|
||||
|
||||
// Set up event emitter
|
||||
Base.call(this);
|
||||
|
||||
// Ensure correct values
|
||||
if(port != null && typeof port == 'object') {
|
||||
options = port;
|
||||
@@ -45,16 +49,19 @@ function Server(host, port, options) {
|
||||
this.poolSize = this.options.poolSize == null ? 5 : this.options.poolSize;
|
||||
this.disableDriverBSONSizeCheck = this.options.disableDriverBSONSizeCheck != null ? this.options.disableDriverBSONSizeCheck : false;
|
||||
this.ssl = this.options.ssl == null ? false : this.options.ssl;
|
||||
this.slaveOk = this.options["slave_ok"];
|
||||
this.slaveOk = this.options["slave_ok"] ? this.options["slave_ok"] : this.options["slaveOk"];
|
||||
this._used = false;
|
||||
this.replicasetInstance = null;
|
||||
|
||||
// Get the readPreference
|
||||
var readPreference = this.options['readPreference'];
|
||||
// If readPreference is an object get the mode string
|
||||
var validateReadPreference = readPreference != null && typeof readPreference == 'object' ? readPreference.mode : readPreference;
|
||||
// Read preference setting
|
||||
if(readPreference != null) {
|
||||
if(readPreference != ReadPreference.PRIMARY && readPreference != ReadPreference.SECONDARY && readPreference != ReadPreference.NEAREST
|
||||
&& readPreference != ReadPreference.SECONDARY_PREFERRED && readPreference != ReadPreference.PRIMARY_PREFERRED) {
|
||||
throw new Error("Illegal readPreference mode specified, " + readPreference);
|
||||
if(validateReadPreference != null) {
|
||||
if(validateReadPreference != ReadPreference.PRIMARY && validateReadPreference != ReadPreference.SECONDARY && validateReadPreference != ReadPreference.NEAREST
|
||||
&& validateReadPreference != ReadPreference.SECONDARY_PREFERRED && validateReadPreference != ReadPreference.PRIMARY_PREFERRED) {
|
||||
throw new Error("Illegal readPreference mode specified, " + validateReadPreference);
|
||||
}
|
||||
|
||||
// Set read Preference
|
||||
@@ -95,8 +102,7 @@ function Server(host, port, options) {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
// Inherit simple event emitter
|
||||
inherits(Server, EventEmitter);
|
||||
inherits(Server, Base);
|
||||
|
||||
//
|
||||
// Deprecated, USE ReadPreferences class
|
||||
@@ -142,7 +148,7 @@ Server.prototype.close = function(callback) {
|
||||
// Set server status as disconnected
|
||||
this._serverState = 'disconnected';
|
||||
// Peform callback if present
|
||||
if(typeof callback === 'function') callback();
|
||||
if(typeof callback === 'function') callback(null);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -163,10 +169,46 @@ Server.prototype.allServerInstances = function() {
|
||||
* @ignore
|
||||
*/
|
||||
Server.prototype.isSetMember = function() {
|
||||
return this['replicasetInstance'] != null || this['mongosInstance'] != null;
|
||||
return this.replicasetInstance != null || this.mongosInstance != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a replica set to this `server`.
|
||||
*
|
||||
* @param {ReplSet} replset
|
||||
* @ignore
|
||||
*/
|
||||
Server.prototype.assignReplicaSet = function (replset) {
|
||||
this.replicasetInstance = replset;
|
||||
this.inheritReplSetOptionsFrom(replset);
|
||||
this.enableRecordQueryStats(replset.recordQueryStats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes needed options from `replset` and overwrites
|
||||
* our own options.
|
||||
*
|
||||
* @param {ReplSet} replset
|
||||
* @ignore
|
||||
*/
|
||||
Server.prototype.inheritReplSetOptionsFrom = function (replset) {
|
||||
this.socketOptions = {};
|
||||
this.socketOptions.connectTimeoutMS = replset._connectTimeoutMS;
|
||||
|
||||
if(replset.ssl)
|
||||
this.socketOptions.ssl = true;
|
||||
|
||||
// If a socket option object exists clone it
|
||||
if(utils.isObject(replset.socketOptions)) {
|
||||
var keys = Object.keys(replset.socketOptions);
|
||||
for(var i = 0; i < keys.length; i++)
|
||||
this.socketOptions[keys[i]] = replset.socketOptions[keys[i]];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens this server connection.
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
Server.prototype.connect = function(dbInstance, options, callback) {
|
||||
@@ -291,8 +333,9 @@ Server.prototype.connect = function(dbInstance, options, callback) {
|
||||
}
|
||||
|
||||
// The command executed another request, log the handler again under that request id
|
||||
if(mongoReply.requestId > 0 && mongoReply.cursorId.toString() != "0" && callbackInfo.info && callbackInfo.info.exhaust) {
|
||||
dbInstance._reRegisterHandler(mongoReply.requestId, callbackInfo);
|
||||
if(mongoReply.requestId > 0 && mongoReply.cursorId.toString() != "0"
|
||||
&& callbackInfo && callbackInfo.info && callbackInfo.info.exhaust) {
|
||||
dbInstance._reRegisterHandler(mongoReply.requestId, callbackInfo);
|
||||
}
|
||||
|
||||
// Only execute callback if we have a caller
|
||||
@@ -317,6 +360,8 @@ Server.prototype.connect = function(dbInstance, options, callback) {
|
||||
|
||||
// Parse the body
|
||||
mongoReply.parseBody(message, connectionPool.bson, callbackInfo.info.raw, function(err) {
|
||||
// console.log("+++++++++++++++++++++++++++++++++++++++ recieved message")
|
||||
// console.dir(message)
|
||||
if(err != null) {
|
||||
// If pool connection is already closed
|
||||
if(server._serverState === 'disconnected') return;
|
||||
@@ -342,7 +387,7 @@ Server.prototype.connect = function(dbInstance, options, callback) {
|
||||
// If we are a single server connection fire errors correctly
|
||||
if(!server.isSetMember()) {
|
||||
// Fire all callback errors
|
||||
_fireCallbackErrors(server, new Error("connection closed due to parseError"));
|
||||
server.__executeAllCallbacksWithError(new Error("connection closed due to parseError"));
|
||||
// Emit error
|
||||
_emitAcrossAllDbInstances(server, eventReceiver, "parseError", server, null, true);
|
||||
}
|
||||
@@ -355,6 +400,7 @@ Server.prototype.connect = function(dbInstance, options, callback) {
|
||||
// If we have an error let's execute the callback and clean up all other
|
||||
// chained commands
|
||||
var firstResult = mongoReply && mongoReply.documents;
|
||||
|
||||
// Check for an error, if we have one let's trigger the callback and clean up
|
||||
// The chained callbacks
|
||||
if(firstResult[0].err != null || firstResult[0].errmsg != null) {
|
||||
@@ -387,6 +433,8 @@ Server.prototype.connect = function(dbInstance, options, callback) {
|
||||
} else if(callbackInfo && callbackInfo.callback && callbackInfo.info) {
|
||||
// Parse the body
|
||||
mongoReply.parseBody(message, connectionPool.bson, callbackInfo.info.raw, function(err) {
|
||||
// console.log("+++++++++++++++++++++++++++++++++++++++ recieved message")
|
||||
// console.dir(message)
|
||||
if(err != null) {
|
||||
// If pool connection is already closed
|
||||
if(server._serverState === 'disconnected') return;
|
||||
@@ -412,7 +460,7 @@ Server.prototype.connect = function(dbInstance, options, callback) {
|
||||
// If we are a single server connection fire errors correctly
|
||||
if(!server.isSetMember()) {
|
||||
// Fire all callback errors
|
||||
_fireCallbackErrors(server, new Error("connection closed due to parseError"));
|
||||
server.__executeAllCallbacksWithError(new Error("connection closed due to parseError"));
|
||||
// Emit error
|
||||
_emitAcrossAllDbInstances(server, eventReceiver, "parseError", server, null, true);
|
||||
}
|
||||
@@ -461,7 +509,7 @@ Server.prototype.connect = function(dbInstance, options, callback) {
|
||||
// If we are a single server connection fire errors correctly
|
||||
if(!server.isSetMember()) {
|
||||
// Fire all callback errors
|
||||
_fireCallbackErrors(server, err);
|
||||
server.__executeAllCallbacksWithError(err);
|
||||
// Emit error
|
||||
_emitAcrossAllDbInstances(server, eventReceiver, "timeout", err, server, true);
|
||||
}
|
||||
@@ -489,7 +537,7 @@ Server.prototype.connect = function(dbInstance, options, callback) {
|
||||
// If we are a single server connection fire errors correctly
|
||||
if(!server.isSetMember()) {
|
||||
// Fire all callback errors
|
||||
_fireCallbackErrors(server, new Error(message && message.err ? message.err : message));
|
||||
server.__executeAllCallbacksWithError(new Error(message && message.err ? message.err : message));
|
||||
// Emit error
|
||||
_emitAcrossAllDbInstances(server, eventReceiver, "error", new Error(message && message.err ? message.err : message), server, true);
|
||||
}
|
||||
@@ -517,7 +565,7 @@ Server.prototype.connect = function(dbInstance, options, callback) {
|
||||
// If we are a single server connection fire errors correctly
|
||||
if(!server.isSetMember()) {
|
||||
// Fire all callback errors
|
||||
_fireCallbackErrors(server, new Error("connection closed"));
|
||||
server.__executeAllCallbacksWithError(new Error("connection closed"));
|
||||
// Emit error
|
||||
_emitAcrossAllDbInstances(server, eventReceiver, "close", server, null, true);
|
||||
}
|
||||
@@ -546,7 +594,7 @@ Server.prototype.connect = function(dbInstance, options, callback) {
|
||||
// If we are a single server connection fire errors correctly
|
||||
if(!server.isSetMember()) {
|
||||
// Fire all callback errors
|
||||
_fireCallbackErrors(server, new Error("connection closed due to parseError"));
|
||||
server.__executeAllCallbacksWithError(new Error("connection closed due to parseError"));
|
||||
// Emit error
|
||||
_emitAcrossAllDbInstances(server, eventReceiver, "parseError", server, null, true);
|
||||
}
|
||||
@@ -556,45 +604,6 @@ Server.prototype.connect = function(dbInstance, options, callback) {
|
||||
connectionPool.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire all the errors
|
||||
* @ignore
|
||||
*/
|
||||
var _fireCallbackErrors = function(server, err) {
|
||||
// Locate all the possible callbacks that need to return
|
||||
for(var i = 0; i < server.dbInstances.length; i++) {
|
||||
// Fetch the db Instance
|
||||
var dbInstance = server.dbInstances[i];
|
||||
// Check all callbacks
|
||||
var keys = Object.keys(dbInstance._callBackStore._notReplied);
|
||||
// For each key check if it's a callback that needs to be returned
|
||||
for(var j = 0; j < keys.length; j++) {
|
||||
var info = dbInstance._callBackStore._notReplied[keys[j]];
|
||||
// Check if we have a chained command (findAndModify)
|
||||
if(info && info['chained'] && Array.isArray(info['chained']) && info['chained'].length > 0) {
|
||||
var chained = info['chained'];
|
||||
// Only callback once and the last one is the right one
|
||||
var finalCallback = chained.pop();
|
||||
if(info.connection.socketOptions.host === server.host && info.connection.socketOptions.port === server.port) {
|
||||
dbInstance._callBackStore.emit(finalCallback, err, null);
|
||||
}
|
||||
|
||||
// Put back the final callback to ensure we don't call all commands in the chain
|
||||
chained.push(finalCallback);
|
||||
|
||||
// Remove all chained callbacks
|
||||
for(var i = 0; i < chained.length; i++) {
|
||||
delete dbInstance._callBackStore._notReplied[chained[i]];
|
||||
}
|
||||
} else {
|
||||
if(info && info.connection.socketOptions.host === server.host && info.connection.socketOptions.port === server.port) {
|
||||
dbInstance._callBackStore.emit(keys[j], err, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@@ -649,6 +658,8 @@ var canCheckoutWriter = function(self, read) {
|
||||
* @ignore
|
||||
*/
|
||||
Server.prototype.checkoutWriter = function(read) {
|
||||
// console.log("===================== checkoutWriter :: " + read)
|
||||
// console.dir(this.isMasterDoc)
|
||||
if(read == true) return this.connectionPool.checkoutConnection();
|
||||
// Check if are allowed to do a checkout (if we try to use an arbiter f.ex)
|
||||
var result = canCheckoutWriter(this, read);
|
||||
@@ -687,6 +698,7 @@ var canCheckoutReader = function(self) {
|
||||
* @ignore
|
||||
*/
|
||||
Server.prototype.checkoutReader = function() {
|
||||
// console.log("===================== checkoutReader")
|
||||
// Check if are allowed to do a checkout (if we try to use an arbiter f.ex)
|
||||
var result = canCheckoutReader(this);
|
||||
// If the result is null check out a writer
|
||||
|
||||
@@ -144,13 +144,13 @@ PingStrategy.prototype._pingServer = function(callback) {
|
||||
new function(serverInstance) {
|
||||
var options = { poolSize: 1, timeout: 500, auto_reconnect: false };
|
||||
var server = new Server(serverInstance.host, serverInstance.port, options);
|
||||
var db = new self.Db(self.replicaset.db.databaseName, server);
|
||||
var db = new self.Db(self.replicaset.db.databaseName, server, { safe: true });
|
||||
|
||||
db.on("error", done);
|
||||
|
||||
// Open the db instance
|
||||
db.open(function(err, _db) {
|
||||
if(err) return done(_db);
|
||||
if(err) return done(err, _db);
|
||||
|
||||
// Startup time of the command
|
||||
var startTime = Date.now();
|
||||
@@ -161,13 +161,13 @@ PingStrategy.prototype._pingServer = function(callback) {
|
||||
serverInstance.runtimeStats['pingMs'] = Date.now() - startTime;
|
||||
}
|
||||
|
||||
done(_db);
|
||||
done(null, _db);
|
||||
})
|
||||
})
|
||||
|
||||
function done (_db) {
|
||||
function done (err, _db) {
|
||||
// Close connection
|
||||
_db.close(true);
|
||||
if (_db) _db.close(true);
|
||||
|
||||
// Adjust the number of checks
|
||||
numberOfEntries--;
|
||||
|
||||
@@ -7,7 +7,7 @@ var StatisticsStrategy = exports.StatisticsStrategy = function(replicaset) {
|
||||
|
||||
// Starts any needed code
|
||||
StatisticsStrategy.prototype.start = function(callback) {
|
||||
callback(null, null);
|
||||
callback && callback(null, null);
|
||||
}
|
||||
|
||||
StatisticsStrategy.prototype.stop = function(callback) {
|
||||
|
||||
212
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/cursor.js
generated
vendored
212
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/cursor.js
generated
vendored
@@ -11,73 +11,77 @@ var QueryCommand = require('./commands/query_command').QueryCommand,
|
||||
* using find. This cursor object is unidirectional and cannot traverse backwards. Clients should not be creating a cursor directly,
|
||||
* but use find to acquire a cursor.
|
||||
*
|
||||
* Options
|
||||
* - **skip** {Number} skip number of documents to skip.
|
||||
* - **limit** {Number}, limit the number of results to return. -1 has a special meaning and is used by Db.eval. A value of 1 will also be treated as if it were -1.
|
||||
* - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc.
|
||||
* - **hint** {Object}, hint force the query to use a specific index.
|
||||
* - **explain** {Boolean}, explain return the explaination of the query.
|
||||
* - **snapshot** {Boolean}, snapshot Snapshot mode assures no duplicates are returned.
|
||||
* - **timeout** {Boolean}, timeout allow the query to timeout.
|
||||
* - **tailable** {Boolean}, tailable allow the cursor to be tailable.
|
||||
* - **awaitdata** {Boolean}, awaitdata allow the cursor to wait for data, only applicable for tailable cursor.
|
||||
* - **batchSize** {Number}, batchSize the number of the subset of results to request the database to return for every request. This should initially be greater than 1 otherwise the database will automatically close the cursor. The batch size can be set to 1 with cursorInstance.batchSize after performing the initial query to the database.
|
||||
* - **raw** {Boolean}, raw return all query documents as raw buffers (default false).
|
||||
* - **read** {Boolean}, read specify override of read from source (primary/secondary).
|
||||
* - **slaveOk** {Boolean}, slaveOk, sets the slaveOk flag on the query wire protocol for secondaries.
|
||||
* - **returnKey** {Boolean}, returnKey only return the index key.
|
||||
* - **maxScan** {Number}, maxScan limit the number of items to scan.
|
||||
* - **min** {Number}, min set index bounds.
|
||||
* - **max** {Number}, max set index bounds.
|
||||
* - **showDiskLoc** {Boolean}, showDiskLoc show disk location of results.
|
||||
* - **comment** {String}, comment you can put a $comment field on a query to make looking in the profiler logs simpler.
|
||||
* - **numberOfRetries** {Number}, numberOfRetries if using awaidata specifies the number of times to retry on timeout.
|
||||
* - **dbName** {String}, dbName override the default dbName.
|
||||
* - **tailableRetryInterval** {Number}, tailableRetryInterval specify the miliseconds between getMores on tailable cursor.
|
||||
* - **exhaust** {Boolean}, exhaust have the server send all the documents at once as getMore packets.
|
||||
* - **partial** {Boolean}, partial have the sharded system return a partial result from mongos.
|
||||
*
|
||||
* @class Represents a Cursor.
|
||||
* @param {Db} db the database object to work with.
|
||||
* @param {Collection} collection the collection to query.
|
||||
* @param {Object} selector the query selector.
|
||||
* @param {Object} fields an object containing what fields to include or exclude from objects returned.
|
||||
* @param {Number} skip number of documents to skip.
|
||||
* @param {Number} limit the number of results to return. -1 has a special meaning and is used by Db.eval. A value of 1 will also be treated as if it were -1.
|
||||
* @param {String|Array|Object} sort the required sorting for the query.
|
||||
* @param {Object} hint force the query to use a specific index.
|
||||
* @param {Boolean} explain return the explaination of the query.
|
||||
* @param {Boolean} snapshot Snapshot mode assures no duplicates are returned.
|
||||
* @param {Boolean} timeout allow the query to timeout.
|
||||
* @param {Boolean} tailable allow the cursor to be tailable.
|
||||
* @param {Boolean} awaitdata allow the cursor to wait for data, only applicable for tailable cursor.
|
||||
* @param {Number} batchSize the number of the subset of results to request the database to return for every request. This should initially be greater than 1 otherwise the database will automatically close the cursor. The batch size can be set to 1 with cursorInstance.batchSize after performing the initial query to the database.
|
||||
* @param {Boolean} raw return all query documents as raw buffers (default false).
|
||||
* @param {Boolean} read specify override of read from source (primary/secondary).
|
||||
* @param {Boolean} returnKey only return the index key.
|
||||
* @param {Number} maxScan limit the number of items to scan.
|
||||
* @param {Number} min set index bounds.
|
||||
* @param {Number} max set index bounds.
|
||||
* @param {Boolean} showDiskLoc show disk location of results.
|
||||
* @param {String} comment you can put a $comment field on a query to make looking in the profiler logs simpler.
|
||||
* @param {Number} numberOfRetries if using awaidata specifies the number of times to retry on timeout.
|
||||
* @param {String} dbName override the default dbName.
|
||||
* @param {Number} tailableRetryInterval specify the miliseconds between getMores on tailable cursor.
|
||||
* @param {Boolean} exhaust have the server send all the documents at once as getMore packets.
|
||||
* @param {Boolean} partial have the sharded system return a partial result from mongos.
|
||||
*/
|
||||
function Cursor(db, collection, selector, fields, skip, limit
|
||||
, sort, hint, explain, snapshot, timeout, tailable, batchSize, slaveOk, raw, read
|
||||
, returnKey, maxScan, min, max, showDiskLoc, comment, awaitdata, numberOfRetries, dbName, tailableRetryInterval, exhaust, partial) {
|
||||
* @param {Object} [options] additional options for the collection.
|
||||
*/
|
||||
function Cursor(db, collection, selector, fields, options) {
|
||||
this.db = db;
|
||||
this.collection = collection;
|
||||
this.selector = selector;
|
||||
this.fields = fields;
|
||||
this.skipValue = skip == null ? 0 : skip;
|
||||
this.limitValue = limit == null ? 0 : limit;
|
||||
this.sortValue = sort;
|
||||
this.hint = hint;
|
||||
this.explainValue = explain;
|
||||
this.snapshot = snapshot;
|
||||
this.timeout = timeout == null ? true : timeout;
|
||||
this.tailable = tailable;
|
||||
this.awaitdata = awaitdata;
|
||||
this.numberOfRetries = numberOfRetries == null ? 5 : numberOfRetries;
|
||||
options = !options ? {} : options;
|
||||
|
||||
this.skipValue = options.skip == null ? 0 : options.skip;
|
||||
this.limitValue = options.limit == null ? 0 : options.limit;
|
||||
this.sortValue = options.sort;
|
||||
this.hint = options.hint;
|
||||
this.explainValue = options.explain;
|
||||
this.snapshot = options.snapshot;
|
||||
this.timeout = options.timeout == null ? true : options.timeout;
|
||||
this.tailable = options.tailable;
|
||||
this.awaitdata = options.awaitdata;
|
||||
this.numberOfRetries = options.numberOfRetries == null ? 5 : options.numberOfRetries;
|
||||
this.currentNumberOfRetries = this.numberOfRetries;
|
||||
this.batchSizeValue = batchSize == null ? 0 : batchSize;
|
||||
this.slaveOk = slaveOk == null ? collection.slaveOk : slaveOk;
|
||||
this.raw = raw == null ? false : raw;
|
||||
this.read = read == null ? ReadPreference.PRIMARY : read;
|
||||
this.returnKey = returnKey;
|
||||
this.maxScan = maxScan;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.showDiskLoc = showDiskLoc;
|
||||
this.comment = comment;
|
||||
this.tailableRetryInterval = tailableRetryInterval || 100;
|
||||
this.exhaust = exhaust || false;
|
||||
this.partial = partial || false;
|
||||
this.batchSizeValue = options.batchSize == null ? 0 : options.batchSize;
|
||||
this.slaveOk = options.slaveOk == null ? collection.slaveOk : options.slaveOk;
|
||||
this.raw = options.raw == null ? false : options.raw;
|
||||
this.read = options.read == null ? ReadPreference.PRIMARY : options.read;
|
||||
this.returnKey = options.returnKey;
|
||||
this.maxScan = options.maxScan;
|
||||
this.min = options.min;
|
||||
this.max = options.max;
|
||||
this.showDiskLoc = options.showDiskLoc;
|
||||
this.comment = options.comment;
|
||||
this.tailableRetryInterval = options.tailableRetryInterval || 100;
|
||||
this.exhaust = options.exhaust || false;
|
||||
this.partial = options.partial || false;
|
||||
|
||||
this.totalNumberOfRecords = 0;
|
||||
this.items = [];
|
||||
this.cursorId = Long.fromInt(0);
|
||||
|
||||
// This name
|
||||
this.dbName = dbName;
|
||||
this.dbName = options.dbName;
|
||||
|
||||
// State variables for the cursor
|
||||
this.state = Cursor.INIT;
|
||||
@@ -126,7 +130,7 @@ Cursor.prototype.rewind = function() {
|
||||
* results when this cursor had been previouly accessed. In that case,
|
||||
* cursor.rewind() can be used to reset the cursor.
|
||||
*
|
||||
* @param {Function} callback This will be called after executing this method successfully. The first paramter will contain the Error object if an error occured, or null otherwise. The second paramter will contain an array of BSON deserialized objects as a result of the query.
|
||||
* @param {Function} callback This will be called after executing this method successfully. The first parameter will contain the Error object if an error occured, or null otherwise. The second parameter will contain an array of BSON deserialized objects as a result of the query.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -168,7 +172,7 @@ Cursor.prototype.toArray = function(callback) {
|
||||
* at any given time if batch size is specified. Otherwise, the caller is responsible
|
||||
* for making sure that the entire result can fit the memory.
|
||||
*
|
||||
* @param {Function} callback this will be called for while iterating every document of the query result. The first paramter will contain the Error object if an error occured, or null otherwise. While the second paramter will contain the document.
|
||||
* @param {Function} callback this will be called for while iterating every document of the query result. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the document.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -204,7 +208,7 @@ Cursor.prototype.each = function(callback) {
|
||||
/**
|
||||
* Determines how many result the query for this cursor will return
|
||||
*
|
||||
* @param {Function} callback this will be after executing this method. The first paramter will contain the Error object if an error occured, or null otherwise. While the second paramter will contain the number of results or null if an error occured.
|
||||
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the number of results or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -293,15 +297,20 @@ Cursor.prototype.limit = function(limit, callback) {
|
||||
*/
|
||||
Cursor.prototype.setReadPreference = function(readPreference, tags, callback) {
|
||||
if(typeof tags == 'function') callback = tags;
|
||||
callback = callback || function() {};
|
||||
|
||||
var _mode = readPreference != null && typeof readPreference == 'object' ? readPreference.mode : readPreference;
|
||||
|
||||
if(this.queryRun == true || this.state == Cursor.CLOSED) {
|
||||
if(callback == null) throw new Error("Cannot change read preference on executed query or closed cursor");
|
||||
callback(new Error("Cannot change read preference on executed query or closed cursor"));
|
||||
} else if(readPreference == null && readPreference != 'primary'
|
||||
&& readPreference != 'secondaryOnly' && readPreference != 'secondary') {
|
||||
callback(new Error("only readPreference of primary, secondary or secondaryOnly supported"));
|
||||
} else if(_mode != null && _mode != 'primary'
|
||||
&& _mode != 'secondaryOnly' && _mode != 'secondary'
|
||||
&& _mode != 'nearest' && _mode != 'primaryPreferred' && _mode != 'secondaryPreferred') {
|
||||
if(callback == null) throw new Error("only readPreference of primary, secondary, secondaryPreferred, primaryPreferred or nearest supported");
|
||||
callback(new Error("only readPreference of primary, secondary, secondaryPreferred, primaryPreferred or nearest supported"));
|
||||
} else {
|
||||
this.read = readPreference;
|
||||
if(callback != null) callback(null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -497,7 +506,10 @@ Cursor.prototype.nextObject = function(callback) {
|
||||
return callback(err, null);
|
||||
}
|
||||
|
||||
// Execute command
|
||||
var commandHandler = function(err, result) {
|
||||
self.state = Cursor.OPEN;
|
||||
// console.dir(err)
|
||||
if(err != null && result == null) return callback(err, null);
|
||||
|
||||
if(!err && result.documents[0] && result.documents[0]['$err']) {
|
||||
@@ -556,6 +568,12 @@ Cursor.prototype.nextObject = function(callback) {
|
||||
var getMore = function(self, callback) {
|
||||
var limit = 0;
|
||||
|
||||
if(self.state == Cursor.GET_MORE) return callback(null, null);
|
||||
|
||||
// Set get more in progress
|
||||
self.state = Cursor.GET_MORE;
|
||||
|
||||
// Set options
|
||||
if (!self.tailable && self.limitValue > 0) {
|
||||
limit = self.limitValue - self.totalNumberOfRecords;
|
||||
if (limit < 1) {
|
||||
@@ -563,6 +581,7 @@ var getMore = function(self, callback) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
var getMoreCommand = new GetMoreCommand(
|
||||
self.db
|
||||
@@ -576,6 +595,9 @@ var getMore = function(self, callback) {
|
||||
|
||||
// Execute the command
|
||||
self.db._executeQueryCommand(getMoreCommand, options, function(err, result) {
|
||||
// Get more done
|
||||
self.state = Cursor.OPEN;
|
||||
|
||||
try {
|
||||
if(err != null) {
|
||||
return callback(err, null);
|
||||
@@ -629,6 +651,9 @@ var getMore = function(self, callback) {
|
||||
|
||||
getMoreCommand = null;
|
||||
} catch(err) {
|
||||
// Get more done
|
||||
self.state = Cursor.OPEN;
|
||||
|
||||
var handleClose = function() {
|
||||
callback(err, null);
|
||||
};
|
||||
@@ -647,11 +672,62 @@ var getMore = function(self, callback) {
|
||||
*/
|
||||
Cursor.prototype.explain = function(callback) {
|
||||
var limit = (-1)*Math.abs(this.limitValue);
|
||||
|
||||
// * - **skip** {Number} skip number of documents to skip.
|
||||
// * - **limit** {Number}, limit the number of results to return. -1 has a special meaning and is used by Db.eval. A value of 1 will also be treated as if it were -1.
|
||||
// * - **hint** {Object}, hint force the query to use a specific index.
|
||||
// * - **explain** {Boolean}, explain return the explaination of the query.
|
||||
// * - **slaveOk** {Boolean}, slaveOk, sets the slaveOk flag on the query wire protocol for secondaries.
|
||||
// * - **snapshot** {Boolean}, snapshot Snapshot mode assures no duplicates are returned.
|
||||
// * - **timeout** {Boolean}, timeout allow the query to timeout.
|
||||
// * - **tailable** {Boolean}, tailable allow the cursor to be tailable.
|
||||
// * - **awaitdata** {Boolean}, awaitdata allow the cursor to wait for data, only applicable for tailable cursor.
|
||||
// * - **batchSize** {Number}, batchSize the number of the subset of results to request the database to return for every request. This should initially be greater than 1 otherwise the database will automatically close the cursor. The batch size can be set to 1 with cursorInstance.batchSize after performing the initial query to the database.
|
||||
// * - **raw** {Boolean}, raw return all query documents as raw buffers (default false).
|
||||
// * - **read** {Boolean}, read specify override of read from source (primary/secondary).
|
||||
// * - **returnKey** {Boolean}, returnKey only return the index key.
|
||||
// * - **maxScan** {Number}, maxScan limit the number of items to scan.
|
||||
// * - **min** {Number}, min set index bounds.
|
||||
// * - **max** {Number}, max set index bounds.
|
||||
// * - **showDiskLoc** {Boolean}, showDiskLoc show disk location of results.
|
||||
// * - **comment** {String}, comment you can put a $comment field on a query to make looking in the profiler logs simpler.
|
||||
// * - **numberOfRetries** {Number}, numberOfRetries if using awaidata specifies the number of times to retry on timeout.
|
||||
// * - **dbName** {String}, dbName override the default dbName.
|
||||
// * - **tailableRetryInterval** {Number}, tailableRetryInterval specify the miliseconds between getMores on tailable cursor.
|
||||
// * - **exhaust** {Boolean}, exhaust have the server send all the documents at once as getMore packets.
|
||||
// * - **partial** {Boolean}, partial have the sharded system return a partial result from mongos.
|
||||
|
||||
// * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc.
|
||||
|
||||
// function Cursor(db, collection, selector, fields, skip, limit
|
||||
// - , sort, hint, explain, snapshot, timeout, tailable, batchSize, slaveOk, raw, read
|
||||
// - , returnKey, maxScan, min, max, showDiskLoc, comment, awaitdata, numberOfRetries, dbName, tailableRetry
|
||||
|
||||
// Create a new cursor and fetch the plan
|
||||
var cursor = new Cursor(this.db, this.collection, this.selector, this.fields, this.skipValue, limit
|
||||
, this.sortValue, this.hint, true, this.snapshot, this.timeout, this.tailable, this.batchSizeValue
|
||||
, this.slaveOk, this.raw, this.read, this.returnKey, this.maxScan, this.min, this.max, this.showDiskLoc
|
||||
, this.comment, this.awaitdata, this.numberOfRetries, this.dbName);
|
||||
var cursor = new Cursor(this.db, this.collection, this.selector, this.fields, {
|
||||
skip: this.skipValue
|
||||
, limit:limit
|
||||
, sort: this.sortValue
|
||||
, hint: this.hint
|
||||
, explain: true
|
||||
, snapshot: this.snapshot
|
||||
, timeout: this.timeout
|
||||
, tailable: this.tailable
|
||||
, batchSize: this.batchSizeValue
|
||||
, slaveOk: this.slaveOk
|
||||
, raw: this.raw
|
||||
, read: this.read
|
||||
, returnKey: this.returnKey
|
||||
, maxScan: this.maxScan
|
||||
, min: this.min
|
||||
, max: this.max
|
||||
, showDiskLoc: this.showDiskLoc
|
||||
, comment: this.comment
|
||||
, awaitdata: this.awaitdata
|
||||
, numberOfRetries: this.numberOfRetries
|
||||
, dbName: this.dbName
|
||||
});
|
||||
|
||||
// Fetch the explaination document
|
||||
cursor.nextObject(function(err, item) {
|
||||
if(err != null) return callback(err, null);
|
||||
@@ -761,7 +837,8 @@ Cursor.prototype.close = function(callback) {
|
||||
if(this.cursorId instanceof Long && this.cursorId.greaterThan(Long.fromInt(0))) {
|
||||
try {
|
||||
var command = new KillCursorCommand(this.db, [this.cursorId]);
|
||||
this.db._executeQueryCommand(command, {read:self.read, raw:self.raw, connection:self.connection}, null);
|
||||
// Added an empty callback to ensure we don't throw any null exceptions
|
||||
this.db._executeQueryCommand(command, {read:self.read, raw:self.raw, connection:self.connection}, function() {});
|
||||
} catch(err) {}
|
||||
}
|
||||
|
||||
@@ -811,8 +888,15 @@ Cursor.OPEN = 1;
|
||||
**/
|
||||
Cursor.CLOSED = 2;
|
||||
|
||||
/**
|
||||
* Cursor performing a get more
|
||||
*
|
||||
* @classconstant OPEN
|
||||
**/
|
||||
Cursor.GET_MORE = 3;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* @api private
|
||||
*/
|
||||
exports.Cursor = Cursor;
|
||||
exports.Cursor = Cursor;
|
||||
24
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/cursorstream.js
generated
vendored
24
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/cursorstream.js
generated
vendored
@@ -70,13 +70,11 @@ CursorStream.prototype._next = function () {
|
||||
if (this.paused || this._destroyed) return;
|
||||
|
||||
var self = this;
|
||||
|
||||
// nextTick is necessary to avoid stack overflows when
|
||||
// dealing with large result sets.
|
||||
process.nextTick(function () {
|
||||
// Get the next object
|
||||
process.nextTick(function() {
|
||||
self._cursor.nextObject(function (err, doc) {
|
||||
self._onNextObject(err, doc);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -86,16 +84,16 @@ CursorStream.prototype._next = function () {
|
||||
* @api private
|
||||
*/
|
||||
CursorStream.prototype._onNextObject = function (err, doc) {
|
||||
if (err) return this.destroy(err);
|
||||
if(err) return this.destroy(err);
|
||||
|
||||
// when doc is null we hit the end of the cursor
|
||||
if (!doc) {
|
||||
if(!doc && (this._cursor.state == 1 || this._cursor.state == 2)) {
|
||||
this.emit('end')
|
||||
return this.destroy();
|
||||
} else if(doc) {
|
||||
this.emit('data', doc);
|
||||
this._next();
|
||||
}
|
||||
|
||||
this.emit('data', doc);
|
||||
this._next();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,8 +112,14 @@ CursorStream.prototype.pause = function () {
|
||||
*/
|
||||
CursorStream.prototype.resume = function () {
|
||||
var self = this;
|
||||
|
||||
// Don't do anything if we are not paused
|
||||
if(!this.paused) return;
|
||||
if(!this._cursor.state == 3) return;
|
||||
|
||||
process.nextTick(function() {
|
||||
self.paused = false;
|
||||
// Only trigger more fetching if the cursor is open
|
||||
self._next();
|
||||
})
|
||||
}
|
||||
|
||||
760
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/db.js
generated
vendored
760
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/db.js
generated
vendored
File diff suppressed because it is too large
Load Diff
29
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/gridfs/grid.js
generated
vendored
29
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/gridfs/grid.js
generated
vendored
@@ -20,9 +20,16 @@ function Grid(db, fsName) {
|
||||
/**
|
||||
* Puts binary data to the grid
|
||||
*
|
||||
* Options
|
||||
* - **_id** {Any}, unique id for this file
|
||||
* - **root** {String}, root collection to use. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**.
|
||||
* - **content_type** {String}, mime type of the file. Defaults to **{GridStore.DEFAULT_CONTENT_TYPE}**.
|
||||
* - **chunk_size** {Number}, size for the chunk. Defaults to **{Chunk.DEFAULT_CHUNK_SIZE}**.
|
||||
* - **metadata** {Object}, arbitrary data the user wants to store.
|
||||
*
|
||||
* @param {Buffer} data buffer with Binary Data.
|
||||
* @param {Object} [options] the options for the files.
|
||||
* @callback {Function} this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
|
||||
* @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
@@ -37,9 +44,11 @@ Grid.prototype.put = function(data, options, callback) {
|
||||
// Return if we don't have a buffer object as data
|
||||
if(!(Buffer.isBuffer(data))) return callback(new Error("Data object must be a buffer object"), null);
|
||||
// Get filename if we are using it
|
||||
var filename = options['filename'];
|
||||
var filename = options['filename'] || null;
|
||||
// Get id if we are using it
|
||||
var id = options['_id'] || null;
|
||||
// Create gridstore
|
||||
var gridStore = new GridStore(this.db, filename, "w", options);
|
||||
var gridStore = new GridStore(this.db, id, filename, "w", options);
|
||||
gridStore.open(function(err, gridStore) {
|
||||
if(err) return callback(err, null);
|
||||
|
||||
@@ -57,16 +66,14 @@ Grid.prototype.put = function(data, options, callback) {
|
||||
/**
|
||||
* Get binary data to the grid
|
||||
*
|
||||
* @param {ObjectID} id ObjectID for file.
|
||||
* @callback {Function} this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
|
||||
* @param {Any} id for file.
|
||||
* @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
Grid.prototype.get = function(id, callback) {
|
||||
// Validate that we have a valid ObjectId
|
||||
if(!(id instanceof ObjectID)) return callback(new Error("Not a valid ObjectID", null));
|
||||
// Create gridstore
|
||||
var gridStore = new GridStore(this.db, id, "r", {root:this.fsName});
|
||||
var gridStore = new GridStore(this.db, id, null, "r", {root:this.fsName});
|
||||
gridStore.open(function(err, gridStore) {
|
||||
if(err) return callback(err, null);
|
||||
|
||||
@@ -80,14 +87,12 @@ Grid.prototype.get = function(id, callback) {
|
||||
/**
|
||||
* Delete file from grid
|
||||
*
|
||||
* @param {ObjectID} id ObjectID for file.
|
||||
* @callback {Function} this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
|
||||
* @param {Any} id for file.
|
||||
* @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
Grid.prototype.delete = function(id, callback) {
|
||||
// Validate that we have a valid ObjectId
|
||||
if(!(id instanceof ObjectID)) return callback(new Error("Not a valid ObjectID", null));
|
||||
// Create gridstore
|
||||
GridStore.unlink(this.db, id, {root:this.fsName}, function(err, result) {
|
||||
if(err) return callback(err, false);
|
||||
|
||||
73
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js
generated
vendored
73
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js
generated
vendored
@@ -35,10 +35,10 @@ var REFERENCE_BY_FILENAME = 0,
|
||||
*
|
||||
* @class Represents the GridStore.
|
||||
* @param {Db} db A database instance to interact with.
|
||||
* @param {ObjectID} id an unique ObjectID for this file
|
||||
* @param {String} [filename] optional a filename for this file, no unique constrain on the field
|
||||
* @param {Any} [id] optional unique id for this file
|
||||
* @param {String} [filename] optional filename for this file, no unique constrain on the field
|
||||
* @param {String} mode set the mode for this file.
|
||||
* @param {Object} options optional properties to specify. Recognized keys:
|
||||
* @param {Object} options optional properties to specify.
|
||||
* @return {GridStore}
|
||||
*/
|
||||
var GridStore = function GridStore(db, id, filename, mode, options) {
|
||||
@@ -56,34 +56,52 @@ var GridStore = function GridStore(db, id, filename, mode, options) {
|
||||
}
|
||||
|
||||
// Handle options
|
||||
if(options == null) options = {};
|
||||
if(typeof options === 'undefined') options = {};
|
||||
// Handle mode
|
||||
if(mode == null) {
|
||||
if(typeof mode === 'undefined') {
|
||||
mode = filename;
|
||||
filename = null;
|
||||
filename = undefined;
|
||||
} else if(typeof mode == 'object') {
|
||||
options = mode;
|
||||
mode = filename;
|
||||
filename = null;
|
||||
filename = undefined;
|
||||
}
|
||||
|
||||
if(id instanceof ObjectID) {
|
||||
this.referenceBy = REFERENCE_BY_ID;
|
||||
this.fileId = id;
|
||||
this.filename = filename;
|
||||
} else if(typeof filename == 'undefined') {
|
||||
this.referenceBy = REFERENCE_BY_FILENAME;
|
||||
this.filename = id;
|
||||
if (mode.indexOf('w') != null) {
|
||||
this.fileId = new ObjectID();
|
||||
}
|
||||
} else {
|
||||
this.referenceBy = REFERENCE_BY_ID;
|
||||
this.fileId = id;
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
/*
|
||||
// Handle id
|
||||
if(id instanceof ObjectID && (typeof filename == 'string' || filename == null)) {
|
||||
this.referenceBy = 1;
|
||||
this.referenceBy = REFERENCE_BY_ID;
|
||||
this.fileId = id;
|
||||
this.filename = filename;
|
||||
} else if(!(id instanceof ObjectID) && typeof id == 'string' && mode.indexOf("w") != null) {
|
||||
this.referenceBy = 0;
|
||||
this.referenceBy = REFERENCE_BY_FILENAME;
|
||||
this.fileId = new ObjectID();
|
||||
this.filename = id;
|
||||
} else if(!(id instanceof ObjectID) && typeof id == 'string' && mode.indexOf("r") != null) {
|
||||
this.referenceBy = 0;
|
||||
this.filename = filename;
|
||||
this.referenceBy = REFERENCE_BY_FILENAME;
|
||||
this.filename = id;
|
||||
} else {
|
||||
this.referenceBy = 1;
|
||||
this.referenceBy = REFERENCE_BY_ID;
|
||||
this.fileId = id;
|
||||
this.filename = filename;
|
||||
}
|
||||
*/
|
||||
|
||||
// Set up the rest
|
||||
this.mode = mode == null ? "r" : mode;
|
||||
@@ -92,8 +110,6 @@ var GridStore = function GridStore(db, id, filename, mode, options) {
|
||||
this.position = 0;
|
||||
// Set default chunk size
|
||||
this.internalChunkSize = this.options['chunkSize'] == null ? Chunk.DEFAULT_CHUNK_SIZE : this.options['chunkSize'];
|
||||
// Previous chunk size
|
||||
this.previousChunkSize = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,7 +214,8 @@ var _open = function(self, callback) {
|
||||
self.length = 0;
|
||||
} else {
|
||||
self.length = 0;
|
||||
return error(new Error((self.referenceBy == REFERENCE_BY_ID ? self.fileId.toHexString() : self.filename) + " does not exist", self));
|
||||
var txtId = self.fileId instanceof ObjectID ? self.fileId.toHexString() : self.fileId;
|
||||
return error(new Error((self.referenceBy == REFERENCE_BY_ID ? txtId : self.filename) + " does not exist", self));
|
||||
}
|
||||
|
||||
// Process the mode of the object
|
||||
@@ -442,19 +459,19 @@ var writeBuffer = function(self, buffer, close, callback) {
|
||||
* @api private
|
||||
*/
|
||||
var buildMongoObject = function(self, callback) {
|
||||
// Keeps the final chunk number
|
||||
var chunkNumber = 0;
|
||||
var previousChunkSize = self.previousChunkSize;
|
||||
// Get the correct chunk Number, if we have an empty chunk return the previous chunk number
|
||||
if(null != self.currentChunk && self.currentChunk.chunkNumber > 0 && self.currentChunk.position == 0) {
|
||||
chunkNumber = self.currentChunk.chunkNumber - 1;
|
||||
} else {
|
||||
chunkNumber = self.currentChunk.chunkNumber;
|
||||
previousChunkSize = self.currentChunk.position;
|
||||
}
|
||||
// // Keeps the final chunk number
|
||||
// var chunkNumber = 0;
|
||||
// var previousChunkSize = 0;
|
||||
// // Get the correct chunk Number, if we have an empty chunk return the previous chunk number
|
||||
// if(null != self.currentChunk && self.currentChunk.chunkNumber > 0 && self.currentChunk.position == 0) {
|
||||
// chunkNumber = self.currentChunk.chunkNumber - 1;
|
||||
// } else {
|
||||
// chunkNumber = self.currentChunk.chunkNumber;
|
||||
// previousChunkSize = self.currentChunk.position;
|
||||
// }
|
||||
|
||||
// Calcuate the length
|
||||
var length = self.currentChunk != null ? (chunkNumber * self.chunkSize + previousChunkSize) : 0;
|
||||
// // Calcuate the length
|
||||
// var length = self.currentChunk != null ? (chunkNumber * self.chunkSize + previousChunkSize) : 0;
|
||||
var mongoObject = {
|
||||
'_id': self.fileId,
|
||||
'filename': self.filename,
|
||||
@@ -1381,6 +1398,8 @@ var _read = function _read(self) {
|
||||
}
|
||||
|
||||
self.resume = function () {
|
||||
if(!self.paused) return;
|
||||
|
||||
self.paused = false;
|
||||
stream.resume();
|
||||
self.readable = stream.readable;
|
||||
|
||||
18
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/gridfs/readstream.js
generated
vendored
18
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/gridfs/readstream.js
generated
vendored
@@ -26,7 +26,7 @@ function ReadStream(autoclose, gstore) {
|
||||
|
||||
this.finalLength = gstore.length - gstore.position;
|
||||
this.completedLength = 0;
|
||||
this.currentChunkNumber = 0;
|
||||
this.currentChunkNumber = gstore.currentChunk.chunkNumber;
|
||||
|
||||
this.paused = false;
|
||||
this.readable = true;
|
||||
@@ -35,6 +35,9 @@ function ReadStream(autoclose, gstore) {
|
||||
|
||||
// Calculate the number of chunks
|
||||
this.numberOfChunks = Math.ceil(gstore.length/gstore.chunkSize);
|
||||
|
||||
// This seek start position inside the current chunk
|
||||
this.seekStartPosition = gstore.position - (this.currentChunkNumber * gstore.chunkSize);
|
||||
|
||||
var self = this;
|
||||
process.nextTick(function() {
|
||||
@@ -81,7 +84,18 @@ ReadStream.prototype._execute = function() {
|
||||
last = true;
|
||||
}
|
||||
|
||||
var data = gstore.currentChunk.readSlice(gstore.currentChunk.length());
|
||||
// Data setup
|
||||
var data = null;
|
||||
|
||||
// Read a slice (with seek set if none)
|
||||
if(this.seekStartPosition > 0 && (gstore.currentChunk.length() - this.seekStartPosition) > 0) {
|
||||
data = gstore.currentChunk.readSlice(gstore.currentChunk.length() - this.seekStartPosition);
|
||||
this.seekStartPosition = 0;
|
||||
} else {
|
||||
data = gstore.currentChunk.readSlice(gstore.currentChunk.length());
|
||||
}
|
||||
|
||||
// Return the data
|
||||
if(data != null && gstore.currentChunk.chunkNumber == self.currentChunkNumber) {
|
||||
self.currentChunkNumber = self.currentChunkNumber + 1;
|
||||
self.completedLength += data.length;
|
||||
|
||||
132
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/index.js
generated
vendored
132
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/index.js
generated
vendored
@@ -6,14 +6,6 @@ try {
|
||||
}
|
||||
|
||||
[ 'commands/base_command'
|
||||
, 'commands/db_command'
|
||||
, 'commands/delete_command'
|
||||
, 'commands/get_more_command'
|
||||
, 'commands/insert_command'
|
||||
, 'commands/kill_cursor_command'
|
||||
, 'commands/query_command'
|
||||
, 'commands/update_command'
|
||||
, 'responses/mongo_reply'
|
||||
, 'admin'
|
||||
, 'collection'
|
||||
, 'connection/read_preference'
|
||||
@@ -21,8 +13,10 @@ try {
|
||||
, 'connection/server'
|
||||
, 'connection/mongos'
|
||||
, 'connection/repl_set'
|
||||
, 'mongo_client'
|
||||
, 'cursor'
|
||||
, 'db'
|
||||
, 'mongo_client'
|
||||
, 'gridfs/grid'
|
||||
, 'gridfs/chunk'
|
||||
, 'gridfs/gridstore'].forEach(function (path) {
|
||||
@@ -48,110 +42,28 @@ try {
|
||||
|
||||
// Add BSON Parser
|
||||
exports.BSON = require('bson').BSONPure.BSON;
|
||||
|
||||
});
|
||||
|
||||
// Exports all the classes for the PURE JS BSON Parser
|
||||
exports.pure = function() {
|
||||
var classes = {};
|
||||
// Map all the classes
|
||||
[ 'commands/base_command'
|
||||
, 'commands/db_command'
|
||||
, 'commands/delete_command'
|
||||
, 'commands/get_more_command'
|
||||
, 'commands/insert_command'
|
||||
, 'commands/kill_cursor_command'
|
||||
, 'commands/query_command'
|
||||
, 'commands/update_command'
|
||||
, 'responses/mongo_reply'
|
||||
, 'admin'
|
||||
, 'collection'
|
||||
, 'connection/read_preference'
|
||||
, 'connection/connection'
|
||||
, 'connection/server'
|
||||
, 'connection/mongos'
|
||||
, 'connection/repl_set'
|
||||
, 'cursor'
|
||||
, 'db'
|
||||
, 'gridfs/grid'
|
||||
, 'gridfs/chunk'
|
||||
, 'gridfs/gridstore'].forEach(function (path) {
|
||||
var module = require('./' + path);
|
||||
for (var i in module) {
|
||||
classes[i] = module[i];
|
||||
}
|
||||
});
|
||||
|
||||
// backwards compat
|
||||
classes.ReplSetServers = exports.ReplSet;
|
||||
|
||||
// Add BSON Classes
|
||||
classes.Binary = require('bson').Binary;
|
||||
classes.Code = require('bson').Code;
|
||||
classes.DBRef = require('bson').DBRef;
|
||||
classes.Double = require('bson').Double;
|
||||
classes.Long = require('bson').Long;
|
||||
classes.MinKey = require('bson').MinKey;
|
||||
classes.MaxKey = require('bson').MaxKey;
|
||||
classes.ObjectID = require('bson').ObjectID;
|
||||
classes.Symbol = require('bson').Symbol;
|
||||
classes.Timestamp = require('bson').Timestamp;
|
||||
|
||||
// Add BSON Parser
|
||||
classes.BSON = require('bson').BSONPure.BSON;
|
||||
|
||||
// Return classes list
|
||||
return classes;
|
||||
// Get the Db object
|
||||
var Db = require('./db').Db;
|
||||
// Set up the connect function
|
||||
var connect = Db.connect;
|
||||
var obj = connect;
|
||||
// Map all values to the exports value
|
||||
for(var name in exports) {
|
||||
obj[name] = exports[name];
|
||||
}
|
||||
|
||||
// Exports all the classes for the PURE JS BSON Parser
|
||||
exports.native = function() {
|
||||
var classes = {};
|
||||
// Map all the classes
|
||||
[ 'commands/base_command'
|
||||
, 'commands/db_command'
|
||||
, 'commands/delete_command'
|
||||
, 'commands/get_more_command'
|
||||
, 'commands/insert_command'
|
||||
, 'commands/kill_cursor_command'
|
||||
, 'commands/query_command'
|
||||
, 'commands/update_command'
|
||||
, 'responses/mongo_reply'
|
||||
, 'admin'
|
||||
, 'collection'
|
||||
, 'connection/read_preference'
|
||||
, 'connection/connection'
|
||||
, 'connection/server'
|
||||
, 'connection/mongos'
|
||||
, 'connection/repl_set'
|
||||
, 'cursor'
|
||||
, 'db'
|
||||
, 'gridfs/grid'
|
||||
, 'gridfs/chunk'
|
||||
, 'gridfs/gridstore'].forEach(function (path) {
|
||||
var module = require('./' + path);
|
||||
for (var i in module) {
|
||||
classes[i] = module[i];
|
||||
}
|
||||
});
|
||||
|
||||
// Add BSON Classes
|
||||
classes.Binary = require('bson').Binary;
|
||||
classes.Code = require('bson').Code;
|
||||
classes.DBRef = require('bson').DBRef;
|
||||
classes.Double = require('bson').Double;
|
||||
classes.Long = require('bson').Long;
|
||||
classes.MinKey = require('bson').MinKey;
|
||||
classes.MaxKey = require('bson').MaxKey;
|
||||
classes.ObjectID = require('bson').ObjectID;
|
||||
classes.Symbol = require('bson').Symbol;
|
||||
classes.Timestamp = require('bson').Timestamp;
|
||||
|
||||
// backwards compat
|
||||
classes.ReplSetServers = exports.ReplSet;
|
||||
|
||||
// Add BSON Parser
|
||||
classes.BSON = require('bson').BSONNative.BSON;
|
||||
|
||||
// Return classes list
|
||||
return classes;
|
||||
// Add the pure and native backward compatible functions
|
||||
exports.pure = exports.native = function() {
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Map all values to the exports value
|
||||
for(var name in exports) {
|
||||
connect[name] = exports[name];
|
||||
}
|
||||
|
||||
// Set our exports to be the connect function
|
||||
module.exports = connect;
|
||||
23
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/utils.js
generated
vendored
23
node_modules/mongoskin/node_modules/mongodb/lib/mongodb/utils.js
generated
vendored
@@ -72,3 +72,26 @@ exports.decodeUInt32 = function(array, index) {
|
||||
exports.decodeUInt8 = function(array, index) {
|
||||
return array[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Context insensitive type checks
|
||||
*/
|
||||
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
exports.isObject = function (arg) {
|
||||
return '[object Object]' == toString.call(arg)
|
||||
}
|
||||
|
||||
exports.isArray = function (arg) {
|
||||
return Array.isArray(arg) ||
|
||||
'object' == typeof arg && '[object Array]' == toString.call(arg)
|
||||
}
|
||||
|
||||
exports.isDate = function (arg) {
|
||||
return 'object' == typeof arg && '[object Date]' == toString.call(arg)
|
||||
}
|
||||
|
||||
exports.isRegExp = function (arg) {
|
||||
return 'object' == typeof arg && '[object RegExp]' == toString.call(arg)
|
||||
}
|
||||
|
||||
2036
node_modules/mongoskin/node_modules/mongodb/node_modules/bson/ext/bson.cc
generated
vendored
2036
node_modules/mongoskin/node_modules/mongodb/node_modules/bson/ext/bson.cc
generated
vendored
File diff suppressed because it is too large
Load Diff
546
node_modules/mongoskin/node_modules/mongodb/node_modules/bson/ext/bson.h
generated
vendored
546
node_modules/mongoskin/node_modules/mongodb/node_modules/bson/ext/bson.h
generated
vendored
@@ -1,273 +1,273 @@
|
||||
//===========================================================================
|
||||
|
||||
#ifndef BSON_H_
|
||||
#define BSON_H_
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#define USE_MISALIGNED_MEMORY_ACCESS 1
|
||||
|
||||
#include <node.h>
|
||||
#include <node_object_wrap.h>
|
||||
#include <v8.h>
|
||||
|
||||
using namespace v8;
|
||||
using namespace node;
|
||||
|
||||
//===========================================================================
|
||||
|
||||
enum BsonType
|
||||
{
|
||||
BSON_TYPE_NUMBER = 1,
|
||||
BSON_TYPE_STRING = 2,
|
||||
BSON_TYPE_OBJECT = 3,
|
||||
BSON_TYPE_ARRAY = 4,
|
||||
BSON_TYPE_BINARY = 5,
|
||||
BSON_TYPE_UNDEFINED = 6,
|
||||
BSON_TYPE_OID = 7,
|
||||
BSON_TYPE_BOOLEAN = 8,
|
||||
BSON_TYPE_DATE = 9,
|
||||
BSON_TYPE_NULL = 10,
|
||||
BSON_TYPE_REGEXP = 11,
|
||||
BSON_TYPE_CODE = 13,
|
||||
BSON_TYPE_SYMBOL = 14,
|
||||
BSON_TYPE_CODE_W_SCOPE = 15,
|
||||
BSON_TYPE_INT = 16,
|
||||
BSON_TYPE_TIMESTAMP = 17,
|
||||
BSON_TYPE_LONG = 18,
|
||||
BSON_TYPE_MAX_KEY = 0x7f,
|
||||
BSON_TYPE_MIN_KEY = 0xff
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
template<typename T> class BSONSerializer;
|
||||
|
||||
class BSON : public ObjectWrap {
|
||||
public:
|
||||
BSON();
|
||||
~BSON() {}
|
||||
|
||||
static void Initialize(Handle<Object> target);
|
||||
static Handle<Value> BSONDeserializeStream(const Arguments &args);
|
||||
|
||||
// JS based objects
|
||||
static Handle<Value> BSONSerialize(const Arguments &args);
|
||||
static Handle<Value> BSONDeserialize(const Arguments &args);
|
||||
|
||||
// Calculate size of function
|
||||
static Handle<Value> CalculateObjectSize(const Arguments &args);
|
||||
static Handle<Value> SerializeWithBufferAndIndex(const Arguments &args);
|
||||
|
||||
// Constructor used for creating new BSON objects from C++
|
||||
static Persistent<FunctionTemplate> constructor_template;
|
||||
|
||||
private:
|
||||
static Handle<Value> New(const Arguments &args);
|
||||
static Handle<Value> deserialize(BSON *bson, char *data, uint32_t dataLength, uint32_t startIndex, bool is_array_item);
|
||||
|
||||
// BSON type instantiate functions
|
||||
Persistent<Function> longConstructor;
|
||||
Persistent<Function> objectIDConstructor;
|
||||
Persistent<Function> binaryConstructor;
|
||||
Persistent<Function> codeConstructor;
|
||||
Persistent<Function> dbrefConstructor;
|
||||
Persistent<Function> symbolConstructor;
|
||||
Persistent<Function> doubleConstructor;
|
||||
Persistent<Function> timestampConstructor;
|
||||
Persistent<Function> minKeyConstructor;
|
||||
Persistent<Function> maxKeyConstructor;
|
||||
|
||||
// Equality Objects
|
||||
Persistent<String> longString;
|
||||
Persistent<String> objectIDString;
|
||||
Persistent<String> binaryString;
|
||||
Persistent<String> codeString;
|
||||
Persistent<String> dbrefString;
|
||||
Persistent<String> symbolString;
|
||||
Persistent<String> doubleString;
|
||||
Persistent<String> timestampString;
|
||||
Persistent<String> minKeyString;
|
||||
Persistent<String> maxKeyString;
|
||||
|
||||
// Equality speed up comparison objects
|
||||
Persistent<String> _bsontypeString;
|
||||
Persistent<String> _longLowString;
|
||||
Persistent<String> _longHighString;
|
||||
Persistent<String> _objectIDidString;
|
||||
Persistent<String> _binaryPositionString;
|
||||
Persistent<String> _binarySubTypeString;
|
||||
Persistent<String> _binaryBufferString;
|
||||
Persistent<String> _doubleValueString;
|
||||
Persistent<String> _symbolValueString;
|
||||
|
||||
Persistent<String> _dbRefRefString;
|
||||
Persistent<String> _dbRefIdRefString;
|
||||
Persistent<String> _dbRefDbRefString;
|
||||
Persistent<String> _dbRefNamespaceString;
|
||||
Persistent<String> _dbRefDbString;
|
||||
Persistent<String> _dbRefOidString;
|
||||
|
||||
Persistent<String> _codeCodeString;
|
||||
Persistent<String> _codeScopeString;
|
||||
Persistent<String> _toBSONString;
|
||||
|
||||
Local<Object> GetSerializeObject(const Handle<Value>& object);
|
||||
|
||||
template<typename T> friend class BSONSerializer;
|
||||
friend class BSONDeserializer;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
class CountStream
|
||||
{
|
||||
public:
|
||||
CountStream() : count(0) { }
|
||||
|
||||
void WriteByte(int value) { ++count; }
|
||||
void WriteByte(const Handle<Object>&, const Handle<String>&) { ++count; }
|
||||
void WriteBool(const Handle<Value>& value) { ++count; }
|
||||
void WriteInt32(int32_t value) { count += 4; }
|
||||
void WriteInt32(const Handle<Value>& value) { count += 4; }
|
||||
void WriteInt32(const Handle<Object>& object, const Handle<String>& key) { count += 4; }
|
||||
void WriteInt64(int64_t value) { count += 8; }
|
||||
void WriteInt64(const Handle<Value>& value) { count += 8; }
|
||||
void WriteDouble(double value) { count += 8; }
|
||||
void WriteDouble(const Handle<Value>& value) { count += 8; }
|
||||
void WriteDouble(const Handle<Object>&, const Handle<String>&) { count += 8; }
|
||||
void WriteUInt32String(uint32_t name) { char buffer[32]; count += sprintf(buffer, "%u", name) + 1; }
|
||||
void WriteLengthPrefixedString(const Local<String>& value) { count += value->Utf8Length()+5; }
|
||||
void WriteObjectId(const Handle<Object>& object, const Handle<String>& key) { count += 12; }
|
||||
void WriteString(const Local<String>& value) { count += value->Utf8Length() + 1; } // This returns the number of bytes exclusive of the NULL terminator
|
||||
void WriteData(const char* data, size_t length) { count += length; }
|
||||
|
||||
void* BeginWriteType() { ++count; return NULL; }
|
||||
void CommitType(void*, BsonType) { }
|
||||
void* BeginWriteSize() { count += 4; return NULL; }
|
||||
void CommitSize(void*) { }
|
||||
|
||||
size_t GetSerializeSize() const { return count; }
|
||||
|
||||
// Do nothing. CheckKey is implemented for DataStream
|
||||
void CheckKey(const Local<String>&) { }
|
||||
|
||||
private:
|
||||
size_t count;
|
||||
};
|
||||
|
||||
class DataStream
|
||||
{
|
||||
public:
|
||||
DataStream(char* aDestinationBuffer) : destinationBuffer(aDestinationBuffer), p(aDestinationBuffer) { }
|
||||
|
||||
void WriteByte(int value) { *p++ = value; }
|
||||
void WriteByte(const Handle<Object>& object, const Handle<String>& key) { *p++ = object->Get(key)->Int32Value(); }
|
||||
#if USE_MISALIGNED_MEMORY_ACCESS
|
||||
void WriteInt32(int32_t value) { *reinterpret_cast<int32_t*>(p) = value; p += 4; }
|
||||
void WriteInt64(int64_t value) { *reinterpret_cast<int64_t*>(p) = value; p += 8; }
|
||||
void WriteDouble(double value) { *reinterpret_cast<double*>(p) = value; p += 8; }
|
||||
#else
|
||||
void WriteInt32(int32_t value) { memcpy(p, &value, 4); p += 4; }
|
||||
void WriteInt64(int64_t value) { memcpy(p, &value, 8); p += 8; }
|
||||
void WriteDouble(double value) { memcpy(p, &value, 8); p += 8; }
|
||||
#endif
|
||||
void WriteBool(const Handle<Value>& value) { WriteByte(value->BooleanValue() ? 1 : 0); }
|
||||
void WriteInt32(const Handle<Value>& value) { WriteInt32(value->Int32Value()); }
|
||||
void WriteInt32(const Handle<Object>& object, const Handle<String>& key) { WriteInt32(object->Get(key)); }
|
||||
void WriteInt64(const Handle<Value>& value) { WriteInt64(value->IntegerValue()); }
|
||||
void WriteDouble(const Handle<Value>& value) { WriteDouble(value->NumberValue()); }
|
||||
void WriteDouble(const Handle<Object>& object, const Handle<String>& key) { WriteDouble(object->Get(key)); }
|
||||
void WriteUInt32String(uint32_t name) { p += sprintf(p, "%u", name) + 1; }
|
||||
void WriteLengthPrefixedString(const Local<String>& value) { WriteInt32(value->Utf8Length()+1); WriteString(value); }
|
||||
void WriteObjectId(const Handle<Object>& object, const Handle<String>& key);
|
||||
void WriteString(const Local<String>& value) { p += value->WriteUtf8(p); } // This returns the number of bytes inclusive of the NULL terminator.
|
||||
void WriteData(const char* data, size_t length) { memcpy(p, data, length); p += length; }
|
||||
|
||||
void* BeginWriteType() { void* returnValue = p; p++; return returnValue; }
|
||||
void CommitType(void* beginPoint, BsonType value) { *reinterpret_cast<unsigned char*>(beginPoint) = value; }
|
||||
void* BeginWriteSize() { void* returnValue = p; p += 4; return returnValue; }
|
||||
|
||||
#if USE_MISALIGNED_MEMORY_ACCESS
|
||||
void CommitSize(void* beginPoint) { *reinterpret_cast<int32_t*>(beginPoint) = (int32_t) (p - (char*) beginPoint); }
|
||||
#else
|
||||
void CommitSize(void* beginPoint) { int32_t value = (int32_t) (p - (char*) beginPoint); memcpy(beginPoint, &value, 4); }
|
||||
#endif
|
||||
|
||||
size_t GetSerializeSize() const { return p - destinationBuffer; }
|
||||
|
||||
void CheckKey(const Local<String>& keyName);
|
||||
|
||||
protected:
|
||||
char *const destinationBuffer; // base, never changes
|
||||
char* p; // cursor into buffer
|
||||
};
|
||||
|
||||
template<typename T> class BSONSerializer : public T
|
||||
{
|
||||
private:
|
||||
typedef T Inherited;
|
||||
|
||||
public:
|
||||
BSONSerializer(BSON* aBson, bool aCheckKeys, bool aSerializeFunctions) : Inherited(), checkKeys(aCheckKeys), serializeFunctions(aSerializeFunctions), bson(aBson) { }
|
||||
BSONSerializer(BSON* aBson, bool aCheckKeys, bool aSerializeFunctions, char* parentParam) : Inherited(parentParam), checkKeys(aCheckKeys), serializeFunctions(aSerializeFunctions), bson(aBson) { }
|
||||
|
||||
void SerializeDocument(const Handle<Value>& value);
|
||||
void SerializeArray(const Handle<Value>& value);
|
||||
void SerializeValue(void* typeLocation, const Handle<Value>& value);
|
||||
|
||||
private:
|
||||
bool checkKeys;
|
||||
bool serializeFunctions;
|
||||
BSON* bson;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
class BSONDeserializer
|
||||
{
|
||||
public:
|
||||
BSONDeserializer(BSON* aBson, char* data, size_t length);
|
||||
BSONDeserializer(BSONDeserializer& parentSerializer, size_t length);
|
||||
|
||||
Handle<Value> DeserializeDocument();
|
||||
|
||||
bool HasMoreData() const { return p < pEnd; }
|
||||
Local<String> ReadCString();
|
||||
uint32_t ReadIntegerString();
|
||||
int32_t ReadRegexOptions();
|
||||
Local<String> ReadString();
|
||||
Local<String> ReadObjectId();
|
||||
|
||||
unsigned char ReadByte() { return *reinterpret_cast<unsigned char*>(p++); }
|
||||
#if USE_MISALIGNED_MEMORY_ACCESS
|
||||
int32_t ReadInt32() { int32_t returnValue = *reinterpret_cast<int32_t*>(p); p += 4; return returnValue; }
|
||||
uint32_t ReadUInt32() { uint32_t returnValue = *reinterpret_cast<uint32_t*>(p); p += 4; return returnValue; }
|
||||
int64_t ReadInt64() { int64_t returnValue = *reinterpret_cast<int64_t*>(p); p += 8; return returnValue; }
|
||||
double ReadDouble() { double returnValue = *reinterpret_cast<double*>(p); p += 8; return returnValue; }
|
||||
#else
|
||||
int32_t ReadInt32() { int32_t returnValue; memcpy(&returnValue, p, 4); p += 4; return returnValue; }
|
||||
uint32_t ReadUInt32() { uint32_t returnValue; memcpy(&returnValue, p, 4); p += 4; return returnValue; }
|
||||
int64_t ReadInt64() { int64_t returnValue; memcpy(&returnValue, p, 8); p += 8; return returnValue; }
|
||||
double ReadDouble() { double returnValue; memcpy(&returnValue, p, 8); p += 8; return returnValue; }
|
||||
#endif
|
||||
|
||||
size_t GetSerializeSize() const { return p - pStart; }
|
||||
|
||||
private:
|
||||
Handle<Value> DeserializeArray();
|
||||
Handle<Value> DeserializeValue(BsonType type);
|
||||
Handle<Value> DeserializeDocumentInternal();
|
||||
Handle<Value> DeserializeArrayInternal();
|
||||
|
||||
BSON* bson;
|
||||
char* const pStart;
|
||||
char* p;
|
||||
char* const pEnd;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#endif // BSON_H_
|
||||
|
||||
//===========================================================================
|
||||
//===========================================================================
|
||||
|
||||
#ifndef BSON_H_
|
||||
#define BSON_H_
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#define USE_MISALIGNED_MEMORY_ACCESS 1
|
||||
|
||||
#include <node.h>
|
||||
#include <node_object_wrap.h>
|
||||
#include <v8.h>
|
||||
|
||||
using namespace v8;
|
||||
using namespace node;
|
||||
|
||||
//===========================================================================
|
||||
|
||||
enum BsonType
|
||||
{
|
||||
BSON_TYPE_NUMBER = 1,
|
||||
BSON_TYPE_STRING = 2,
|
||||
BSON_TYPE_OBJECT = 3,
|
||||
BSON_TYPE_ARRAY = 4,
|
||||
BSON_TYPE_BINARY = 5,
|
||||
BSON_TYPE_UNDEFINED = 6,
|
||||
BSON_TYPE_OID = 7,
|
||||
BSON_TYPE_BOOLEAN = 8,
|
||||
BSON_TYPE_DATE = 9,
|
||||
BSON_TYPE_NULL = 10,
|
||||
BSON_TYPE_REGEXP = 11,
|
||||
BSON_TYPE_CODE = 13,
|
||||
BSON_TYPE_SYMBOL = 14,
|
||||
BSON_TYPE_CODE_W_SCOPE = 15,
|
||||
BSON_TYPE_INT = 16,
|
||||
BSON_TYPE_TIMESTAMP = 17,
|
||||
BSON_TYPE_LONG = 18,
|
||||
BSON_TYPE_MAX_KEY = 0x7f,
|
||||
BSON_TYPE_MIN_KEY = 0xff
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
template<typename T> class BSONSerializer;
|
||||
|
||||
class BSON : public ObjectWrap {
|
||||
public:
|
||||
BSON();
|
||||
~BSON() {}
|
||||
|
||||
static void Initialize(Handle<Object> target);
|
||||
static Handle<Value> BSONDeserializeStream(const Arguments &args);
|
||||
|
||||
// JS based objects
|
||||
static Handle<Value> BSONSerialize(const Arguments &args);
|
||||
static Handle<Value> BSONDeserialize(const Arguments &args);
|
||||
|
||||
// Calculate size of function
|
||||
static Handle<Value> CalculateObjectSize(const Arguments &args);
|
||||
static Handle<Value> SerializeWithBufferAndIndex(const Arguments &args);
|
||||
|
||||
// Constructor used for creating new BSON objects from C++
|
||||
static Persistent<FunctionTemplate> constructor_template;
|
||||
|
||||
private:
|
||||
static Handle<Value> New(const Arguments &args);
|
||||
static Handle<Value> deserialize(BSON *bson, char *data, uint32_t dataLength, uint32_t startIndex, bool is_array_item);
|
||||
|
||||
// BSON type instantiate functions
|
||||
Persistent<Function> longConstructor;
|
||||
Persistent<Function> objectIDConstructor;
|
||||
Persistent<Function> binaryConstructor;
|
||||
Persistent<Function> codeConstructor;
|
||||
Persistent<Function> dbrefConstructor;
|
||||
Persistent<Function> symbolConstructor;
|
||||
Persistent<Function> doubleConstructor;
|
||||
Persistent<Function> timestampConstructor;
|
||||
Persistent<Function> minKeyConstructor;
|
||||
Persistent<Function> maxKeyConstructor;
|
||||
|
||||
// Equality Objects
|
||||
Persistent<String> longString;
|
||||
Persistent<String> objectIDString;
|
||||
Persistent<String> binaryString;
|
||||
Persistent<String> codeString;
|
||||
Persistent<String> dbrefString;
|
||||
Persistent<String> symbolString;
|
||||
Persistent<String> doubleString;
|
||||
Persistent<String> timestampString;
|
||||
Persistent<String> minKeyString;
|
||||
Persistent<String> maxKeyString;
|
||||
|
||||
// Equality speed up comparison objects
|
||||
Persistent<String> _bsontypeString;
|
||||
Persistent<String> _longLowString;
|
||||
Persistent<String> _longHighString;
|
||||
Persistent<String> _objectIDidString;
|
||||
Persistent<String> _binaryPositionString;
|
||||
Persistent<String> _binarySubTypeString;
|
||||
Persistent<String> _binaryBufferString;
|
||||
Persistent<String> _doubleValueString;
|
||||
Persistent<String> _symbolValueString;
|
||||
|
||||
Persistent<String> _dbRefRefString;
|
||||
Persistent<String> _dbRefIdRefString;
|
||||
Persistent<String> _dbRefDbRefString;
|
||||
Persistent<String> _dbRefNamespaceString;
|
||||
Persistent<String> _dbRefDbString;
|
||||
Persistent<String> _dbRefOidString;
|
||||
|
||||
Persistent<String> _codeCodeString;
|
||||
Persistent<String> _codeScopeString;
|
||||
Persistent<String> _toBSONString;
|
||||
|
||||
Local<Object> GetSerializeObject(const Handle<Value>& object);
|
||||
|
||||
template<typename T> friend class BSONSerializer;
|
||||
friend class BSONDeserializer;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
class CountStream
|
||||
{
|
||||
public:
|
||||
CountStream() : count(0) { }
|
||||
|
||||
void WriteByte(int value) { ++count; }
|
||||
void WriteByte(const Handle<Object>&, const Handle<String>&) { ++count; }
|
||||
void WriteBool(const Handle<Value>& value) { ++count; }
|
||||
void WriteInt32(int32_t value) { count += 4; }
|
||||
void WriteInt32(const Handle<Value>& value) { count += 4; }
|
||||
void WriteInt32(const Handle<Object>& object, const Handle<String>& key) { count += 4; }
|
||||
void WriteInt64(int64_t value) { count += 8; }
|
||||
void WriteInt64(const Handle<Value>& value) { count += 8; }
|
||||
void WriteDouble(double value) { count += 8; }
|
||||
void WriteDouble(const Handle<Value>& value) { count += 8; }
|
||||
void WriteDouble(const Handle<Object>&, const Handle<String>&) { count += 8; }
|
||||
void WriteUInt32String(uint32_t name) { char buffer[32]; count += sprintf(buffer, "%u", name) + 1; }
|
||||
void WriteLengthPrefixedString(const Local<String>& value) { count += value->Utf8Length()+5; }
|
||||
void WriteObjectId(const Handle<Object>& object, const Handle<String>& key) { count += 12; }
|
||||
void WriteString(const Local<String>& value) { count += value->Utf8Length() + 1; } // This returns the number of bytes exclusive of the NULL terminator
|
||||
void WriteData(const char* data, size_t length) { count += length; }
|
||||
|
||||
void* BeginWriteType() { ++count; return NULL; }
|
||||
void CommitType(void*, BsonType) { }
|
||||
void* BeginWriteSize() { count += 4; return NULL; }
|
||||
void CommitSize(void*) { }
|
||||
|
||||
size_t GetSerializeSize() const { return count; }
|
||||
|
||||
// Do nothing. CheckKey is implemented for DataStream
|
||||
void CheckKey(const Local<String>&) { }
|
||||
|
||||
private:
|
||||
size_t count;
|
||||
};
|
||||
|
||||
class DataStream
|
||||
{
|
||||
public:
|
||||
DataStream(char* aDestinationBuffer) : destinationBuffer(aDestinationBuffer), p(aDestinationBuffer) { }
|
||||
|
||||
void WriteByte(int value) { *p++ = value; }
|
||||
void WriteByte(const Handle<Object>& object, const Handle<String>& key) { *p++ = object->Get(key)->Int32Value(); }
|
||||
#if USE_MISALIGNED_MEMORY_ACCESS
|
||||
void WriteInt32(int32_t value) { *reinterpret_cast<int32_t*>(p) = value; p += 4; }
|
||||
void WriteInt64(int64_t value) { *reinterpret_cast<int64_t*>(p) = value; p += 8; }
|
||||
void WriteDouble(double value) { *reinterpret_cast<double*>(p) = value; p += 8; }
|
||||
#else
|
||||
void WriteInt32(int32_t value) { memcpy(p, &value, 4); p += 4; }
|
||||
void WriteInt64(int64_t value) { memcpy(p, &value, 8); p += 8; }
|
||||
void WriteDouble(double value) { memcpy(p, &value, 8); p += 8; }
|
||||
#endif
|
||||
void WriteBool(const Handle<Value>& value) { WriteByte(value->BooleanValue() ? 1 : 0); }
|
||||
void WriteInt32(const Handle<Value>& value) { WriteInt32(value->Int32Value()); }
|
||||
void WriteInt32(const Handle<Object>& object, const Handle<String>& key) { WriteInt32(object->Get(key)); }
|
||||
void WriteInt64(const Handle<Value>& value) { WriteInt64(value->IntegerValue()); }
|
||||
void WriteDouble(const Handle<Value>& value) { WriteDouble(value->NumberValue()); }
|
||||
void WriteDouble(const Handle<Object>& object, const Handle<String>& key) { WriteDouble(object->Get(key)); }
|
||||
void WriteUInt32String(uint32_t name) { p += sprintf(p, "%u", name) + 1; }
|
||||
void WriteLengthPrefixedString(const Local<String>& value) { WriteInt32(value->Utf8Length()+1); WriteString(value); }
|
||||
void WriteObjectId(const Handle<Object>& object, const Handle<String>& key);
|
||||
void WriteString(const Local<String>& value) { p += value->WriteUtf8(p); } // This returns the number of bytes inclusive of the NULL terminator.
|
||||
void WriteData(const char* data, size_t length) { memcpy(p, data, length); p += length; }
|
||||
|
||||
void* BeginWriteType() { void* returnValue = p; p++; return returnValue; }
|
||||
void CommitType(void* beginPoint, BsonType value) { *reinterpret_cast<unsigned char*>(beginPoint) = value; }
|
||||
void* BeginWriteSize() { void* returnValue = p; p += 4; return returnValue; }
|
||||
|
||||
#if USE_MISALIGNED_MEMORY_ACCESS
|
||||
void CommitSize(void* beginPoint) { *reinterpret_cast<int32_t*>(beginPoint) = (int32_t) (p - (char*) beginPoint); }
|
||||
#else
|
||||
void CommitSize(void* beginPoint) { int32_t value = (int32_t) (p - (char*) beginPoint); memcpy(beginPoint, &value, 4); }
|
||||
#endif
|
||||
|
||||
size_t GetSerializeSize() const { return p - destinationBuffer; }
|
||||
|
||||
void CheckKey(const Local<String>& keyName);
|
||||
|
||||
protected:
|
||||
char *const destinationBuffer; // base, never changes
|
||||
char* p; // cursor into buffer
|
||||
};
|
||||
|
||||
template<typename T> class BSONSerializer : public T
|
||||
{
|
||||
private:
|
||||
typedef T Inherited;
|
||||
|
||||
public:
|
||||
BSONSerializer(BSON* aBson, bool aCheckKeys, bool aSerializeFunctions) : Inherited(), checkKeys(aCheckKeys), serializeFunctions(aSerializeFunctions), bson(aBson) { }
|
||||
BSONSerializer(BSON* aBson, bool aCheckKeys, bool aSerializeFunctions, char* parentParam) : Inherited(parentParam), checkKeys(aCheckKeys), serializeFunctions(aSerializeFunctions), bson(aBson) { }
|
||||
|
||||
void SerializeDocument(const Handle<Value>& value);
|
||||
void SerializeArray(const Handle<Value>& value);
|
||||
void SerializeValue(void* typeLocation, const Handle<Value>& value);
|
||||
|
||||
private:
|
||||
bool checkKeys;
|
||||
bool serializeFunctions;
|
||||
BSON* bson;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
class BSONDeserializer
|
||||
{
|
||||
public:
|
||||
BSONDeserializer(BSON* aBson, char* data, size_t length);
|
||||
BSONDeserializer(BSONDeserializer& parentSerializer, size_t length);
|
||||
|
||||
Handle<Value> DeserializeDocument();
|
||||
|
||||
bool HasMoreData() const { return p < pEnd; }
|
||||
Local<String> ReadCString();
|
||||
uint32_t ReadIntegerString();
|
||||
int32_t ReadRegexOptions();
|
||||
Local<String> ReadString();
|
||||
Local<String> ReadObjectId();
|
||||
|
||||
unsigned char ReadByte() { return *reinterpret_cast<unsigned char*>(p++); }
|
||||
#if USE_MISALIGNED_MEMORY_ACCESS
|
||||
int32_t ReadInt32() { int32_t returnValue = *reinterpret_cast<int32_t*>(p); p += 4; return returnValue; }
|
||||
uint32_t ReadUInt32() { uint32_t returnValue = *reinterpret_cast<uint32_t*>(p); p += 4; return returnValue; }
|
||||
int64_t ReadInt64() { int64_t returnValue = *reinterpret_cast<int64_t*>(p); p += 8; return returnValue; }
|
||||
double ReadDouble() { double returnValue = *reinterpret_cast<double*>(p); p += 8; return returnValue; }
|
||||
#else
|
||||
int32_t ReadInt32() { int32_t returnValue; memcpy(&returnValue, p, 4); p += 4; return returnValue; }
|
||||
uint32_t ReadUInt32() { uint32_t returnValue; memcpy(&returnValue, p, 4); p += 4; return returnValue; }
|
||||
int64_t ReadInt64() { int64_t returnValue; memcpy(&returnValue, p, 8); p += 8; return returnValue; }
|
||||
double ReadDouble() { double returnValue; memcpy(&returnValue, p, 8); p += 8; return returnValue; }
|
||||
#endif
|
||||
|
||||
size_t GetSerializeSize() const { return p - pStart; }
|
||||
|
||||
private:
|
||||
Handle<Value> DeserializeArray();
|
||||
Handle<Value> DeserializeValue(BsonType type);
|
||||
Handle<Value> DeserializeDocumentInternal();
|
||||
Handle<Value> DeserializeArrayInternal();
|
||||
|
||||
BSON* bson;
|
||||
char* const pStart;
|
||||
char* p;
|
||||
char* const pEnd;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#endif // BSON_H_
|
||||
|
||||
//===========================================================================
|
||||
|
||||
7
node_modules/mongoskin/node_modules/mongodb/node_modules/bson/package.json
generated
vendored
7
node_modules/mongoskin/node_modules/mongodb/node_modules/bson/package.json
generated
vendored
@@ -48,11 +48,8 @@
|
||||
"dependencies": {},
|
||||
"optionalDependencies": {},
|
||||
"_engineSupported": true,
|
||||
"_npmVersion": "1.1.21",
|
||||
"_nodeVersion": "v0.6.18",
|
||||
"_npmVersion": "1.1.24",
|
||||
"_nodeVersion": "v0.6.19",
|
||||
"_defaultsLoaded": true,
|
||||
"dist": {
|
||||
"shasum": "d6954ee604c768436a1956ad487ea2bd571910da"
|
||||
},
|
||||
"_from": "bson@0.1.5"
|
||||
}
|
||||
|
||||
17
node_modules/mongoskin/node_modules/mongodb/package.json
generated
vendored
Normal file → Executable file
17
node_modules/mongoskin/node_modules/mongodb/package.json
generated
vendored
Normal file → Executable file
@@ -7,7 +7,7 @@
|
||||
"driver",
|
||||
"db"
|
||||
],
|
||||
"version": "1.1.11",
|
||||
"version": "1.2.8",
|
||||
"author": {
|
||||
"name": "Christian Amor Kvalheim",
|
||||
"email": "christkv@gmail.com"
|
||||
@@ -165,6 +165,9 @@
|
||||
},
|
||||
{
|
||||
"name": "Roman Shtylman"
|
||||
},
|
||||
{
|
||||
"name": "Matt Self"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
@@ -193,6 +196,7 @@
|
||||
"native": false
|
||||
},
|
||||
"main": "./lib/mongodb/index",
|
||||
"homepage": "http://mongodb.github.com/node-mongodb-native/",
|
||||
"directories": {
|
||||
"lib": "./lib/mongodb"
|
||||
},
|
||||
@@ -208,14 +212,11 @@
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0"
|
||||
}
|
||||
],
|
||||
"_id": "mongodb@1.1.11",
|
||||
"_id": "mongodb@1.2.8",
|
||||
"optionalDependencies": {},
|
||||
"_engineSupported": true,
|
||||
"_npmVersion": "1.1.21",
|
||||
"_nodeVersion": "v0.6.18",
|
||||
"_npmVersion": "1.1.24",
|
||||
"_nodeVersion": "v0.6.19",
|
||||
"_defaultsLoaded": true,
|
||||
"dist": {
|
||||
"shasum": "51f813dad01721d585f3588f4233920d23d5169e"
|
||||
},
|
||||
"_from": "mongodb@< 1.2.0"
|
||||
"_from": "mongodb@1.2.x"
|
||||
}
|
||||
|
||||
16
node_modules/mongoskin/package.json
generated
vendored
16
node_modules/mongoskin/package.json
generated
vendored
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "mongoskin",
|
||||
"description": "The future layer above node-mongodb-native",
|
||||
"version": "0.4.4",
|
||||
"version": "0.5.0",
|
||||
"author": {
|
||||
"name": "Gui Lin",
|
||||
"email": "guileen@gmail.com"
|
||||
@@ -24,21 +24,22 @@
|
||||
"node": ">= 0.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"mongodb": "< 1.2.0"
|
||||
"mongodb": "1.2.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "*",
|
||||
"jscover": "*",
|
||||
"should": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "make test-version"
|
||||
"test": "make test"
|
||||
},
|
||||
"directories": {
|
||||
"example": "./examples",
|
||||
"lib": "./lib/mongoskin"
|
||||
},
|
||||
"license": "MIT",
|
||||
"_id": "mongoskin@0.4.4",
|
||||
"_id": "mongoskin@0.5.0",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Gui Lin",
|
||||
@@ -103,11 +104,8 @@
|
||||
],
|
||||
"optionalDependencies": {},
|
||||
"_engineSupported": true,
|
||||
"_npmVersion": "1.1.21",
|
||||
"_nodeVersion": "v0.6.18",
|
||||
"_npmVersion": "1.1.24",
|
||||
"_nodeVersion": "v0.6.19",
|
||||
"_defaultsLoaded": true,
|
||||
"dist": {
|
||||
"shasum": "dec69b0cbcbcb30f3327e1fc26f6f29ad35781bc"
|
||||
},
|
||||
"_from": "mongoskin@>= 0.0.1"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user