mongo 1.2.4 → 1.3.0.rc0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +13 -25
- data/Rakefile +9 -1
- data/docs/HISTORY.md +19 -0
- data/docs/RELEASES.md +33 -0
- data/docs/REPLICA_SETS.md +4 -3
- data/lib/mongo.rb +20 -2
- data/lib/mongo/collection.rb +15 -2
- data/lib/mongo/connection.rb +75 -14
- data/lib/mongo/cursor.rb +12 -4
- data/lib/mongo/db.rb +3 -3
- data/lib/mongo/exceptions.rb +3 -0
- data/lib/mongo/gridfs/grid_io.rb +88 -7
- data/lib/mongo/repl_set_connection.rb +29 -11
- data/lib/mongo/util/pool.rb +15 -6
- data/lib/mongo/util/timeout.rb +42 -0
- data/lib/mongo/util/uri_parser.rb +5 -1
- data/test/auxillary/fork_test.rb +30 -0
- data/test/bson/bson_test.rb +68 -27
- data/test/bson/byte_buffer_test.rb +11 -0
- data/test/bson/object_id_test.rb +14 -1
- data/test/bson/ordered_hash_test.rb +7 -0
- data/test/bson/timestamp_test.rb +24 -0
- data/test/collection_test.rb +41 -24
- data/test/connection_test.rb +33 -2
- data/test/conversions_test.rb +10 -11
- data/test/cursor_fail_test.rb +1 -1
- data/test/cursor_message_test.rb +1 -1
- data/test/cursor_test.rb +33 -4
- data/test/db_api_test.rb +13 -2
- data/test/db_test.rb +3 -3
- data/test/grid_file_system_test.rb +0 -1
- data/test/grid_io_test.rb +72 -1
- data/test/grid_test.rb +16 -16
- data/test/replica_sets/connect_test.rb +8 -0
- data/test/replica_sets/query_test.rb +10 -0
- data/test/support/hash_with_indifferent_access.rb +0 -13
- data/test/support_test.rb +0 -1
- data/test/test_helper.rb +27 -8
- data/test/timeout_test.rb +14 -0
- data/test/unit/collection_test.rb +1 -1
- data/test/unit/connection_test.rb +0 -13
- data/test/unit/cursor_test.rb +16 -6
- data/test/unit/db_test.rb +9 -11
- data/test/unit/repl_set_connection_test.rb +0 -13
- data/test/unit/safe_test.rb +1 -1
- metadata +15 -23
data/README.md
CHANGED
@@ -10,6 +10,7 @@ This documentation includes other articles of interest, include:
|
|
10
10
|
4. [GridFS in Ruby](http://api.mongodb.org/ruby/current/file.GridFS.html).
|
11
11
|
5. [Frequently Asked Questions](http://api.mongodb.org/ruby/current/file.FAQ.html).
|
12
12
|
6. [History](http://api.mongodb.org/ruby/current/file.HISTORY.html).
|
13
|
+
6. [Release plan](http://api.mongodb.org/ruby/current/file.RELEASES.html).
|
13
14
|
7. [Credits](http://api.mongodb.org/ruby/current/file.CREDITS.html).
|
14
15
|
|
15
16
|
Here's a quick code sample. Again, see the [MongoDB Ruby Tutorial](http://api.mongodb.org/ruby/current/file.TUTORIAL.html)
|
@@ -141,32 +142,11 @@ To set up a pooled connection to a single MongoDB instance:
|
|
141
142
|
Though the pooling architecture will undoubtedly evolve, it currently owes much credit
|
142
143
|
to the connection pooling implementations in ActiveRecord and PyMongo.
|
143
144
|
|
144
|
-
##
|
145
|
-
|
146
|
-
When Passenger and Unicorn are in smart spawning mode you need to be sure that child
|
147
|
-
processes will create a new connection to the database. In Passenger, this can be handled like so:
|
148
|
-
|
149
|
-
if defined?(PhusionPassenger)
|
150
|
-
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
151
|
-
if forked
|
152
|
-
# Reset all connection objects. How you do this depends on where
|
153
|
-
# you keep your connection object. In any case, call the #connect
|
154
|
-
# method on the connection object. For example:
|
155
|
-
# CONN.connect
|
156
|
-
#
|
157
|
-
# If you're using MongoMapper:
|
158
|
-
# MongoMapper.connection.connect
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
145
|
+
## Forking
|
162
146
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
# Handle reconnection
|
167
|
-
end
|
168
|
-
|
169
|
-
The above code should be put into a Rails initializer or similar initialization script.
|
147
|
+
Certain Ruby application servers work by forking, and it has long been necessary to
|
148
|
+
re-establish the child process's connection to the database after fork. But with the release
|
149
|
+
of v1.3.0, the Ruby driver detects forking and reconnects automatically.
|
170
150
|
|
171
151
|
## String Encoding
|
172
152
|
|
@@ -271,6 +251,14 @@ Notes:
|
|
271
251
|
* Cursors will timeout on the server after 10 minutes. If you need to keep a cursor
|
272
252
|
open for more than 10 minutes, specify `:timeout => false` when you create the cursor.
|
273
253
|
|
254
|
+
## Socket timeouts
|
255
|
+
|
256
|
+
The Ruby driver support timeouts on socket read operations. To enable them, set the
|
257
|
+
`:op_timeout` option when you create a `Mongo::Connection` object.
|
258
|
+
|
259
|
+
If implementing higher-level timeouts, using tools like `Rack::Timeout`, it's very important
|
260
|
+
to call `Mongo::Connection#close` to prevent the subsequent operation from receiving the previous
|
261
|
+
request.
|
274
262
|
|
275
263
|
# Testing
|
276
264
|
|
data/Rakefile
CHANGED
@@ -77,41 +77,49 @@ namespace :test do
|
|
77
77
|
Rake::TestTask.new(:rs) do |t|
|
78
78
|
t.test_files = FileList['test/replica_sets/*_test.rb']
|
79
79
|
t.verbose = true
|
80
|
+
t.ruby_opts << '-w'
|
80
81
|
end
|
81
82
|
|
82
83
|
Rake::TestTask.new(:unit) do |t|
|
83
84
|
t.test_files = FileList['test/unit/*_test.rb']
|
84
85
|
t.verbose = true
|
86
|
+
t.ruby_opts << '-w'
|
85
87
|
end
|
86
88
|
|
87
89
|
Rake::TestTask.new(:functional) do |t|
|
88
90
|
t.test_files = FileList['test/*_test.rb']
|
89
91
|
t.verbose = true
|
92
|
+
t.ruby_opts << '-w'
|
90
93
|
end
|
91
94
|
|
92
95
|
Rake::TestTask.new(:pooled_threading) do |t|
|
93
96
|
t.test_files = FileList['test/threading/*_test.rb']
|
94
97
|
t.verbose = true
|
98
|
+
t.ruby_opts << '-w'
|
95
99
|
end
|
96
100
|
|
97
101
|
Rake::TestTask.new(:auto_reconnect) do |t|
|
98
102
|
t.test_files = FileList['test/auxillary/autoreconnect_test.rb']
|
99
103
|
t.verbose = true
|
104
|
+
t.ruby_opts << '-w'
|
100
105
|
end
|
101
106
|
|
102
107
|
Rake::TestTask.new(:authentication) do |t|
|
103
108
|
t.test_files = FileList['test/auxillary/authentication_test.rb']
|
104
109
|
t.verbose = true
|
110
|
+
t.ruby_opts << '-w'
|
105
111
|
end
|
106
112
|
|
107
113
|
Rake::TestTask.new(:new_features) do |t|
|
108
114
|
t.test_files = FileList['test/auxillary/1.4_features.rb']
|
109
115
|
t.verbose = true
|
116
|
+
t.ruby_opts << '-w'
|
110
117
|
end
|
111
118
|
|
112
119
|
Rake::TestTask.new(:bson) do |t|
|
113
120
|
t.test_files = FileList['test/bson/*_test.rb']
|
114
121
|
t.verbose = true
|
122
|
+
t.ruby_opts << '-w'
|
115
123
|
end
|
116
124
|
|
117
125
|
task :drop_databases do |t|
|
@@ -138,7 +146,7 @@ task :ydoc do
|
|
138
146
|
require File.join(File.dirname(__FILE__), 'lib', 'mongo')
|
139
147
|
out = File.join('ydoc', Mongo::VERSION)
|
140
148
|
FileUtils.rm_rf('ydoc')
|
141
|
-
system "yardoc lib/**/*.rb lib/mongo/**/*.rb lib/bson/**/*.rb -e yard/yard_ext.rb -p yard/templates -o #{out} --title MongoRuby-#{Mongo::VERSION} --files docs/TUTORIAL.md,docs/GridFS.md,docs/FAQ.md,docs/REPLICA_SETS.md,docs/WRITE_CONCERN.md,docs/HISTORY.md,docs/CREDITS.md,docs/1.0_UPGRADE.md"
|
149
|
+
system "yardoc lib/**/*.rb lib/mongo/**/*.rb lib/bson/**/*.rb -e yard/yard_ext.rb -p yard/templates -o #{out} --title MongoRuby-#{Mongo::VERSION} --files docs/TUTORIAL.md,docs/GridFS.md,docs/FAQ.md,docs/REPLICA_SETS.md,docs/WRITE_CONCERN.md,docs/HISTORY.md,docs/CREDITS.md,docs/1.0_UPGRADE.md,docs/RELEASES.md"
|
142
150
|
end
|
143
151
|
|
144
152
|
namespace :bamboo do
|
data/docs/HISTORY.md
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
# MongoDB Ruby Driver History
|
2
2
|
|
3
|
+
### 1.3.0.rc0
|
4
|
+
2011-3-29
|
5
|
+
|
6
|
+
* Add option to set timeouts on socket read calls. Use
|
7
|
+
the :op_timeout option when creating a new connection.
|
8
|
+
* Add StringIO methods to GridIO objects
|
9
|
+
* Support for BSON timestamp type with BSON::Timestamp
|
10
|
+
* Change the BSON binary subtype from 2 to 0
|
11
|
+
* Remove private method Connection#reset_conection
|
12
|
+
and deprecate public method ReplSetConnection#reset_connection
|
13
|
+
* ByteBuffer#== and OrderedHash#dup (FooBarWidget)
|
14
|
+
* Better check for UTF8 validity in Ruby 1.9
|
15
|
+
* Added previously removed Connection#host and Connection#port
|
16
|
+
* Added transformers to allow Mongo::Cursor to allow instantiated objects (jnunemaker)
|
17
|
+
* Automated reconnection on fork
|
18
|
+
* Added Cursor#next alias for Cursor#next_document
|
19
|
+
* Audit tests after enabling warnings (wpiekutowski)
|
20
|
+
* Various bug fixes thanks to FooBarWidget, Datanoise, Malitogeek
|
21
|
+
|
3
22
|
### 1.2.4
|
4
23
|
2011-2-23
|
5
24
|
|
data/docs/RELEASES.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# MongoDB Ruby Driver Release Plan
|
2
|
+
|
3
|
+
This is a description of a formalized release plan that will take effect
|
4
|
+
with version 1.3.0.
|
5
|
+
|
6
|
+
## Semantic versioning
|
7
|
+
|
8
|
+
The most significant difference is that releases will now adhere to the conventions of
|
9
|
+
[semantic versioning](http://semver.org). In particular, we will strictly abide by the
|
10
|
+
following release rules:
|
11
|
+
|
12
|
+
1. Patch versions of the driver (Z in x.y.Z) will be released only when backward-compatible bug fixes are introduced. A bug fix is defined as an internal change that fixes incorrect behavior.
|
13
|
+
|
14
|
+
2. Minor versions (Y in x.Y.z) will be released if new, backward-compatible functionality is introduced to the public API.
|
15
|
+
|
16
|
+
3. Major versions (X in X.y.z) will be incremented if any backward-incompatibl changes are introduced to the public API.
|
17
|
+
|
18
|
+
This policy will clearly indicate to users when an upgrade may affect their code. As a side effect, version numbers will climb more quickly than before.
|
19
|
+
|
20
|
+
|
21
|
+
## Release checklist
|
22
|
+
|
23
|
+
Before each relese to Rubygems.org, the following steps will be taken:
|
24
|
+
|
25
|
+
1. All driver tests will be run on Linux, OS X, and Windows via continuous integration system.
|
26
|
+
|
27
|
+
2. HISTORY file will document all significant commits.
|
28
|
+
|
29
|
+
3. Version number will be incremented per the semantic version spec described above.
|
30
|
+
|
31
|
+
4. Appropriate branches and tags will be created in Git repository, as necessary.
|
32
|
+
|
33
|
+
5. Docs will be updated to the latest version of the driver and posted [online](http://api.mongodb.org/ruby/current/index.html).
|
data/docs/REPLICA_SETS.md
CHANGED
@@ -6,12 +6,13 @@ Here follow a few considerations for those using the MongoDB Ruby driver with [r
|
|
6
6
|
|
7
7
|
First, make sure that you've configured and initialized a replica set.
|
8
8
|
|
9
|
-
Use `ReplSetConnection.new` to connect to a replica set
|
9
|
+
Use `ReplSetConnection.new` to connect to a replica set. This method, which accepts a variable number of arugments,
|
10
|
+
takes a list of seed nodes followed by any connection options. You'll want to specify at least two seed nodes. This gives
|
11
|
+
the driver more chances to connect in the event that any one seed node is offline. Once the driver connects, it will
|
12
|
+
cache the replica set topology as reported by the given seed node and use that information if a failover is later required.
|
10
13
|
|
11
14
|
@connection = ReplSetConnection.new(['n1.mydb.net', 27017], ['n2.mydb.net', 27017], ['n3.mydb.net', 27017])
|
12
15
|
|
13
|
-
The driver will attempt to connect to a master node and, when found, will replace all seed nodes with known members of the replica set.
|
14
|
-
|
15
16
|
### Read slaves
|
16
17
|
|
17
18
|
If you want to read from a seconday node, you can pass :read_secondary => true to ReplSetConnection#new.
|
data/lib/mongo.rb
CHANGED
@@ -19,7 +19,7 @@
|
|
19
19
|
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
20
20
|
|
21
21
|
module Mongo
|
22
|
-
VERSION = "1.
|
22
|
+
VERSION = "1.3.0.rc0"
|
23
23
|
end
|
24
24
|
|
25
25
|
module Mongo
|
@@ -76,4 +76,22 @@ if RUBY_PLATFORM =~ /java/
|
|
76
76
|
end
|
77
77
|
require 'mongo/gridfs/grid_file_system'
|
78
78
|
|
79
|
-
|
79
|
+
# Use SystemTimer on Ruby 1.8
|
80
|
+
if !defined?(RUBY_ENGINE) || (RUBY_ENGINE == 'ruby' && RUBY_VERSION < '1.9.0')
|
81
|
+
begin
|
82
|
+
require 'system_timer'
|
83
|
+
if SystemTimer.method(:timeout).arity.abs != 2
|
84
|
+
raise LoadError
|
85
|
+
end
|
86
|
+
Mongo::TimeoutHandler = SystemTimer
|
87
|
+
rescue LoadError
|
88
|
+
warn "Could not load SystemTimer >= v1.2.0. Falling back to timeout.rb. " +
|
89
|
+
"SystemTimer is STRONGLY recommended for timeouts in Ruby 1.8.7. " +
|
90
|
+
"See http://ph7spot.com/blog/system-timer-1-2-release for details."
|
91
|
+
require 'timeout'
|
92
|
+
Mongo::TimeoutHandler = Timeout
|
93
|
+
end
|
94
|
+
else
|
95
|
+
require 'timeout'
|
96
|
+
Mongo::TimeoutHandler = Timeout
|
97
|
+
end
|
data/lib/mongo/collection.rb
CHANGED
@@ -157,6 +157,8 @@ module Mongo
|
|
157
157
|
# the normal cursor timeout behavior of the mongod process. When +false+, the returned cursor will never timeout. Note
|
158
158
|
# that disabling timeout will only work when #find is invoked with a block. This is to prevent any inadvertant failure to
|
159
159
|
# close the cursor, as the cursor is explicitly closed when block code finishes.
|
160
|
+
# @option opts [Block] :transformer (nil) a block for tranforming returned documents.
|
161
|
+
# This is normally used by object mappers to convert each returned document to an instance of a class.
|
160
162
|
#
|
161
163
|
# @raise [ArgumentError]
|
162
164
|
# if timeout is set to false and find is not invoked in a block
|
@@ -175,6 +177,7 @@ module Mongo
|
|
175
177
|
snapshot = opts.delete(:snapshot)
|
176
178
|
batch_size = opts.delete(:batch_size)
|
177
179
|
timeout = (opts.delete(:timeout) == false) ? false : true
|
180
|
+
transformer = opts.delete(:transformer)
|
178
181
|
|
179
182
|
if timeout == false && !block_given?
|
180
183
|
raise ArgumentError, "Collection#find must be invoked with a block when timeout is disabled."
|
@@ -188,8 +191,18 @@ module Mongo
|
|
188
191
|
|
189
192
|
raise RuntimeError, "Unknown options [#{opts.inspect}]" unless opts.empty?
|
190
193
|
|
191
|
-
cursor = Cursor.new(self,
|
192
|
-
:
|
194
|
+
cursor = Cursor.new(self, {
|
195
|
+
:selector => selector,
|
196
|
+
:fields => fields,
|
197
|
+
:skip => skip,
|
198
|
+
:limit => limit,
|
199
|
+
:order => sort,
|
200
|
+
:hint => hint,
|
201
|
+
:snapshot => snapshot,
|
202
|
+
:timeout => timeout,
|
203
|
+
:batch_size => batch_size,
|
204
|
+
:transformer => transformer,
|
205
|
+
})
|
193
206
|
|
194
207
|
if block_given?
|
195
208
|
yield cursor
|
data/lib/mongo/connection.rb
CHANGED
@@ -68,6 +68,8 @@ module Mongo
|
|
68
68
|
# @option opts [Float] :timeout (5.0) When all of the connections a pool are checked out,
|
69
69
|
# this is the number of seconds to wait for a new connection to be released before throwing an exception.
|
70
70
|
# Note: this setting is relevant only for multi-threaded applications (which in Ruby are rare).
|
71
|
+
# @option opts [Float] :op_timeout (nil) The number of seconds to wait for a read operation to time out.
|
72
|
+
# Disabled by default.
|
71
73
|
#
|
72
74
|
# @example localhost, 27017
|
73
75
|
# Connection.new
|
@@ -157,6 +159,20 @@ module Mongo
|
|
157
159
|
end
|
158
160
|
end
|
159
161
|
|
162
|
+
# The host name used for this connection.
|
163
|
+
#
|
164
|
+
# @return [String]
|
165
|
+
def host
|
166
|
+
@primary_pool.host
|
167
|
+
end
|
168
|
+
|
169
|
+
# The port used for this connection.
|
170
|
+
#
|
171
|
+
# @return [Integer]
|
172
|
+
def port
|
173
|
+
@primary_pool.port
|
174
|
+
end
|
175
|
+
|
160
176
|
# Fsync, then lock the mongod process against writes. Use this to get
|
161
177
|
# the datafiles in a state safe for snapshotting, backing up, etc.
|
162
178
|
#
|
@@ -329,13 +345,22 @@ module Mongo
|
|
329
345
|
self["admin"].command(oh)
|
330
346
|
end
|
331
347
|
|
332
|
-
|
348
|
+
# Checks if a server is alive. This command will return immediately
|
349
|
+
# even if the server is in a lock.
|
350
|
+
#
|
351
|
+
# @return [Hash]
|
352
|
+
def ping
|
353
|
+
self["admin"].command({:ping => 1})
|
354
|
+
end
|
355
|
+
|
356
|
+
# Get the build information for the current connection.
|
333
357
|
#
|
334
358
|
# @return [Hash]
|
335
359
|
def server_info
|
336
360
|
self["admin"].command({:buildinfo => 1})
|
337
361
|
end
|
338
362
|
|
363
|
+
|
339
364
|
# Get the build version of the current server.
|
340
365
|
#
|
341
366
|
# @return [Mongo::ServerVersion]
|
@@ -450,7 +475,7 @@ module Mongo
|
|
450
475
|
#
|
451
476
|
# @raise [ConnectionFailure] if unable to connect to any host or port.
|
452
477
|
def connect
|
453
|
-
|
478
|
+
close
|
454
479
|
|
455
480
|
config = check_is_master(@host_to_try)
|
456
481
|
if config
|
@@ -482,6 +507,22 @@ module Mongo
|
|
482
507
|
@primary_pool && @primary_pool.host && @primary_pool.port
|
483
508
|
end
|
484
509
|
|
510
|
+
# Determine if the connection is active. In a normal case the *server_info* operation
|
511
|
+
# will be performed without issues, but if the connection was dropped by the server or
|
512
|
+
# for some reason the sockets are unsynchronized, a ConnectionFailure will be raised and
|
513
|
+
# the return will be false.
|
514
|
+
#
|
515
|
+
# @return [Boolean]
|
516
|
+
def active?
|
517
|
+
return false unless connected?
|
518
|
+
|
519
|
+
ping
|
520
|
+
true
|
521
|
+
|
522
|
+
rescue ConnectionFailure
|
523
|
+
false
|
524
|
+
end
|
525
|
+
|
485
526
|
# Determine whether we're reading from a primary node. If false,
|
486
527
|
# this connection connects to a secondary node and @slave_ok is true.
|
487
528
|
#
|
@@ -495,6 +536,7 @@ module Mongo
|
|
495
536
|
def close
|
496
537
|
@primary_pool.close if @primary_pool
|
497
538
|
@primary_pool = nil
|
539
|
+
@primary = nil
|
498
540
|
end
|
499
541
|
|
500
542
|
# Returns the maximum BSON object size as returned by the core server.
|
@@ -559,6 +601,9 @@ module Mongo
|
|
559
601
|
@pool_size = opts[:pool_size] || 1
|
560
602
|
@timeout = opts[:timeout] || 5.0
|
561
603
|
|
604
|
+
# Timeout on socket read operation.
|
605
|
+
@op_timeout = opts[:op_timeout] || nil
|
606
|
+
|
562
607
|
# Mutex for synchronizing pool access
|
563
608
|
@connection_mutex = Mutex.new
|
564
609
|
|
@@ -611,7 +656,7 @@ module Mongo
|
|
611
656
|
msg += payload.values_at(:selector, :document, :documents, :fields ).compact.map(&:inspect).join(', ') + ")"
|
612
657
|
msg += ".skip(#{payload[:skip]})" if payload[:skip]
|
613
658
|
msg += ".limit(#{payload[:limit]})" if payload[:limit]
|
614
|
-
msg += ".sort(#{payload[:
|
659
|
+
msg += ".sort(#{payload[:order]})" if payload[:order]
|
615
660
|
@logger.debug "MONGODB #{msg}"
|
616
661
|
end
|
617
662
|
|
@@ -624,7 +669,6 @@ module Mongo
|
|
624
669
|
# TODO: evaluate whether this method is actually necessary
|
625
670
|
def reset_connection
|
626
671
|
close
|
627
|
-
@primary = nil
|
628
672
|
end
|
629
673
|
|
630
674
|
def check_is_master(node)
|
@@ -793,20 +837,37 @@ module Mongo
|
|
793
837
|
# Requires length and an available socket.
|
794
838
|
def receive_message_on_socket(length, socket)
|
795
839
|
begin
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
chunk = new_binary_string
|
801
|
-
while message.length < length
|
802
|
-
socket.read(length - message.length, chunk)
|
803
|
-
raise ConnectionFailure, "connection closed" unless chunk.length > 0
|
804
|
-
message << chunk
|
840
|
+
if @op_timeout
|
841
|
+
message = nil
|
842
|
+
Mongo::TimeoutHandler.timeout(@op_timeout, OperationTimeout) do
|
843
|
+
message = receive_data(length, socket)
|
805
844
|
end
|
845
|
+
else
|
846
|
+
message = receive_data(length, socket)
|
806
847
|
end
|
807
848
|
rescue => ex
|
808
849
|
close
|
809
|
-
|
850
|
+
|
851
|
+
if ex.class == OperationTimeout
|
852
|
+
raise OperationTimeout, "Timed out waiting on socket read."
|
853
|
+
else
|
854
|
+
raise ConnectionFailure, "Operation failed with the following exception: #{ex}"
|
855
|
+
end
|
856
|
+
end
|
857
|
+
message
|
858
|
+
end
|
859
|
+
|
860
|
+
def receive_data(length, socket)
|
861
|
+
message = new_binary_string
|
862
|
+
socket.read(length, message)
|
863
|
+
raise ConnectionFailure, "connection closed" unless message && message.length > 0
|
864
|
+
if message.length < length
|
865
|
+
chunk = new_binary_string
|
866
|
+
while message.length < length
|
867
|
+
socket.read(length - message.length, chunk)
|
868
|
+
raise ConnectionFailure, "connection closed" unless chunk.length > 0
|
869
|
+
message << chunk
|
870
|
+
end
|
810
871
|
end
|
811
872
|
message
|
812
873
|
end
|
data/lib/mongo/cursor.rb
CHANGED
@@ -23,7 +23,7 @@ module Mongo
|
|
23
23
|
|
24
24
|
attr_reader :collection, :selector, :fields,
|
25
25
|
:order, :hint, :snapshot, :timeout,
|
26
|
-
:full_collection_name
|
26
|
+
:full_collection_name, :transformer
|
27
27
|
|
28
28
|
# Create a new cursor.
|
29
29
|
#
|
@@ -34,6 +34,8 @@ module Mongo
|
|
34
34
|
#
|
35
35
|
# @core cursors constructor_details
|
36
36
|
def initialize(collection, opts={})
|
37
|
+
@cursor_id = nil
|
38
|
+
|
37
39
|
@db = collection.db
|
38
40
|
@collection = collection
|
39
41
|
@connection = @db.connection
|
@@ -52,6 +54,7 @@ module Mongo
|
|
52
54
|
@tailable = opts[:tailable] || false
|
53
55
|
@closed = false
|
54
56
|
@query_run = false
|
57
|
+
@transformer = opts[:transformer]
|
55
58
|
batch_size(opts[:batch_size] || 0)
|
56
59
|
|
57
60
|
@full_collection_name = "#{@collection.db.name}.#{@collection.name}"
|
@@ -86,8 +89,13 @@ module Mongo
|
|
86
89
|
raise OperationFailure, err
|
87
90
|
end
|
88
91
|
|
89
|
-
|
92
|
+
if @transformer.nil?
|
93
|
+
doc
|
94
|
+
else
|
95
|
+
@transformer.call(doc) if doc
|
96
|
+
end
|
90
97
|
end
|
98
|
+
alias :next :next_document
|
91
99
|
|
92
100
|
# Reset this cursor on the server. Cursor options, such as the
|
93
101
|
# query string and the values for skip and limit, are preserved.
|
@@ -307,8 +315,8 @@ module Mongo
|
|
307
315
|
def query_options_hash
|
308
316
|
{ :selector => @selector,
|
309
317
|
:fields => @fields,
|
310
|
-
:skip => @
|
311
|
-
:limit => @
|
318
|
+
:skip => @skip,
|
319
|
+
:limit => @limit,
|
312
320
|
:order => @order,
|
313
321
|
:hint => @hint,
|
314
322
|
:snapshot => @snapshot,
|