2010-05-07 19:33:27 +00:00
# encoding: UTF-8
2008-12-17 16:49:06 +00:00
# --
2011-01-17 17:26:32 +00:00
# Copyright (C) 2008-2011 10gen Inc.
2008-11-22 01:00:51 +00:00
#
2009-02-15 13:24:14 +00:00
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
2008-11-22 01:00:51 +00:00
#
2009-02-15 13:24:14 +00:00
# http://www.apache.org/licenses/LICENSE-2.0
2008-11-22 01:00:51 +00:00
#
2009-02-15 13:24:14 +00:00
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
2008-12-17 16:49:06 +00:00
# ++
2008-11-22 01:00:51 +00:00
2009-11-23 20:20:05 +00:00
require 'set'
require 'socket'
2009-12-28 18:05:45 +00:00
require 'thread'
2009-08-20 14:50:48 +00:00
module Mongo
2011-11-03 22:37:23 +00:00
# Instantiates and manages self.connections to MongoDB.
2009-08-20 22:48:09 +00:00
class Connection
2011-09-07 21:14:53 +00:00
include Mongo :: Logging
2011-11-02 22:00:52 +00:00
include Mongo :: Networking
2011-09-07 21:14:53 +00:00
2012-04-03 19:40:38 +00:00
TCPSocket = Mongo :: TCPSocket
2010-08-15 06:04:12 +00:00
Mutex = :: Mutex
ConditionVariable = :: ConditionVariable
2009-08-20 14:50:48 +00:00
2011-10-13 21:58:20 +00:00
Thread . abort_on_exception = true
2012-05-18 16:17:21 +00:00
DEFAULT_HOST = 'localhost'
2009-08-20 14:50:48 +00:00
DEFAULT_PORT = 27017
2012-02-27 19:06:07 +00:00
GENERIC_OPTS = [ :ssl , :auths , :pool_size , :pool_timeout , :timeout , :op_timeout , :connect_timeout , :safe , :logger , :connect ]
CONNECTION_OPTS = [ :slave_ok ]
2009-11-23 20:20:05 +00:00
2011-11-03 22:37:23 +00:00
mongo_thread_local_accessor :connections
2012-02-16 19:00:52 +00:00
attr_reader :logger , :size , :auths , :primary , :safe , :host_to_try ,
2011-11-02 19:21:46 +00:00
:pool_size , :connect_timeout , :pool_timeout ,
2012-01-17 23:45:09 +00:00
:primary_pool , :socket_class , :op_timeout
2009-11-23 20:20:05 +00:00
2010-11-24 18:49:34 +00:00
# Create a connection to single MongoDB instance.
2009-08-20 14:50:48 +00:00
#
2012-05-18 16:17:21 +00:00
# If no args are provided, it will check <code>ENV["MONGODB_URI"]</code>.
#
2010-11-24 18:49:34 +00:00
# You may specify whether connection to slave is permitted.
2010-01-07 17:37:53 +00:00
# In all cases, the default host is "localhost" and the default port is 27017.
2009-08-20 14:50:48 +00:00
#
2010-12-15 19:15:49 +00:00
# If you're connecting to a replica set, you'll need to use ReplSetConnection.new instead.
2010-01-08 20:43:13 +00:00
#
2010-08-24 15:20:54 +00:00
# Once connected to a replica set, you can find out which nodes are primary, secondary, and
# arbiters with the corresponding accessors: Connection#primary, Connection#secondaries, and
# Connection#arbiters. This is useful if your application needs to connect manually to nodes other
# than the primary.
#
2012-01-17 23:45:09 +00:00
# @param [String, Hash] host
2010-04-07 21:10:28 +00:00
# @param [Integer] port specify a port number here if only one host is being specified.
2009-08-20 14:50:48 +00:00
#
2011-01-05 16:30:20 +00:00
# @option opts [Boolean, Hash] :safe (false) Set the default safe-mode options
2010-11-03 21:36:08 +00:00
# propogated to DB objects instantiated off of this Connection. This
# default can be overridden upon instantiation of any DB by explicity setting a :safe value
# on initialization.
2011-01-05 16:30:20 +00:00
# @option opts [Boolean] :slave_ok (false) Must be set to +true+ when connecting
2010-01-07 17:37:53 +00:00
# to a single, slave node.
2011-01-31 20:51:39 +00:00
# @option opts [Logger, #debug] :logger (nil) A Logger instance for debugging driver ops. Note that
# logging negatively impacts performance; therefore, it should not be used for high-performance apps.
2011-11-03 22:37:23 +00:00
# @option opts [Integer] :pool_size (1) The maximum number of socket self.connections allowed per
2010-11-24 18:49:34 +00:00
# connection pool. Note: this setting is relevant only for multi-threaded applications.
2012-04-03 19:40:38 +00:00
# @option opts [Float] :timeout (5.0) When all of the self.connections a pool are checked out,
2010-01-07 17:37:53 +00:00
# this is the number of seconds to wait for a new connection to be released before throwing an exception.
2010-11-24 18:49:34 +00:00
# Note: this setting is relevant only for multi-threaded applications (which in Ruby are rare).
2011-03-28 15:09:27 +00:00
# @option opts [Float] :op_timeout (nil) The number of seconds to wait for a read operation to time out.
# Disabled by default.
2011-06-15 18:20:11 +00:00
# @option opts [Float] :connect_timeout (nil) The number of seconds to wait before timing out a
# connection attempt.
2011-08-26 21:35:40 +00:00
# @option opts [Boolean] :ssl (false) If true, create the connection to the server using SSL.
2009-11-23 21:03:33 +00:00
#
2012-05-18 16:17:21 +00:00
# @example localhost, 27017 (or <code>ENV["MONGODB_URI"]</code> if available)
2012-05-02 21:43:54 +00:00
# Mongo::Connection.new
2009-12-16 19:03:15 +00:00
#
2010-01-07 17:37:53 +00:00
# @example localhost, 27017
2012-05-02 21:43:54 +00:00
# Mongo::Connection.new("localhost")
2009-08-20 14:50:48 +00:00
#
2011-11-03 22:37:23 +00:00
# @example localhost, 3000, max 5 self.connections, with max 5 seconds of wait time.
2012-05-02 21:43:54 +00:00
# Mongo::Connection.new("localhost", 3000, :pool_size => 5, :timeout => 5)
2009-08-20 14:50:48 +00:00
#
2010-01-07 17:37:53 +00:00
# @example localhost, 3000, where this node may be a slave
2012-05-02 21:43:54 +00:00
# Mongo::Connection.new("localhost", 3000, :slave_ok => true)
2009-08-20 14:50:48 +00:00
#
2010-11-24 18:49:34 +00:00
# @see http://api.mongodb.org/ruby/current/file.REPLICA_SETS.html Replica sets in Ruby
2010-02-08 17:12:18 +00:00
#
2010-11-03 19:12:15 +00:00
# @raise [ReplicaSetConnectionError] This is raised if a replica set name is specified and the
# driver fails to connect to a replica set with that name.
#
2012-05-18 16:17:21 +00:00
# @raise [MongoArgumentError] If called with no arguments and <code>ENV["MONGODB_URI"]</code> implies a replica set.
#
2011-11-03 22:37:23 +00:00
# @core self.connections
2011-01-05 16:30:20 +00:00
def initialize ( host = nil , port = nil , opts = { } )
2012-05-18 16:17:21 +00:00
if host . nil? and ENV . has_key? ( 'MONGODB_URI' )
parser = URIParser . new ENV [ 'MONGODB_URI' ] , opts
if parser . replicaset?
raise MongoArgumentError , " Mongo::Connection.new called with no arguments, but ENV['MONGODB_URI'] implies a replica set. "
end
opts = parser . connection_options
@host_to_try = [ parser . host , parser . port ]
elsif host . is_a? ( String )
@host_to_try = [ host , ( port || DEFAULT_PORT ) . to_i ]
else
@host_to_try = [ DEFAULT_HOST , DEFAULT_PORT ]
end
2009-11-23 20:20:05 +00:00
# Host and port of current master.
@host = @port = nil
2012-02-27 19:06:07 +00:00
# Default maximum BSON object size
@max_bson_size = Mongo :: DEFAULT_MAX_BSON_SIZE
# Lock for request ids.
@id_lock = Mutex . new
# Connection pool for primay node
@primary = nil
@primary_pool = nil
2009-12-16 19:03:15 +00:00
2012-02-27 19:06:07 +00:00
check_opts ( opts )
2011-01-05 16:30:20 +00:00
setup ( opts )
2010-02-17 20:15:07 +00:00
end
2010-12-10 21:00:35 +00:00
# DEPRECATED
#
2010-07-26 22:05:23 +00:00
# Initialize a connection to a MongoDB replica set using an array of seed nodes.
2010-07-19 16:07:46 +00:00
#
2010-11-24 18:49:34 +00:00
# The seed nodes specified will be used on the initial connection to the replica set, but note
# that this list of nodes will be replced by the list of canonical nodes returned by running the
# is_master command on the replica set.
2010-07-26 22:05:23 +00:00
#
# @param nodes [Array] An array of arrays, each of which specifies a host and port.
2010-11-24 18:49:34 +00:00
# @param opts [Hash] Any of the available options that can be passed to Connection.new.
2010-07-19 16:07:46 +00:00
#
2011-01-05 16:30:20 +00:00
# @option opts [String] :rs_name (nil) The name of the replica set to connect to. An exception will be
2010-11-24 18:49:34 +00:00
# raised if unable to connect to a replica set with this name.
2011-01-05 16:30:20 +00:00
# @option opts [Boolean] :read_secondary (false) When true, this connection object will pick a random slave
2010-11-24 18:49:34 +00:00
# to send reads to.
2010-07-19 16:07:46 +00:00
#
# @example
2012-05-02 21:43:54 +00:00
# Mongo::Connection.multi([["db1.example.com", 27017], ["db2.example.com", 27017]])
2010-11-24 18:49:34 +00:00
#
# @example This connection will read from a random secondary node.
2012-05-02 21:43:54 +00:00
# Mongo::Connection.multi([["db1.example.com", 27017], ["db2.example.com", 27017], ["db3.example.com", 27017]],
2010-11-24 18:49:34 +00:00
# :read_secondary => true)
2010-07-19 16:07:46 +00:00
#
# @return [Mongo::Connection]
2010-12-10 21:00:35 +00:00
#
# @deprecated
2010-07-19 16:07:46 +00:00
def self . multi ( nodes , opts = { } )
2011-09-06 18:30:00 +00:00
warn " Connection.multi is now deprecated and will be removed in v2.0. Please use ReplSetConnection.new instead. "
2010-11-16 20:43:59 +00:00
2012-05-18 16:17:21 +00:00
ReplSetConnection . new ( * ( nodes + [ opts ] ) )
2010-07-19 16:07:46 +00:00
end
2012-06-04 15:23:21 +00:00
# Initialize a connection to MongoDB using the MongoDB URI spec.
#
# Since Connection.new cannot be used with any <code>ENV["MONGODB_URI"]</code> 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 <code>ENV["MONGODB_URI"]</code>.
2010-02-17 20:15:07 +00:00
#
# @param uri [String]
# A string of the format mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/database]
#
# @param opts Any of the options available for Connection.new
#
2010-12-30 20:40:50 +00:00
# @return [Mongo::Connection, Mongo::ReplSetConnection]
2012-06-04 15:23:21 +00:00
def self . from_uri ( uri = ENV [ 'MONGODB_URI' ] , extra_opts = { } )
2012-05-18 16:17:21 +00:00
parser = URIParser . new uri , extra_opts
parser . connection
2009-10-07 23:39:36 +00:00
end
2009-01-16 14:52:31 +00:00
2011-03-23 20:34:42 +00:00
# The host name used for this connection.
#
# @return [String]
def host
@primary_pool . host
end
# The port used for this connection.
#
# @return [Integer]
def port
@primary_pool . port
end
2010-09-28 16:15:45 +00:00
# Fsync, then lock the mongod process against writes. Use this to get
# the datafiles in a state safe for snapshotting, backing up, etc.
#
# @return [BSON::OrderedHash] the command response
def lock!
cmd = BSON :: OrderedHash . new
cmd [ :fsync ] = 1
cmd [ :lock ] = true
self [ 'admin' ] . command ( cmd )
end
2010-10-04 15:38:20 +00:00
# Is this database locked against writes?
#
# @return [Boolean]
def locked?
self [ 'admin' ] [ '$cmd.sys.inprog' ] . find_one [ 'fsyncLock' ] == 1
end
2010-09-28 16:15:45 +00:00
# Unlock a previously fsync-locked mongod process.
#
# @return [BSON::OrderedHash] command response
def unlock!
self [ 'admin' ] [ '$cmd.sys.unlock' ] . find_one
end
2010-02-25 19:58:32 +00:00
# Apply each of the saved database authentications.
#
# @return [Boolean] returns true if authentications exist and succeeed, false
# if none exists.
#
# @raise [AuthenticationError] raises an exception if any one
# authentication fails.
2011-01-31 19:47:05 +00:00
def apply_saved_authentication ( opts = { } )
2010-02-25 19:58:32 +00:00
return false if @auths . empty?
@auths . each do | auth |
2011-01-31 19:47:05 +00:00
self [ auth [ 'db_name' ] ] . issue_authentication ( auth [ 'username' ] , auth [ 'password' ] , false ,
:socket = > opts [ :socket ] )
2010-02-25 19:58:32 +00:00
end
true
end
# Save an authentication to this connection. When connecting,
# the connection will attempt to re-authenticate on every db
2010-03-01 15:39:50 +00:00
# specificed in the list of auths. This method is called automatically
# by DB#authenticate.
2010-02-25 19:58:32 +00:00
#
2010-05-04 20:06:06 +00:00
# Note: this method will not actually issue an authentication command. To do that,
# either run Connection#apply_saved_authentication or DB#authenticate.
#
2010-02-25 19:58:32 +00:00
# @param [String] db_name
# @param [String] username
# @param [String] password
#
# @return [Hash] a hash representing the authentication just added.
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
# Remove a saved authentication for this connection.
#
# @param [String] db_name
#
# @return [Boolean]
def remove_auth ( db_name )
return unless @auths
if @auths . reject! { | a | a [ 'db_name' ] == db_name }
true
else
false
end
end
# Remove all authenication information stored in this connection.
#
# @return [true] this operation return true because it always succeeds.
def clear_auths
@auths = [ ]
true
end
2011-01-31 19:47:05 +00:00
def authenticate_pools
@primary_pool . authenticate_existing
end
def logout_pools ( db )
@primary_pool . logout_existing ( db )
end
2010-01-07 17:37:53 +00:00
# Return a hash with all database names
# and their respective sizes on disk.
#
# @return [Hash]
2009-08-20 14:50:48 +00:00
def database_info
2010-05-18 20:17:17 +00:00
doc = self [ 'admin' ] . command ( { :listDatabases = > 1 } )
2010-09-04 13:14:46 +00:00
doc [ 'databases' ] . each_with_object ( { } ) do | db , info |
info [ db [ 'name' ] ] = db [ 'sizeOnDisk' ] . to_i
2009-11-23 20:20:05 +00:00
end
2009-08-20 14:50:48 +00:00
end
2008-11-22 01:00:51 +00:00
2010-01-07 17:37:53 +00:00
# Return an array of database names.
#
# @return [Array]
2009-08-20 14:50:48 +00:00
def database_names
database_info . keys
end
2008-11-22 01:00:51 +00:00
2010-01-07 17:37:53 +00:00
# Return a database with the given name.
# See DB#new for valid options hash parameters.
#
# @param [String] db_name a valid database name.
2011-01-05 16:30:20 +00:00
# @param [Hash] opts options to be passed to the DB constructor.
2010-01-07 17:37:53 +00:00
#
# @return [Mongo::DB]
2010-02-08 17:12:18 +00:00
#
# @core databases db-instance_method
2011-01-05 16:30:20 +00:00
def db ( db_name , opts = { } )
DB . new ( db_name , self , opts )
2009-11-23 20:20:05 +00:00
end
2010-01-07 17:37:53 +00:00
# Shortcut for returning a database. Use DB#db to accept options.
#
# @param [String] db_name a valid database name.
#
# @return [Mongo::DB]
2010-02-08 17:12:18 +00:00
#
# @core databases []-instance_method
2009-11-23 20:20:05 +00:00
def [] ( db_name )
2011-08-29 21:49:58 +00:00
DB . new ( db_name , self )
2009-11-23 20:20:05 +00:00
end
2010-01-07 17:37:53 +00:00
# Drop a database.
#
# @param [String] name name of an existing database.
2009-08-20 14:50:48 +00:00
def drop_database ( name )
2009-11-23 20:20:05 +00:00
self [ name ] . command ( :dropDatabase = > 1 )
2009-08-20 14:50:48 +00:00
end
2009-01-23 18:30:59 +00:00
2010-03-16 17:56:30 +00:00
# Copy the database +from+ to +to+ on localhost. The +from+ database is
# assumed to be on localhost, but an alternate host can be specified.
2010-01-07 17:37:53 +00:00
#
# @param [String] from name of the database to copy from.
# @param [String] to name of the database to copy to.
# @param [String] from_host host of the 'from' database.
2010-03-16 17:56:30 +00:00
# @param [String] username username for authentication against from_db (>=1.3.x).
# @param [String] password password for authentication against from_db (>=1.3.x).
2012-05-18 16:17:21 +00:00
def copy_database ( from , to , from_host = DEFAULT_HOST , username = nil , password = nil )
2010-05-07 01:25:18 +00:00
oh = BSON :: OrderedHash . new
2009-11-04 16:57:03 +00:00
oh [ :copydb ] = 1
2010-01-07 17:37:53 +00:00
oh [ :fromhost ] = from_host
2009-11-04 16:57:03 +00:00
oh [ :fromdb ] = from
oh [ :todb ] = to
2010-03-16 17:56:30 +00:00
if username || password
unless username && password
raise MongoArgumentError , " Both username and password must be supplied for authentication. "
end
2010-05-07 01:25:18 +00:00
nonce_cmd = BSON :: OrderedHash . new
2010-03-16 17:56:30 +00:00
nonce_cmd [ :copydbgetnonce ] = 1
nonce_cmd [ :fromhost ] = from_host
2010-05-18 20:17:17 +00:00
result = self [ " admin " ] . command ( nonce_cmd )
2010-03-16 17:56:30 +00:00
oh [ :nonce ] = result [ " nonce " ]
oh [ :username ] = username
oh [ :key ] = Mongo :: Support . auth_key ( username , password , oh [ :nonce ] )
end
2010-05-18 20:17:17 +00:00
self [ " admin " ] . command ( oh )
2009-11-23 20:20:05 +00:00
end
2012-02-03 16:29:30 +00:00
# Checks if a server is alive. This command will return immediately
2011-03-03 19:22:32 +00:00
# even if the server is in a lock.
#
# @return [Hash]
def ping
self [ " admin " ] . command ( { :ping = > 1 } )
end
# Get the build information for the current connection.
2010-01-07 17:37:53 +00:00
#
# @return [Hash]
2009-10-26 18:54:33 +00:00
def server_info
2010-05-18 20:17:17 +00:00
self [ " admin " ] . command ( { :buildinfo = > 1 } )
2009-10-26 18:54:33 +00:00
end
2011-03-03 19:22:32 +00:00
2010-01-07 17:37:53 +00:00
# Get the build version of the current server.
#
# @return [Mongo::ServerVersion]
# object allowing easy comparability of version.
2009-10-26 18:54:33 +00:00
def server_version
ServerVersion . new ( server_info [ " version " ] )
end
2010-01-08 21:18:07 +00:00
# Is it okay to connect to a slave?
#
# @return [Boolean]
def slave_ok?
2010-12-15 17:36:43 +00:00
@slave_ok
2010-01-08 21:18:07 +00:00
end
2010-01-07 17:37:53 +00:00
# Create a new socket and attempt to connect to master.
2010-01-05 22:42:52 +00:00
# If successful, sets host and port to master and returns the socket.
2010-01-07 17:37:53 +00:00
#
2010-11-03 19:32:19 +00:00
# If connecting to a replica set, this method will replace the
2010-07-19 16:07:46 +00:00
# initially-provided seed list with any nodes known to the set.
#
2010-01-07 17:37:53 +00:00
# @raise [ConnectionFailure] if unable to connect to any host or port.
2010-07-19 16:07:46 +00:00
def connect
2011-03-29 16:18:58 +00:00
close
2010-07-19 16:07:46 +00:00
2010-12-10 21:00:35 +00:00
config = check_is_master ( @host_to_try )
2010-12-29 18:01:05 +00:00
if config
if config [ 'ismaster' ] == 1 || config [ 'ismaster' ] == true
@read_primary = true
elsif @slave_ok
@read_primary = false
end
2011-08-25 18:57:24 +00:00
@max_bson_size = config [ 'maxBsonObjectSize' ] || Mongo :: DEFAULT_MAX_BSON_SIZE
2010-12-10 21:00:35 +00:00
set_primary ( @host_to_try )
2010-07-19 16:07:46 +00:00
end
2011-08-25 18:57:24 +00:00
if ! connected?
2010-12-15 17:36:43 +00:00
raise ConnectionFailure , " Failed to connect to a master node at #{ @host_to_try [ 0 ] } : #{ @host_to_try [ 1 ] } "
end
2010-07-19 16:07:46 +00:00
end
2011-02-02 16:36:56 +00:00
alias :reconnect :connect
2010-07-19 16:07:46 +00:00
2010-11-16 20:43:59 +00:00
# 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.
2009-11-23 20:20:05 +00:00
def connected?
2011-10-17 20:09:54 +00:00
@primary_pool && ! @primary_pool . closed?
2009-11-23 20:20:05 +00:00
end
2011-03-03 10:32:10 +00:00
# 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.
#
# @return [Boolean]
def active?
return false unless connected?
2011-03-03 19:22:32 +00:00
ping
2011-03-03 10:32:10 +00:00
true
rescue ConnectionFailure
false
end
2010-12-29 18:01:05 +00:00
# Determine whether we're reading from a primary node. If false,
# this connection connects to a secondary node and @slave_ok is true.
#
# @return [Boolean]
def read_primary?
@read_primary
end
2011-01-17 18:37:41 +00:00
alias :primary? :read_primary?
2010-12-29 18:01:05 +00:00
2011-10-17 18:41:09 +00:00
# The socket pool that this connection reads from.
#
# @return [Mongo::Pool]
def read_pool
@primary_pool
end
2011-12-05 20:25:37 +00:00
# The value of the read preference.
2011-08-29 21:49:58 +00:00
def read_preference
2011-12-05 20:25:37 +00:00
if slave_ok?
:secondary
else
:primary
end
2011-08-29 21:49:58 +00:00
end
2009-11-23 20:20:05 +00:00
# Close the connection to the database.
def close
2010-11-16 20:43:59 +00:00
@primary_pool . close if @primary_pool
@primary_pool = nil
2011-03-29 16:18:58 +00:00
@primary = nil
2010-02-17 20:15:07 +00:00
end
2010-12-29 23:06:31 +00:00
# Returns the maximum BSON object size as returned by the core server.
# Use the 4MB default when the server doesn't report this.
#
# @return [Integer]
def max_bson_size
2011-08-25 18:57:24 +00:00
@max_bson_size
2010-12-29 23:06:31 +00:00
end
2012-03-15 17:50:02 +00:00
# Prefer primary pool but fall back to secondary
def checkout_best
connect unless connected?
@primary_pool . checkout
end
2010-11-16 20:43:59 +00:00
# Checkout a socket for reading (i.e., a secondary node).
2010-12-15 17:36:43 +00:00
# Note: this is overridden in ReplSetConnection.
2010-11-16 20:43:59 +00:00
def checkout_reader
connect unless connected?
2010-12-15 17:36:43 +00:00
@primary_pool . checkout
2010-11-16 20:43:59 +00:00
end
# Checkout a socket for writing (i.e., a primary node).
2010-12-15 17:36:43 +00:00
# Note: this is overridden in ReplSetConnection.
2010-11-16 20:43:59 +00:00
def checkout_writer
connect unless connected?
@primary_pool . checkout
end
# Checkin a socket used for reading.
2010-12-15 17:36:43 +00:00
# Note: this is overridden in ReplSetConnection.
2010-11-16 20:43:59 +00:00
def checkin_reader ( socket )
2011-08-29 21:49:58 +00:00
checkin ( socket )
2010-11-16 20:43:59 +00:00
end
# Checkin a socket used for writing.
2010-12-15 17:36:43 +00:00
# Note: this is overridden in ReplSetConnection.
2010-11-16 20:43:59 +00:00
def checkin_writer ( socket )
2011-08-29 21:49:58 +00:00
checkin ( socket )
end
# Check a socket back into its pool.
def checkin ( socket )
2012-03-07 03:20:28 +00:00
if @primary_pool && socket
socket . pool . checkin ( socket )
2010-11-16 20:43:59 +00:00
end
end
2012-03-15 17:50:02 +00:00
# Excecutes block with the best available socket
def best_available_socket
socket = nil
begin
socket = checkout_best
yield socket
ensure
if socket
socket . pool . checkin ( socket )
end
end
end
2010-12-13 19:07:32 +00:00
protected
2012-02-27 21:42:16 +00:00
2012-02-27 19:06:07 +00:00
def valid_opts
GENERIC_OPTS + CONNECTION_OPTS
end
2012-02-27 21:42:16 +00:00
2012-02-27 19:06:07 +00:00
def check_opts ( opts )
bad_opts = opts . keys . reject { | opt | valid_opts . include? ( opt ) }
2010-12-13 19:07:32 +00:00
2012-02-27 19:06:07 +00:00
unless bad_opts . empty?
bad_opts . each { | opt | warn " #{ opt } is not a valid option for #{ self . class } " }
end
end
2011-08-25 18:57:24 +00:00
2012-02-27 19:06:07 +00:00
# Parse option hash
def setup ( opts )
# slave_ok can be true only if one node is specified
@slave_ok = opts [ :slave_ok ]
2011-08-26 21:35:40 +00:00
# Determine whether to use SSL.
@ssl = opts . fetch ( :ssl , false )
if @ssl
@socket_class = Mongo :: SSLSocket
else
2012-03-03 00:09:02 +00:00
@socket_class = Mongo :: TCPSocket
2011-08-26 21:35:40 +00:00
end
2010-12-13 19:07:32 +00:00
# Authentication objects
2011-01-05 16:30:20 +00:00
@auths = opts . fetch ( :auths , [ ] )
2010-12-13 19:07:32 +00:00
# Pool size and timeout.
2011-01-05 16:30:20 +00:00
@pool_size = opts [ :pool_size ] || 1
2011-06-15 20:17:42 +00:00
if opts [ :timeout ]
warn " The :timeout option has been deprecated " +
" and will be removed in the 2.0 release. Use :pool_timeout instead. "
end
2011-11-02 19:21:46 +00:00
@pool_timeout = opts [ :pool_timeout ] || opts [ :timeout ] || 5 . 0
2010-12-13 19:07:32 +00:00
2011-03-28 15:09:27 +00:00
# Timeout on socket read operation.
@op_timeout = opts [ :op_timeout ] || nil
2011-06-15 18:20:11 +00:00
# Timeout on socket connect.
@connect_timeout = opts [ :connect_timeout ] || nil
2010-12-13 19:07:32 +00:00
# Global safe option. This is false by default.
2011-01-05 16:30:20 +00:00
@safe = opts [ :safe ] || false
2010-12-13 19:07:32 +00:00
2012-02-16 19:00:52 +00:00
@logger = opts . fetch ( :logger , nil )
2011-01-31 20:51:39 +00:00
if @logger
2011-11-15 20:59:42 +00:00
write_logging_startup_message
2011-01-31 20:51:39 +00:00
end
2010-12-13 19:07:32 +00:00
2012-05-18 16:17:21 +00:00
if opts . fetch ( :connect , true )
connect
2010-11-19 23:26:38 +00:00
end
end
2009-11-24 19:23:43 +00:00
private
2010-12-15 17:41:33 +00:00
## Methods for establishing a connection:
2010-07-19 16:23:12 +00:00
# If a ConnectionFailure is raised, this method will be called
# to close the connection and reset connection values.
2010-12-10 21:00:35 +00:00
# TODO: evaluate whether this method is actually necessary
2010-07-19 16:23:12 +00:00
def reset_connection
close
end
def check_is_master ( node )
begin
host , port = * node
2012-01-06 08:37:56 +00:00
socket = nil
config = nil
2011-06-15 18:20:11 +00:00
2012-04-08 14:48:25 +00:00
socket = @socket_class . new ( host , port , @op_timeout , @connect_timeout )
2012-04-03 19:40:38 +00:00
config = self [ 'admin' ] . command ( { :ismaster = > 1 } , :socket = > socket )
2012-03-16 20:17:33 +00:00
rescue OperationFailure , SocketError , SystemCallError , IOError
2010-12-14 18:14:45 +00:00
close
2010-07-19 16:23:12 +00:00
ensure
2012-04-05 16:47:58 +00:00
if socket
socket . close unless socket . closed?
end
2010-07-19 16:23:12 +00:00
end
config
end
2011-01-31 19:47:05 +00:00
# Set the specified node as primary.
2010-07-19 16:23:12 +00:00
def set_primary ( node )
2010-11-16 20:43:59 +00:00
host , port = * node
@primary = [ host , port ]
2011-11-02 19:21:46 +00:00
@primary_pool = Pool . new ( self , host , port , :size = > @pool_size , :timeout = > @pool_timeout )
2010-07-19 16:23:12 +00:00
end
2009-08-20 22:48:09 +00:00
end
2008-11-22 01:00:51 +00:00
end