RUBY-147 check for CursorNotFound response flag

This commit is contained in:
Kyle Banker 2010-07-12 12:11:01 -04:00
parent 030c850669
commit 265f074f10
5 changed files with 43 additions and 9 deletions

View File

@ -21,11 +21,18 @@ module Mongo
OP_DELETE = 2006 OP_DELETE = 2006
OP_KILL_CURSORS = 2007 OP_KILL_CURSORS = 2007
OP_QUERY_TAILABLE = 2 OP_QUERY_TAILABLE = 2 ** 1
OP_QUERY_SLAVE_OK = 4 OP_QUERY_SLAVE_OK = 2 ** 2
OP_QUERY_NO_CURSOR_TIMEOUT = 16 OP_QUERY_OPLOG_REPLAY = 2 ** 3
end OP_QUERY_NO_CURSOR_TIMEOUT = 2 ** 4
OP_QUERY_AWAIT_DATA = 2 ** 5
OP_QUERY_EXHAUST = 2 ** 6
REPLY_CURSOR_NOT_FOUND = 2 ** 0
REPLY_QUERY_FAILURE = 2 ** 1
REPLY_SHARD_CONFIG_STALE = 2 ** 2
REPLY_AWAIT_CAPABLE = 2 ** 3
end
end end
require 'bson' require 'bson'

View File

@ -158,6 +158,7 @@ module Mongo
cursor = Cursor.new(self, :selector => selector, :fields => fields, :skip => skip, :limit => limit, cursor = Cursor.new(self, :selector => selector, :fields => fields, :skip => skip, :limit => limit,
:order => sort, :hint => hint, :snapshot => snapshot, :timeout => timeout, :batch_size => batch_size) :order => sort, :hint => hint, :snapshot => snapshot, :timeout => timeout, :batch_size => batch_size)
if block_given? if block_given?
yield cursor yield cursor
cursor.close() cursor.close()

View File

@ -632,13 +632,22 @@ module Mongo
"expected #{RESPONSE_HEADER_SIZE} bytes, saw #{header_buf.length}" "expected #{RESPONSE_HEADER_SIZE} bytes, saw #{header_buf.length}"
end end
header_buf.rewind header_buf.rewind
result_flags = header_buf.get_int check_response_flags(header_buf.get_int)
cursor_id = header_buf.get_long cursor_id = header_buf.get_long
starting_from = header_buf.get_int starting_from = header_buf.get_int
number_remaining = header_buf.get_int number_remaining = header_buf.get_int
[number_remaining, cursor_id] [number_remaining, cursor_id]
end end
def check_response_flags(flags)
if flags & Mongo::Constants::REPLY_CURSOR_NOT_FOUND != 0
raise Mongo::OperationFailure, "Query response returned CURSOR_NOT_FOUND. " +
"Either an invalid cursor was specified, or the cursor may have timed out on the server."
elsif flags & Mongo::Constants::REPLY_QUERY_FAILURE != 0
raise Mongo::OperationFailure, "Query response returned QUERY_FAILURE."
end
end
def read_documents(number_received, cursor_id, sock) def read_documents(number_received, cursor_id, sock)
docs = [] docs = []
number_remaining = number_received number_remaining = number_received

View File

@ -23,7 +23,7 @@ module Mongo
attr_reader :collection, :selector, :admin, :fields, attr_reader :collection, :selector, :admin, :fields,
:order, :hint, :snapshot, :timeout, :order, :hint, :snapshot, :timeout,
:full_collection_name :full_collection_name, :batch_size
# Create a new cursor. # Create a new cursor.
# #
@ -237,7 +237,7 @@ module Mongo
message = BSON::ByteBuffer.new([0, 0, 0, 0]) message = BSON::ByteBuffer.new([0, 0, 0, 0])
message.put_int(1) message.put_int(1)
message.put_long(@cursor_id) message.put_long(@cursor_id)
@connection.send_message(Mongo::Constants::OP_KILL_CURSORS, message, "cursor.close") @connection.send_message(Mongo::Constants::OP_KILL_CURSORS, message, "cursor.close #{@cursor_id}")
end end
@cursor_id = 0 @cursor_id = 0
@closed = true @closed = true

View File

@ -137,7 +137,7 @@ class CursorTest < Test::Unit::TestCase
@@coll.save({:t => 't2'}) @@coll.save({:t => 't2'})
@@coll.save({:t => 't2'}) @@coll.save({:t => 't2'})
assert_equal 3, @@coll.find({'_id' => {'$gt' => t1_id}, '_id' => {'$lt' => t2_id}}).count assert_equal 3, @@coll.find({'_id' => {'$gt' => t1_id, '$lt' => t2_id}}).count
@@coll.find({'_id' => {'$gt' => t2_id}}).each do |doc| @@coll.find({'_id' => {'$gt' => t2_id}}).each do |doc|
assert_equal 't2', doc['t'] assert_equal 't2', doc['t']
end end
@ -396,4 +396,21 @@ class CursorTest < Test::Unit::TestCase
assert_equal false, cursor.has_next? assert_equal false, cursor.has_next?
end end
def test_cursor_invalid
@@coll.remove
1000.times do |n|
@@coll.insert({:a => n})
end
cursor = @@coll.find({})
cursor.next_document
cursor.close
assert_raise_error(Mongo::OperationFailure, "CURSOR_NOT_FOUND") do
999.times do
cursor.next_document
end
end
end
end end