mongodb-mongo 0.10.1 → 0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/mongo/collection.rb +47 -0
- data/lib/mongo/cursor.rb +11 -7
- data/lib/mongo/db.rb +30 -19
- data/lib/mongo/util/bson.rb +22 -4
- data/mongo-ruby-driver.gemspec +2 -1
- data/tests/test_bson.rb +16 -2
- data/tests/test_db.rb +12 -0
- data/tests/test_db_api.rb +95 -5
- data/tests/test_threading.rb +37 -0
- metadata +2 -1
data/lib/mongo/collection.rb
CHANGED
@@ -26,6 +26,24 @@ module XGen
|
|
26
26
|
attr_reader :db, :name, :hint
|
27
27
|
|
28
28
|
def initialize(db, name)
|
29
|
+
case name
|
30
|
+
when Symbol, String
|
31
|
+
else
|
32
|
+
raise RuntimeError, "new_name must be a string or symbol"
|
33
|
+
end
|
34
|
+
|
35
|
+
name = name.to_s
|
36
|
+
|
37
|
+
if name.empty? or name.include? ".."
|
38
|
+
raise RuntimeError, "collection names cannot be empty"
|
39
|
+
end
|
40
|
+
if name.include? "$" and not name.match(/^\$cmd/)
|
41
|
+
raise RuntimeError, "collection names must not contain '$'"
|
42
|
+
end
|
43
|
+
if name.match(/^\./) or name.match(/\.$/)
|
44
|
+
raise RuntimeError, "collection names must not start or end with '.'"
|
45
|
+
end
|
46
|
+
|
29
47
|
@db, @name = db, name
|
30
48
|
@hint = nil
|
31
49
|
end
|
@@ -192,6 +210,35 @@ EOS
|
|
192
210
|
}))["result"]
|
193
211
|
end
|
194
212
|
|
213
|
+
# Rename this collection.
|
214
|
+
#
|
215
|
+
# If operating in auth mode, client must be authorized as an admin to
|
216
|
+
# perform this operation. Raises an error if +new_name+ is an invalid
|
217
|
+
# collection name.
|
218
|
+
#
|
219
|
+
# :new_name :: new name for this collection
|
220
|
+
def rename(new_name)
|
221
|
+
case new_name
|
222
|
+
when Symbol, String
|
223
|
+
else
|
224
|
+
raise RuntimeError, "new_name must be a string or symbol"
|
225
|
+
end
|
226
|
+
|
227
|
+
new_name = new_name.to_s
|
228
|
+
|
229
|
+
if new_name.empty? or new_name.include? ".."
|
230
|
+
raise RuntimeError, "collection names cannot be empty"
|
231
|
+
end
|
232
|
+
if new_name.include? "$"
|
233
|
+
raise RuntimeError, "collection names must not contain '$'"
|
234
|
+
end
|
235
|
+
if new_name.match(/^\./) or new_name.match(/\.$/)
|
236
|
+
raise RuntimeError, "collection names must not start or end with '.'"
|
237
|
+
end
|
238
|
+
|
239
|
+
@db.rename_collection(@name, new_name)
|
240
|
+
end
|
241
|
+
|
195
242
|
# Get information on the indexes for the collection +collection_name+.
|
196
243
|
# Returns a hash where the keys are index names (as returned by
|
197
244
|
# Collection#create_index and the values are lists of [key, direction]
|
data/lib/mongo/cursor.rb
CHANGED
@@ -31,8 +31,8 @@ module XGen
|
|
31
31
|
|
32
32
|
attr_reader :db, :collection, :query
|
33
33
|
|
34
|
-
def initialize(db, collection, query)
|
35
|
-
@db, @collection, @query = db, collection, query
|
34
|
+
def initialize(db, collection, query, admin=false)
|
35
|
+
@db, @collection, @query, @admin = db, collection, query, admin
|
36
36
|
@num_to_return = @query.number_to_return || 0
|
37
37
|
@cache = []
|
38
38
|
@closed = false
|
@@ -194,8 +194,10 @@ module XGen
|
|
194
194
|
def refill_via_get_more
|
195
195
|
send_query_if_needed
|
196
196
|
return if @cursor_id == 0
|
197
|
-
@db.
|
198
|
-
|
197
|
+
@db._synchronize {
|
198
|
+
@db.send_to_db(GetMoreMessage.new(@admin ? 'admin' : @db.name, @collection.name, @cursor_id))
|
199
|
+
read_all
|
200
|
+
}
|
199
201
|
end
|
200
202
|
|
201
203
|
def object_from_stream
|
@@ -212,9 +214,11 @@ module XGen
|
|
212
214
|
def send_query_if_needed
|
213
215
|
# Run query first time we request an object from the wire
|
214
216
|
unless @query_run
|
215
|
-
@db.
|
216
|
-
|
217
|
-
|
217
|
+
@db._synchronize {
|
218
|
+
@db.send_query_message(QueryMessage.new(@admin ? 'admin' : @db.name, @collection.name, @query))
|
219
|
+
@query_run = true
|
220
|
+
read_all
|
221
|
+
}
|
218
222
|
end
|
219
223
|
end
|
220
224
|
|
data/lib/mongo/db.rb
CHANGED
@@ -173,12 +173,11 @@ module XGen
|
|
173
173
|
raise "error logging out: #{doc.inspect}" unless ok?(doc)
|
174
174
|
end
|
175
175
|
|
176
|
-
# Returns an array of collection names
|
177
|
-
# "database_name.collection_name".
|
176
|
+
# Returns an array of collection names in this database.
|
178
177
|
def collection_names
|
179
178
|
names = collections_info.collect { |doc| doc['name'] || '' }
|
180
|
-
names.
|
181
|
-
names
|
179
|
+
names = names.delete_if {|name| name.index(@name).nil? || name.index('$')}
|
180
|
+
names.map {|name| name.sub(@name + '.', '')}
|
182
181
|
end
|
183
182
|
|
184
183
|
# Returns a cursor over query result hashes. Each hash contains a
|
@@ -205,7 +204,7 @@ module XGen
|
|
205
204
|
# :max :: Max number of records in a capped collection. Optional.
|
206
205
|
def create_collection(name, options={})
|
207
206
|
# First check existence
|
208
|
-
if collection_names.include?(
|
207
|
+
if collection_names.include?(name)
|
209
208
|
if strict?
|
210
209
|
raise "Collection #{name} already exists. Currently in strict mode."
|
211
210
|
else
|
@@ -230,14 +229,14 @@ module XGen
|
|
230
229
|
# new collection. If +strict+ is true, will raise an error if
|
231
230
|
# collection +name+ does not already exists.
|
232
231
|
def collection(name)
|
233
|
-
return Collection.new(self, name) if !strict? || collection_names.include?(
|
232
|
+
return Collection.new(self, name) if !strict? || collection_names.include?(name)
|
234
233
|
raise "Collection #{name} doesn't exist. Currently in strict mode."
|
235
234
|
end
|
236
235
|
|
237
236
|
# Drop collection +name+. Returns +true+ on success or if the
|
238
237
|
# collection does not exist, +false+ otherwise.
|
239
238
|
def drop_collection(name)
|
240
|
-
return true unless collection_names.include?(
|
239
|
+
return true unless collection_names.include?(name)
|
241
240
|
|
242
241
|
ok?(db_command(:drop => name))
|
243
242
|
end
|
@@ -340,21 +339,19 @@ module XGen
|
|
340
339
|
# Note that the query gets sent lazily; the cursor calls
|
341
340
|
# #send_query_message when needed. If the caller never requests an
|
342
341
|
# object from the cursor, the query never gets sent.
|
343
|
-
def query(collection, query)
|
344
|
-
Cursor.new(self, collection, query)
|
342
|
+
def query(collection, query, admin=false)
|
343
|
+
Cursor.new(self, collection, query, admin)
|
345
344
|
end
|
346
345
|
|
347
346
|
# Used by a Cursor to lazily send the query to the database.
|
348
347
|
def send_query_message(query_message)
|
349
|
-
|
350
|
-
send_to_db(query_message)
|
351
|
-
}
|
348
|
+
send_to_db(query_message)
|
352
349
|
end
|
353
350
|
|
354
351
|
# Remove the records that match +selector+ from +collection_name+.
|
355
352
|
# Normally called by Collection#remove or Collection#clear.
|
356
353
|
def remove_from_db(collection_name, selector)
|
357
|
-
|
354
|
+
_synchronize {
|
358
355
|
send_to_db(RemoveMessage.new(@name, collection_name, selector))
|
359
356
|
}
|
360
357
|
end
|
@@ -362,7 +359,7 @@ module XGen
|
|
362
359
|
# Update records in +collection_name+ that match +selector+ by
|
363
360
|
# applying +obj+ as an update. Normally called by Collection#replace.
|
364
361
|
def replace_in_db(collection_name, selector, obj)
|
365
|
-
|
362
|
+
_synchronize {
|
366
363
|
send_to_db(UpdateMessage.new(@name, collection_name, selector, obj, false))
|
367
364
|
}
|
368
365
|
end
|
@@ -374,7 +371,7 @@ module XGen
|
|
374
371
|
# applying +obj+ as an update. If no match, inserts (???). Normally
|
375
372
|
# called by Collection#repsert.
|
376
373
|
def repsert_in_db(collection_name, selector, obj)
|
377
|
-
|
374
|
+
_synchronize {
|
378
375
|
obj = @pk_factory.create_pk(obj) if @pk_factory
|
379
376
|
send_to_db(UpdateMessage.new(@name, collection_name, selector, obj, true))
|
380
377
|
obj
|
@@ -416,6 +413,16 @@ module XGen
|
|
416
413
|
raise "Error with eval command: #{doc.inspect}"
|
417
414
|
end
|
418
415
|
|
416
|
+
# Rename collection +from+ to +to+. Meant to be called by
|
417
|
+
# Collection#rename.
|
418
|
+
def rename_collection(from, to)
|
419
|
+
oh = OrderedHash.new
|
420
|
+
oh[:renameCollection] = "#{@name}.#{from}"
|
421
|
+
oh[:to] = "#{@name}.#{to}"
|
422
|
+
doc = db_command(oh, true)
|
423
|
+
raise "Error renaming collection: #{doc.inspect}" unless ok?(doc)
|
424
|
+
end
|
425
|
+
|
419
426
|
# Drop index +name+ from +collection_name+. Normally called from
|
420
427
|
# Collection#drop_index or Collection#drop_indexes.
|
421
428
|
def drop_index(collection_name, name)
|
@@ -460,7 +467,7 @@ module XGen
|
|
460
467
|
:key => field_h,
|
461
468
|
:unique => unique
|
462
469
|
}
|
463
|
-
|
470
|
+
_synchronize {
|
464
471
|
send_to_db(InsertMessage.new(@name, SYSTEM_INDEX_COLLECTION, false, sel))
|
465
472
|
}
|
466
473
|
name
|
@@ -470,7 +477,7 @@ module XGen
|
|
470
477
|
# Collection#insert. Returns a new array containing +objects+,
|
471
478
|
# possibly modified by @pk_factory.
|
472
479
|
def insert_into_db(collection_name, objects)
|
473
|
-
|
480
|
+
_synchronize {
|
474
481
|
if @pk_factory
|
475
482
|
objects.collect! { |o|
|
476
483
|
@pk_factory.create_pk(o)
|
@@ -511,7 +518,7 @@ module XGen
|
|
511
518
|
# that the "command" key be first.
|
512
519
|
#
|
513
520
|
# Do not call this. Intended for driver use only.
|
514
|
-
def db_command(selector)
|
521
|
+
def db_command(selector, use_admin_db=false)
|
515
522
|
if !selector.kind_of?(OrderedHash)
|
516
523
|
if !selector.kind_of?(Hash) || selector.keys.length > 1
|
517
524
|
raise "db_command must be given an OrderedHash when there is more than one key"
|
@@ -520,7 +527,11 @@ module XGen
|
|
520
527
|
|
521
528
|
q = Query.new(selector)
|
522
529
|
q.number_to_return = 1
|
523
|
-
query(Collection.new(self, SYSTEM_COMMAND_COLLECTION), q).next_object
|
530
|
+
query(Collection.new(self, SYSTEM_COMMAND_COLLECTION), q, use_admin_db).next_object
|
531
|
+
end
|
532
|
+
|
533
|
+
def _synchronize &block
|
534
|
+
@semaphore.synchronize &block
|
524
535
|
end
|
525
536
|
|
526
537
|
private
|
data/lib/mongo/util/bson.rb
CHANGED
@@ -47,6 +47,7 @@ class BSON
|
|
47
47
|
CODE_W_SCOPE = 15
|
48
48
|
NUMBER_INT = 16
|
49
49
|
TIMESTAMP = 17
|
50
|
+
NUMBER_LONG = 18
|
50
51
|
MAXKEY = 127
|
51
52
|
|
52
53
|
if RUBY_VERSION >= '1.9'
|
@@ -180,6 +181,9 @@ class BSON
|
|
180
181
|
when NUMBER_INT
|
181
182
|
key = deserialize_cstr(@buf)
|
182
183
|
doc[key] = deserialize_number_int_data(@buf)
|
184
|
+
when NUMBER_LONG
|
185
|
+
key = deserialize_cstr(@buf)
|
186
|
+
doc[key] = deserialize_number_long_data(@buf)
|
183
187
|
when OID
|
184
188
|
key = deserialize_cstr(@buf)
|
185
189
|
doc[key] = deserialize_oid_data(@buf)
|
@@ -263,6 +267,12 @@ class BSON
|
|
263
267
|
unsigned >= 2**32 / 2 ? unsigned - 2**32 : unsigned
|
264
268
|
end
|
265
269
|
|
270
|
+
def deserialize_number_long_data(buf)
|
271
|
+
# same note as above applies here...
|
272
|
+
unsigned = buf.get_long
|
273
|
+
unsigned >= 2 ** 64 / 2 ? unsigned - 2**64 : unsigned
|
274
|
+
end
|
275
|
+
|
266
276
|
def deserialize_object_data(buf)
|
267
277
|
size = buf.get_int
|
268
278
|
buf.position -= 4
|
@@ -394,15 +404,23 @@ class BSON
|
|
394
404
|
end
|
395
405
|
|
396
406
|
def serialize_number_element(buf, key, val, type)
|
397
|
-
buf.put(type)
|
398
|
-
self.class.serialize_cstr(buf, key)
|
399
407
|
if type == NUMBER
|
408
|
+
buf.put(type)
|
409
|
+
self.class.serialize_cstr(buf, key)
|
400
410
|
buf.put_double(val)
|
401
411
|
else
|
412
|
+
if val > 2**64 / 2 - 1 or val < -2**64 / 2
|
413
|
+
raise RangeError.new("MongoDB can only handle 8-byte ints")
|
414
|
+
end
|
402
415
|
if val > 2**32 / 2 - 1 or val < -2**32 / 2
|
403
|
-
|
416
|
+
buf.put(NUMBER_LONG)
|
417
|
+
self.class.serialize_cstr(buf, key)
|
418
|
+
buf.put_long(val)
|
419
|
+
else
|
420
|
+
buf.put(type)
|
421
|
+
self.class.serialize_cstr(buf, key)
|
422
|
+
buf.put_int(val)
|
404
423
|
end
|
405
|
-
buf.put_int(val)
|
406
424
|
end
|
407
425
|
end
|
408
426
|
|
data/mongo-ruby-driver.gemspec
CHANGED
@@ -75,11 +75,12 @@ TEST_FILES = ['tests/mongo-qa/_common.rb',
|
|
75
75
|
'tests/test_mongo.rb',
|
76
76
|
'tests/test_objectid.rb',
|
77
77
|
'tests/test_ordered_hash.rb',
|
78
|
+
'tests/test_threading.rb',
|
78
79
|
'tests/test_round_trip.rb']
|
79
80
|
|
80
81
|
Gem::Specification.new do |s|
|
81
82
|
s.name = 'mongo'
|
82
|
-
s.version = '0.
|
83
|
+
s.version = '0.11'
|
83
84
|
s.platform = Gem::Platform::RUBY
|
84
85
|
s.summary = 'Ruby driver for the 10gen Mongo DB'
|
85
86
|
s.description = 'A Ruby driver for the 10gen Mongo DB. For more information about Mongo, see http://www.mongodb.org.'
|
data/tests/test_bson.rb
CHANGED
@@ -215,18 +215,32 @@ class BSONTest < Test::Unit::TestCase
|
|
215
215
|
end
|
216
216
|
|
217
217
|
def test_overflow
|
218
|
-
doc = {"x" => 2**
|
218
|
+
doc = {"x" => 2**75}
|
219
219
|
assert_raise RangeError do
|
220
220
|
@b.serialize(doc)
|
221
221
|
end
|
222
222
|
|
223
|
-
doc = {"x" =>
|
223
|
+
doc = {"x" => 9223372036854775}
|
224
|
+
assert_equal doc, @b.deserialize(@b.serialize(doc).to_a)
|
225
|
+
|
226
|
+
doc = {"x" => 9223372036854775807}
|
224
227
|
assert_equal doc, @b.deserialize(@b.serialize(doc).to_a)
|
225
228
|
|
226
229
|
doc["x"] = doc["x"] + 1
|
227
230
|
assert_raise RangeError do
|
228
231
|
@b.serialize(doc)
|
229
232
|
end
|
233
|
+
|
234
|
+
doc = {"x" => -9223372036854775}
|
235
|
+
assert_equal doc, @b.deserialize(@b.serialize(doc).to_a)
|
236
|
+
|
237
|
+
doc = {"x" => -9223372036854775808}
|
238
|
+
assert_equal doc, @b.deserialize(@b.serialize(doc).to_a)
|
239
|
+
|
240
|
+
doc["x"] = doc["x"] - 1
|
241
|
+
assert_raise RangeError do
|
242
|
+
@b.serialize(doc)
|
243
|
+
end
|
230
244
|
end
|
231
245
|
|
232
246
|
def test_do_not_change_original_object
|
data/tests/test_db.rb
CHANGED
@@ -51,6 +51,18 @@ class DBTest < Test::Unit::TestCase
|
|
51
51
|
assert_equal 'ruby-mongo-test.test', @@db.full_coll_name(coll.name)
|
52
52
|
end
|
53
53
|
|
54
|
+
def test_collection_names
|
55
|
+
@@db.collection("test").insert("foo" => 5)
|
56
|
+
@@db.collection("test.mike").insert("bar" => 0)
|
57
|
+
|
58
|
+
colls = @@db.collection_names()
|
59
|
+
assert colls.include?("test")
|
60
|
+
assert colls.include?("test.mike")
|
61
|
+
colls.each { |name|
|
62
|
+
assert !name.include?("$")
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
54
66
|
def test_pair
|
55
67
|
@@db.close
|
56
68
|
@@users = nil
|
data/tests/test_db_api.rb
CHANGED
@@ -241,25 +241,25 @@ class DBAPITest < Test::Unit::TestCase
|
|
241
241
|
|
242
242
|
def test_drop_collection
|
243
243
|
assert @@db.drop_collection(@@coll.name), "drop of collection #{@@coll.name} failed"
|
244
|
-
assert !@@db.collection_names.include?(@@
|
244
|
+
assert !@@db.collection_names.include?(@@coll.name)
|
245
245
|
end
|
246
246
|
|
247
247
|
def test_other_drop
|
248
|
-
assert @@db.collection_names.include?(@@
|
248
|
+
assert @@db.collection_names.include?(@@coll.name)
|
249
249
|
@@coll.drop
|
250
|
-
assert !@@db.collection_names.include?(@@
|
250
|
+
assert !@@db.collection_names.include?(@@coll.name)
|
251
251
|
end
|
252
252
|
|
253
253
|
def test_collection_names
|
254
254
|
names = @@db.collection_names
|
255
255
|
assert names.length >= 1
|
256
|
-
assert names.include?(@@
|
256
|
+
assert names.include?(@@coll.name)
|
257
257
|
|
258
258
|
coll2 = @@db.collection('test2')
|
259
259
|
coll2.insert('a' => 1) # collection not created until it's used
|
260
260
|
names = @@db.collection_names
|
261
261
|
assert names.length >= 2
|
262
|
-
assert names.include?(@@
|
262
|
+
assert names.include?(@@coll.name)
|
263
263
|
assert names.include?('ruby-mongo-test.test2')
|
264
264
|
ensure
|
265
265
|
@@db.drop_collection('test2')
|
@@ -639,6 +639,28 @@ class DBAPITest < Test::Unit::TestCase
|
|
639
639
|
assert_equal 2, @@coll.count
|
640
640
|
end
|
641
641
|
|
642
|
+
def test_save_long
|
643
|
+
@@coll.clear
|
644
|
+
@@coll.insert("x" => 9223372036854775807)
|
645
|
+
assert_equal 9223372036854775807, @@coll.find_first()["x"]
|
646
|
+
end
|
647
|
+
|
648
|
+
def test_find_by_oid
|
649
|
+
@@coll.clear
|
650
|
+
|
651
|
+
@@coll.save("hello" => "mike")
|
652
|
+
id = @@coll.save("hello" => "world")
|
653
|
+
assert_kind_of ObjectID, id
|
654
|
+
|
655
|
+
assert_equal "world", @@coll.find_first(:_id => id)["hello"]
|
656
|
+
@@coll.find(:_id => id).to_a.each do |doc|
|
657
|
+
assert_equal "world", doc["hello"]
|
658
|
+
end
|
659
|
+
|
660
|
+
id = ObjectID.from_string(id.to_s)
|
661
|
+
assert_equal "world", @@coll.find_first(:_id => id)["hello"]
|
662
|
+
end
|
663
|
+
|
642
664
|
def test_save_with_object_that_has_id_but_does_not_actually_exist_in_collection
|
643
665
|
@@coll.clear
|
644
666
|
|
@@ -691,6 +713,74 @@ class DBAPITest < Test::Unit::TestCase
|
|
691
713
|
@@coll.modify({"hello" => "world"}, {"$inc" => "hello"})
|
692
714
|
end
|
693
715
|
|
716
|
+
def test_collection_names
|
717
|
+
assert_raise RuntimeError do
|
718
|
+
@@db.collection(5)
|
719
|
+
end
|
720
|
+
assert_raise RuntimeError do
|
721
|
+
@@db.collection("")
|
722
|
+
end
|
723
|
+
assert_raise RuntimeError do
|
724
|
+
@@db.collection("te$t")
|
725
|
+
end
|
726
|
+
assert_raise RuntimeError do
|
727
|
+
@@db.collection(".test")
|
728
|
+
end
|
729
|
+
assert_raise RuntimeError do
|
730
|
+
@@db.collection("test.")
|
731
|
+
end
|
732
|
+
assert_raise RuntimeError do
|
733
|
+
@@db.collection("tes..t")
|
734
|
+
end
|
735
|
+
end
|
736
|
+
|
737
|
+
def test_rename_collection
|
738
|
+
@@db.drop_collection("foo")
|
739
|
+
@@db.drop_collection("bar")
|
740
|
+
a = @@db.collection("foo")
|
741
|
+
b = @@db.collection("bar")
|
742
|
+
|
743
|
+
assert_raise RuntimeError do
|
744
|
+
a.rename(5)
|
745
|
+
end
|
746
|
+
assert_raise RuntimeError do
|
747
|
+
a.rename("")
|
748
|
+
end
|
749
|
+
assert_raise RuntimeError do
|
750
|
+
a.rename("te$t")
|
751
|
+
end
|
752
|
+
assert_raise RuntimeError do
|
753
|
+
a.rename(".test")
|
754
|
+
end
|
755
|
+
assert_raise RuntimeError do
|
756
|
+
a.rename("test.")
|
757
|
+
end
|
758
|
+
assert_raise RuntimeError do
|
759
|
+
a.rename("tes..t")
|
760
|
+
end
|
761
|
+
|
762
|
+
assert_equal 0, a.count()
|
763
|
+
assert_equal 0, b.count()
|
764
|
+
|
765
|
+
a.insert("x" => 1)
|
766
|
+
a.insert("x" => 2)
|
767
|
+
|
768
|
+
assert_equal 2, a.count()
|
769
|
+
|
770
|
+
a.rename("bar")
|
771
|
+
|
772
|
+
assert_equal 0, a.count()
|
773
|
+
assert_equal 2, b.count()
|
774
|
+
|
775
|
+
assert_equal 1, b.find().to_a()[0]["x"]
|
776
|
+
assert_equal 2, b.find().to_a()[1]["x"]
|
777
|
+
|
778
|
+
b.rename(:foo)
|
779
|
+
|
780
|
+
assert_equal 2, a.count()
|
781
|
+
assert_equal 0, b.count()
|
782
|
+
end
|
783
|
+
|
694
784
|
# TODO this test fails with error message "Undefed Before end of object"
|
695
785
|
# That is a database error. The undefined type may go away.
|
696
786
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
+
require 'mongo'
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class TestThreading < Test::Unit::TestCase
|
6
|
+
|
7
|
+
include XGen::Mongo::Driver
|
8
|
+
|
9
|
+
@@host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
|
10
|
+
@@port = ENV['MONGO_RUBY_DRIVER_PORT'] || Mongo::DEFAULT_PORT
|
11
|
+
@@db = Mongo.new(@@host, @@port).db('ruby-mongo-test')
|
12
|
+
@@coll = @@db.collection('thread-test-collection')
|
13
|
+
|
14
|
+
def test_threading
|
15
|
+
@@coll.clear
|
16
|
+
|
17
|
+
1000.times do |i|
|
18
|
+
@@coll.insert("x" => i)
|
19
|
+
end
|
20
|
+
|
21
|
+
threads = []
|
22
|
+
|
23
|
+
10.times do |i|
|
24
|
+
threads[i] = Thread.new{
|
25
|
+
sum = 0
|
26
|
+
@@coll.find().each { |document|
|
27
|
+
sum += document["x"]
|
28
|
+
}
|
29
|
+
assert_equal 499500, sum
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
10.times do |i|
|
34
|
+
threads[i].join
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongodb-mongo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: "0.11"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jim Menard
|
@@ -130,4 +130,5 @@ test_files:
|
|
130
130
|
- tests/test_mongo.rb
|
131
131
|
- tests/test_objectid.rb
|
132
132
|
- tests/test_ordered_hash.rb
|
133
|
+
- tests/test_threading.rb
|
133
134
|
- tests/test_round_trip.rb
|