mongo 1.0.9 → 1.1
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/HISTORY +8 -0
- data/Rakefile +23 -0
- data/lib/mongo.rb +1 -1
- data/lib/mongo/connection.rb +25 -38
- data/lib/mongo/cursor.rb +1 -21
- data/lib/mongo/db.rb +0 -27
- data/test/bson/basic_test.rb +99 -0
- data/test/bson/bench_test.rb +172 -0
- data/test/bson/binary_test.rb +15 -0
- data/test/bson/bson_test.rb +528 -0
- data/test/bson/byte_buffer_test.rb +190 -0
- data/test/bson/c_encode_test.rb +51 -0
- data/test/bson/java_bson_test.rb +146 -0
- data/test/bson/jruby_bson_test.rb +24 -0
- data/test/bson/jruby_encode_test.rb +438 -0
- data/test/bson/json_test.rb +16 -0
- data/test/bson/object_id_test.rb +132 -0
- data/test/bson/ordered_hash_test.rb +197 -0
- data/test/collection_test.rb +1 -1
- data/test/connection_test.rb +23 -2
- data/test/db_api_test.rb +3 -10
- data/test/db_test.rb +0 -14
- metadata +118 -148
data/HISTORY
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
1.1 2010-10-4
|
2
|
+
* Official JRuby support via Java extensons for BSON (beta)
|
3
|
+
* Connection#lock! and Connection#unlock! for easy fsync lock
|
4
|
+
* Note: BSON::Code is no longer a subclass of String.
|
5
|
+
|
6
|
+
1.0.9 2010-9-20
|
7
|
+
* Significant performance improvements
|
8
|
+
|
1
9
|
1.0.8 2010-8-27
|
2
10
|
|
3
11
|
* Cursor#rewind! and more consistent Cursor Enumberable behavior
|
data/Rakefile
CHANGED
@@ -13,6 +13,29 @@ require 'rbconfig'
|
|
13
13
|
include Config
|
14
14
|
ENV['TEST_MODE'] = 'TRUE'
|
15
15
|
|
16
|
+
task :java do
|
17
|
+
Rake::Task['build:java'].invoke
|
18
|
+
Rake::Task['test:ruby'].invoke
|
19
|
+
end
|
20
|
+
|
21
|
+
namespace :build do
|
22
|
+
desc "Build the java extensions."
|
23
|
+
task :java do
|
24
|
+
puts "Building Java extensions..."
|
25
|
+
java_dir = File.join(File.dirname(__FILE__), 'ext', 'java')
|
26
|
+
jar_dir = File.join(java_dir, 'jar')
|
27
|
+
|
28
|
+
jruby_jar = File.join(jar_dir, 'jruby.jar')
|
29
|
+
mongo_jar = File.join(jar_dir, 'mongo.jar')
|
30
|
+
bson_jar = File.join(jar_dir, 'bson.jar')
|
31
|
+
|
32
|
+
src_base = File.join(java_dir, 'src')
|
33
|
+
|
34
|
+
system("javac -Xlint:unchecked -classpath #{jruby_jar}:#{mongo_jar}:#{bson_jar} #{File.join(src_base, 'org', 'jbson', '*.java')}")
|
35
|
+
system("cd #{src_base} && jar cf #{File.join(jar_dir, 'jbson.jar')} #{File.join('.', 'org', 'jbson', '*.class')}")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
16
39
|
desc "Test the MongoDB Ruby driver."
|
17
40
|
task :test do
|
18
41
|
puts "\nThis option has changed."
|
data/lib/mongo.rb
CHANGED
data/lib/mongo/connection.rb
CHANGED
@@ -168,35 +168,6 @@ module Mongo
|
|
168
168
|
end
|
169
169
|
end
|
170
170
|
|
171
|
-
# @deprecated
|
172
|
-
#
|
173
|
-
# Initialize a paired connection to MongoDB.
|
174
|
-
#
|
175
|
-
# @param nodes [Array] An array of arrays, each of which specified a host and port.
|
176
|
-
# @param opts Takes the same options as Connection.new
|
177
|
-
#
|
178
|
-
# @example
|
179
|
-
# Connection.paired([["db1.example.com", 27017],
|
180
|
-
# ["db2.example.com", 27017]])
|
181
|
-
#
|
182
|
-
# @example
|
183
|
-
# Connection.paired([["db1.example.com", 27017],
|
184
|
-
# ["db2.example.com", 27017]],
|
185
|
-
# :pool_size => 20, :timeout => 5)
|
186
|
-
#
|
187
|
-
# @return [Mongo::Connection]
|
188
|
-
def self.paired(nodes, opts={})
|
189
|
-
warn "Connection.paired is deprecated. Please use Connection.multi instead."
|
190
|
-
unless nodes.length == 2 && nodes.all? {|n| n.is_a? Array}
|
191
|
-
raise MongoArgumentError, "Connection.paired requires that exactly two nodes be specified."
|
192
|
-
end
|
193
|
-
# Block returns an array, the first element being an array of nodes and the second an array
|
194
|
-
# of authorizations for the database.
|
195
|
-
new(nil, nil, opts) do |con|
|
196
|
-
[con.pair_val_to_connection(nodes[0]), con.pair_val_to_connection(nodes[1])]
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
171
|
# Initialize a connection to MongoDB using the MongoDB URI spec:
|
201
172
|
#
|
202
173
|
# @param uri [String]
|
@@ -211,6 +182,31 @@ module Mongo
|
|
211
182
|
end
|
212
183
|
end
|
213
184
|
|
185
|
+
# Fsync, then lock the mongod process against writes. Use this to get
|
186
|
+
# the datafiles in a state safe for snapshotting, backing up, etc.
|
187
|
+
#
|
188
|
+
# @return [BSON::OrderedHash] the command response
|
189
|
+
def lock!
|
190
|
+
cmd = BSON::OrderedHash.new
|
191
|
+
cmd[:fsync] = 1
|
192
|
+
cmd[:lock] = true
|
193
|
+
self['admin'].command(cmd)
|
194
|
+
end
|
195
|
+
|
196
|
+
# Is this database locked against writes?
|
197
|
+
#
|
198
|
+
# @return [Boolean]
|
199
|
+
def locked?
|
200
|
+
self['admin']['$cmd.sys.inprog'].find_one['fsyncLock'] == 1
|
201
|
+
end
|
202
|
+
|
203
|
+
# Unlock a previously fsync-locked mongod process.
|
204
|
+
#
|
205
|
+
# @return [BSON::OrderedHash] command response
|
206
|
+
def unlock!
|
207
|
+
self['admin']['$cmd.sys.unlock'].find_one
|
208
|
+
end
|
209
|
+
|
214
210
|
# Apply each of the saved database authentications.
|
215
211
|
#
|
216
212
|
# @return [Boolean] returns true if authentications exist and succeeed, false
|
@@ -483,15 +479,6 @@ module Mongo
|
|
483
479
|
raise ConnectionFailure, "failed to connect to any given host:port" unless connected?
|
484
480
|
end
|
485
481
|
|
486
|
-
# @deprecated
|
487
|
-
#
|
488
|
-
# Create a new socket and attempt to connect to master.
|
489
|
-
# If successful, sets host and port to master and returns the socket.
|
490
|
-
def connect_to_master
|
491
|
-
warn "Connection#connect_to_master is deprecated. Use Connection#connect instead."
|
492
|
-
connect
|
493
|
-
end
|
494
|
-
|
495
482
|
def connected?
|
496
483
|
@host && @port
|
497
484
|
end
|
data/lib/mongo/cursor.rb
CHANGED
@@ -39,7 +39,7 @@ module Mongo
|
|
39
39
|
@connection = @db.connection
|
40
40
|
@logger = @connection.logger
|
41
41
|
|
42
|
-
@selector =
|
42
|
+
@selector = options[:selector] || {}
|
43
43
|
@fields = convert_fields_for_query(options[:fields])
|
44
44
|
@skip = options[:skip] || 0
|
45
45
|
@limit = options[:limit] || 0
|
@@ -327,26 +327,6 @@ module Mongo
|
|
327
327
|
end
|
328
328
|
end
|
329
329
|
|
330
|
-
# Set the query selector hash. If the selector is a Code or String object,
|
331
|
-
# the selector will be used in a $where clause.
|
332
|
-
# See http://www.mongodb.org/display/DOCS/Server-side+Code+Execution
|
333
|
-
def convert_selector_for_query(selector)
|
334
|
-
case selector
|
335
|
-
when Hash
|
336
|
-
selector
|
337
|
-
when nil
|
338
|
-
{}
|
339
|
-
when BSON::Code
|
340
|
-
warn "Collection#find will no longer take a JavaScript string in future versions. " +
|
341
|
-
"Please specify your $where query explicitly."
|
342
|
-
{"$where" => selector}
|
343
|
-
when String
|
344
|
-
warn "Collection#find will no longer take a JavaScript string in future versions. " +
|
345
|
-
"Please specify your $where query explicitly."
|
346
|
-
{"$where" => BSON::Code.new(selector)}
|
347
|
-
end
|
348
|
-
end
|
349
|
-
|
350
330
|
# Return the number of documents remaining for this cursor.
|
351
331
|
def num_remaining
|
352
332
|
refresh if @cache.length == 0
|
data/lib/mongo/db.rb
CHANGED
@@ -276,23 +276,6 @@ module Mongo
|
|
276
276
|
ok?(command(:drop => name))
|
277
277
|
end
|
278
278
|
|
279
|
-
# @deprecated
|
280
|
-
#
|
281
|
-
# Get the error message from the most recently executed database
|
282
|
-
# operation for this connection.
|
283
|
-
#
|
284
|
-
# @option opts [Boolean] :fsync (false)
|
285
|
-
# @option opts [Integer] :w (nil)
|
286
|
-
# @option opts [Integer] :wtimeout (nil)
|
287
|
-
#
|
288
|
-
# @return [String, Nil] either the text describing an error or nil if no
|
289
|
-
# error has occurred.
|
290
|
-
def error(opts={})
|
291
|
-
warn "DB#error is deprecated. Please use DB#get_last_error instead"
|
292
|
-
opts.assert_valid_keys(:w, :wtimeout, :fsync)
|
293
|
-
get_last_error(opts)['err']
|
294
|
-
end
|
295
|
-
|
296
279
|
# Run the getlasterror command with the specified replication options.
|
297
280
|
#
|
298
281
|
# @option opts [Boolean] :fsync (false)
|
@@ -311,16 +294,6 @@ module Mongo
|
|
311
294
|
doc
|
312
295
|
end
|
313
296
|
|
314
|
-
# @deprecated
|
315
|
-
#
|
316
|
-
# Get status information from the last operation on this connection.
|
317
|
-
#
|
318
|
-
# @return [Hash] a hash representing the status of the last db op.
|
319
|
-
def last_status
|
320
|
-
warn "DB#last_status is deprecated. Please use the equivalent DB#get_last_error instead"
|
321
|
-
command(:getlasterror => 1)
|
322
|
-
end
|
323
|
-
|
324
297
|
# Return +true+ if an error was caused by the most recently executed
|
325
298
|
# database operation.
|
326
299
|
#
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# encoding:utf-8
|
2
|
+
require './test/test_helper'
|
3
|
+
require 'complex'
|
4
|
+
require 'bigdecimal'
|
5
|
+
require 'rational'
|
6
|
+
require 'benchmark'
|
7
|
+
|
8
|
+
MEDIUM = {
|
9
|
+
'integer' => 5,
|
10
|
+
'number' => 5.05,
|
11
|
+
'boolean' => false,
|
12
|
+
'array' => ['test', 'benchmark']
|
13
|
+
}
|
14
|
+
|
15
|
+
|
16
|
+
LARGE = {
|
17
|
+
'base_url' => 'http://www.example.com/test-me',
|
18
|
+
'total_word_count' => 6743,
|
19
|
+
'access_time' => Time.now,
|
20
|
+
'meta_tags' => {
|
21
|
+
'description' => 'i am a long description string',
|
22
|
+
'author' => 'Holly Man',
|
23
|
+
'dynamically_created_meta_tag' => 'who know\n what'
|
24
|
+
},
|
25
|
+
'page_structure' => {
|
26
|
+
'counted_tags' => 3450,
|
27
|
+
'no_of_js_attached' => 10,
|
28
|
+
'no_of_images' => 6
|
29
|
+
},
|
30
|
+
'harvested_words' => ['10gen','web','open','source','application','paas',
|
31
|
+
'platform-as-a-service','technology','helps',
|
32
|
+
'developers','focus','building','mongodb','mongo'] * 20
|
33
|
+
}
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
begin
|
38
|
+
require 'active_support/core_ext'
|
39
|
+
require 'active_support/hash_with_indifferent_access'
|
40
|
+
Time.zone = "Pacific Time (US & Canada)"
|
41
|
+
Zone = Time.zone.now
|
42
|
+
rescue LoadError
|
43
|
+
warn 'Could not test BSON with HashWithIndifferentAccess.'
|
44
|
+
module ActiveSupport
|
45
|
+
class TimeWithZone
|
46
|
+
end
|
47
|
+
end
|
48
|
+
Zone = ActiveSupport::TimeWithZone.new
|
49
|
+
end
|
50
|
+
|
51
|
+
class BSONTest < Test::Unit::TestCase
|
52
|
+
include BSON
|
53
|
+
|
54
|
+
def test_string
|
55
|
+
doc = {'doc' => 'hello, world'}
|
56
|
+
bson = bson = BSON::BSON_CODER.serialize(doc)
|
57
|
+
assert_equal doc, BSON::BSON_CODER.deserialize(bson)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_object
|
61
|
+
doc = {'doc' => {'age' => 42, 'name' => 'Spongebob', 'shoe_size' => 9.5}}
|
62
|
+
bson = BSON::BSON_CODER.serialize(doc)
|
63
|
+
assert_equal doc, BSON::BSON_CODER.deserialize(bson)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_oid
|
67
|
+
doc = {'doc' => ObjectID.new}
|
68
|
+
bson = BSON::BSON_CODER.serialize(doc)
|
69
|
+
assert_equal doc, BSON::BSON_CODER.deserialize(bson)
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_array
|
73
|
+
doc = {'doc' => [1, 2, "a", "b"]}
|
74
|
+
bson = BSON::BSON_CODER.serialize(doc)
|
75
|
+
assert_equal doc, BSON::BSON_CODER.deserialize(bson)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_speed
|
79
|
+
|
80
|
+
Benchmark.bm do |x|
|
81
|
+
x.report('serialize obj') do
|
82
|
+
1000.times do
|
83
|
+
BSON::BSON_CODER.serialize(LARGE)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
Benchmark.bm do |x|
|
91
|
+
b = BSON::BSON_CODER.serialize(LARGE)
|
92
|
+
x.report('deserialize obj') do
|
93
|
+
1000.times do
|
94
|
+
BSON::BSON_CODER.deserialize(b)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
# encoding:utf-8
|
2
|
+
require './test/test_helper'
|
3
|
+
require 'complex'
|
4
|
+
require 'bigdecimal'
|
5
|
+
require 'rational'
|
6
|
+
require 'benchmark'
|
7
|
+
|
8
|
+
MEDIUM = {
|
9
|
+
'integer' => 5,
|
10
|
+
'number' => 5.05,
|
11
|
+
'boolean' => false,
|
12
|
+
'array' => ['test', 'benchmark']
|
13
|
+
}
|
14
|
+
|
15
|
+
|
16
|
+
LARGE = {
|
17
|
+
'base_url' => 'http://www.example.com/test-me',
|
18
|
+
'total_word_count' => 6743,
|
19
|
+
'access_time' => 1,# Time.now,
|
20
|
+
'meta_tags' => {
|
21
|
+
'description' => 'i am a long description string',
|
22
|
+
'author' => 'Holly Man',
|
23
|
+
'dynamically_created_meta_tag' => 'who know\n what'
|
24
|
+
},
|
25
|
+
'page_structure' => {
|
26
|
+
'counted_tags' => 3450,
|
27
|
+
'no_of_js_attached' => 10,
|
28
|
+
'no_of_images' => 6
|
29
|
+
},
|
30
|
+
'harvested_words' => ['10gen','web','open','source','application','paas',
|
31
|
+
'platform-as-a-service','technology','helps',
|
32
|
+
'developers','focus','building','mongodb','mongo'] * 20
|
33
|
+
}
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
begin
|
38
|
+
require 'active_support/core_ext'
|
39
|
+
require 'active_support/hash_with_indifferent_access'
|
40
|
+
Time.zone = "Pacific Time (US & Canada)"
|
41
|
+
Zone = Time.zone.now
|
42
|
+
rescue LoadError
|
43
|
+
warn 'Could not test BSON with HashWithIndifferentAccess.'
|
44
|
+
module ActiveSupport
|
45
|
+
class TimeWithZone
|
46
|
+
end
|
47
|
+
end
|
48
|
+
Zone = ActiveSupport::TimeWithZone.new
|
49
|
+
end
|
50
|
+
|
51
|
+
class BSONTest < Test::Unit::TestCase
|
52
|
+
include BSON
|
53
|
+
|
54
|
+
def setup
|
55
|
+
@encoder = BSON::BSON_RUBY
|
56
|
+
@decoder = BSON::BSON_RUBY
|
57
|
+
@con = Mongo::Connection.new
|
58
|
+
end
|
59
|
+
|
60
|
+
def assert_doc_pass(doc, options={})
|
61
|
+
bson = @encoder.serialize(doc)
|
62
|
+
if options[:debug]
|
63
|
+
puts "DEBUGGIN DOC:"
|
64
|
+
p bson.to_a
|
65
|
+
puts "DESERIALIZES TO:"
|
66
|
+
p @decoder.deserialize(bson)
|
67
|
+
end
|
68
|
+
assert_equal @decoder.serialize(doc).to_a, bson.to_a
|
69
|
+
assert_equal doc, @decoder.deserialize(bson)
|
70
|
+
end
|
71
|
+
|
72
|
+
# def test_bench_big_string
|
73
|
+
# t0 = Time.now
|
74
|
+
# @con['foo']['bar'].remove
|
75
|
+
# doc = {'doc' => 'f' * 2_000_000}
|
76
|
+
# 10.times do
|
77
|
+
# @con['foo']['bar'].save({'d' => doc})
|
78
|
+
# @con['foo']['bar'].find.to_a
|
79
|
+
# end
|
80
|
+
# puts "Big String"
|
81
|
+
# puts Time.now - t0
|
82
|
+
# end
|
83
|
+
#
|
84
|
+
# def test_big_array
|
85
|
+
# t0 = Time.now
|
86
|
+
# @con['foo']['bar'].remove
|
87
|
+
# doc = {'doc' => 'f' * 2_000_000}
|
88
|
+
# 10.times do
|
89
|
+
# @con['foo']['bar'].save({'d' => doc})
|
90
|
+
# @con['foo']['bar'].find.to_a
|
91
|
+
# end
|
92
|
+
# puts "Big String"
|
93
|
+
# puts Time.now - t0
|
94
|
+
# end
|
95
|
+
#
|
96
|
+
# def test_string
|
97
|
+
# doc = {'doc' => "Hello world!", 'awesome' => true, 'a' => 1, 'b' => 4_333_433_232, 'c' => 2.33, 'd' => nil,
|
98
|
+
# 'f' => BSON::Code.new("function"), 'g' => BSON::ObjectId.new, 'h' => [1, 2, 3]}
|
99
|
+
# bson = @encoder.serialize(doc)
|
100
|
+
# d = @encoder.deserialize(bson)
|
101
|
+
# puts "Array"
|
102
|
+
# puts d
|
103
|
+
# puts d['h']
|
104
|
+
# puts "End Array"
|
105
|
+
# puts d['h'][0]
|
106
|
+
# puts d['h'][1]
|
107
|
+
# puts (d['h'][2] + 100).class
|
108
|
+
# puts "ObjecId Info"
|
109
|
+
# bson2 = @encoder.serialize(d)
|
110
|
+
# doc2 = @encoder.deserialize(bson2)
|
111
|
+
# assert_equal doc2, @encoder.deserialize(bson)
|
112
|
+
# end
|
113
|
+
#
|
114
|
+
|
115
|
+
def test_eval
|
116
|
+
code = BSON::Code.new('f')
|
117
|
+
oh = BSON::OrderedHash.new
|
118
|
+
oh[:$eval] = code
|
119
|
+
oh[:args] = [1]
|
120
|
+
|
121
|
+
assert_equal BSON::BSON_RUBY.serialize(oh).to_a, BSON::BSON_JAVA.serialize(oh).to_a
|
122
|
+
assert_equal 3, @con['admin'].eval('function (x) {return x;}', 3)
|
123
|
+
end
|
124
|
+
|
125
|
+
# def test_oid
|
126
|
+
# b = Java::OrgBsonTypes::ObjectId.new.toByteArray
|
127
|
+
# o = ObjectId.new(b)
|
128
|
+
# p o
|
129
|
+
# end
|
130
|
+
#
|
131
|
+
def test_speed
|
132
|
+
@con['foo']['bar'].remove
|
133
|
+
|
134
|
+
puts "Test OID"
|
135
|
+
t0 = Time.now
|
136
|
+
5000.times do
|
137
|
+
ids = [BSON::ObjectId.new] * 1000
|
138
|
+
@encoder.serialize({'doc' => BSON::ObjectId.new})
|
139
|
+
end
|
140
|
+
puts Time.now - t0
|
141
|
+
|
142
|
+
puts "Decode OID"
|
143
|
+
ids = [BSON::ObjectId.new] * 1000
|
144
|
+
doc = {'doc' => ids}
|
145
|
+
bson = @encoder.serialize(doc)
|
146
|
+
t0 = Time.now
|
147
|
+
50.times do
|
148
|
+
@encoder.deserialize(bson)
|
149
|
+
end
|
150
|
+
puts Time.now - t0
|
151
|
+
|
152
|
+
|
153
|
+
puts "Test insert"
|
154
|
+
t0 = Time.now
|
155
|
+
1000.times do |n|
|
156
|
+
if n % 1000 == 0
|
157
|
+
puts Time.now - t0
|
158
|
+
t0 = Time.now
|
159
|
+
end
|
160
|
+
@con['foo']['bar'].insert({'doc' => MEDIUM})
|
161
|
+
end
|
162
|
+
puts Time.now - t0
|
163
|
+
|
164
|
+
puts "Test query / deserialize"
|
165
|
+
t0 = Time.now
|
166
|
+
@con['foo']['bar'].find.to_a
|
167
|
+
t1 = Time.now
|
168
|
+
puts t1 - t0
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
end
|