Mongo and DB ctors can now take array of nodes. Tests now close @db in teardown.

This commit is contained in:
Jim Menard 2009-01-14 18:37:28 -05:00
parent 6d2a012c7f
commit c3d73e4151
6 changed files with 93 additions and 32 deletions

View File

@ -49,25 +49,47 @@ module XGen
# The name of the database. # The name of the database.
attr_reader :name attr_reader :name
attr_reader :host, :port # Host to which we are currently connected.
attr_reader :host
# Port to which we are currently connected.
attr_reader :port
# An array of [host, port] pairs.
attr_reader :nodes
# The database's socket. For internal (and Cursor) use only. # The database's socket. For internal (and Cursor) use only.
attr_reader :socket attr_reader :socket
# db_name :: The database name # db_name :: The database name
# #
# host :: The database host name or IP address. Defaults to 'localhost'. # nodes :: An array of [host, port] pairs.
# #
# port :: The database port number. Defaults to # When a DB object first connects, it tries the first node. If that
# XGen::Mongo::Driver::Mongo::DEFAULT_PORT. # fails, it keeps trying to connect to the remaining nodes until it
# # sucessfully connects.
def initialize(db_name, host='localhost', port=XGen::Mongo::Driver::Mongo::DEFAULT_PORT) def initialize(db_name, nodes)
raise "Invalid DB name" if !db_name || (db_name && db_name.length > 0 && db_name.include?(".")) raise "Invalid DB name" if !db_name || (db_name && db_name.length > 0 && db_name.include?("."))
@name, @host, @port = db_name, host, port @name, @nodes = db_name, nodes
@socket = TCPSocket.new(@host, @port)
@strict = false @strict = false
@semaphore = Object.new @semaphore = Object.new
@semaphore.extend Mutex_m @semaphore.extend Mutex_m
connect_to_first_available_host
end
def connect_to_first_available_host
close if @socket
@host = @port = nil
@nodes.detect { |hp|
@host, @port = *hp
begin
@socket = TCPSocket.new(@host, @port)
break if ok?(db_command(:ismaster => 1)) # success
rescue => ex
close if @socket
end
@socket
}
raise "error: failed to connect to any given host:port" unless @socket
end end
# Returns an array of collection names. Each name is of the form # Returns an array of collection names. Each name is of the form
@ -183,7 +205,12 @@ module XGen
# Close the connection to the database. # Close the connection to the database.
def close def close
@socket.close @socket.close if @socket
@socket = nil
end
def connected?
@socket != nil
end end
# Send a MsgMessage to the database. # Send a MsgMessage to the database.

View File

@ -25,14 +25,36 @@ module XGen
DEFAULT_PORT = 27017 DEFAULT_PORT = 27017
# Host default is 'localhost', port default is DEFAULT_PORT. # Either nodes_or_host is a host name string and port is an optional
def initialize(host='localhost', port=DEFAULT_PORT) # port number that defaults to DEFAULT_PORT, or nodes_or_host is an
@host, @port = host, port # array of arrays, where each is a host/port pair (or a host with no
# port). Finally, if both args are nil then host is 'localhost' and
# port is DEFAULT_PORT. Since that's so confusing, here are a few
# examples:
#
# Mongo.new # localhost, DEFAULT_PORT
# Mongo.new("localhost") # localhost, DEFAULT_PORT
# Mongo.new("localhost", 3000) # localhost, 3000
# Mongo.new([["localhost"]]) # localhost, DEFAULT_PORT
# Mongo.new([["localhost", 3000]]) # localhost, 3000
# Mongo.new([["db1.example.com", 3000], ["db2.example.com", 3000]]])
#
# When a DB object first connects, it tries nodes and stops at the
# first one it connects to.
def initialize(nodes_or_host, port=nil)
@nodes = case nodes_or_host
when String
[[nodes_or_host, port || DEFAULT_PORT]]
when Array
nodes_or_host.collect { |nh| [nh[0], nh[1] || DEFAULT_PORT] }
when nil
[['localhost', DEFAULT_PORT]]
end
end end
# Return the XGen::Mongo::Driver::DB named +db_name+. # Return the XGen::Mongo::Driver::DB named +db_name+.
def db(db_name) def db(db_name)
XGen::Mongo::Driver::DB.new(db_name, @host, @port) XGen::Mongo::Driver::DB.new(db_name, @nodes)
end end
# Not implemented. # Not implemented.

View File

@ -20,9 +20,10 @@ class AdminTest < Test::Unit::TestCase
end end
def teardown def teardown
unless @db.socket.closed? if @db.connected?
@admin.profiling_level = :off @admin.profiling_level = :off
@coll.clear unless @coll == nil @coll.clear if @coll
@db.close
end end
end end

View File

@ -18,7 +18,10 @@ class CursorTest < Test::Unit::TestCase
end end
def teardown def teardown
@coll.clear unless @coll == nil || @db.socket.closed? if @db.connected?
@coll.clear if @coll
@db.close
end
end end
def test_explain def test_explain

View File

@ -8,39 +8,44 @@ class DBAPITest < Test::Unit::TestCase
include XGen::Mongo::Driver include XGen::Mongo::Driver
def setup def setup
host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost' @host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
port = ENV['MONGO_RUBY_DRIVER_PORT'] || Mongo::DEFAULT_PORT @port = ENV['MONGO_RUBY_DRIVER_PORT'] || Mongo::DEFAULT_PORT
@db = Mongo.new(host, port).db('ruby-mongo-test') @db = Mongo.new(@host, @port).db('ruby-mongo-test')
@coll = @db.collection('test')
@coll.clear
@r1 = @coll.insert('a' => 1) # collection not created until it's used
@coll_full_name = 'ruby-mongo-test.test'
end end
def teardown def teardown
@coll.clear unless @coll == nil || @db.socket.closed? if @db.connected?
@db.close
end
end end
def test_close def test_close
@db.close @db.close
assert @db.socket.closed? assert !@db.connected?
begin begin
@coll.insert('a' => 1) @db.collection('test').insert('a' => 1)
fail "expected IOError exception" fail "expected 'NilClass' exception"
rescue IOError => ex rescue => ex
assert_match /closed stream/, ex.to_s assert_match /NilClass/, ex.to_s
end end
end end
def test_full_coll_name def test_full_coll_name
assert_equal @coll_full_name, @db.full_coll_name(@coll.name) coll = @db.collection('test')
assert_equal 'ruby-mongo-test.test', @db.full_coll_name(coll.name)
end end
def test_master def test_master
# Doesn't really test anything since we probably only have one database # Doesn't really test anything since we probably only have one database
# during this test. # during this test.
@db.switch_to_master @db.switch_to_master
assert_not_nil @db.socket assert @db.connected?
end
def test_array
@db.close
@db = Mongo.new([["nosuch.example.com"], [@host, @port]]).db('ruby-mongo-test')
assert @db.connected?
end end
end end

View File

@ -18,7 +18,10 @@ class DBAPITest < Test::Unit::TestCase
end end
def teardown def teardown
@coll.clear unless @coll == nil || @db.socket.closed? if @db.connected?
@coll.clear unless @coll == nil
@db.close
end
end end
def test_clear def test_clear