Removed GetMoreMessage and QueryMessage classes with initial refactoring.
This commit is contained in:
parent
5586d53c6a
commit
b938765ac0
|
@ -3,6 +3,8 @@ require 'mongo/types/dbref'
|
||||||
require 'mongo/types/objectid'
|
require 'mongo/types/objectid'
|
||||||
require 'mongo/types/regexp_of_holding'
|
require 'mongo/types/regexp_of_holding'
|
||||||
|
|
||||||
|
require 'mongo/util/conversions'
|
||||||
|
|
||||||
require 'mongo/errors'
|
require 'mongo/errors'
|
||||||
require 'mongo/connection'
|
require 'mongo/connection'
|
||||||
require 'mongo/message'
|
require 'mongo/message'
|
||||||
|
|
|
@ -20,6 +20,7 @@ module Mongo
|
||||||
|
|
||||||
# A cursor over query results. Returned objects are hashes.
|
# A cursor over query results. Returned objects are hashes.
|
||||||
class Cursor
|
class Cursor
|
||||||
|
include Mongo::Conversions
|
||||||
|
|
||||||
include Enumerable
|
include Enumerable
|
||||||
|
|
||||||
|
@ -246,11 +247,22 @@ module Mongo
|
||||||
end
|
end
|
||||||
|
|
||||||
def refill_via_get_more
|
def refill_via_get_more
|
||||||
if send_query_if_needed or @cursor_id == 0
|
return if send_query_if_needed || @cursor_id.zero?
|
||||||
return
|
|
||||||
end
|
|
||||||
@db._synchronize {
|
@db._synchronize {
|
||||||
@db.send_to_db(GetMoreMessage.new(@admin ? 'admin' : @db.name, @collection.name, @cursor_id))
|
message = ByteBuffer.new
|
||||||
|
# Reserved.
|
||||||
|
message.put_int(0)
|
||||||
|
|
||||||
|
# DB name.
|
||||||
|
db_name = @admin ? 'admin' : @db.name
|
||||||
|
BSON.serialize_cstr(message, "#{db_name}.#{@collection.name}")
|
||||||
|
|
||||||
|
# Number of results to return; db decides for now.
|
||||||
|
message.put_int(0)
|
||||||
|
|
||||||
|
# Cursor id.
|
||||||
|
message.put_long(@cursor_id)
|
||||||
|
@db.send_message_with_operation_without_synchronize(OP_GET_MORE, message)
|
||||||
read_all
|
read_all
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
@ -272,14 +284,55 @@ module Mongo
|
||||||
false
|
false
|
||||||
else
|
else
|
||||||
@db._synchronize {
|
@db._synchronize {
|
||||||
@db.send_query_message(QueryMessage.new(@admin ? 'admin' : @db.name, @collection.name, @query))
|
message = construct_query_message(@query)
|
||||||
@query_run = true
|
@query_run = true
|
||||||
|
@db.send_message_with_operation_without_synchronize(OP_QUERY, message)
|
||||||
read_all
|
read_all
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def construct_query_message(query)
|
||||||
|
message = ByteBuffer.new
|
||||||
|
message.put_int(query.query_opts)
|
||||||
|
db_name = @admin ? 'admin' : @db.name
|
||||||
|
BSON.serialize_cstr(message, "#{db_name}.#{@collection.name}")
|
||||||
|
message.put_int(query.number_to_skip)
|
||||||
|
message.put_int(query.number_to_return)
|
||||||
|
sel = query.selector
|
||||||
|
if query.contains_special_fields
|
||||||
|
sel = add_special_query_fields(sel, query)
|
||||||
|
end
|
||||||
|
message.put_array(BSON.new.serialize(sel).to_a)
|
||||||
|
message.put_array(BSON.new.serialize(query.fields).to_a) if query.fields
|
||||||
|
message
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_special_query_fields(sel, query)
|
||||||
|
sel = OrderedHash.new
|
||||||
|
sel['query'] = query.selector
|
||||||
|
order_by = query.order_by
|
||||||
|
sel['orderby'] = get_query_order_by(order_by) if order_by
|
||||||
|
sel['$hint'] = query.hint if query.hint && query.hint.length > 0
|
||||||
|
sel['$explain'] = true if query.explain
|
||||||
|
sel['$snapshot'] = true if query.snapshot
|
||||||
|
sel
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_query_order_by(order_by)
|
||||||
|
case order_by
|
||||||
|
when String then string_as_sort_parameters(order_by)
|
||||||
|
when Symbol then symbol_as_sort_parameters(order_by)
|
||||||
|
when Array then array_as_sort_parameters(order_by)
|
||||||
|
when Hash # Should be an ordered hash, but this message doesn't care
|
||||||
|
warn_if_deprecated(order_by)
|
||||||
|
order_by
|
||||||
|
else
|
||||||
|
raise InvalidSortValueError, "Illegal order_by, '#{query.order_by.class.name}'; must be String, Array, Hash, or OrderedHash"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
"DBResponse(flags=#@result_flags, cursor_id=#@cursor_id, start=#@starting_from)"
|
"DBResponse(flags=#@result_flags, cursor_id=#@cursor_id, start=#@starting_from)"
|
||||||
end
|
end
|
||||||
|
|
|
@ -372,11 +372,6 @@ module Mongo
|
||||||
Cursor.new(self, collection, query, admin)
|
Cursor.new(self, collection, query, admin)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Used by a Cursor to lazily send the query to the database.
|
|
||||||
def send_query_message(query_message)
|
|
||||||
send_to_db(query_message)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Dereference a DBRef, getting the document it points to.
|
# Dereference a DBRef, getting the document it points to.
|
||||||
def dereference(dbref)
|
def dereference(dbref)
|
||||||
collection(dbref.namespace).find_one("_id" => dbref.object_id)
|
collection(dbref.namespace).find_one("_id" => dbref.object_id)
|
||||||
|
@ -460,7 +455,7 @@ module Mongo
|
||||||
# Takes a MongoDB opcode, +operation+, and a message of class ByteBuffer,
|
# Takes a MongoDB opcode, +operation+, and a message of class ByteBuffer,
|
||||||
# +message+, and sends the message to the databse, adding the necessary headers.
|
# +message+, and sends the message to the databse, adding the necessary headers.
|
||||||
def send_message_with_operation(operation, message)
|
def send_message_with_operation(operation, message)
|
||||||
_synchronize do
|
@semaphore.synchronize do
|
||||||
connect_to_master if !connected? && @auto_reconnect
|
connect_to_master if !connected? && @auto_reconnect
|
||||||
begin
|
begin
|
||||||
message_with_headers = add_message_headers(operation, message)
|
message_with_headers = add_message_headers(operation, message)
|
||||||
|
@ -474,6 +469,26 @@ module Mongo
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def send_message_with_operation_without_synchronize(operation, message)
|
||||||
|
connect_to_master if !connected? && @auto_reconnect
|
||||||
|
begin
|
||||||
|
message_with_headers = add_message_headers(operation, message)
|
||||||
|
@logger.debug(" MONGODB #{operation} #{message}") if @logger
|
||||||
|
@socket.print(message_with_headers.to_s)
|
||||||
|
@socket.flush
|
||||||
|
rescue => ex
|
||||||
|
close
|
||||||
|
raise ex
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def receive_message_with_operation(operation, message)
|
||||||
|
@semaphore.synchronize do
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Return +true+ if +doc+ contains an 'ok' field with the value 1.
|
# Return +true+ if +doc+ contains an 'ok' field with the value 1.
|
||||||
def ok?(doc)
|
def ok?(doc)
|
||||||
ok = doc['ok']
|
ok = doc['ok']
|
||||||
|
|
|
@ -31,5 +31,5 @@ module Mongo
|
||||||
class InvalidName < RuntimeError; end
|
class InvalidName < RuntimeError; end
|
||||||
|
|
||||||
# Raised when the client supplies an invalid value to sort by.
|
# Raised when the client supplies an invalid value to sort by.
|
||||||
class InvalidSortValueError < RuntimeError; end
|
class InvalidSortValueError < MongoRubyError; end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
# ++
|
# ++
|
||||||
|
|
||||||
%w(get_more_message kill_cursors_message message_header
|
%w(kill_cursors_message message_header
|
||||||
msg_message query_message).each { |f|
|
msg_message).each { |f|
|
||||||
require "mongo/message/#{f}"
|
require "mongo/message/#{f}"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
# --
|
|
||||||
# Copyright (C) 2008-2009 10gen Inc.
|
|
||||||
#
|
|
||||||
# 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
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
# ++
|
|
||||||
|
|
||||||
require 'mongo/message/message'
|
|
||||||
require 'mongo/message/opcodes'
|
|
||||||
|
|
||||||
module Mongo
|
|
||||||
|
|
||||||
class GetMoreMessage < Message
|
|
||||||
|
|
||||||
def initialize(db_name, collection_name, cursor)
|
|
||||||
super(OP_GET_MORE)
|
|
||||||
write_int(0)
|
|
||||||
write_string("#{db_name}.#{collection_name}")
|
|
||||||
write_int(0) # num to return; leave it up to the db for now
|
|
||||||
write_long(cursor)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,69 +0,0 @@
|
||||||
# --
|
|
||||||
# Copyright (C) 2008-2009 10gen Inc.
|
|
||||||
#
|
|
||||||
# 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
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
# ++
|
|
||||||
|
|
||||||
require 'mongo/message/message'
|
|
||||||
require 'mongo/message/opcodes'
|
|
||||||
require 'mongo/util/conversions'
|
|
||||||
require 'mongo/util/ordered_hash'
|
|
||||||
|
|
||||||
module Mongo
|
|
||||||
class QueryMessage < Message
|
|
||||||
include Mongo::Conversions
|
|
||||||
|
|
||||||
attr_reader :query
|
|
||||||
|
|
||||||
def initialize(db_name, collection_name, query)
|
|
||||||
super(OP_QUERY)
|
|
||||||
@query = query
|
|
||||||
@collection_name = collection_name
|
|
||||||
write_int(@query.query_opts)
|
|
||||||
write_string("#{db_name}.#{collection_name}")
|
|
||||||
write_int(query.number_to_skip)
|
|
||||||
write_int(query.number_to_return)
|
|
||||||
sel = query.selector
|
|
||||||
if query.contains_special_fields
|
|
||||||
sel = OrderedHash.new
|
|
||||||
sel['query'] = query.selector
|
|
||||||
if query.order_by
|
|
||||||
order_by = query.order_by
|
|
||||||
sel['orderby'] = case order_by
|
|
||||||
when String then string_as_sort_parameters(order_by)
|
|
||||||
when Symbol then symbol_as_sort_parameters(order_by)
|
|
||||||
when Array then array_as_sort_parameters(order_by)
|
|
||||||
when Hash # Should be an ordered hash, but this message doesn't care
|
|
||||||
warn_if_deprecated(order_by)
|
|
||||||
order_by
|
|
||||||
else
|
|
||||||
raise InvalidSortValueError.new("illegal order_by: is a #{query.order_by.class.name}, must be String, Array, Hash, or OrderedHash")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
sel['$hint'] = query.hint if query.hint && query.hint.length > 0
|
|
||||||
sel['$explain'] = true if query.explain
|
|
||||||
sel['$snapshot'] = true if query.snapshot
|
|
||||||
end
|
|
||||||
write_doc(sel)
|
|
||||||
write_doc(query.fields) if query.fields
|
|
||||||
end
|
|
||||||
|
|
||||||
def first_key(key)
|
|
||||||
@first_key = key
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s
|
|
||||||
"db.#{@collection_name}.#{@query}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,58 +0,0 @@
|
||||||
# --
|
|
||||||
# Copyright (C) 2008-2009 10gen Inc.
|
|
||||||
#
|
|
||||||
# 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
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
# ++
|
|
||||||
|
|
||||||
$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
|
|
||||||
require 'mongo'
|
|
||||||
require 'test/unit'
|
|
||||||
|
|
||||||
class TestQueryMessage < Test::Unit::TestCase
|
|
||||||
|
|
||||||
include Mongo
|
|
||||||
|
|
||||||
def test_timeout_opcodes
|
|
||||||
@timeout = true
|
|
||||||
@query = Query.new({}, nil, 0, 0, nil, nil, nil, @timeout)
|
|
||||||
@query_message = QueryMessage.new('db', 'collection', @query)
|
|
||||||
buf = @query_message.buf.instance_variable_get(:@buf)
|
|
||||||
assert_equal 0, buf[16]
|
|
||||||
|
|
||||||
|
|
||||||
@timeout = false
|
|
||||||
@query = Query.new({}, nil, 0, 0, nil, nil, nil, @timeout)
|
|
||||||
@query_message = QueryMessage.new('db', 'collection', @query)
|
|
||||||
buf = @query_message.buf.instance_variable_get(:@buf)
|
|
||||||
assert_equal 16, buf[16]
|
|
||||||
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
|
|
|
@ -61,10 +61,8 @@ class TestConnection < Test::Unit::TestCase
|
||||||
logger = Logger.new(output)
|
logger = Logger.new(output)
|
||||||
logger.level = Logger::DEBUG
|
logger.level = Logger::DEBUG
|
||||||
db = Connection.new(@host, @port, :logger => logger).db('ruby-mongo-test')
|
db = Connection.new(@host, @port, :logger => logger).db('ruby-mongo-test')
|
||||||
db['test'].find().to_a
|
|
||||||
|
|
||||||
assert output.string.include?("db.test.find")
|
assert output.string.include?("2004")
|
||||||
assert !output.string.include?("db.test.remove")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_connection_logger
|
def test_connection_logger
|
||||||
|
|
Loading…
Reference in New Issue