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:



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/mongo/mongo_client.rb', line 127

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

  # Default maximum BSON object size
  @max_bson_size = Mongo::DEFAULT_MAX_BSON_SIZE

  # 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.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

def acceptable_latency
  @acceptable_latency
end

#authsObject (readonly)

Returns the value of attribute auths.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

def auths
  @auths
end

#connect_timeoutObject (readonly)

Returns the value of attribute connect_timeout.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

def connect_timeout
  @connect_timeout
end

#host_to_tryObject (readonly)

Returns the value of attribute host_to_try.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

def host_to_try
  @host_to_try
end

#loggerObject (readonly)

Returns the value of attribute logger.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

def logger
  @logger
end

#op_timeoutObject (readonly)

Returns the value of attribute op_timeout.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

def op_timeout
  @op_timeout
end

#pool_sizeObject (readonly)

Returns the value of attribute pool_size.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

def pool_size
  @pool_size
end

#pool_timeoutObject (readonly)

Returns the value of attribute pool_timeout.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

def pool_timeout
  @pool_timeout
end

#primaryObject (readonly)

Returns the value of attribute primary.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

def primary
  @primary
end

#primary_poolObject (readonly)

Returns the value of attribute primary_pool.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

def primary_pool
  @primary_pool
end

#readObject (readonly)

Returns the value of attribute read.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

def read
  @read
end

#sizeObject (readonly)

Returns the value of attribute size.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

def size
  @size
end

#socket_classObject (readonly)

Returns the value of attribute socket_class.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

def socket_class
  @socket_class
end

#tag_setsObject (readonly)

Returns the value of attribute tag_sets.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

def tag_sets
  @tag_sets
end

#write_concernObject (readonly)

Returns the value of attribute write_concern.



46
47
48
# File 'lib/mongo/mongo_client.rb', line 46

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://host1[,host2,…[,hostN]][/database]

  • opts

    Any of the options available for MongoClient.new

Returns:



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

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:



176
177
178
179
180
# File 'lib/mongo/mongo_client.rb', line 176

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:



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

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)


500
501
502
503
504
505
506
507
508
# File 'lib/mongo/mongo_client.rb', line 500

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.



284
285
286
287
288
289
290
291
292
# File 'lib/mongo/mongo_client.rb', line 284

def add_auth(db_name, username, password)
  remove_auth(db_name)
  auth = {}
  auth['db_name']  = db_name
  auth['username'] = username
  auth['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:



262
263
264
265
266
267
268
269
# File 'lib/mongo/mongo_client.rb', line 262

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



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

def authenticate_pools
  @primary_pool.authenticate_existing
end

#checkin(socket) ⇒ Object

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



560
561
562
563
564
# File 'lib/mongo/mongo_client.rb', line 560

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

#checkout_reader(mode = :primary, tag_sets = {}, acceptable_latency = 15) ⇒ Object

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



546
547
548
549
# File 'lib/mongo/mongo_client.rb', line 546

def checkout_reader(mode=:primary, tag_sets={}, acceptable_latency=15)
  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.



553
554
555
556
# File 'lib/mongo/mongo_client.rb', line 553

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.



311
312
313
314
# File 'lib/mongo/mongo_client.rb', line 311

def clear_auths
  @auths = []
  true
end

#closeObject

Close the connection to the database.



530
531
532
533
534
# File 'lib/mongo/mongo_client.rb', line 530

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

#connectObject

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:



458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
# File 'lib/mongo/mongo_client.rb', line 458

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'] || Mongo::DEFAULT_MAX_BSON_SIZE
    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)


490
491
492
# File 'lib/mongo/mongo_client.rb', line 490

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).



396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
# File 'lib/mongo/mongo_client.rb', line 396

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:



328
329
330
331
332
333
# File 'lib/mongo/mongo_client.rb', line 328

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)


338
339
340
# File 'lib/mongo/mongo_client.rb', line 338

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:



351
352
353
354
355
356
357
358
359
# File 'lib/mongo/mongo_client.rb', line 351

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.



384
385
386
# File 'lib/mongo/mongo_client.rb', line 384

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

#hostString

The host name used for this connection.

Returns:



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

def host
  @primary_pool.host
end

#host_portObject



226
227
228
# File 'lib/mongo/mongo_client.rb', line 226

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



234
235
236
237
238
239
# File 'lib/mongo/mongo_client.rb', line 234

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)


244
245
246
# File 'lib/mongo/mongo_client.rb', line 244

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

#logout_pools(db) ⇒ Object



320
321
322
# File 'lib/mongo/mongo_client.rb', line 320

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)


540
541
542
# File 'lib/mongo/mongo_client.rb', line 540

def max_bson_size
  @max_bson_size
end

#mongos?Boolean

Returns:

  • (Boolean)


447
448
449
# File 'lib/mongo/mongo_client.rb', line 447

def mongos?
  @mongos
end

#parse_init(host, port, opts) ⇒ Object



198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/mongo/mongo_client.rb', line 198

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) ⇒ Object



375
376
# File 'lib/mongo/mongo_client.rb', line 375

def pin_pool(pool)
end

#pingHash

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

Returns:



421
422
423
# File 'lib/mongo/mongo_client.rb', line 421

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

#portInteger

The port used for this connection.

Returns:

  • (Integer)


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

def port
  @primary_pool.port
end

#primary?Boolean

Ensures that the alias carries over to the overridden connect method when using the replica set or sharded clients.

Returns:

  • (Boolean)


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

def primary?; read_primary? end

#read_poolMongo::Pool

The socket pool that this connection reads from.

Returns:



525
526
527
# File 'lib/mongo/mongo_client.rb', line 525

def read_pool
  @primary_pool
end

#read_primary?Boolean

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)


514
515
516
# File 'lib/mongo/mongo_client.rb', line 514

def read_primary?
  @read_primary
end

#reconnectObject

Ensures that the alias carries over to the overridden connect method when using the replica set or sharded clients.



485
# File 'lib/mongo/mongo_client.rb', line 485

def reconnect; connect end

#refreshObject



372
373
# File 'lib/mongo/mongo_client.rb', line 372

def refresh
end

#remove_auth(db_name) ⇒ Boolean

Remove a saved authentication for this connection.

Parameters:

Returns:

  • (Boolean)


299
300
301
302
303
304
305
306
# File 'lib/mongo/mongo_client.rb', line 299

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

#server_infoHash

Get the build information for the current connection.

Returns:



428
429
430
# File 'lib/mongo/mongo_client.rb', line 428

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

#server_versionMongo::ServerVersion

Get the build version of the current server.

Returns:



436
437
438
# File 'lib/mongo/mongo_client.rb', line 436

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

#slave_ok?Boolean

Is it okay to connect to a slave?

Returns:

  • (Boolean)


443
444
445
# File 'lib/mongo/mongo_client.rb', line 443

def slave_ok?
  @slave_ok
end

#unlock!BSON::OrderedHash

Unlock a previously fsync-locked mongod process.

Returns:

  • (BSON::OrderedHash)

    command response



251
252
253
# File 'lib/mongo/mongo_client.rb', line 251

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

#unpin_pool(pool) ⇒ Object



378
379
# File 'lib/mongo/mongo_client.rb', line 378

def unpin_pool(pool)
end