mongo 0.18.2 → 0.18.3

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.
Files changed (51) hide show
  1. data/README.rdoc +37 -28
  2. data/Rakefile +19 -0
  3. data/bin/objectid_benchmark.rb +23 -0
  4. data/examples/admin.rb +7 -6
  5. data/examples/capped.rb +3 -4
  6. data/examples/cursor.rb +4 -3
  7. data/examples/gridfs.rb +3 -2
  8. data/examples/index_test.rb +10 -9
  9. data/examples/info.rb +3 -2
  10. data/examples/queries.rb +3 -2
  11. data/examples/simple.rb +3 -2
  12. data/examples/strict.rb +2 -1
  13. data/examples/types.rb +4 -3
  14. data/lib/mongo.rb +29 -12
  15. data/lib/mongo/admin.rb +17 -2
  16. data/lib/mongo/collection.rb +230 -169
  17. data/lib/mongo/connection.rb +136 -91
  18. data/lib/mongo/cursor.rb +68 -40
  19. data/lib/mongo/db.rb +247 -123
  20. data/lib/mongo/{errors.rb → exceptions.rb} +6 -5
  21. data/lib/mongo/gridfs.rb +6 -0
  22. data/lib/mongo/gridfs/grid_store.rb +142 -94
  23. data/lib/mongo/types/binary.rb +11 -1
  24. data/lib/mongo/types/code.rb +6 -1
  25. data/lib/mongo/types/dbref.rb +7 -2
  26. data/lib/mongo/types/min_max_keys.rb +58 -0
  27. data/lib/mongo/types/objectid.rb +76 -20
  28. data/lib/mongo/types/regexp_of_holding.rb +5 -0
  29. data/lib/mongo/util/bson_ruby.rb +36 -2
  30. data/lib/mongo/util/byte_buffer.rb +18 -2
  31. data/lib/mongo/util/conversions.rb +6 -5
  32. data/lib/mongo/util/ordered_hash.rb +3 -1
  33. data/lib/mongo/util/support.rb +3 -0
  34. data/lib/mongo/util/xml_to_ruby.rb +7 -0
  35. data/test/test_bson.rb +48 -0
  36. data/test/test_collection.rb +13 -0
  37. data/test/test_connection.rb +35 -0
  38. data/test/test_conversions.rb +1 -1
  39. data/test/test_cursor.rb +37 -5
  40. data/test/test_db.rb +51 -2
  41. data/test/test_db_api.rb +4 -7
  42. data/test/test_grid_store.rb +10 -0
  43. data/test/test_objectid.rb +16 -2
  44. data/test/test_ordered_hash.rb +14 -0
  45. data/test/threading/test_threading_large_pool.rb +4 -4
  46. data/test/unit/db_test.rb +43 -0
  47. metadata +5 -7
  48. data/examples/benchmarks.rb +0 -42
  49. data/examples/blog.rb +0 -76
  50. data/lib/mongo/constants.rb +0 -15
  51. data/test/mongo-qa/_common.rb +0 -8
@@ -20,11 +20,10 @@ require 'thread'
20
20
 
21
21
  module Mongo
22
22
 
23
- # A connection to MongoDB.
23
+ # Instantiates and manages connections to MongoDB.
24
24
  class Connection
25
25
 
26
- # We need to make sure that all connection abort when
27
- # a ConnectionError is raised.
26
+ # Abort connections if a ConnectionError is raised.
28
27
  Thread.abort_on_exception = true
29
28
 
30
29
  DEFAULT_PORT = 27017
@@ -33,70 +32,59 @@ module Mongo
33
32
 
34
33
  attr_reader :logger, :size, :host, :port, :nodes, :sockets, :checked_out
35
34
 
36
- def slave_ok?
37
- @slave_ok
38
- end
39
-
40
35
  # Counter for generating unique request ids.
41
36
  @@current_request_id = 0
42
37
 
43
- # Creates a connection to MongoDB. Specify either one or a pair of servers,
38
+ # Create a connection to MongoDB. Specify either one or a pair of servers,
44
39
  # along with a maximum connection pool size and timeout.
45
40
  #
46
- # == Connecting
47
41
  # If connecting to just one server, you may specify whether connection to slave is permitted.
42
+ # In all cases, the default host is "localhost" and the default port is 27017.
48
43
  #
49
- # In all cases, the default host is "localhost" and the default port, is 27017.
50
- #
51
- # When specifying a pair, pair_or_host, is a hash with two keys: :left and :right. Each key maps to either
44
+ # When specifying a pair, +pair_or_host+, is a hash with two keys: :left and :right. Each key maps to either
52
45
  # * a server name, in which case port is 27017,
53
46
  # * a port number, in which case the server is "localhost", or
54
47
  # * an array containing [server_name, port_number]
55
48
  #
56
- # === Options
57
- #
58
- # :slave_ok :: Defaults to +false+. Must be set to +true+ when connecting
59
- # to a single, slave node.
60
- #
61
- # :logger :: Optional Logger instance to which driver usage information
62
- # will be logged.
63
- #
64
- # :auto_reconnect :: DEPRECATED. See http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby
65
- #
66
- # :pool_size :: The maximum number of socket connections that can be opened
67
- # that can be opened to the database.
68
- #
69
- # :timeout :: When all of the connections to the pool are checked out,
70
- # this is the number of seconds to wait for a new connection
71
- # to be released before throwing an exception.
72
- #
73
49
  # Note that there are a few issues when using connection pooling with Ruby 1.9 on Windows. These
74
50
  # should be resolved in the next release.
75
51
  #
76
- # === Examples:
52
+ # @param [String, Hash] pair_or_host See explanation above.
53
+ # @param [Integer] port specify a port number here if only one host is being specified. Leave nil if
54
+ # specifying a pair of servers in +pair_or_host+.
77
55
  #
78
- # # localhost, 27017
79
- # Connection.new
56
+ # @option options [Boolean] :slave_ok (false) Must be set to +true+ when connecting
57
+ # to a single, slave node.
58
+ # @option options [Logger, #debug] :logger (nil) Logger instance to receive driver operation log.
59
+ # @option options [Boolean] :auto_reconnect DEPRECATED. See http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby
60
+ # @option options [Integer] :pool_size (1) The maximum number of socket connections that can be opened to the database.
61
+ # @option options [Float] :timeout (5.0) When all of the connections to the pool are checked out,
62
+ # this is the number of seconds to wait for a new connection to be released before throwing an exception.
80
63
  #
81
- # # localhost, 27017
82
- # Connection.new("localhost")
83
64
  #
84
- # # localhost, 3000, max 5 connections, with max 5 seconds of wait time.
85
- # Connection.new("localhost", 3000, :pool_size => 5, :timeout => 5)
65
+ # @example localhost, 27017
66
+ # Connection.new
86
67
  #
87
- # # localhost, 3000, where this node may be a slave
88
- # Connection.new("localhost", 3000, :slave_ok => true)
68
+ # @example localhost, 27017
69
+ # Connection.new("localhost")
89
70
  #
90
- # # A pair of servers. The driver will always talk to master.
91
- # # On connection errors, Mongo::ConnectionFailure will be raised.
92
- # # See http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby
93
- # Connection.new({:left => ["db1.example.com", 27017],
71
+ # @example localhost, 3000, max 5 connections, with max 5 seconds of wait time.
72
+ # Connection.new("localhost", 3000, :pool_size => 5, :timeout => 5)
73
+ #
74
+ # @example localhost, 3000, where this node may be a slave
75
+ # Connection.new("localhost", 3000, :slave_ok => true)
76
+ #
77
+ # @example A pair of servers. The driver will always talk to master.
78
+ # # On connection errors, Mongo::ConnectionFailure will be raised.
79
+ # Connection.new({:left => ["db1.example.com", 27017],
94
80
  # :right => ["db2.example.com", 27017]})
95
81
  #
96
- # A pair of servers, with connection pooling. Not the nil param placeholder for port.
97
- # Connection.new({:left => ["db1.example.com", 27017],
98
- # :right => ["db2.example.com", 27017]}, nil,
99
- # :pool_size => 20, :timeout => 5)
82
+ # @example A pair of servers with connection pooling enabled. Note the nil param placeholder for port.
83
+ # Connection.new({:left => ["db1.example.com", 27017],
84
+ # :right => ["db2.example.com", 27017]}, nil,
85
+ # :pool_size => 20, :timeout => 5)
86
+ #
87
+ # @see http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby Replica pairs in Ruby
100
88
  def initialize(pair_or_host=nil, port=nil, options={})
101
89
  @nodes = format_pair(pair_or_host, port)
102
90
 
@@ -124,7 +112,7 @@ module Mongo
124
112
  warn(":auto_reconnect is deprecated. see http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby")
125
113
  end
126
114
 
127
- # Slave ok can be true only if one node is specified
115
+ # slave_ok can be true only if one node is specified
128
116
  @slave_ok = options[:slave_ok] && @nodes.length == 1
129
117
  @logger = options[:logger] || nil
130
118
  @options = options
@@ -133,8 +121,10 @@ module Mongo
133
121
  connect_to_master if should_connect
134
122
  end
135
123
 
136
- # Returns a hash with all database names and their respective sizes on
137
- # disk.
124
+ # Return a hash with all database names
125
+ # and their respective sizes on disk.
126
+ #
127
+ # @return [Hash]
138
128
  def database_info
139
129
  doc = self['admin'].command(:listDatabases => 1)
140
130
  returning({}) do |info|
@@ -142,39 +132,57 @@ module Mongo
142
132
  end
143
133
  end
144
134
 
145
- # Returns an array of database names.
135
+ # Return an array of database names.
136
+ #
137
+ # @return [Array]
146
138
  def database_names
147
139
  database_info.keys
148
140
  end
149
141
 
150
- # Returns the database named +db_name+. The slave_ok and
151
- # See DB#new for other options you can pass in.
142
+ # Return a database with the given name.
143
+ # See DB#new for valid options hash parameters.
144
+ #
145
+ # @param [String] db_name a valid database name.
146
+ #
147
+ # @return [Mongo::DB]
152
148
  def db(db_name, options={})
153
149
  DB.new(db_name, self, options.merge(:logger => @logger))
154
150
  end
155
151
 
156
- # Returns the database named +db_name+.
152
+ # Shortcut for returning a database. Use DB#db to accept options.
153
+ #
154
+ # @param [String] db_name a valid database name.
155
+ #
156
+ # @return [Mongo::DB]
157
157
  def [](db_name)
158
158
  DB.new(db_name, self, :logger => @logger)
159
159
  end
160
160
 
161
- # Drops the database +name+.
161
+ # Drop a database.
162
+ #
163
+ # @param [String] name name of an existing database.
162
164
  def drop_database(name)
163
165
  self[name].command(:dropDatabase => 1)
164
166
  end
165
167
 
166
- # Copies the database +from+ on the local server to +to+ on the specified +host+.
168
+ # Copy the database +from+ on the local server to +to+ on the specified +host+.
167
169
  # +host+ defaults to 'localhost' if no value is provided.
168
- def copy_database(from, to, host="localhost")
170
+ #
171
+ # @param [String] from name of the database to copy from.
172
+ # @param [String] to name of the database to copy to.
173
+ # @param [String] from_host host of the 'from' database.
174
+ def copy_database(from, to, from_host="localhost")
169
175
  oh = OrderedHash.new
170
176
  oh[:copydb] = 1
171
- oh[:fromhost] = host
177
+ oh[:fromhost] = from_host
172
178
  oh[:fromdb] = from
173
179
  oh[:todb] = to
174
180
  self["admin"].command(oh)
175
181
  end
176
182
 
177
- # Increments and returns the next available request id.
183
+ # Increment and return the next available request id.
184
+ #
185
+ # return [Integer]
178
186
  def get_request_id
179
187
  request_id = ''
180
188
  @id_lock.synchronize do
@@ -183,51 +191,75 @@ module Mongo
183
191
  request_id
184
192
  end
185
193
 
186
- # Returns the build information for the current connection.
194
+ # Get the build information for the current connection.
195
+ #
196
+ # @return [Hash]
187
197
  def server_info
188
198
  db("admin").command({:buildinfo => 1}, {:admin => true, :check_response => true})
189
199
  end
190
200
 
191
- # Gets the build version of the current server.
192
- # Returns a ServerVersion object for comparability.
201
+ # Get the build version of the current server.
202
+ #
203
+ # @return [Mongo::ServerVersion]
204
+ # object allowing easy comparability of version.
193
205
  def server_version
194
206
  ServerVersion.new(server_info["version"])
195
207
  end
196
208
 
209
+ # Is it okay to connect to a slave?
210
+ #
211
+ # @return [Boolean]
212
+ def slave_ok?
213
+ @slave_ok
214
+ end
215
+
197
216
 
198
217
  ## Connections and pooling ##
199
218
 
200
- # Sends a message to MongoDB.
219
+ # Send a message to MongoDB, adding the necessary headers.
201
220
  #
202
- # Takes a MongoDB opcode, +operation+, a message of class ByteBuffer,
203
- # +message+, and an optional formatted +log_message+.
204
- # Sends the message to the databse, adding the necessary headers.
221
+ # @param [Integer] operation a MongoDB opcode.
222
+ # @param [ByteBuffer] message a message to send to the database.
223
+ # @param [String] log_message text version of +message+ for logging.
224
+ #
225
+ # @return [True]
205
226
  def send_message(operation, message, log_message=nil)
206
227
  @logger.debug(" MONGODB #{log_message || message}") if @logger
207
- packed_message = add_message_headers(operation, message).to_s
208
- socket = checkout
209
- send_message_on_socket(packed_message, socket)
210
- checkin(socket)
228
+ begin
229
+ packed_message = add_message_headers(operation, message).to_s
230
+ socket = checkout
231
+ send_message_on_socket(packed_message, socket)
232
+ ensure
233
+ checkin(socket)
234
+ end
211
235
  end
212
236
 
213
237
  # Sends a message to the database, waits for a response, and raises
214
238
  # an exception if the operation has failed.
215
239
  #
216
- # Takes a MongoDB opcode, +operation+, a message of class ByteBuffer,
217
- # +message+, the +db_name+, and an optional formatted +log_message+.
218
- # Sends the message to the database, adding the necessary headers.
240
+ # @param [Integer] operation a MongoDB opcode.
241
+ # @param [ByteBuffer] message a message to send to the database.
242
+ # @param [String] db_name the name of the database. used on call to get_last_error.
243
+ # @param [String] log_message text version of +message+ for logging.
244
+ #
245
+ # @return [Array]
246
+ # An array whose indexes include [0] documents returned, [1] number of document received,
247
+ # and [3] a cursor_id.
219
248
  def send_message_with_safe_check(operation, message, db_name, log_message=nil)
220
249
  message_with_headers = add_message_headers(operation, message)
221
250
  message_with_check = last_error_message(db_name)
222
251
  @logger.debug(" MONGODB #{log_message || message}") if @logger
223
- sock = checkout
224
- packed_message = message_with_headers.append!(message_with_check).to_s
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)
252
+ begin
253
+ sock = checkout
254
+ packed_message = message_with_headers.append!(message_with_check).to_s
255
+ docs = num_received = cursor_id = ''
256
+ @safe_mutex.synchronize do
257
+ send_message_on_socket(packed_message, sock)
258
+ docs, num_received, cursor_id = receive(sock)
259
+ end
260
+ ensure
261
+ checkin(sock)
229
262
  end
230
- checkin(sock)
231
263
  if num_received == 1 && error = docs[0]['err']
232
264
  raise Mongo::OperationFailure, error
233
265
  end
@@ -236,25 +268,35 @@ module Mongo
236
268
 
237
269
  # Sends a message to the database and waits for the response.
238
270
  #
239
- # Takes a MongoDB opcode, +operation+, a message of class ByteBuffer,
240
- # +message+, and an optional formatted +log_message+. This method
241
- # also takes an options socket for internal use with #connect_to_master.
271
+ # @param [Integer] operation a MongoDB opcode.
272
+ # @param [ByteBuffer] message a message to send to the database.
273
+ # @param [String] log_message text version of +message+ for logging.
274
+ # @param [Socket] socket a socket to use in lieu of checking out a new one.
275
+ #
276
+ # @return [Array]
277
+ # An array whose indexes include [0] documents returned, [1] number of document received,
278
+ # and [3] a cursor_id.
242
279
  def receive_message(operation, message, log_message=nil, socket=nil)
243
280
  packed_message = add_message_headers(operation, message).to_s
244
281
  @logger.debug(" MONGODB #{log_message || message}") if @logger
245
- sock = socket || checkout
282
+ begin
283
+ sock = socket || checkout
246
284
 
247
- result = ''
248
- @safe_mutex.synchronize do
249
- send_message_on_socket(packed_message, sock)
250
- result = receive(sock)
285
+ result = ''
286
+ @safe_mutex.synchronize do
287
+ send_message_on_socket(packed_message, sock)
288
+ result = receive(sock)
289
+ end
290
+ ensure
291
+ checkin(sock)
251
292
  end
252
- checkin(sock)
253
293
  result
254
294
  end
255
295
 
256
- # Creates a new socket and tries to connect to master.
257
- # If successful, sets @host and @port to master and returns the socket.
296
+ # Create a new socket and attempt to connect to master.
297
+ # If successful, sets host and port to master and returns the socket.
298
+ #
299
+ # @raise [ConnectionFailure] if unable to connect to any host or port.
258
300
  def connect_to_master
259
301
  close
260
302
  @host = @port = nil
@@ -286,7 +328,7 @@ module Mongo
286
328
  end
287
329
 
288
330
  # Are we connected to MongoDB? This is determined by checking whether
289
- # @host and @port have values, since they're set to nil on calls to #close.
331
+ # host and port have values, since they're set to nil on calls to #close.
290
332
  def connected?
291
333
  @host && @port
292
334
  end
@@ -361,6 +403,9 @@ module Mongo
361
403
  return socket if socket
362
404
 
363
405
  # Otherwise, wait
406
+ if @logger
407
+ @logger.warn "Waiting for available connection; #{@checked_out.size} of #{@size} connections checked out."
408
+ end
364
409
  @queue.wait(@connection_mutex)
365
410
  end
366
411
  end
@@ -25,7 +25,10 @@ module Mongo
25
25
 
26
26
  # Create a new cursor.
27
27
  #
28
- # Should not be called directly by application developers.
28
+ # Note: cursors are created when executing queries using [Collection#find] and other
29
+ # similar methods. Application developers shouldn't have to create cursors manually.
30
+ #
31
+ # @return [Cursor]
29
32
  def initialize(collection, options={})
30
33
  @db = collection.db
31
34
  @collection = collection
@@ -49,7 +52,9 @@ module Mongo
49
52
  @query_run = false
50
53
  end
51
54
 
52
- # Return the next document or nil if there are no more.
55
+ # Get the next document specified the cursor options.
56
+ #
57
+ # @return [Hash, Nil] the next document or Nil if no documents remain.
53
58
  def next_document
54
59
  refill_via_get_more if num_remaining == 0
55
60
  doc = @cache.shift
@@ -71,6 +76,7 @@ module Mongo
71
76
  doc
72
77
  end
73
78
 
79
+ # @deprecated use Cursor#next_document instead.
74
80
  def next_object
75
81
  warn "Cursor#next_object is deprecated; please use Cursor#next_document instead."
76
82
  next_document
@@ -78,9 +84,10 @@ module Mongo
78
84
 
79
85
  # Get the size of the result set for this query.
80
86
  #
81
- # Returns the number of objects in the result set for this query. Does
82
- # not take limit and skip into account. Raises OperationFailure on a
83
- # database error.
87
+ # @return [Integer] the number of objects in the result set for this query. Does
88
+ # not take limit and skip into account.
89
+ #
90
+ # @raise [OperationFailure] on a database error.
84
91
  def count
85
92
  command = OrderedHash["count", @collection.name,
86
93
  "query", @selector,
@@ -93,15 +100,16 @@ module Mongo
93
100
 
94
101
  # Sort this cursor's results.
95
102
  #
96
- # Takes either a single key and a direction, or an array of [key,
97
- # direction] pairs. Directions should be specified as Mongo::ASCENDING / Mongo::DESCENDING
98
- # (or :ascending / :descending, :asc / :desc).
99
- #
100
- # Raises InvalidOperation if this cursor has already been used. Raises
101
- # InvalidSortValueError if the specified order is invalid.
102
- #
103
103
  # This method overrides any sort order specified in the Collection#find
104
104
  # method, and only the last sort applied has an effect.
105
+ #
106
+ # @param [Symbol, Array] key_or_list either 1) a key to sort by or 2)
107
+ # an array of [key, direction] pairs to sort by. Direction should
108
+ # be specified as Mongo::ASCENDING (or :ascending / :asc) or Mongo::DESCENDING (or :descending / :desc)
109
+ #
110
+ # @raise [InvalidOperation] if this cursor has already been used.
111
+ #
112
+ # @raise [InvalidSortValueError] if the specified order is invalid.
105
113
  def sort(key_or_list, direction=nil)
106
114
  check_modifiable
107
115
 
@@ -115,13 +123,14 @@ module Mongo
115
123
  self
116
124
  end
117
125
 
118
- # Limits the number of results to be returned by this cursor.
119
- # Returns the current number_to_return if no parameter is given.
120
- #
121
- # Raises InvalidOperation if this cursor has already been used.
126
+ # Limit the number of results to be returned by this cursor.
122
127
  #
123
128
  # This method overrides any limit specified in the Collection#find method,
124
129
  # and only the last limit applied has an effect.
130
+ #
131
+ # @return [Integer] the current number_to_return if no parameter is given.
132
+ #
133
+ # @raise [InvalidOperation] if this cursor has already been used.
125
134
  def limit(number_to_return=nil)
126
135
  return @limit unless number_to_return
127
136
  check_modifiable
@@ -134,10 +143,12 @@ module Mongo
134
143
  # Skips the first +number_to_skip+ results of this cursor.
135
144
  # Returns the current number_to_skip if no parameter is given.
136
145
  #
137
- # Raises InvalidOperation if this cursor has already been used.
138
- #
139
146
  # This method overrides any skip specified in the Collection#find method,
140
147
  # and only the last skip applied has an effect.
148
+ #
149
+ # @return [Integer]
150
+ #
151
+ # @raise [InvalidOperation] if this cursor has already been used.
141
152
  def skip(number_to_skip=nil)
142
153
  return @skip unless number_to_skip
143
154
  check_modifiable
@@ -151,6 +162,13 @@ module Mongo
151
162
  # block.
152
163
  #
153
164
  # Iterating over an entire cursor will close it.
165
+ #
166
+ # @yield passes each document to a block for processing.
167
+ #
168
+ # @example if 'comments' represents a collection of comments:
169
+ # comments.find.each do |doc|
170
+ # puts doc['user']
171
+ # end
154
172
  def each
155
173
  num_returned = 0
156
174
  while more? && (@limit <= 0 || num_returned < @limit)
@@ -159,13 +177,15 @@ module Mongo
159
177
  end
160
178
  end
161
179
 
162
- # Return all of the documents in this cursor as an array of hashes.
180
+ # Receive all the documents from this cursor as an array of hashes.
163
181
  #
164
- # Raises InvalidOperation if this cursor has already been used or if
165
- # this methods has already been called on the cursor.
182
+ # Note: use of this method is discouraged - in most cases, it's much more
183
+ # efficient to retrieve documents as you need them by iterating over the cursor.
166
184
  #
167
- # Use of this method is discouraged - iterating over a cursor is much
168
- # more efficient in most cases.
185
+ # @return [Array] an array of documents.
186
+ #
187
+ # @raise [InvalidOperation] if this cursor has already been used or if
188
+ # this method has already been called on the cursor.
169
189
  def to_a
170
190
  raise InvalidOperation, "can't call Cursor#to_a on a used cursor" if @query_run
171
191
  rows = []
@@ -177,7 +197,9 @@ module Mongo
177
197
  rows
178
198
  end
179
199
 
180
- # Returns an explain plan document for this cursor.
200
+ # Get the explain plan for this cursor.
201
+ #
202
+ # @return [Hash] a document containing the explain plan for this cursor.
181
203
  def explain
182
204
  c = Cursor.new(@collection, query_options_hash.merge(:limit => -@limit.abs, :explain => true))
183
205
  explanation = c.next_document
@@ -186,19 +208,19 @@ module Mongo
186
208
  explanation
187
209
  end
188
210
 
189
- # Closes the cursor.
211
+ # Close the cursor.
190
212
  #
191
213
  # Note: if a cursor is read until exhausted (read until Mongo::Constants::OP_QUERY or
192
214
  # Mongo::Constants::OP_GETMORE returns zero for the cursor id), there is no need to
193
- # close it by calling this method.
215
+ # close it manually.
216
+ #
217
+ # Note also: Collection#find takes an optional block argument which can be used to
218
+ # ensure that your cursors get closed.
194
219
  #
195
- # Collection#find takes an optional block argument which can be used to
196
- # ensure that your cursors get closed. See the documentation for
197
- # Collection#find for details.
220
+ # @return [True]
198
221
  def close
199
222
  if @cursor_id
200
- message = ByteBuffer.new
201
- message.put_int(0)
223
+ message = ByteBuffer.new([0, 0, 0, 0])
202
224
  message.put_int(1)
203
225
  message.put_long(@cursor_id)
204
226
  @connection.send_message(Mongo::Constants::OP_KILL_CURSORS, message, "cursor.close()")
@@ -207,18 +229,26 @@ module Mongo
207
229
  @closed = true
208
230
  end
209
231
 
210
- # Returns true if this cursor is closed, false otherwise.
232
+ # Is this cursor closed?
233
+ #
234
+ # @return [Boolean]
211
235
  def closed?; @closed; end
212
236
 
213
237
  # Returns an integer indicating which query options have been selected.
214
- # See http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-Mongo::Constants::OPQUERY
238
+ #
239
+ # @return [Integer]
240
+ #
241
+ # @see http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-Mongo::Constants::OPQUERY
242
+ # The MongoDB wire protocol.
215
243
  def query_opts
216
244
  timeout = @timeout ? 0 : Mongo::Constants::OP_QUERY_NO_CURSOR_TIMEOUT
217
245
  slave_ok = @connection.slave_ok? ? Mongo::Constants::OP_QUERY_SLAVE_OK : 0
218
246
  slave_ok + timeout
219
247
  end
220
248
 
221
- # Returns the query options for this Cursor.
249
+ # Get the query options for this Cursor.
250
+ #
251
+ # @return [Hash]
222
252
  def query_options_hash
223
253
  { :selector => @selector,
224
254
  :fields => @fields,
@@ -233,7 +263,7 @@ module Mongo
233
263
 
234
264
  private
235
265
 
236
- # Converts the +:fields+ parameter from a single field name or an array
266
+ # Convert the +:fields+ parameter from a single field name or an array
237
267
  # of fields names to a hash, with the field names for keys and '1' for each
238
268
  # value.
239
269
  def convert_fields_for_query(fields)
@@ -284,9 +314,7 @@ module Mongo
284
314
 
285
315
  def refill_via_get_more
286
316
  return if send_initial_query || @cursor_id.zero?
287
- message = ByteBuffer.new
288
- # Reserved.
289
- message.put_int(0)
317
+ message = ByteBuffer.new([0, 0, 0, 0])
290
318
 
291
319
  # DB name.
292
320
  db_name = @admin ? 'admin' : @db.name
@@ -328,8 +356,8 @@ module Mongo
328
356
  if query_contains_special_fields?
329
357
  selector = selector_with_special_query_fields
330
358
  end
331
- message.put_array(BSON.serialize(selector, false).unpack("C*"))
332
- message.put_array(BSON.serialize(@fields, false).unpack("C*")) if @fields
359
+ message.put_array(BSON.serialize(selector, false).to_a)
360
+ message.put_array(BSON.serialize(@fields, false).to_a) if @fields
333
361
  message
334
362
  end
335
363