PageRenderTime 54ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/node_modules/mongodb/lib/server.js

https://gitlab.com/thomasphillips3/beerlocker
JavaScript | 448 lines | 234 code | 73 blank | 141 comment | 42 complexity | b77f4dedafa305f701b179a1a8a7707e MD5 | raw file
  1. "use strict";
  2. var EventEmitter = require('events').EventEmitter
  3. , inherits = require('util').inherits
  4. , CServer = require('mongodb-core').Server
  5. , Cursor = require('./cursor')
  6. , AggregationCursor = require('./aggregation_cursor')
  7. , CommandCursor = require('./command_cursor')
  8. , f = require('util').format
  9. , ServerCapabilities = require('./topology_base').ServerCapabilities
  10. , Store = require('./topology_base').Store
  11. , Define = require('./metadata')
  12. , MongoError = require('mongodb-core').MongoError
  13. , shallowClone = require('./utils').shallowClone
  14. , MAX_JS_INT = require('./utils').MAX_JS_INT;
  15. /**
  16. * @fileOverview The **Server** class is a class that represents a single server topology and is
  17. * used to construct connections.
  18. *
  19. * **Server Should not be used, use MongoClient.connect**
  20. * @example
  21. * var Db = require('mongodb').Db,
  22. * Server = require('mongodb').Server,
  23. * test = require('assert');
  24. * // Connect using single Server
  25. * var db = new Db('test', new Server('localhost', 27017););
  26. * db.open(function(err, db) {
  27. * // Get an additional db
  28. * db.close();
  29. * });
  30. */
  31. /**
  32. * Creates a new Server instance
  33. * @class
  34. * @deprecated
  35. * @param {string} host The host for the server, can be either an IP4, IP6 or domain socket style host.
  36. * @param {number} [port] The server port if IP4.
  37. * @param {object} [options=null] Optional settings.
  38. * @param {number} [options.poolSize=5] Number of connections in the connection pool for each server instance, set to 5 as default for legacy reasons.
  39. * @param {boolean} [options.ssl=false] Use ssl connection (needs to have a mongod server with ssl support)
  40. * @param {object} [options.sslValidate=true] Validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher)
  41. * @param {boolean|function} [options.checkServerIdentity=true] Ensure we check server identify during SSL, set to false to disable checking. Only works for Node 0.12.x or higher. You can pass in a boolean or your own checkServerIdentity override function.
  42. * @param {array} [options.sslCA=null] Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher)
  43. * @param {(Buffer|string)} [options.sslCert=null] String or buffer containing the certificate we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
  44. * @param {(Buffer|string)} [options.sslKey=null] String or buffer containing the certificate private key we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
  45. * @param {(Buffer|string)} [options.sslPass=null] String or buffer containing the certificate password (needs to have a mongod server with ssl support, 2.4 or higher)
  46. * @param {object} [options.socketOptions=null] Socket options
  47. * @param {boolean} [options.socketOptions.autoReconnect=false] Reconnect on error.
  48. * @param {boolean} [options.socketOptions.noDelay=true] TCP Socket NoDelay option.
  49. * @param {number} [options.socketOptions.keepAlive=0] TCP KeepAlive on the socket with a X ms delay before start.
  50. * @param {number} [options.socketOptions.connectTimeoutMS=0] TCP Connection timeout setting
  51. * @param {number} [options.socketOptions.socketTimeoutMS=0] TCP Socket timeout setting
  52. * @param {number} [options.reconnectTries=30] Server attempt to reconnect #times
  53. * @param {number} [options.reconnectInterval=1000] Server will wait # milliseconds between retries
  54. * @fires Server#connect
  55. * @fires Server#close
  56. * @fires Server#error
  57. * @fires Server#timeout
  58. * @fires Server#parseError
  59. * @fires Server#reconnect
  60. * @return {Server} a Server instance.
  61. */
  62. var Server = function(host, port, options) {
  63. options = options || {};
  64. if(!(this instanceof Server)) return new Server(host, port, options);
  65. EventEmitter.call(this);
  66. var self = this;
  67. // Store option defaults
  68. var storeOptions = {
  69. force: false
  70. , bufferMaxEntries: -1
  71. }
  72. // If we have "unlimited" set to max Number
  73. if(storeOptions.bufferMaxEntries == -1) {
  74. storeOptions.bufferMaxEntries = MAX_JS_INT;
  75. }
  76. // Shared global store
  77. var store = options.store || new Store(self, storeOptions);
  78. // Detect if we have a socket connection
  79. if(host.indexOf('\/') != -1) {
  80. if(port != null && typeof port == 'object') {
  81. options = port;
  82. port = null;
  83. }
  84. } else if(port == null) {
  85. throw MongoError.create({message: 'port must be specified', driver:true});
  86. }
  87. // Clone options
  88. var clonedOptions = shallowClone(options);
  89. clonedOptions.host = host;
  90. clonedOptions.port = port;
  91. // Reconnect
  92. var reconnect = typeof options.auto_reconnect == 'boolean' ? options.auto_reconnect : true;
  93. reconnect = typeof options.autoReconnect == 'boolean' ? options.autoReconnect : reconnect;
  94. var emitError = typeof options.emitError == 'boolean' ? options.emitError : true;
  95. var poolSize = typeof options.poolSize == 'number' ? options.poolSize : 5;
  96. // Socket options passed down
  97. if(options.socketOptions) {
  98. if(options.socketOptions.connectTimeoutMS) {
  99. this.connectTimeoutMS = options.socketOptions.connectTimeoutMS;
  100. clonedOptions.connectionTimeout = options.socketOptions.connectTimeoutMS;
  101. }
  102. if(options.socketOptions.socketTimeoutMS) {
  103. clonedOptions.socketTimeout = options.socketOptions.socketTimeoutMS;
  104. }
  105. if(typeof options.socketOptions.keepAlive == 'number') {
  106. clonedOptions.keepAliveInitialDelay = options.socketOptions.keepAlive;
  107. clonedOptions.keepAlive = true;
  108. }
  109. if(typeof options.socketOptions.noDelay == 'boolean') {
  110. clonedOptions.noDelay = options.socketOptions.noDelay;
  111. }
  112. }
  113. // Add the cursor factory function
  114. clonedOptions.cursorFactory = Cursor;
  115. clonedOptions.reconnect = reconnect;
  116. clonedOptions.emitError = emitError;
  117. clonedOptions.size = poolSize;
  118. // Translate the options
  119. if(clonedOptions.sslCA) clonedOptions.ca = clonedOptions.sslCA;
  120. if(typeof clonedOptions.sslValidate == 'boolean') clonedOptions.rejectUnauthorized = clonedOptions.sslValidate;
  121. if(clonedOptions.sslKey) clonedOptions.key = clonedOptions.sslKey;
  122. if(clonedOptions.sslCert) clonedOptions.cert = clonedOptions.sslCert;
  123. if(clonedOptions.sslPass) clonedOptions.passphrase = clonedOptions.sslPass;
  124. // Add the non connection store
  125. clonedOptions.disconnectHandler = store;
  126. // Create an instance of a server instance from mongodb-core
  127. var server = new CServer(clonedOptions);
  128. // Server capabilities
  129. var sCapabilities = null;
  130. // Define the internal properties
  131. this.s = {
  132. // Create an instance of a server instance from mongodb-core
  133. server: server
  134. // Server capabilities
  135. , sCapabilities: null
  136. // Cloned options
  137. , clonedOptions: clonedOptions
  138. // Reconnect
  139. , reconnect: reconnect
  140. // Emit error
  141. , emitError: emitError
  142. // Pool size
  143. , poolSize: poolSize
  144. // Store Options
  145. , storeOptions: storeOptions
  146. // Store
  147. , store: store
  148. // Host
  149. , host: host
  150. // Port
  151. , port: port
  152. // Options
  153. , options: options
  154. }
  155. // BSON property
  156. Object.defineProperty(this, 'bson', {
  157. enumerable: true, get: function() {
  158. return self.s.server.bson;
  159. }
  160. });
  161. // Last ismaster
  162. Object.defineProperty(this, 'isMasterDoc', {
  163. enumerable:true, get: function() {
  164. return self.s.server.lastIsMaster();
  165. }
  166. });
  167. // Last ismaster
  168. Object.defineProperty(this, 'poolSize', {
  169. enumerable:true, get: function() { return self.s.server.connections().length; }
  170. });
  171. Object.defineProperty(this, 'autoReconnect', {
  172. enumerable:true, get: function() { return self.s.reconnect; }
  173. });
  174. Object.defineProperty(this, 'host', {
  175. enumerable:true, get: function() { return self.s.host; }
  176. });
  177. Object.defineProperty(this, 'port', {
  178. enumerable:true, get: function() { return self.s.port; }
  179. });
  180. }
  181. inherits(Server, EventEmitter);
  182. var define = Server.define = new Define('Server', Server, false);
  183. Server.prototype.parserType = function() {
  184. return this.s.server.parserType();
  185. }
  186. define.classMethod('parserType', {callback: false, promise:false, returns: [String]});
  187. // Connect
  188. Server.prototype.connect = function(db, _options, callback) {
  189. var self = this;
  190. if('function' === typeof _options) callback = _options, _options = {};
  191. if(_options == null) _options = {};
  192. if(!('function' === typeof callback)) callback = null;
  193. self.s.options = _options;
  194. // Update bufferMaxEntries
  195. self.s.storeOptions.bufferMaxEntries = db.bufferMaxEntries;
  196. // Error handler
  197. var connectErrorHandler = function(event) {
  198. return function(err) {
  199. // Remove all event handlers
  200. var events = ['timeout', 'error', 'close'];
  201. events.forEach(function(e) {
  202. self.s.server.removeListener(e, connectHandlers[e]);
  203. });
  204. self.s.server.removeListener('connect', connectErrorHandler);
  205. // Try to callback
  206. try {
  207. callback(err);
  208. } catch(err) {
  209. process.nextTick(function() { throw err; })
  210. }
  211. }
  212. }
  213. // Actual handler
  214. var errorHandler = function(event) {
  215. return function(err) {
  216. if(event != 'error') {
  217. self.emit(event, err);
  218. }
  219. }
  220. }
  221. // Error handler
  222. var reconnectHandler = function(err) {
  223. self.emit('reconnect', self);
  224. self.s.store.execute();
  225. }
  226. // Destroy called on topology, perform cleanup
  227. var destroyHandler = function() {
  228. self.s.store.flush();
  229. }
  230. // Connect handler
  231. var connectHandler = function() {
  232. // Clear out all the current handlers left over
  233. ["timeout", "error", "close"].forEach(function(e) {
  234. self.s.server.removeAllListeners(e);
  235. });
  236. // Set up listeners
  237. self.s.server.once('timeout', errorHandler('timeout'));
  238. self.s.server.once('error', errorHandler('error'));
  239. self.s.server.on('close', errorHandler('close'));
  240. // Only called on destroy
  241. self.s.server.once('destroy', destroyHandler);
  242. // Emit open event
  243. self.emit('open', null, self);
  244. // Return correctly
  245. try {
  246. callback(null, self);
  247. } catch(err) {
  248. console.log(err.stack)
  249. process.nextTick(function() { throw err; })
  250. }
  251. }
  252. // Set up listeners
  253. var connectHandlers = {
  254. timeout: connectErrorHandler('timeout'),
  255. error: connectErrorHandler('error'),
  256. close: connectErrorHandler('close')
  257. };
  258. // Add the event handlers
  259. self.s.server.once('timeout', connectHandlers.timeout);
  260. self.s.server.once('error', connectHandlers.error);
  261. self.s.server.once('close', connectHandlers.close);
  262. self.s.server.once('connect', connectHandler);
  263. // Reconnect server
  264. self.s.server.on('reconnect', reconnectHandler);
  265. // Start connection
  266. self.s.server.connect(_options);
  267. }
  268. // Server capabilities
  269. Server.prototype.capabilities = function() {
  270. if(this.s.sCapabilities) return this.s.sCapabilities;
  271. if(this.s.server.lastIsMaster() == null) return null;
  272. this.s.sCapabilities = new ServerCapabilities(this.s.server.lastIsMaster());
  273. return this.s.sCapabilities;
  274. }
  275. define.classMethod('capabilities', {callback: false, promise:false, returns: [ServerCapabilities]});
  276. // Command
  277. Server.prototype.command = function(ns, cmd, options, callback) {
  278. this.s.server.command(ns, cmd, options, callback);
  279. }
  280. define.classMethod('command', {callback: true, promise:false});
  281. // Insert
  282. Server.prototype.insert = function(ns, ops, options, callback) {
  283. this.s.server.insert(ns, ops, options, callback);
  284. }
  285. define.classMethod('insert', {callback: true, promise:false});
  286. // Update
  287. Server.prototype.update = function(ns, ops, options, callback) {
  288. this.s.server.update(ns, ops, options, callback);
  289. }
  290. define.classMethod('update', {callback: true, promise:false});
  291. // Remove
  292. Server.prototype.remove = function(ns, ops, options, callback) {
  293. this.s.server.remove(ns, ops, options, callback);
  294. }
  295. define.classMethod('remove', {callback: true, promise:false});
  296. // IsConnected
  297. Server.prototype.isConnected = function() {
  298. return this.s.server.isConnected();
  299. }
  300. Server.prototype.isDestroyed = function() {
  301. return this.s.server.isDestroyed();
  302. }
  303. define.classMethod('isConnected', {callback: false, promise:false, returns: [Boolean]});
  304. // Insert
  305. Server.prototype.cursor = function(ns, cmd, options) {
  306. options.disconnectHandler = this.s.store;
  307. return this.s.server.cursor(ns, cmd, options);
  308. }
  309. define.classMethod('cursor', {callback: false, promise:false, returns: [Cursor, AggregationCursor, CommandCursor]});
  310. Server.prototype.setBSONParserType = function(type) {
  311. return this.s.server.setBSONParserType(type);
  312. }
  313. Server.prototype.lastIsMaster = function() {
  314. return this.s.server.lastIsMaster();
  315. }
  316. Server.prototype.close = function(forceClosed) {
  317. this.s.server.destroy();
  318. // We need to wash out all stored processes
  319. if(forceClosed == true) {
  320. this.s.storeOptions.force = forceClosed;
  321. this.s.store.flush();
  322. }
  323. }
  324. define.classMethod('close', {callback: false, promise:false});
  325. Server.prototype.auth = function() {
  326. var args = Array.prototype.slice.call(arguments, 0);
  327. this.s.server.auth.apply(this.s.server, args);
  328. }
  329. define.classMethod('auth', {callback: true, promise:false});
  330. /**
  331. * All raw connections
  332. * @method
  333. * @return {array}
  334. */
  335. Server.prototype.connections = function() {
  336. return this.s.server.connections();
  337. }
  338. define.classMethod('connections', {callback: false, promise:false, returns:[Array]});
  339. /**
  340. * Server connect event
  341. *
  342. * @event Server#connect
  343. * @type {object}
  344. */
  345. /**
  346. * Server close event
  347. *
  348. * @event Server#close
  349. * @type {object}
  350. */
  351. /**
  352. * Server reconnect event
  353. *
  354. * @event Server#reconnect
  355. * @type {object}
  356. */
  357. /**
  358. * Server error event
  359. *
  360. * @event Server#error
  361. * @type {MongoError}
  362. */
  363. /**
  364. * Server timeout event
  365. *
  366. * @event Server#timeout
  367. * @type {object}
  368. */
  369. /**
  370. * Server parseError event
  371. *
  372. * @event Server#parseError
  373. * @type {object}
  374. */
  375. module.exports = Server;