Class: Mongo::MongoClient

Inherits:
Object show all
Includes:
Logging, Networking, WriteConcern
Defined in:
lib/mongo/mongo_client.rb

Overview

Instantiates and manages self.connections to MongoDB.

Direct Known Subclasses

Connection, MongoReplicaSetClient

Constant Summary collapse

Mutex =
::Mutex
ConditionVariable =
::ConditionVariable
DEFAULT_HOST =
'localhost'
DEFAULT_PORT =
27017
DEFAULT_DB_NAME =
'test'
GENERIC_OPTS =
[:ssl, :auths, :logger, :connect]
TIMEOUT_OPTS =
[:timeout, :op_timeout, :connect_timeout]
POOL_OPTS =
[:pool_size, :pool_timeout]
READ_PREFERENCE_OPTS =
[:read, :tag_sets, :secondary_acceptable_latency_ms]
WRITE_CONCERN_OPTS =
[:w, :j, :fsync, :wtimeout]
CLIENT_ONLY_OPTS =
[:slave_ok]

Constants included from Networking

Networking::RESPONSE_HEADER_SIZE, Networking::STANDARD_HEADER_SIZE

Instance Attribute Summary collapse

Attributes included from WriteConcern

#legacy_write_concern

Class Method Summary collapse

Instance Method Summary collapse

Methods included from WriteConcern

#get_write_concern, gle?, #write_concern_from_legacy

Methods included from Networking

#receive_message, #send_message, #send_message_with_gle

Methods included from Logging

#instrument, instrumenter, instrumenter=, #log, #write_logging_startup_message

Constructor Details

#initialize(*args) ⇒ MongoClient

Create a connection to single MongoDB instance.

If no args are provided, it will check ENV["MONGODB_URI"].

You may specify whether connection to slave is permitted. In all cases, the default host is “localhost” and the default port is 27017.

If you’re connecting to a replica set, you’ll need to use MongoReplicaSetClient.new instead.

Once connected to a replica set, you can find out which nodes are primary, secondary, and arbiters with the corresponding accessors: MongoClient#primary, MongoClient#secondaries, and MongoClient#arbiters. This is useful if your application needs to connect manually to nodes other than the primary.

Examples:

localhost, 27017 (or ENV["MONGODB_URI"] if available)

MongoClient.new

localhost, 27017

MongoClient.new("localhost")

localhost, 3000, max 5 self.connections, with max 5 seconds of wait time.

MongoClient.new("localhost", 3000, :pool_size => 5, :timeout => 5)

localhost, 3000, where this node may be a slave

MongoClient.new("localhost", 3000, :slave_ok => true)

Unix Domain Socket

MongoClient.new("/var/run/mongodb.sock")

Parameters:

  • host (String)
  • port (Integer)

    specify a port number here if only one host is being specified.

  • opts (Hash)

    a customizable set of options

Raises:

  • (ReplicaSetConnectionError)

    This is raised if a replica set name is specified and the driver fails to connect to a replica set with that name.

  • (MongoArgumentError)

    If called with no arguments and ENV["MONGODB_URI"] implies a replica set.

See Also:



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/mongo/mongo_client.rb', line 109

def initialize(*args)
  opts = args.last.is_a?(Hash) ? args.pop : {}
  @host, @port = parse_init(args[0], args[1], opts)

  # Lock for request ids.
  @id_lock = Mutex.new

  # Connection pool for primary node
  @primary      = nil
  @primary_pool = nil
  @mongos       = false

  # Not set for direct connection
  @tag_sets = []
  @acceptable_latency = 15

  check_opts(opts)
  setup(opts.dup)
end

Instance Attribute Details

#acceptable_latencyObject (readonly)

Returns the value of attribute acceptable_latency.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def acceptable_latency
  @acceptable_latency
end

#authsObject (readonly)

Returns the value of attribute auths.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def auths
  @auths
end

#connect_timeoutObject (readonly)

Returns the value of attribute connect_timeout.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def connect_timeout
  @connect_timeout
end

#host_to_tryObject (readonly)

Returns the value of attribute host_to_try.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def host_to_try
  @host_to_try
end

#loggerObject (readonly)

Returns the value of attribute logger.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def logger
  @logger
end

#op_timeoutObject (readonly)

Returns the value of attribute op_timeout.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def op_timeout
  @op_timeout
end

#pool_sizeObject (readonly)

Returns the value of attribute pool_size.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def pool_size
  @pool_size
end

#pool_timeoutObject (readonly)

Returns the value of attribute pool_timeout.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def pool_timeout
  @pool_timeout
end

#primaryObject (readonly)

Returns the value of attribute primary.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def primary
  @primary
end

#primary_poolObject (readonly)

Returns the value of attribute primary_pool.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def primary_pool
  @primary_pool
end

#readObject (readonly)

Returns the value of attribute read.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def read
  @read
end

#sizeObject (readonly)

Returns the value of attribute size.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def size
  @size
end

#socket_classObject (readonly)

Returns the value of attribute socket_class.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def socket_class
  @socket_class
end

#tag_setsObject (readonly)

Returns the value of attribute tag_sets.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def tag_sets
  @tag_sets
end

#write_concernObject (readonly)

Returns the value of attribute write_concern.



28
29
30
# File 'lib/mongo/mongo_client.rb', line 28

def write_concern
  @write_concern
end

Class Method Details

.from_uri(uri = , extra_opts = {}) ⇒ Mongo::MongoClient, Mongo::MongoReplicaSetClient

Initialize a connection to MongoDB using the MongoDB URI spec.

Since MongoClient.new cannot be used with any ENV["MONGODB_URI"] that has multiple hosts (implying a replicaset), you may use this when the type of your connection varies by environment and should be determined solely from ENV["MONGODB_URI"].

Parameters:

  • uri (String) (defaults to: )

    A string of the format mongodb://[username:password@]host1[,host2,…[,hostN]][/database]

  • opts

    Any of the options available for MongoClient.new

Returns:



172
173
174
175
# File 'lib/mongo/mongo_client.rb', line 172

def self.from_uri(uri = ENV['MONGODB_URI'], extra_opts={})
  parser = URIParser.new uri
  parser.connection(extra_opts)
end

.multi(nodes, opts = {}) ⇒ Mongo::MongoClient

Deprecated.

DEPRECATED

Initialize a connection to a MongoDB replica set using an array of seed nodes.

The seed nodes specified will be used on the initial connection to the replica set, but note that this list of nodes will be replaced by the list of canonical nodes returned by running the is_master command on the replica set.

Examples:

Mongo::MongoClient.multi([["db1.example.com", 27017], ["db2.example.com", 27017]])

This connection will read from a random secondary node.

Mongo::MongoClient.multi([["db1.example.com", 27017], ["db2.example.com", 27017], ["db3.example.com", 27017]],
                :read_secondary => true)

Parameters:

  • nodes (Array)

    An array of arrays, each of which specifies a host and port.

  • opts (Hash) (defaults to: {})

    Any of the available options that can be passed to MongoClient.new.

Options Hash (opts):

  • :rs_name (String) — default: nil

    The name of the replica set to connect to. An exception will be raised if unable to connect to a replica set with this name.

  • :read_secondary (Boolean) — default: false

    When true, this connection object will pick a random slave to send reads to.

Returns:



155
156
157
158
159
# File 'lib/mongo/mongo_client.rb', line 155

def self.multi(nodes, opts={})
  warn "MongoClient.multi is now deprecated and will be removed in v2.0. Please use MongoReplicaSetClient.new instead."

  MongoReplicaSetClient.new(nodes, opts)
end

Instance Method Details

#[](db_name) ⇒ Mongo::DB

Shortcut for returning a database. Use DB#db to accept options.

Parameters:

  • db_name (String)

    a valid database name.

Returns:



347
348
349
# File 'lib/mongo/mongo_client.rb', line 347

def [](db_name)
  DB.new(db_name, self)
end

#active?Boolean

Determine if the connection is active. In a normal case the server_info operation will be performed without issues, but if the connection was dropped by the server or for some reason the sockets are unsynchronized, a ConnectionFailure will be raised and the return will be false.

Returns:

  • (Boolean)


481
482
483
484
485
486
487
488
489
# File 'lib/mongo/mongo_client.rb', line 481

def active?
  return false unless connected?

  ping
  true

  rescue ConnectionFailure
  false
end

#add_auth(db_name, username, password) ⇒ Hash

Save an authentication to this connection. When connecting, the connection will attempt to re-authenticate on every db specified in the list of auths. This method is called automatically by DB#authenticate.

Note: this method will not actually issue an authentication command. To do that, either run MongoClient#apply_saved_authentication or DB#authenticate.

Parameters:

Returns:

  • (Hash)

    a hash representing the authentication just added.



263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/mongo/mongo_client.rb', line 263

def add_auth(db_name, username, password)
  if @auths.any? {|a| a[:db_name] == db_name}
    raise MongoArgumentError, "Cannot apply multiple authentications to database '#{db_name}'"
  end

  auth = {
    :db_name  => db_name,
    :username => username,
    :password => password
  }
  @auths << auth
  auth
end

#apply_saved_authentication(opts = {}) ⇒ Boolean

Apply each of the saved database authentications.

Returns:

  • (Boolean)

    returns true if authentications exist and succeeds, false if none exists.

Raises:



241
242
243
244
245
246
247
248
# File 'lib/mongo/mongo_client.rb', line 241

def apply_saved_authentication(opts={})
  return false if @auths.empty?
  @auths.each do |auth|
    self[auth[:db_name]].issue_authentication(auth[:username], auth[:password], false,
      :socket => opts[:socket])
  end
  true
end

#authenticate_poolsObject



295
296
297
# File 'lib/mongo/mongo_client.rb', line 295

def authenticate_pools
  @primary_pool.authenticate_existing
end

#checkin(socket) ⇒ Object

Check a socket back into its pool. Note: this is overridden in MongoReplicaSetClient.



542
543
544
545
546
# File 'lib/mongo/mongo_client.rb', line 542

def checkin(socket)
  if @primary_pool && socket && socket.pool
    socket.checkin
  end
end

#checkout_reader(read_preference) ⇒ Object

Checkout a socket for reading (i.e., a secondary node). Note: this is overridden in MongoReplicaSetClient.



528
529
530
531
# File 'lib/mongo/mongo_client.rb', line 528

def checkout_reader(read_preference)
  connect unless connected?
  @primary_pool.checkout
end

#checkout_writerObject

Checkout a socket for writing (i.e., a primary node). Note: this is overridden in MongoReplicaSetClient.



535
536
537
538
# File 'lib/mongo/mongo_client.rb', line 535

def checkout_writer
  connect unless connected?
  @primary_pool.checkout
end

#clear_authstrue

Remove all authentication information stored in this connection.

Returns:

  • (true)

    this operation return true because it always succeeds.



290
291
292
293
# File 'lib/mongo/mongo_client.rb', line 290

def clear_auths
  @auths = []
  true
end

#closeObject

Close the connection to the database.



508
509
510
511
512
# File 'lib/mongo/mongo_client.rb', line 508

def close
  @primary_pool.close if @primary_pool
  @primary_pool = nil
  @primary = nil
end

#connectObject Also known as: reconnect

Create a new socket and attempt to connect to master. If successful, sets host and port to master and returns the socket.

If connecting to a replica set, this method will replace the initially-provided seed list with any nodes known to the set.

Raises:



441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
# File 'lib/mongo/mongo_client.rb', line 441

def connect
  close

  config = check_is_master(host_port)

  if config
    if config['ismaster'] == 1 || config['ismaster'] == true
      @read_primary = true
    elsif @slave_ok
      @read_primary = false
    end

    if config.has_key?('msg') && config['msg'] == 'isdbgrid'
      @mongos = true
    end

    @max_bson_size = config['maxBsonObjectSize']
    @max_message_size = config['maxMessageSizeBytes']
    set_primary(host_port)
  end

  if !connected?
    raise ConnectionFailure, "Failed to connect to a master node at #{host_port.join(":")}"
  end
end

#connected?Boolean

It’s possible that we defined connected as all nodes being connected??? NOTE: Do check if this needs to be more stringent. Probably not since if any node raises a connection failure, all nodes will be closed.

Returns:

  • (Boolean)


471
472
473
# File 'lib/mongo/mongo_client.rb', line 471

def connected?
  @primary_pool && !@primary_pool.closed?
end

#copy_database(from, to, from_host = DEFAULT_HOST, username = nil, password = nil) ⇒ Object

Copy the database from to to on localhost. The from database is assumed to be on localhost, but an alternate host can be specified.

Parameters:

  • from (String)

    name of the database to copy from.

  • to (String)

    name of the database to copy to.

  • from_host (String) (defaults to: DEFAULT_HOST)

    host of the ‘from’ database.

  • username (String) (defaults to: nil)

    username for authentication against from_db (>=1.3.x).

  • password (String) (defaults to: nil)

    password for authentication against from_db (>=1.3.x).



379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/mongo/mongo_client.rb', line 379

def copy_database(from, to, from_host=DEFAULT_HOST, username=nil, password=nil)
  oh = BSON::OrderedHash.new
  oh[:copydb]   = 1
  oh[:fromhost] = from_host
  oh[:fromdb]   = from
  oh[:todb]     = to
  if username || password
    unless username && password
      raise MongoArgumentError, "Both username and password must be supplied for authentication."
    end
    nonce_cmd = BSON::OrderedHash.new
    nonce_cmd[:copydbgetnonce] = 1
    nonce_cmd[:fromhost] = from_host
    result = self["admin"].command(nonce_cmd)
    oh[:nonce] = result["nonce"]
    oh[:username] = username
    oh[:key] = Mongo::Support.auth_key(username, password, oh[:nonce])
  end
  self["admin"].command(oh)
end

#database_infoHash

Return a hash with all database names and their respective sizes on disk.

Returns:



307
308
309
310
311
312
# File 'lib/mongo/mongo_client.rb', line 307

def database_info
  doc = self['admin'].command({:listDatabases => 1})
  doc['databases'].each_with_object({}) do |db, info|
    info[db['name']] = db['sizeOnDisk'].to_i
  end
end

#database_namesArray

Return an array of database names.

Returns:

  • (Array)


317
318
319
# File 'lib/mongo/mongo_client.rb', line 317

def database_names
  database_info.keys
end

#db(db_name = nil, opts = {}) ⇒ Mongo::DB

Return a database with the given name. See DB#new for valid options hash parameters.

Parameters:

  • db_name (String) (defaults to: nil)

    a valid database name.

  • opts (Hash) (defaults to: {})

    options to be passed to the DB constructor.

Returns:



330
331
332
333
334
335
336
337
338
# File 'lib/mongo/mongo_client.rb', line 330

def db(db_name=nil, opts={})
  if !db_name && uri = ENV['MONGODB_URI']
    db_name = uri[%r{/([^/\?]+)(\?|$)}, 1]
  end

  db_name ||= DEFAULT_DB_NAME

  DB.new(db_name, self, opts)
end

#drop_database(name) ⇒ Object

Drop a database.

Parameters:

  • name (String)

    name of an existing database.



367
368
369
# File 'lib/mongo/mongo_client.rb', line 367

def drop_database(name)
  self[name].command(:dropDatabase => 1)
end

#hostString

The host name used for this connection.

Returns:



194
195
196
# File 'lib/mongo/mongo_client.rb', line 194

def host
  @primary_pool.host
end

#host_portObject



205
206
207
# File 'lib/mongo/mongo_client.rb', line 205

def host_port
  [@host, @port]
end

#lock!BSON::OrderedHash

Fsync, then lock the mongod process against writes. Use this to get the datafiles in a state safe for snapshotting, backing up, etc.

Returns:

  • (BSON::OrderedHash)

    the command response



213
214
215
216
217
218
# File 'lib/mongo/mongo_client.rb', line 213

def lock!
  cmd = BSON::OrderedHash.new
  cmd[:fsync] = 1
  cmd[:lock]  = true
  self['admin'].command(cmd)
end

#locked?Boolean

Is this database locked against writes?

Returns:

  • (Boolean)


223
224
225
# File 'lib/mongo/mongo_client.rb', line 223

def locked?
  [1, true].include? self['admin']['$cmd.sys.inprog'].find_one['fsyncLock']
end

#logout_pools(db) ⇒ Object



299
300
301
# File 'lib/mongo/mongo_client.rb', line 299

def logout_pools(db)
  @primary_pool.logout_existing(db)
end

#max_bson_sizeInteger

Returns the maximum BSON object size as returned by the core server. Use the 4MB default when the server doesn’t report this.

Returns:

  • (Integer)


518
519
520
# File 'lib/mongo/mongo_client.rb', line 518

def max_bson_size
  @max_bson_size || DEFAULT_MAX_BSON_SIZE
end

#max_message_sizeObject



522
523
524
# File 'lib/mongo/mongo_client.rb', line 522

def max_message_size
  @max_message_size || DEFAULT_MAX_MESSAGE_SIZE
end

#mongos?Boolean

Returns:

  • (Boolean)


430
431
432
# File 'lib/mongo/mongo_client.rb', line 430

def mongos?
  @mongos
end

#parse_init(host, port, opts) ⇒ Object



177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/mongo/mongo_client.rb', line 177

def parse_init(host, port, opts)
  if host.nil? && port.nil? && ENV.has_key?('MONGODB_URI')
    parser = URIParser.new(ENV['MONGODB_URI'])
    if parser.replicaset?
      raise MongoArgumentError,
        "ENV['MONGODB_URI'] implies a replica set."
    end
    opts.merge! parser.connection_options
    [parser.host, parser.port]
  else
    [host || DEFAULT_HOST, port || DEFAULT_PORT]
  end
end

#pin_pool(pool, read_prefs) ⇒ Object



358
359
# File 'lib/mongo/mongo_client.rb', line 358

def pin_pool(pool, read_prefs)
end

#pingHash

Checks if a server is alive. This command will return immediately even if the server is in a lock.

Returns:



404
405
406
# File 'lib/mongo/mongo_client.rb', line 404

def ping
  self["admin"].command({:ping => 1})
end

#pinned_poolObject



354
355
356
# File 'lib/mongo/mongo_client.rb', line 354

def pinned_pool
  @primary_pool
end

#portInteger

The port used for this connection.

Returns:

  • (Integer)


201
202
203
# File 'lib/mongo/mongo_client.rb', line 201

def port
  @primary_pool.port
end

#read_poolMongo::Pool

The socket pool that this connection reads from.

Returns:



503
504
505
# File 'lib/mongo/mongo_client.rb', line 503

def read_pool
  @primary_pool
end

#read_primary?Boolean Also known as: primary?

Determine whether we’re reading from a primary node. If false, this connection connects to a secondary node and @slave_ok is true.

Returns:

  • (Boolean)


495
496
497
# File 'lib/mongo/mongo_client.rb', line 495

def read_primary?
  @read_primary
end

#refreshObject



351
352
# File 'lib/mongo/mongo_client.rb', line 351

def refresh
end

#remove_auth(db_name) ⇒ Boolean

Remove a saved authentication for this connection.

Parameters:

Returns:

  • (Boolean)


282
283
284
285
# File 'lib/mongo/mongo_client.rb', line 282

def remove_auth(db_name)
  return unless @auths
  @auths.reject! { |a| a[:db_name] == db_name } ? true : false
end

#server_infoHash

Get the build information for the current connection.

Returns:



411
412
413
# File 'lib/mongo/mongo_client.rb', line 411

def server_info
  self["admin"].command({:buildinfo => 1})
end

#server_versionMongo::ServerVersion

Get the build version of the current server.

Returns:



419
420
421
# File 'lib/mongo/mongo_client.rb', line 419

def server_version
  ServerVersion.new(server_info["version"])
end

#slave_ok?Boolean

Is it okay to connect to a slave?

Returns:

  • (Boolean)


426
427
428
# File 'lib/mongo/mongo_client.rb', line 426

def slave_ok?
  @slave_ok
end

#unlock!BSON::OrderedHash

Unlock a previously fsync-locked mongod process.

Returns:

  • (BSON::OrderedHash)

    command response



230
231
232
# File 'lib/mongo/mongo_client.rb', line 230

def unlock!
  self['admin']['$cmd.sys.unlock'].find_one
end

#unpin_poolObject



361
362
# File 'lib/mongo/mongo_client.rb', line 361

def unpin_pool
end