jaydata-librets
Version:
A node.js driver for libRETS
895 lines (786 loc) • 31.5 kB
JavaScript
/**
* Module dependencies.
* @ignore
*/
var QueryCommand = require('./commands/query_command').QueryCommand
, DbCommand = require('./commands/db_command').DbCommand
, Collection = require('./collection').Collection
, Server = require('./connection/server').Server
, EventEmitter = require('events').EventEmitter
, inherits = require('util').inherits
, crypto = require('crypto')
, timers = require('timers')
, utils = require('./utils');
var hasKerberos = false;
// Check if we have a the kerberos library
try {
require('kerberos');
hasKerberos = true;
} catch(err) {}
// Set processor, setImmediate if 0.10 otherwise nextTick
var processor = require('./utils').processor();
/**
* Create a new Db instance.
*
* Options
* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement 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)
* - **native_parser** {Boolean, default:false}, use c++ bson parser.
* - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation.
* - **serializeFunctions** {Boolean, default:false}, serialize functions.
* - **raw** {Boolean, default:false}, perform operations using raw bson buffers.
* - **recordQueryStats** {Boolean, default:false}, record query statistics during execution.
* - **retryMiliSeconds** {Number, default:5000}, number of milliseconds between retries.
* - **numberOfRetries** {Number, default:5}, number of retries off connection.
* - **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) {}})**.
* - **slaveOk** {Number, default:null}, force setting of SlaveOk flag on queries (only use when explicitly connecting to a secondary server).
* - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits
* - **bufferMaxEntries** {Boolean, default: -1}, sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited
*
* @class Represents a Db
* @param {Object} serverConfig server config object.
* @param {Object} [options] additional options for the collection.
*/
function Db(serverConfig, options) {
if(!(this instanceof Db)) return new Db(serverConfig, options);
EventEmitter.call(this);
var self = this;
this.serverConfig = serverConfig;
this.options = options == null ? {} : options;
// State to check against if the user force closed db
this._applicationClosed = false;
// Fetch the override flag if any
var overrideUsedFlag = this.options['override_used_flag'] == null ? false : this.options['override_used_flag'];
// Verify that nobody is using this config
if(!overrideUsedFlag && this.serverConfig != null && typeof this.serverConfig == 'object' && this.serverConfig._isUsed && this.serverConfig._isUsed()) {
throw new Error('A Server instance cannot be shared across multiple Db instances');
} else if(!overrideUsedFlag && typeof this.serverConfig == 'object'){
// Set being used
this.serverConfig._used = true;
}
// Allow slaveOk override
this.slaveOk = this.options['slave_ok'] == null ? false : this.options['slave_ok'];
this.slaveOk = this.options['slaveOk'] == null ? this.slaveOk : this.options['slaveOk'];
// Number of operations to buffer before failure
this.bufferMaxEntries = typeof this.options['bufferMaxEntries'] == 'number' ? this.options['bufferMaxEntries'] : -1;
// Contains all the connections for the db
try {
this.native_parser = this.options.native_parser;
// The bson lib
var bsonLib = this.bsonLib = this.options.native_parser ? require('bson').BSONNative : require('bson').BSONPure;
// Fetch the serializer object
var BSON = bsonLib.BSON;
// Create a new instance
this.bson = new BSON([bsonLib.Long, bsonLib.ObjectID, bsonLib.Binary, bsonLib.Code, bsonLib.DBRef, bsonLib.Symbol, bsonLib.Double, bsonLib.Timestamp, bsonLib.MaxKey, bsonLib.MinKey]);
this.bson.promoteLongs = this.options.promoteLongs == null ? true : this.options.promoteLongs;
// Backward compatibility to access types
this.bson_deserializer = bsonLib;
this.bson_serializer = bsonLib;
// Add any overrides to the serializer and deserializer
this.bson_deserializer.promoteLongs = this.options.promoteLongs == null ? true : this.options.promoteLongs;
} catch (err) {
// If we tried to instantiate the native driver
var msg = 'Native bson parser not compiled, please compile '
+ 'or avoid using native_parser=true';
throw Error(msg);
}
// Internal state of the server
this._state = 'disconnected';
this.pkFactory = this.options.pk == null ? bsonLib.ObjectID : this.options.pk;
// Internal states variables
this.notReplied ={};
this.isInitializing = true;
this.openCalled = false;
// Command queue, keeps a list of incoming commands that need to be executed once the connection is up
this.commands = [];
// Set up logger
this.logger = this.options.logger != null
&& (typeof this.options.logger.debug == 'function')
&& (typeof this.options.logger.error == 'function')
&& (typeof this.options.logger.log == 'function')
? this.options.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}};
// Associate the logger with the server config
this.serverConfig.logger = this.logger;
if(this.serverConfig.strategyInstance) this.serverConfig.strategyInstance.logger = this.logger;
this.tag = new Date().getTime();
// Just keeps list of events we allow
this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[]};
// Controls serialization options
this.serializeFunctions = this.options.serializeFunctions != null ? this.options.serializeFunctions : false;
// Raw mode
this.raw = this.options.raw != null ? this.options.raw : false;
// Record query stats
this.recordQueryStats = this.options.recordQueryStats != null ? this.options.recordQueryStats : false;
// If we have server stats let's make sure the driver objects have it enabled
if(this.recordQueryStats == true) {
this.serverConfig.enableRecordQueryStats(true);
}
// Retry information
this.retryMiliSeconds = this.options.retryMiliSeconds != null ? this.options.retryMiliSeconds : 1000;
this.numberOfRetries = this.options.numberOfRetries != null ? this.options.numberOfRetries : 60;
// Ensure we keep a reference to this db
this.serverConfig._dbStore.add(this);
};
/**
* @ignore
*/
inherits(Db, EventEmitter);
/**
* Initialize the database connection.
*
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the index information or null if an error occurred.
* @return {null}
* @api public
*/
Db.prototype.open = function(callback) {
var self = this;
// Check that the user has not called this twice
if(this.openCalled) {
// Close db
this.close();
// Throw error
throw new Error("db object already connecting, open cannot be called multiple times");
}
// Set that db has been opened
this.openCalled = true;
// Set the status of the server
self._state = 'connecting';
// Set up connections
if(self.serverConfig instanceof Server) {
// Ensure we have the original options passed in for the server config
var connect_options = {};
for(var name in self.serverConfig.options) {
connect_options[name] = self.serverConfig.options[name]
}
connect_options.firstCall = true;
// Attempt to connect
self.serverConfig.connect(self, connect_options, function(err, result) {
if(err != null) {
// Close db to reset connection
return self.close(function () {
// Return error from connection
return callback(err, null);
});
}
// Set the status of the server
self._state = 'connected';
// If we have queued up commands execute a command to trigger replays
if(self.commands.length > 0) _execute_queued_command(self);
// Callback
process.nextTick(function() {
try {
callback(null, self);
} catch(err) {
self.close();
throw err;
}
});
});
} else {
try {
callback(Error("Server parameter must be of type Server"), null);
} catch(err) {
self.close();
throw err;
}
}
};
/**
* Create a new Db instance sharing the current socket connections.
*
* @param {String} dbName the name of the database we want to use.
* @return {Db} a db instance using the new database.
* @api public
*/
Db.prototype.db = function(dbName) {
// Copy the options and add out internal override of the not shared flag
var options = {};
for(var key in this.options) {
options[key] = this.options[key];
}
// Add override flag
options['override_used_flag'] = true;
// Check if the db already exists and reuse if it's the case
var db = this.serverConfig._dbStore.fetch(dbName);
// Create a new instance
if(!db) {
db = new Db(dbName, this.serverConfig, options);
}
// Return the db object
return db;
};
/**
* Close the current db connection, including all the child db instances. Emits close event if no callback is provided.
*
* @param {Boolean} [forceClose] connection can never be reused.
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results or null if an error occurred.
* @return {null}
* @api public
*/
Db.prototype.close = function(forceClose, callback) {
var self = this;
// Ensure we force close all connections
this._applicationClosed = false;
if(typeof forceClose == 'function') {
callback = forceClose;
} else if(typeof forceClose == 'boolean') {
this._applicationClosed = forceClose;
}
this.serverConfig.close(function(err, result) {
// You can reuse the db as everything is shut down
self.openCalled = false;
// If we have a callback call it
if(callback) callback(err, result);
});
};
/**
* Logout user from server, fire off on all connections and remove all auth info
*
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from logout or null if an error occurred.
* @return {null}
* @api public
*/
Db.prototype.logout = function(options, callback) {
var self = this;
// Unpack calls
var args = Array.prototype.slice.call(arguments, 0);
callback = args.pop();
options = args.length ? args.shift() || {} : {};
// Number of connections we need to logout from
var numberOfConnections = this.serverConfig.allRawConnections().length;
// Let's generate the logout command object
var logoutCommand = DbCommand.logoutCommand(self, {logout:1}, options);
self._executeQueryCommand(logoutCommand, {onAll:true}, function(err, result) {
// Count down
numberOfConnections = numberOfConnections - 1;
// Work around the case where the number of connections are 0
if(numberOfConnections <= 0 && typeof callback == 'function') {
var internalCallback = callback;
callback = null;
// Handle error result
utils.handleSingleCommandResultReturn(true, false, internalCallback)(err, result);
}
});
};
/**
* Authenticate a user against the server.
* authMechanism
* Options
* - **authMechanism** {String, default:DIGEST}, The authentication mechanism to use, BASIC, OAUTH or DIGEST
*
* @param {String} username username.
* @param {String} password password.
* @param {Object} [options] the options
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from authentication or null if an error occurred.
* @return {null}
* @api public
*/
Db.prototype.authenticate = function(username, password, options, callback) {
var self = this;
if(typeof options == 'function') {
callback = options;
options = {};
}
// Set default mechanism
if(!options.authMechanism) {
options.authMechanism = 'DIGEST';
} else if(options.authMechanism != 'BASIC'
&& options.authMechanism != 'OAUTH'
&& options.authMechanism != 'DIGEST') {
return callback(new Error("only BASIC, OAUTH or DIGEST is supported by authMechanism"));
}
// Callback
var _callback = function(err, result) {
if(self.listeners("authenticated").length > 9) {
self.emit("authenticated", err, result);
}
// Return to caller
callback(err, result);
}
callback(null, true);
};
/**
* Return last error message for the given connection, note options can be combined.
*
* Options
* - **w** {Number}, until a write operation has been replicated to N servers.
* - **wtimeout** {Number}, number of miliseconds to wait before timing out.
*
* Connection Options
* - **connection** {Connection}, fire the getLastError down a specific connection.
*
* @param {Object} [options] returns option results.
* @param {Object} [connectionOptions] 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 occurred, or null otherwise. While the second parameter will contain the results from lastError or null if an error occurred.
* @return {null}
* @api public
*/
Db.prototype.lastError = function(options, connectionOptions, callback) {
// Unpack calls
var args = Array.prototype.slice.call(arguments, 0);
callback = args.pop();
options = args.length ? args.shift() || {} : {};
connectionOptions = args.length ? args.shift() || {} : {};
this._executeQueryCommand(DbCommand.createGetLastErrorCommand(options, this), connectionOptions, function(err, error) {
callback(err, error && error.documents);
});
};
/**
* Legacy method calls.
*
* @ignore
* @api private
*/
Db.prototype.error = Db.prototype.lastError;
Db.prototype.lastStatus = Db.prototype.lastError;
/**
* Return all errors up to the last time db reset_error_history was called.
*
* Options
* - **connection** {Connection}, fire the getLastError down a specific connection.
*
* @param {Object} [options] 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 occurred, or null otherwise. While the second parameter will contain the results from previousErrors or null if an error occurred.
* @return {null}
* @api public
*/
Db.prototype.previousErrors = function(options, callback) {
// Unpack calls
var args = Array.prototype.slice.call(arguments, 0);
callback = args.pop();
options = args.length ? args.shift() || {} : {};
this._executeQueryCommand(DbCommand.createGetPreviousErrorsCommand(this), options, function(err, error) {
callback(err, error.documents);
});
};
/**
* Runs a command on the database.
* @ignore
* @api private
*/
Db.prototype.executeDbCommand = function(command_hash, options, callback) {
if(callback == null) { callback = options; options = {}; }
this._executeQueryCommand(DbCommand.createDbSlaveOkCommand(this, command_hash, options), options, function(err, result) {
if(callback) callback(err, result);
});
};
/**
* Resets the error history of the mongo instance.
*
* Options
* - **connection** {Connection}, fire the getLastError down a specific connection.
*
* @param {Object} [options] 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 occurred, or null otherwise. While the second parameter will contain the results from resetErrorHistory or null if an error occurred.
* @return {null}
* @api public
*/
Db.prototype.resetErrorHistory = function(options, callback) {
// Unpack calls
var args = Array.prototype.slice.call(arguments, 0);
callback = args.pop();
options = args.length ? args.shift() || {} : {};
this._executeQueryCommand(DbCommand.createResetErrorHistoryCommand(this), options, function(err, error) {
if(callback) callback(err, error && error.documents);
});
};
/**
* Get all the db statistics.
*
* Options
* - **scale** {Number}, divide the returned sizes by scale value.
*
* @param {Objects} [options] options for the stats command
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from stats or null if an error occurred.
* @return {null}
* @api public
*/
Db.prototype.stats = function stats(options, callback) {
var args = Array.prototype.slice.call(arguments, 0);
callback = args.pop();
// Fetch all commands
options = args.length ? args.shift() || {} : {};
// Build command object
var commandObject = {
dbStats:this.collectionName
};
// Check if we have the scale value
if(options['scale'] != null) commandObject['scale'] = options['scale'];
// Execute the command
this.command(commandObject, options, callback);
}
/**
* @ignore
*/
var __executeQueryCommand = function(self, db_command, options, callback) {
// Options unpacking
var read = options['read'] != null ? options['read'] : false;
var raw = options['raw'] != null ? options['raw'] : self.raw;
var onAll = options['onAll'] != null ? options['onAll'] : false;
var specifiedConnection = options['connection'] != null ? options['connection'] : null;
// If we got a callback object
if(typeof callback === 'function' && !onAll) {
// Override connection if we passed in a specific connection
var connection = specifiedConnection != null ? specifiedConnection : null;
if(connection instanceof Error) return callback(connection, null);
// Fetch either a reader or writer dependent on the specified read option if no connection
// was passed in
if(connection == null) {
connection = self.serverConfig.checkoutReader(read);
}
if(connection == null) {
return callback(new Error("no open connections"));
} else if(connection instanceof Error || connection['message'] != null) {
return callback(connection);
}
// Exhaust Option
var exhaust = options.exhaust || false;
// Register the handler in the data structure
self.serverConfig._registerHandler(db_command, raw, connection, exhaust, callback);
// Write the message out and handle any errors if there are any
connection.write(db_command, function(err) {
if(err != null) {
// Call the handler with an error
if(Array.isArray(db_command))
self.serverConfig._callHandler(db_command[0].getRequestId(), null, err);
else
self.serverConfig._callHandler(db_command.getRequestId(), null, err);
}
});
} else if(typeof callback === 'function' && onAll) {
var connections = self.serverConfig.allRawConnections();
var numberOfEntries = connections.length;
// Go through all the connections
for(var i = 0; i < connections.length; i++) {
// Fetch a connection
var connection = connections[i];
// Ensure we have a valid connection
if(connection == null) {
return callback(new Error("no open connections"));
} else if(connection instanceof Error) {
return callback(connection);
}
// Register the handler in the data structure
self.serverConfig._registerHandler(db_command, raw, connection, callback);
// Write the message out
connection.write(db_command, function(err) {
// Adjust the number of entries we need to process
numberOfEntries = numberOfEntries - 1;
// Remove listener
if(err != null) {
// Clean up listener and return error
self.serverConfig._removeHandler(db_command.getRequestId());
}
// No more entries to process callback with the error
if(numberOfEntries <= 0) {
callback(err);
}
});
// Update the db_command request id
db_command.updateRequestId();
}
} else {
// Fetch either a reader or writer dependent on the specified read option
// var connection = read == null || read == 'primary' || read == false ? self.serverConfig.checkoutWriter(true) : self.serverConfig.checkoutReader(read);
var connection = self.serverConfig.checkoutReader(read);
// Override connection if needed
connection = specifiedConnection != null ? specifiedConnection : connection;
// Ensure we have a valid connection
if(connection == null || connection instanceof Error || connection['message'] != null) return null;
// Write the message out
connection.write(db_command, function(err) {
if(err != null) {
// Emit the error
self.emit("error", err);
}
});
}
};
/**
* Execute db query command
* @ignore
* @api private
*/
Db.prototype._executeQueryCommand = function(db_command, options, callback) {
var self = this;
// Unpack the parameters
if (typeof callback === 'undefined') {
callback = options;
options = {};
}
// fast fail option used for HA, no retry
var failFast = options['failFast'] != null
? options['failFast']
: false;
// Check if the user force closed the command
if(this._applicationClosed) {
var err = new Error("db closed by application");
if('function' == typeof callback) {
return callback(err, null);
} else {
throw err;
}
}
if(this.serverConfig.isDestroyed())
return callback(new Error("Connection was destroyed by application"));
// Specific connection
var connection = options.connection;
// Check if the connection is actually live
if(connection
&& (!connection.isConnected || !connection.isConnected())) connection = null;
// Get the configuration
var config = this.serverConfig;
var read = options.read;
if(!connection && !config.canRead(read) && !config.canWrite() && config.isAutoReconnect()) {
if(read == ReadPreference.PRIMARY
|| read == ReadPreference.PRIMARY_PREFERRED
|| (read != null && typeof read == 'object' && read.mode)
|| read == null) {
// Save the command
self.serverConfig._commandsStore.read_from_writer(
{ type: 'query'
, db_command: db_command
, options: options
, callback: callback
, db: self
, executeQueryCommand: __executeQueryCommand
, executeInsertCommand: __executeInsertCommand
}
);
} else {
self.serverConfig._commandsStore.read(
{ type: 'query'
, db_command: db_command
, options: options
, callback: callback
, db: self
, executeQueryCommand: __executeQueryCommand
, executeInsertCommand: __executeInsertCommand
}
);
}
// If we have blown through the number of items let's
if(!self.serverConfig._commandsStore.validateBufferLimit(self.bufferMaxEntries)) {
self.close();
}
} else if(!connection && !config.canRead(read) && !config.canWrite() && !config.isAutoReconnect()) {
return callback(new Error("no open connections"), null);
} else {
if(typeof callback == 'function') {
__executeQueryCommand(self, db_command, options, function (err, result, conn) {
callback(err, result, conn);
});
} else {
__executeQueryCommand(self, db_command, options);
}
}
};
/**
* @ignore
*/
var __executeInsertCommand = function(self, db_command, options, callback) {
// Always checkout a writer for this kind of operations
var connection = self.serverConfig.checkoutWriter();
var raw = options['raw'] != null ? options['raw'] : self.raw;
var specifiedConnection = options['connection'] != null ? options['connection'] : null;
// Override connection if needed
connection = specifiedConnection != null ? specifiedConnection : connection;
// Validate if we can use this server 2.6 wire protocol
if(!connection.isCompatible()) {
return callback(utils.toError("driver is incompatible with this server version"), null);
}
// Ensure we have a valid connection
if(typeof callback === 'function') {
// Ensure we have a valid connection
if(connection == null) {
return callback(new Error("no open connections"));
} else if(connection instanceof Error) {
return callback(connection);
}
var errorOptions = _getWriteConcern(self, options);
if(errorOptions.w > 0 || errorOptions.w == 'majority' || errorOptions.j) {
// db command is now an array of commands (original command + lastError)
db_command = [db_command, DbCommand.createGetLastErrorCommand(self)];
// Register the handler in the data structure
self.serverConfig._registerHandler(db_command[1], raw, connection, callback);
}
}
// If we have no callback and there is no connection
if(connection == null) return null;
if(connection instanceof Error && typeof callback == 'function') return callback(connection, null);
if(connection instanceof Error) return null;
if(connection == null && typeof callback == 'function') return callback(new Error("no primary server found"), null);
// Write the message out
connection.write(db_command, function(err) {
if(typeof callback === 'function') {
// Call the handler with an error
self.serverConfig._callHandler(db_command[1].getRequestId(), null, err);
}
});
};
/**
* Execute an insert Command
* @ignore
* @api private
*/
Db.prototype._executeInsertCommand = function(db_command, options, callback) {
var self = this;
// Unpack the parameters
if(callback == null && typeof options === 'function') {
callback = options;
options = {};
}
// Ensure options are not null
options = options == null ? {} : options;
// Check if the user force closed the command
if(this._applicationClosed) {
if(typeof callback == 'function') {
return callback(new Error("db closed by application"), null);
} else {
throw new Error("db closed by application");
}
}
if(this.serverConfig.isDestroyed()) return callback(new Error("Connection was destroyed by application"));
// Specific connection
var connection = options.connection;
// Check if the connection is actually live
if(connection
&& (!connection.isConnected || !connection.isConnected())) connection = null;
// Get config
var config = self.serverConfig;
// Check if we are connected
if(!connection && !config.canWrite() && config.isAutoReconnect()) {
self.serverConfig._commandsStore.write(
{ type:'insert'
, 'db_command':db_command
, 'options':options
, 'callback':callback
, db: self
, executeQueryCommand: __executeQueryCommand
, executeInsertCommand: __executeInsertCommand
}
);
// If we have blown through the number of items let's
if(!self.serverConfig._commandsStore.validateBufferLimit(self.bufferMaxEntries)) {
self.close();
}
} else if(!connection && !config.canWrite() && !config.isAutoReconnect()) {
return callback(new Error("no open connections"), null);
} else {
__executeInsertCommand(self, db_command, options, callback);
}
};
/**
* Update command is the same
* @ignore
* @api private
*/
Db.prototype._executeUpdateCommand = Db.prototype._executeInsertCommand;
/**
* Remove command is the same
* @ignore
* @api private
*/
Db.prototype._executeRemoveCommand = Db.prototype._executeInsertCommand;
/**
* Wrap a Mongo error document into an Error instance.
* Deprecated. Use utils.toError instead.
*
* @ignore
* @api private
* @deprecated
*/
Db.prototype.wrap = utils.toError;
/**
* Default URL
*
* @classconstant DEFAULT_URL
**/
Db.DEFAULT_URL = 'https://localhost:6103';
/**
* Connect with libRETS using a url as documented at
*
* docs.mongodb.org/manual/reference/connection-string/
*
* Options
* - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication
* - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor**
* - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor**
*
* @param {String} url connection url for libRETS.
* @param {Object} [options] optional options for insert command
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the db instance or null if an error occurred.
* @return {null}
* @api public
*/
Db.connect = function(url, options, callback) {
// Ensure correct mapping of the callback
if(typeof options == 'function') {
callback = options;
options = {};
}
};
/**
* State of the db connection
* @ignore
*/
Object.defineProperty(Db.prototype, "state", { enumerable: true
, get: function () {
return this.serverConfig._serverState;
}
});
/**
* @ignore
*/
var _hasWriteConcern = function(errorOptions) {
return errorOptions == true
|| errorOptions.w > 0
|| errorOptions.w == 'majority'
|| errorOptions.j == true
};
/**
* @ignore
*/
var _setWriteConcernHash = function(options) {
var finalOptions = {};
if(options.w != null) finalOptions.w = options.w;
if(options.j == true) finalOptions.j = options.j;
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') {
finalOptions = _setWriteConcernHash(options);
} else if(self.options.w != null || typeof self.options.j == 'boolean') {
finalOptions = _setWriteConcernHash(self.options);
}
// Return the options
return finalOptions;
};
/**
* Legacy support
*
* @ignore
* @api private
*/
exports.connect = Db.connect;
exports.Db = Db;
/**
* Remove all listeners to the db instance.
* @ignore
* @api private
*/
Db.prototype.removeAllEventListeners = function() {
this.removeAllListeners("close");
this.removeAllListeners("error");
this.removeAllListeners("timeout");
this.removeAllListeners("parseError");
this.removeAllListeners("poolReady");
this.removeAllListeners("message");
};