mongo 0.18.1 → 0.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +3 -59
- data/Rakefile +7 -13
- data/bin/perf.rb +30 -0
- data/examples/cursor.rb +4 -4
- data/examples/types.rb +1 -1
- data/lib/mongo.rb +2 -2
- data/lib/mongo/admin.rb +1 -2
- data/lib/mongo/collection.rb +85 -45
- data/lib/mongo/connection.rb +55 -102
- data/lib/mongo/constants.rb +3 -3
- data/lib/mongo/cursor.rb +48 -44
- data/lib/mongo/db.rb +8 -8
- data/lib/mongo/errors.rb +8 -2
- data/lib/mongo/gridfs/chunk.rb +0 -1
- data/lib/mongo/gridfs/grid_store.rb +57 -14
- data/lib/mongo/types/code.rb +1 -0
- data/lib/mongo/types/objectid.rb +5 -6
- data/lib/mongo/util/bson_ruby.rb +25 -15
- data/lib/mongo/util/conversions.rb +12 -4
- data/lib/mongo/util/ordered_hash.rb +18 -0
- data/lib/mongo/util/server_version.rb +3 -3
- data/test/replica/count_test.rb +3 -3
- data/test/replica/insert_test.rb +6 -6
- data/test/replica/pooled_insert_test.rb +8 -8
- data/test/replica/query_test.rb +3 -3
- data/test/test_bson.rb +32 -0
- data/test/test_collection.rb +140 -65
- data/test/test_connection.rb +2 -2
- data/test/test_conversions.rb +3 -3
- data/test/test_cursor.rb +44 -20
- data/test/test_db_api.rb +7 -1
- data/test/test_grid_store.rb +16 -2
- data/test/test_objectid.rb +12 -0
- data/test/test_ordered_hash.rb +16 -0
- data/test/test_threading.rb +3 -3
- data/test/threading/test_threading_large_pool.rb +7 -7
- data/test/unit/collection_test.rb +7 -7
- data/test/unit/connection_test.rb +0 -79
- data/test/unit/cursor_test.rb +12 -12
- data/test/unit/db_test.rb +11 -11
- metadata +7 -5
- data/bin/autoreconnect.rb +0 -26
data/lib/mongo/connection.rb
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
|
17
17
|
require 'set'
|
18
18
|
require 'socket'
|
19
|
-
require '
|
19
|
+
require 'thread'
|
20
20
|
|
21
21
|
module Mongo
|
22
22
|
|
@@ -31,12 +31,12 @@ module Mongo
|
|
31
31
|
STANDARD_HEADER_SIZE = 16
|
32
32
|
RESPONSE_HEADER_SIZE = 20
|
33
33
|
|
34
|
-
attr_reader :logger, :size, :host, :port, :nodes, :sockets, :checked_out
|
34
|
+
attr_reader :logger, :size, :host, :port, :nodes, :sockets, :checked_out
|
35
35
|
|
36
|
-
def slave_ok?
|
36
|
+
def slave_ok?
|
37
37
|
@slave_ok
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
# Counter for generating unique request ids.
|
41
41
|
@@current_request_id = 0
|
42
42
|
|
@@ -45,7 +45,7 @@ module Mongo
|
|
45
45
|
#
|
46
46
|
# == Connecting
|
47
47
|
# If connecting to just one server, you may specify whether connection to slave is permitted.
|
48
|
-
#
|
48
|
+
#
|
49
49
|
# In all cases, the default host is "localhost" and the default port, is 27017.
|
50
50
|
#
|
51
51
|
# When specifying a pair, pair_or_host, is a hash with two keys: :left and :right. Each key maps to either
|
@@ -69,13 +69,15 @@ module Mongo
|
|
69
69
|
# :timeout :: When all of the connections to the pool are checked out,
|
70
70
|
# this is the number of seconds to wait for a new connection
|
71
71
|
# to be released before throwing an exception.
|
72
|
-
#
|
72
|
+
#
|
73
|
+
# Note that there are a few issues when using connection pooling with Ruby 1.9 on Windows. These
|
74
|
+
# should be resolved in the next release.
|
73
75
|
#
|
74
76
|
# === Examples:
|
75
77
|
#
|
76
78
|
# # localhost, 27017
|
77
79
|
# Connection.new
|
78
|
-
#
|
80
|
+
#
|
79
81
|
# # localhost, 27017
|
80
82
|
# Connection.new("localhost")
|
81
83
|
#
|
@@ -85,9 +87,9 @@ module Mongo
|
|
85
87
|
# # localhost, 3000, where this node may be a slave
|
86
88
|
# Connection.new("localhost", 3000, :slave_ok => true)
|
87
89
|
#
|
88
|
-
# # A pair of servers. The driver will always talk to master.
|
90
|
+
# # A pair of servers. The driver will always talk to master.
|
89
91
|
# # On connection errors, Mongo::ConnectionFailure will be raised.
|
90
|
-
# # See http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby
|
92
|
+
# # See http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby
|
91
93
|
# Connection.new({:left => ["db1.example.com", 27017],
|
92
94
|
# :right => ["db2.example.com", 27017]})
|
93
95
|
#
|
@@ -100,22 +102,20 @@ module Mongo
|
|
100
102
|
|
101
103
|
# Host and port of current master.
|
102
104
|
@host = @port = nil
|
103
|
-
|
105
|
+
|
104
106
|
# Lock for request ids.
|
105
107
|
@id_lock = Mutex.new
|
106
108
|
|
107
109
|
# Pool size and timeout.
|
108
110
|
@size = options[:pool_size] || 1
|
109
|
-
@timeout = options[:timeout] ||
|
110
|
-
|
111
|
-
# Cache of reserved sockets mapped to threads
|
112
|
-
@reserved_connections = {}
|
111
|
+
@timeout = options[:timeout] || 5.0
|
113
112
|
|
114
113
|
# Mutex for synchronizing pool access
|
115
|
-
@connection_mutex =
|
114
|
+
@connection_mutex = Mutex.new
|
115
|
+
@safe_mutex = Mutex.new
|
116
116
|
|
117
117
|
# Condition variable for signal and wait
|
118
|
-
@queue =
|
118
|
+
@queue = ConditionVariable.new
|
119
119
|
|
120
120
|
@sockets = []
|
121
121
|
@checked_out = []
|
@@ -123,7 +123,7 @@ module Mongo
|
|
123
123
|
if options[:auto_reconnect]
|
124
124
|
warn(":auto_reconnect is deprecated. see http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby")
|
125
125
|
end
|
126
|
-
|
126
|
+
|
127
127
|
# Slave ok can be true only if one node is specified
|
128
128
|
@slave_ok = options[:slave_ok] && @nodes.length == 1
|
129
129
|
@logger = options[:logger] || nil
|
@@ -177,7 +177,7 @@ module Mongo
|
|
177
177
|
# Increments and returns the next available request id.
|
178
178
|
def get_request_id
|
179
179
|
request_id = ''
|
180
|
-
@id_lock.synchronize do
|
180
|
+
@id_lock.synchronize do
|
181
181
|
request_id = @@current_request_id += 1
|
182
182
|
end
|
183
183
|
request_id
|
@@ -196,7 +196,7 @@ module Mongo
|
|
196
196
|
|
197
197
|
|
198
198
|
## Connections and pooling ##
|
199
|
-
|
199
|
+
|
200
200
|
# Sends a message to MongoDB.
|
201
201
|
#
|
202
202
|
# Takes a MongoDB opcode, +operation+, a message of class ByteBuffer,
|
@@ -211,19 +211,22 @@ module Mongo
|
|
211
211
|
end
|
212
212
|
|
213
213
|
# Sends a message to the database, waits for a response, and raises
|
214
|
-
#
|
214
|
+
# an exception if the operation has failed.
|
215
215
|
#
|
216
216
|
# Takes a MongoDB opcode, +operation+, a message of class ByteBuffer,
|
217
217
|
# +message+, the +db_name+, and an optional formatted +log_message+.
|
218
|
-
# Sends the message to the
|
218
|
+
# Sends the message to the database, adding the necessary headers.
|
219
219
|
def send_message_with_safe_check(operation, message, db_name, log_message=nil)
|
220
220
|
message_with_headers = add_message_headers(operation, message)
|
221
221
|
message_with_check = last_error_message(db_name)
|
222
222
|
@logger.debug(" MONGODB #{log_message || message}") if @logger
|
223
223
|
sock = checkout
|
224
224
|
packed_message = message_with_headers.append!(message_with_check).to_s
|
225
|
-
|
226
|
-
|
225
|
+
docs = num_received = cursor_id = ''
|
226
|
+
@safe_mutex.synchronize do
|
227
|
+
send_message_on_socket(packed_message, sock)
|
228
|
+
docs, num_received, cursor_id = receive(sock)
|
229
|
+
end
|
227
230
|
checkin(sock)
|
228
231
|
if num_received == 1 && error = docs[0]['err']
|
229
232
|
raise Mongo::OperationFailure, error
|
@@ -234,15 +237,18 @@ module Mongo
|
|
234
237
|
# Sends a message to the database and waits for the response.
|
235
238
|
#
|
236
239
|
# Takes a MongoDB opcode, +operation+, a message of class ByteBuffer,
|
237
|
-
# +message+, and an optional formatted +log_message+. This method
|
240
|
+
# +message+, and an optional formatted +log_message+. This method
|
238
241
|
# also takes an options socket for internal use with #connect_to_master.
|
239
242
|
def receive_message(operation, message, log_message=nil, socket=nil)
|
240
243
|
packed_message = add_message_headers(operation, message).to_s
|
241
244
|
@logger.debug(" MONGODB #{log_message || message}") if @logger
|
242
245
|
sock = socket || checkout
|
243
246
|
|
244
|
-
|
245
|
-
|
247
|
+
result = ''
|
248
|
+
@safe_mutex.synchronize do
|
249
|
+
send_message_on_socket(packed_message, sock)
|
250
|
+
result = receive(sock)
|
251
|
+
end
|
246
252
|
checkin(sock)
|
247
253
|
result
|
248
254
|
end
|
@@ -275,7 +281,7 @@ module Mongo
|
|
275
281
|
socket.close if socket
|
276
282
|
false
|
277
283
|
end
|
278
|
-
end
|
284
|
+
end
|
279
285
|
raise ConnectionFailure, "failed to connect to any given host:port" unless socket
|
280
286
|
end
|
281
287
|
|
@@ -291,55 +297,25 @@ module Mongo
|
|
291
297
|
sock.close
|
292
298
|
end
|
293
299
|
@host = @port = nil
|
294
|
-
@sockets.clear
|
300
|
+
@sockets.clear
|
295
301
|
@checked_out.clear
|
296
|
-
@reserved_connections.clear
|
297
302
|
end
|
298
303
|
|
299
304
|
private
|
300
305
|
|
301
|
-
# Get a socket from the pool, mapped to the current thread.
|
302
|
-
def checkout
|
303
|
-
#return @socket ||= checkout_new_socket if @size == 1
|
304
|
-
if sock = @reserved_connections[Thread.current.object_id]
|
305
|
-
sock
|
306
|
-
else
|
307
|
-
sock = obtain_socket
|
308
|
-
@reserved_connections[Thread.current.object_id] = sock
|
309
|
-
end
|
310
|
-
sock
|
311
|
-
end
|
312
|
-
|
313
306
|
# Return a socket to the pool.
|
314
307
|
def checkin(socket)
|
315
|
-
@connection_mutex.synchronize do
|
316
|
-
@reserved_connections.delete Thread.current.object_id
|
308
|
+
@connection_mutex.synchronize do
|
317
309
|
@checked_out.delete(socket)
|
318
310
|
@queue.signal
|
319
311
|
end
|
320
312
|
true
|
321
313
|
end
|
322
314
|
|
323
|
-
# Releases the connection for any dead threads.
|
324
|
-
# Called when the connection pool grows too large to free up more sockets.
|
325
|
-
def clear_stale_cached_connections!
|
326
|
-
keys = @reserved_connections.keys
|
327
|
-
|
328
|
-
Thread.list.each do |thread|
|
329
|
-
keys.delete(thread.object_id) if thread.alive?
|
330
|
-
end
|
331
|
-
|
332
|
-
keys.each do |key|
|
333
|
-
next unless @reserved_connections.has_key?(key)
|
334
|
-
checkin(@reserved_connections[key])
|
335
|
-
@reserved_connections.delete(key)
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
315
|
# Adds a new socket to the pool and checks it out.
|
340
316
|
#
|
341
|
-
# This method is called exclusively from #
|
342
|
-
# therefore, it runs within a mutex
|
317
|
+
# This method is called exclusively from #checkout;
|
318
|
+
# therefore, it runs within a mutex.
|
343
319
|
def checkout_new_socket
|
344
320
|
begin
|
345
321
|
socket = TCPSocket.new(@host, @port)
|
@@ -354,8 +330,8 @@ module Mongo
|
|
354
330
|
|
355
331
|
# Checks out the first available socket from the pool.
|
356
332
|
#
|
357
|
-
# This method is called exclusively from #
|
358
|
-
# therefore, it runs within a mutex
|
333
|
+
# This method is called exclusively from #checkout;
|
334
|
+
# therefore, it runs within a mutex.
|
359
335
|
def checkout_existing_socket
|
360
336
|
socket = (@sockets - @checked_out).first
|
361
337
|
@checked_out << socket
|
@@ -365,11 +341,17 @@ module Mongo
|
|
365
341
|
# Check out an existing socket or create a new socket if the maximum
|
366
342
|
# pool size has not been exceeded. Otherwise, wait for the next
|
367
343
|
# available socket.
|
368
|
-
def
|
369
|
-
|
370
|
-
|
344
|
+
def checkout
|
345
|
+
connect_to_master if !connected?
|
346
|
+
start_time = Time.now
|
347
|
+
loop do
|
348
|
+
if (Time.now - start_time) > @timeout
|
349
|
+
raise ConnectionTimeoutError, "could not obtain connection within " +
|
350
|
+
"#{@timeout} seconds. The max pool size is currently #{@size}; " +
|
351
|
+
"consider increasing the pool size or timeout."
|
352
|
+
end
|
371
353
|
|
372
|
-
|
354
|
+
@connection_mutex.synchronize do
|
373
355
|
socket = if @checked_out.size < @sockets.size
|
374
356
|
checkout_existing_socket
|
375
357
|
elsif @sockets.size < @size
|
@@ -378,39 +360,10 @@ module Mongo
|
|
378
360
|
|
379
361
|
return socket if socket
|
380
362
|
|
381
|
-
#
|
382
|
-
|
383
|
-
next if @checked_out.size < @sockets.size
|
384
|
-
|
385
|
-
# Otherwise, wait.
|
386
|
-
if wait
|
387
|
-
next
|
388
|
-
else
|
389
|
-
|
390
|
-
# Try to clear stale threads once more before failing.
|
391
|
-
clear_stale_cached_connections!
|
392
|
-
if @size == @sockets.size
|
393
|
-
raise ConnectionTimeoutError, "could not obtain connection within " +
|
394
|
-
"#{@timeout} seconds. The max pool size is currently #{@size}; " +
|
395
|
-
"consider increasing it."
|
396
|
-
end
|
397
|
-
end # if
|
398
|
-
end # loop
|
399
|
-
end # synchronize
|
400
|
-
end
|
401
|
-
|
402
|
-
if RUBY_VERSION >= '1.9'
|
403
|
-
# Ruby 1.9's Condition Variables don't support timeouts yet;
|
404
|
-
# until they do, we'll make do with this hack.
|
405
|
-
def wait
|
406
|
-
Timeout.timeout(@timeout) do
|
407
|
-
@queue.wait
|
363
|
+
# Otherwise, wait
|
364
|
+
@queue.wait(@connection_mutex)
|
408
365
|
end
|
409
366
|
end
|
410
|
-
else
|
411
|
-
def wait
|
412
|
-
@queue.wait(@timeout)
|
413
|
-
end
|
414
367
|
end
|
415
368
|
|
416
369
|
def receive(sock)
|
@@ -424,7 +377,7 @@ module Mongo
|
|
424
377
|
header.put_array(receive_message_on_socket(16, sock).unpack("C*"))
|
425
378
|
unless header.size == STANDARD_HEADER_SIZE
|
426
379
|
raise "Short read for DB response header: " +
|
427
|
-
"expected #{STANDARD_HEADER_SIZE} bytes, saw #{header.size}"
|
380
|
+
"expected #{STANDARD_HEADER_SIZE} bytes, saw #{header.size}"
|
428
381
|
end
|
429
382
|
header.rewind
|
430
383
|
size = header.get_int
|
@@ -473,7 +426,7 @@ module Mongo
|
|
473
426
|
message.put_array(BSON.serialize({:getlasterror => 1}, false).unpack("C*"))
|
474
427
|
add_message_headers(Mongo::Constants::OP_QUERY, message)
|
475
428
|
end
|
476
|
-
|
429
|
+
|
477
430
|
# Prepares a message for transmission to MongoDB by
|
478
431
|
# constructing a valid message header.
|
479
432
|
def add_message_headers(operation, message)
|
@@ -494,7 +447,7 @@ module Mongo
|
|
494
447
|
end
|
495
448
|
|
496
449
|
# Low-level method for sending a message on a socket.
|
497
|
-
# Requires a packed message and an available socket,
|
450
|
+
# Requires a packed message and an available socket,
|
498
451
|
def send_message_on_socket(packed_message, socket)
|
499
452
|
begin
|
500
453
|
socket.send(packed_message, 0)
|
@@ -537,7 +490,7 @@ module Mongo
|
|
537
490
|
[['localhost', DEFAULT_PORT]]
|
538
491
|
end
|
539
492
|
end
|
540
|
-
|
493
|
+
|
541
494
|
# Turns an array containing a host name string and a
|
542
495
|
# port number integer into a [host, port] pair array.
|
543
496
|
def pair_val_to_connection(a)
|
data/lib/mongo/constants.rb
CHANGED
data/lib/mongo/cursor.rb
CHANGED
@@ -19,7 +19,7 @@ module Mongo
|
|
19
19
|
include Mongo::Conversions
|
20
20
|
include Enumerable
|
21
21
|
|
22
|
-
attr_reader :collection, :selector, :admin, :fields,
|
22
|
+
attr_reader :collection, :selector, :admin, :fields,
|
23
23
|
:order, :hint, :snapshot, :timeout,
|
24
24
|
:full_collection_name
|
25
25
|
|
@@ -49,19 +49,17 @@ module Mongo
|
|
49
49
|
@query_run = false
|
50
50
|
end
|
51
51
|
|
52
|
-
# Return the next
|
53
|
-
|
54
|
-
def next_object
|
52
|
+
# Return the next document or nil if there are no more.
|
53
|
+
def next_document
|
55
54
|
refill_via_get_more if num_remaining == 0
|
56
|
-
|
55
|
+
doc = @cache.shift
|
57
56
|
|
58
|
-
if
|
59
|
-
err =
|
57
|
+
if doc && doc['$err']
|
58
|
+
err = doc['$err']
|
60
59
|
|
61
60
|
# If the server has stopped being the master (e.g., it's one of a
|
62
61
|
# pair but it has died or something like that) then we close that
|
63
|
-
# connection.
|
64
|
-
# servers, next request will re-open on master server.
|
62
|
+
# connection. The next request will re-open on master server.
|
65
63
|
if err == "not master"
|
66
64
|
raise ConnectionFailure, err
|
67
65
|
@connection.close
|
@@ -70,12 +68,17 @@ module Mongo
|
|
70
68
|
raise OperationFailure, err
|
71
69
|
end
|
72
70
|
|
73
|
-
|
71
|
+
doc
|
72
|
+
end
|
73
|
+
|
74
|
+
def next_object
|
75
|
+
warn "Cursor#next_object is deprecated; please use Cursor#next_document instead."
|
76
|
+
next_document
|
74
77
|
end
|
75
78
|
|
76
|
-
# Get the size of the
|
79
|
+
# Get the size of the result set for this query.
|
77
80
|
#
|
78
|
-
# Returns the number of objects in the
|
81
|
+
# Returns the number of objects in the result set for this query. Does
|
79
82
|
# not take limit and skip into account. Raises OperationFailure on a
|
80
83
|
# database error.
|
81
84
|
def count
|
@@ -88,17 +91,17 @@ module Mongo
|
|
88
91
|
raise OperationFailure, "Count failed: #{response['errmsg']}"
|
89
92
|
end
|
90
93
|
|
91
|
-
# Sort this cursor's
|
94
|
+
# Sort this cursor's results.
|
92
95
|
#
|
93
96
|
# Takes either a single key and a direction, or an array of [key,
|
94
|
-
# direction] pairs. Directions should be specified as Mongo::ASCENDING
|
95
|
-
#
|
97
|
+
# direction] pairs. Directions should be specified as Mongo::ASCENDING / Mongo::DESCENDING
|
98
|
+
# (or :ascending / :descending, :asc / :desc).
|
96
99
|
#
|
97
100
|
# Raises InvalidOperation if this cursor has already been used. Raises
|
98
|
-
# InvalidSortValueError if specified order is invalid.
|
101
|
+
# InvalidSortValueError if the specified order is invalid.
|
99
102
|
#
|
100
103
|
# This method overrides any sort order specified in the Collection#find
|
101
|
-
# method, and only the last sort applied has an effect
|
104
|
+
# method, and only the last sort applied has an effect.
|
102
105
|
def sort(key_or_list, direction=nil)
|
103
106
|
check_modifiable
|
104
107
|
|
@@ -130,7 +133,7 @@ module Mongo
|
|
130
133
|
|
131
134
|
# Skips the first +number_to_skip+ results of this cursor.
|
132
135
|
# Returns the current number_to_skip if no parameter is given.
|
133
|
-
#
|
136
|
+
#
|
134
137
|
# Raises InvalidOperation if this cursor has already been used.
|
135
138
|
#
|
136
139
|
# This method overrides any skip specified in the Collection#find method,
|
@@ -151,15 +154,15 @@ module Mongo
|
|
151
154
|
def each
|
152
155
|
num_returned = 0
|
153
156
|
while more? && (@limit <= 0 || num_returned < @limit)
|
154
|
-
yield
|
157
|
+
yield next_document
|
155
158
|
num_returned += 1
|
156
159
|
end
|
157
160
|
end
|
158
161
|
|
159
162
|
# Return all of the documents in this cursor as an array of hashes.
|
160
163
|
#
|
161
|
-
# Raises InvalidOperation if this cursor has already been used
|
162
|
-
#
|
164
|
+
# Raises InvalidOperation if this cursor has already been used or if
|
165
|
+
# this methods has already been called on the cursor.
|
163
166
|
#
|
164
167
|
# Use of this method is discouraged - iterating over a cursor is much
|
165
168
|
# more efficient in most cases.
|
@@ -168,22 +171,22 @@ module Mongo
|
|
168
171
|
rows = []
|
169
172
|
num_returned = 0
|
170
173
|
while more? && (@limit <= 0 || num_returned < @limit)
|
171
|
-
rows <<
|
174
|
+
rows << next_document
|
172
175
|
num_returned += 1
|
173
176
|
end
|
174
177
|
rows
|
175
178
|
end
|
176
179
|
|
177
|
-
# Returns an explain plan
|
180
|
+
# Returns an explain plan document for this cursor.
|
178
181
|
def explain
|
179
182
|
c = Cursor.new(@collection, query_options_hash.merge(:limit => -@limit.abs, :explain => true))
|
180
|
-
explanation = c.
|
183
|
+
explanation = c.next_document
|
181
184
|
c.close
|
182
185
|
|
183
186
|
explanation
|
184
187
|
end
|
185
188
|
|
186
|
-
#
|
189
|
+
# Closes the cursor.
|
187
190
|
#
|
188
191
|
# Note: if a cursor is read until exhausted (read until Mongo::Constants::OP_QUERY or
|
189
192
|
# Mongo::Constants::OP_GETMORE returns zero for the cursor id), there is no need to
|
@@ -211,20 +214,20 @@ module Mongo
|
|
211
214
|
# See http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-Mongo::Constants::OPQUERY
|
212
215
|
def query_opts
|
213
216
|
timeout = @timeout ? 0 : Mongo::Constants::OP_QUERY_NO_CURSOR_TIMEOUT
|
214
|
-
slave_ok = @connection.slave_ok? ? Mongo::Constants::OP_QUERY_SLAVE_OK : 0
|
217
|
+
slave_ok = @connection.slave_ok? ? Mongo::Constants::OP_QUERY_SLAVE_OK : 0
|
215
218
|
slave_ok + timeout
|
216
219
|
end
|
217
220
|
|
218
|
-
# Returns the query options
|
221
|
+
# Returns the query options for this Cursor.
|
219
222
|
def query_options_hash
|
220
223
|
{ :selector => @selector,
|
221
|
-
:fields => @fields,
|
222
|
-
:admin => @admin,
|
223
|
-
:skip => @skip_num,
|
224
|
-
:limit => @limit_num,
|
225
|
-
:order => @order,
|
226
|
-
:hint => @hint,
|
227
|
-
:snapshot => @snapshot,
|
224
|
+
:fields => @fields,
|
225
|
+
:admin => @admin,
|
226
|
+
:skip => @skip_num,
|
227
|
+
:limit => @limit_num,
|
228
|
+
:order => @order,
|
229
|
+
:hint => @hint,
|
230
|
+
:snapshot => @snapshot,
|
228
231
|
:timeout => @timeout }
|
229
232
|
end
|
230
233
|
|
@@ -245,7 +248,7 @@ module Mongo
|
|
245
248
|
end
|
246
249
|
end
|
247
250
|
|
248
|
-
# Set query selector hash. If the selector is a Code or String object,
|
251
|
+
# Set the query selector hash. If the selector is a Code or String object,
|
249
252
|
# the selector will be used in a $where clause.
|
250
253
|
# See http://www.mongodb.org/display/DOCS/Server-side+Code+Execution
|
251
254
|
def convert_selector_for_query(selector)
|
@@ -266,20 +269,21 @@ module Mongo
|
|
266
269
|
@order || @explain || @hint || @snapshot
|
267
270
|
end
|
268
271
|
|
272
|
+
# Return a number of documents remaining for this cursor.
|
269
273
|
def num_remaining
|
270
274
|
refill_via_get_more if @cache.length == 0
|
271
275
|
@cache.length
|
272
276
|
end
|
273
277
|
|
274
278
|
# Internal method, not for general use. Return +true+ if there are
|
275
|
-
# more records to retrieve. This
|
276
|
-
# #each is responsible for doing that.
|
279
|
+
# more records to retrieve. This method does not check @limit;
|
280
|
+
# Cursor#each is responsible for doing that.
|
277
281
|
def more?
|
278
282
|
num_remaining > 0
|
279
283
|
end
|
280
284
|
|
281
285
|
def refill_via_get_more
|
282
|
-
return if
|
286
|
+
return if send_initial_query || @cursor_id.zero?
|
283
287
|
message = ByteBuffer.new
|
284
288
|
# Reserved.
|
285
289
|
message.put_int(0)
|
@@ -290,7 +294,7 @@ module Mongo
|
|
290
294
|
|
291
295
|
# Number of results to return; db decides for now.
|
292
296
|
message.put_int(0)
|
293
|
-
|
297
|
+
|
294
298
|
# Cursor id.
|
295
299
|
message.put_long(@cursor_id)
|
296
300
|
results, @n_received, @cursor_id = @connection.receive_message(Mongo::Constants::OP_GET_MORE, message, "cursor.get_more()", @socket)
|
@@ -299,13 +303,13 @@ module Mongo
|
|
299
303
|
end
|
300
304
|
|
301
305
|
# Run query the first time we request an object from the wire
|
302
|
-
def
|
306
|
+
def send_initial_query
|
303
307
|
if @query_run
|
304
308
|
false
|
305
309
|
else
|
306
310
|
message = construct_query_message
|
307
|
-
results, @n_received, @cursor_id = @connection.receive_message(Mongo::Constants::OP_QUERY, message,
|
308
|
-
(query_log_message if @connection.logger), @socket)
|
311
|
+
results, @n_received, @cursor_id = @connection.receive_message(Mongo::Constants::OP_QUERY, message,
|
312
|
+
(query_log_message if @connection.logger), @socket)
|
309
313
|
@cache += results
|
310
314
|
@query_run = true
|
311
315
|
close_cursor_if_query_complete
|
@@ -331,7 +335,7 @@ module Mongo
|
|
331
335
|
|
332
336
|
def query_log_message
|
333
337
|
"#{@admin ? 'admin' : @db.name}.#{@collection.name}.find(#{@selector.inspect}, #{@fields ? @fields.inspect : '{}'})" +
|
334
|
-
"#{@skip != 0 ? ('.skip(' + @skip.to_s + ')') : ''}#{@limit != 0 ? ('.limit(' + @limit.to_s + ')') : ''}"
|
338
|
+
"#{@skip != 0 ? ('.skip(' + @skip.to_s + ')') : ''}#{@limit != 0 ? ('.limit(' + @limit.to_s + ')') : ''}"
|
335
339
|
end
|
336
340
|
|
337
341
|
def selector_with_special_query_fields
|
@@ -349,7 +353,7 @@ module Mongo
|
|
349
353
|
when String, Symbol then string_as_sort_parameters(@order)
|
350
354
|
when Array then array_as_sort_parameters(@order)
|
351
355
|
else
|
352
|
-
raise InvalidSortValueError, "Illegal sort clause, '#{@order.class.name}'; must be of the form " +
|
356
|
+
raise InvalidSortValueError, "Illegal sort clause, '#{@order.class.name}'; must be of the form " +
|
353
357
|
"[['field1', '(ascending|descending)'], ['field2', '(ascending|descending)']]"
|
354
358
|
end
|
355
359
|
end
|