Raise exception if connecting to single slave with slave_ok set to false; pass slave_ok on to queries when set to true.
This commit is contained in:
parent
c6d4150a51
commit
4e2781faf1
|
@ -130,7 +130,7 @@ module Mongo
|
||||||
end
|
end
|
||||||
raise RuntimeError, "Unknown options [#{options.inspect}]" unless options.empty?
|
raise RuntimeError, "Unknown options [#{options.inspect}]" unless options.empty?
|
||||||
|
|
||||||
cursor = @db.query(self, Query.new(selector, fields, skip, limit, sort, hint, snapshot, timeout))
|
cursor = @db.query(self, Query.new(selector, fields, skip, limit, sort, hint, snapshot, timeout, @db.slave_ok?))
|
||||||
if block_given?
|
if block_given?
|
||||||
yield cursor
|
yield cursor
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
|
@ -160,6 +160,9 @@ module Mongo
|
||||||
is_master = master?
|
is_master = master?
|
||||||
@semaphore.lock if semaphore_is_locked
|
@semaphore.lock if semaphore_is_locked
|
||||||
|
|
||||||
|
if !@slave_ok && !is_master
|
||||||
|
raise ConfigurationError, "Trying to connect directly to slave; if this is what you want, specify :slave_ok => true."
|
||||||
|
end
|
||||||
@slave_ok || is_master
|
@slave_ok || is_master
|
||||||
rescue SocketError, SystemCallError, IOError => ex
|
rescue SocketError, SystemCallError, IOError => ex
|
||||||
close if @socket
|
close if @socket
|
||||||
|
|
|
@ -15,6 +15,12 @@
|
||||||
# Exceptions raised by the MongoDB driver.
|
# Exceptions raised by the MongoDB driver.
|
||||||
|
|
||||||
module Mongo
|
module Mongo
|
||||||
|
# Generic Mongo Ruby Driver exception class.
|
||||||
|
class MongoRubyError < StandardError; end
|
||||||
|
|
||||||
|
# Raised when configuration options cause connections, queries, etc., to fail.
|
||||||
|
class ConfigurationError < MongoRubyError; end
|
||||||
|
|
||||||
# Raised when a database operation fails.
|
# Raised when a database operation fails.
|
||||||
class OperationFailure < RuntimeError; end
|
class OperationFailure < RuntimeError; end
|
||||||
|
|
||||||
|
|
|
@ -25,5 +25,6 @@ module Mongo
|
||||||
OP_DELETE = 2006
|
OP_DELETE = 2006
|
||||||
OP_KILL_CURSORS = 2007
|
OP_KILL_CURSORS = 2007
|
||||||
|
|
||||||
|
OP_QUERY_SLAVE_OK = 4
|
||||||
OP_QUERY_NO_CURSOR_TIMEOUT = 16
|
OP_QUERY_NO_CURSOR_TIMEOUT = 16
|
||||||
end
|
end
|
||||||
|
|
|
@ -67,9 +67,9 @@ module Mongo
|
||||||
# the normal cursor timeout behavior of the mongod process.
|
# the normal cursor timeout behavior of the mongod process.
|
||||||
# When +false+, the returned cursor will never timeout. Care should
|
# When +false+, the returned cursor will never timeout. Care should
|
||||||
# be taken to ensure that cursors with timeout disabled are properly closed.
|
# be taken to ensure that cursors with timeout disabled are properly closed.
|
||||||
def initialize(sel={}, return_fields=nil, number_to_skip=0, number_to_return=0, order_by=nil, hint=nil, snapshot=nil, timeout=true)
|
def initialize(sel={}, return_fields=nil, number_to_skip=0, number_to_return=0, order_by=nil, hint=nil, snapshot=nil, timeout=true, slave_ok=false)
|
||||||
@number_to_skip, @number_to_return, @order_by, @hint, @snapshot, @timeout =
|
@number_to_skip, @number_to_return, @order_by, @hint, @snapshot, @timeout, @slave_ok =
|
||||||
number_to_skip, number_to_return, order_by, hint, snapshot, timeout
|
number_to_skip, number_to_return, order_by, hint, snapshot, timeout, slave_ok
|
||||||
@explain = nil
|
@explain = nil
|
||||||
self.selector = sel
|
self.selector = sel
|
||||||
self.fields = return_fields
|
self.fields = return_fields
|
||||||
|
@ -121,7 +121,9 @@ module Mongo
|
||||||
# Returns an integer indicating which query options have been selected.
|
# Returns an integer indicating which query options have been selected.
|
||||||
# See http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-OPQUERY
|
# See http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-OPQUERY
|
||||||
def query_opts
|
def query_opts
|
||||||
@timeout ? 0 : OP_QUERY_NO_CURSOR_TIMEOUT
|
timeout = @timeout ? 0 : OP_QUERY_NO_CURSOR_TIMEOUT
|
||||||
|
slave_ok = @slave_ok ? OP_QUERY_SLAVE_OK : 0
|
||||||
|
slave_ok + timeout
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
|
|
|
@ -37,4 +37,22 @@ class TestQueryMessage < Test::Unit::TestCase
|
||||||
assert_equal 16, buf[16]
|
assert_equal 16, buf[16]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_timeout_opcodes
|
||||||
|
@timeout = true
|
||||||
|
@slave_ok = true
|
||||||
|
@query = Query.new({}, nil, 0, 0, nil, nil, nil, @timeout, @slave_ok)
|
||||||
|
@query_message = QueryMessage.new('db', 'collection', @query)
|
||||||
|
buf = @query_message.buf.instance_variable_get(:@buf)
|
||||||
|
assert_equal 4, buf[16]
|
||||||
|
|
||||||
|
|
||||||
|
@timeout = false
|
||||||
|
@slave_ok = true
|
||||||
|
@query = Query.new({}, nil, 0, 0, nil, nil, nil, @timeout, @slave_ok)
|
||||||
|
@query_message = QueryMessage.new('db', 'collection', @query)
|
||||||
|
buf = @query_message.buf.instance_variable_get(:@buf)
|
||||||
|
assert_equal 20, buf[16]
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -33,4 +33,22 @@ class TestQuery < Test::Unit::TestCase
|
||||||
assert_equal 16, @query.query_opts
|
assert_equal 16, @query.query_opts
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_slave_ok_opcodes
|
||||||
|
@slave_ok = true
|
||||||
|
@query = Query.new({}, nil, 0, 0, nil, nil, nil, true, @slave_ok)
|
||||||
|
assert_equal 4, @query.query_opts
|
||||||
|
|
||||||
|
|
||||||
|
@slave_ok = false
|
||||||
|
@query = Query.new({}, nil, 0, 0, nil, nil, nil, true, @slave_ok)
|
||||||
|
assert_equal 0, @query.query_opts
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_combined_opcodes
|
||||||
|
@timeout = false
|
||||||
|
@slave_ok = true
|
||||||
|
@query = Query.new({}, nil, 0, 0, nil, nil, nil, @timeout, @slave_ok)
|
||||||
|
assert_equal 20, @query.query_opts
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
|
||||||
|
require 'mongo'
|
||||||
|
require 'test/unit'
|
||||||
|
|
||||||
|
# NOTE: these tests are run only if we can connect to a single MongoDB in slave mode.
|
||||||
|
class SlaveConnectionTest < Test::Unit::TestCase
|
||||||
|
include Mongo
|
||||||
|
|
||||||
|
def self.connect_to_slave
|
||||||
|
@@host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
|
||||||
|
@@port = ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT
|
||||||
|
db = Connection.new(@@host, @@port, :slave_ok => true).db('ruby-mongo-demo')
|
||||||
|
!db.master?
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.connect_to_slave
|
||||||
|
puts "Connected to slave; running slave tests."
|
||||||
|
|
||||||
|
def test_connect_to_slave
|
||||||
|
assert_raise Mongo::ConfigurationError do
|
||||||
|
@db = Connection.new(@@host, @@port, :slave_ok => false).db('ruby-mongo-demo')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_slave_ok_sent_to_queries
|
||||||
|
@db = Connection.new(@@host, @@port, :slave_ok => true).db('ruby-mongo-demo')
|
||||||
|
@coll = @db['test-collection']
|
||||||
|
@cursor = @coll.find({})
|
||||||
|
assert_equal true, @cursor.query.instance_variable_get(:@slave_ok)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
puts "Not connected to slave; skipping slave connection tests."
|
||||||
|
|
||||||
|
def test_slave_ok_false_on_queries
|
||||||
|
@db = Connection.new(@@host, @@port).db('ruby-mongo-demo')
|
||||||
|
@coll = @db['test-collection']
|
||||||
|
@cursor = @coll.find({})
|
||||||
|
assert_nil @cursor.query.instance_variable_get(:@slave_ok)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in New Issue