mongo 1.0.9 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|