mongo 1.8.0 → 1.8.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +14 -29
- data/VERSION +1 -1
- data/lib/mongo.rb +3 -0
- data/lib/mongo/collection.rb +99 -49
- data/lib/mongo/cursor.rb +17 -17
- data/lib/mongo/db.rb +30 -14
- data/lib/mongo/gridfs/grid.rb +5 -3
- data/lib/mongo/gridfs/grid_file_system.rb +5 -3
- data/lib/mongo/gridfs/grid_io.rb +5 -3
- data/lib/mongo/legacy.rb +9 -2
- data/lib/mongo/mongo_client.rb +100 -72
- data/lib/mongo/mongo_replica_set_client.rb +46 -60
- data/lib/mongo/mongo_sharded_client.rb +5 -66
- data/lib/mongo/networking.rb +2 -1
- data/lib/mongo/util/node.rb +41 -42
- data/lib/mongo/util/pool.rb +15 -43
- data/lib/mongo/util/pool_manager.rb +16 -65
- data/lib/mongo/util/read_preference.rb +82 -0
- data/lib/mongo/util/sharding_pool_manager.rb +0 -86
- data/lib/mongo/util/ssl_socket.rb +2 -1
- data/lib/mongo/util/support.rb +8 -18
- data/lib/mongo/util/tcp_socket.rb +5 -4
- data/lib/mongo/util/thread_local_variable_manager.rb +29 -0
- data/lib/mongo/util/unix_socket.rb +23 -0
- data/lib/mongo/util/uri_parser.rb +31 -18
- data/lib/mongo/util/write_concern.rb +7 -2
- data/mongo.gemspec +1 -1
- data/test/auxillary/repl_set_auth_test.rb +2 -2
- data/test/bson/bson_test.rb +1 -1
- data/test/bson/byte_buffer_test.rb +24 -26
- data/test/bson/hash_with_indifferent_access_test.rb +11 -1
- data/test/functional/collection_test.rb +16 -16
- data/test/functional/connection_test.rb +1 -4
- data/test/functional/db_api_test.rb +14 -10
- data/test/functional/pool_test.rb +23 -31
- data/test/functional/timeout_test.rb +3 -5
- data/test/functional/uri_test.rb +10 -5
- data/test/replica_set/basic_test.rb +3 -8
- data/test/replica_set/client_test.rb +47 -31
- data/test/replica_set/complex_connect_test.rb +12 -10
- data/test/replica_set/connection_test.rb +8 -151
- data/test/replica_set/count_test.rb +9 -5
- data/test/replica_set/cursor_test.rb +17 -27
- data/test/replica_set/insert_test.rb +5 -10
- data/test/replica_set/query_test.rb +4 -9
- data/test/replica_set/read_preference_test.rb +200 -0
- data/test/replica_set/refresh_test.rb +54 -65
- data/test/replica_set/replication_ack_test.rb +16 -14
- data/test/sharded_cluster/basic_test.rb +30 -0
- data/test/test_helper.rb +33 -15
- data/test/threading/basic_test.rb +79 -0
- data/test/tools/mongo_config.rb +62 -22
- data/test/unit/client_test.rb +36 -14
- data/test/unit/collection_test.rb +23 -0
- data/test/unit/connection_test.rb +30 -14
- data/test/unit/cursor_test.rb +137 -7
- data/test/unit/db_test.rb +17 -4
- data/test/unit/grid_test.rb +2 -2
- data/test/unit/node_test.rb +2 -1
- data/test/unit/pool_manager_test.rb +29 -1
- data/test/unit/read_test.rb +15 -15
- data/test/unit/safe_test.rb +4 -4
- data/test/unit/write_concern_test.rb +4 -4
- metadata +134 -143
- data/examples/admin.rb +0 -43
- data/examples/capped.rb +0 -22
- data/examples/cursor.rb +0 -48
- data/examples/gridfs.rb +0 -44
- data/examples/index_test.rb +0 -126
- data/examples/info.rb +0 -31
- data/examples/queries.rb +0 -74
- data/examples/replica_set.rb +0 -26
- data/examples/simple.rb +0 -25
- data/examples/strict.rb +0 -35
- data/examples/types.rb +0 -36
- data/examples/web/thin/load.rb +0 -23
- data/examples/web/unicorn/load.rb +0 -25
- data/test/support/hash_with_indifferent_access.rb +0 -186
- data/test/support/keys.rb +0 -45
- data/test/threading/threading_with_large_pool_test.rb +0 -90
data/examples/strict.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
-
|
3
|
-
require 'mongo'
|
4
|
-
|
5
|
-
include Mongo
|
6
|
-
|
7
|
-
host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
|
8
|
-
port = ENV['MONGO_RUBY_DRIVER_PORT'] || MongoClient::DEFAULT_PORT
|
9
|
-
|
10
|
-
puts "Connecting to #{host}:#{port}"
|
11
|
-
db = MongoClient.new(host, port).db('ruby-mongo-examples')
|
12
|
-
|
13
|
-
db.drop_collection('does-not-exist')
|
14
|
-
db.create_collection('test')
|
15
|
-
|
16
|
-
db.strict = true
|
17
|
-
|
18
|
-
begin
|
19
|
-
# Can't reference collection that does not exist
|
20
|
-
db.collection('does-not-exist')
|
21
|
-
puts "error: expected exception"
|
22
|
-
rescue => ex
|
23
|
-
puts "expected exception: #{ex}"
|
24
|
-
end
|
25
|
-
|
26
|
-
begin
|
27
|
-
# Can't create collection that already exists
|
28
|
-
db.create_collection('test')
|
29
|
-
puts "error: expected exception"
|
30
|
-
rescue => ex
|
31
|
-
puts "expected exception: #{ex}"
|
32
|
-
end
|
33
|
-
|
34
|
-
db.strict = false
|
35
|
-
db.drop_collection('test')
|
data/examples/types.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
-
|
3
|
-
require 'mongo'
|
4
|
-
require 'pp'
|
5
|
-
|
6
|
-
include Mongo
|
7
|
-
|
8
|
-
host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
|
9
|
-
port = ENV['MONGO_RUBY_DRIVER_PORT'] || MongoClient::DEFAULT_PORT
|
10
|
-
|
11
|
-
puts "Connecting to #{host}:#{port}"
|
12
|
-
db = MongoClient.new(host, port).db('ruby-mongo-examples')
|
13
|
-
coll = db.collection('test')
|
14
|
-
|
15
|
-
# Remove all records, if any
|
16
|
-
coll.remove
|
17
|
-
|
18
|
-
# Insert record with all sorts of values
|
19
|
-
coll.insert('array' => [1, 2, 3],
|
20
|
-
'string' => 'hello',
|
21
|
-
'hash' => {'a' => 1, 'b' => 2},
|
22
|
-
'date' => Time.now, # milliseconds only; microseconds are not stored
|
23
|
-
'oid' => ObjectID.new,
|
24
|
-
'binary' => Binary.new([1, 2, 3]),
|
25
|
-
'int' => 42,
|
26
|
-
'float' => 33.33333,
|
27
|
-
'regex' => /foobar/i,
|
28
|
-
'boolean' => true,
|
29
|
-
'where' => Code.new('this.x == 3'),
|
30
|
-
'dbref' => DBRef.new(coll.name, ObjectID.new),
|
31
|
-
'null' => nil,
|
32
|
-
'symbol' => :zildjian)
|
33
|
-
|
34
|
-
pp coll.find().next_document
|
35
|
-
|
36
|
-
coll.remove
|
data/examples/web/thin/load.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), '..', '..', '..', 'lib', 'mongo')
|
2
|
-
require 'logger'
|
3
|
-
|
4
|
-
include Mongo
|
5
|
-
|
6
|
-
$con = MongoReplicaSetClient.new(['localhost:30000', 'localhost:30001'], :read => :secondary, :refresh_mode => :sync, :refresh_interval => 30)
|
7
|
-
$db = $con['foo']
|
8
|
-
|
9
|
-
class Load < Sinatra::Base
|
10
|
-
|
11
|
-
configure do
|
12
|
-
LOGGER = Logger.new("sinatra.log")
|
13
|
-
enable :logging, :dump_errors
|
14
|
-
set :raise_errors, true
|
15
|
-
end
|
16
|
-
|
17
|
-
get '/' do
|
18
|
-
$db['test'].insert({:a => rand(1000)})
|
19
|
-
$db['test'].find({:a => {'$gt' => rand(2)}}, :read => :secondary).limit(2).to_a
|
20
|
-
"ok"
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'mongo')
|
2
|
-
|
3
|
-
include Mongo
|
4
|
-
|
5
|
-
$client = MongoClient.new('localhost', 27017)
|
6
|
-
$db = $client['foo']
|
7
|
-
|
8
|
-
class Load < Sinatra::Base
|
9
|
-
|
10
|
-
configure do
|
11
|
-
LOGGER = Logger.new("sinatra.log")
|
12
|
-
enable :logging, :dump_errors
|
13
|
-
set :raise_errors, true
|
14
|
-
end
|
15
|
-
|
16
|
-
get '/' do
|
17
|
-
3.times do |n|
|
18
|
-
if (v=$db.eval("1 + #{n}")) != 1 + n
|
19
|
-
STDERR << "#{1 + n} expected but got #{v}"
|
20
|
-
raise StandardError, "#{1 + n} expected but got #{v}"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
@@ -1,186 +0,0 @@
|
|
1
|
-
# Note: HashWithIndifferentAccess is so commonly used
|
2
|
-
# that we always need to make sure that the driver works
|
3
|
-
# with it.
|
4
|
-
#require File.join(File.dirname(__FILE__), 'keys.rb')
|
5
|
-
|
6
|
-
# This class has dubious semantics and we only have it so that
|
7
|
-
# people can write params[:key] instead of params['key']
|
8
|
-
# and they get the same value for both keys.
|
9
|
-
|
10
|
-
class Hash
|
11
|
-
# Return a new hash with all keys converted to strings.
|
12
|
-
def stringify_keys
|
13
|
-
dup.stringify_keys!
|
14
|
-
end
|
15
|
-
|
16
|
-
# Destructively convert all keys to strings.
|
17
|
-
def stringify_keys!
|
18
|
-
keys.each do |key|
|
19
|
-
self[key.to_s] = delete(key)
|
20
|
-
end
|
21
|
-
self
|
22
|
-
end
|
23
|
-
|
24
|
-
# Return a new hash with all keys converted to symbols, as long as
|
25
|
-
# they respond to +to_sym+.
|
26
|
-
def symbolize_keys
|
27
|
-
dup.symbolize_keys!
|
28
|
-
end
|
29
|
-
|
30
|
-
# Destructively convert all keys to symbols, as long as they respond
|
31
|
-
# to +to_sym+.
|
32
|
-
def symbolize_keys!
|
33
|
-
keys.each do |key|
|
34
|
-
self[(key.to_sym rescue key) || key] = delete(key)
|
35
|
-
end
|
36
|
-
self
|
37
|
-
end
|
38
|
-
|
39
|
-
alias_method :to_options, :symbolize_keys
|
40
|
-
#alias_method :to_options!, :symbolize_keys!
|
41
|
-
end
|
42
|
-
|
43
|
-
module ActiveSupport
|
44
|
-
class HashWithIndifferentAccess < Hash
|
45
|
-
def extractable_options?
|
46
|
-
true
|
47
|
-
end
|
48
|
-
|
49
|
-
def initialize(constructor = {})
|
50
|
-
if constructor.is_a?(Hash)
|
51
|
-
super()
|
52
|
-
update(constructor)
|
53
|
-
else
|
54
|
-
super(constructor)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def default(key = nil)
|
59
|
-
if key.is_a?(Symbol) && include?(key = key.to_s)
|
60
|
-
self[key]
|
61
|
-
else
|
62
|
-
super
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def self.new_from_hash_copying_default(hash)
|
67
|
-
ActiveSupport::HashWithIndifferentAccess.new(hash).tap do |new_hash|
|
68
|
-
new_hash.default = hash.default
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
|
73
|
-
alias_method :regular_update, :update unless method_defined?(:regular_update)
|
74
|
-
|
75
|
-
# Assigns a new value to the hash:
|
76
|
-
#
|
77
|
-
# hash = HashWithIndifferentAccess.new
|
78
|
-
# hash[:key] = "value"
|
79
|
-
#
|
80
|
-
def []=(key, value)
|
81
|
-
regular_writer(convert_key(key), convert_value(value))
|
82
|
-
end
|
83
|
-
|
84
|
-
# Updates the instantized hash with values from the second:
|
85
|
-
#
|
86
|
-
# hash_1 = HashWithIndifferentAccess.new
|
87
|
-
# hash_1[:key] = "value"
|
88
|
-
#
|
89
|
-
# hash_2 = HashWithIndifferentAccess.new
|
90
|
-
# hash_2[:key] = "New Value!"
|
91
|
-
#
|
92
|
-
# hash_1.update(hash_2) # => {"key"=>"New Value!"}
|
93
|
-
#
|
94
|
-
def update(other_hash)
|
95
|
-
other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
|
96
|
-
self
|
97
|
-
end
|
98
|
-
|
99
|
-
alias_method :merge!, :update
|
100
|
-
|
101
|
-
# Checks the hash for a key matching the argument passed in:
|
102
|
-
#
|
103
|
-
# hash = HashWithIndifferentAccess.new
|
104
|
-
# hash["key"] = "value"
|
105
|
-
# hash.key? :key # => true
|
106
|
-
# hash.key? "key" # => true
|
107
|
-
#
|
108
|
-
def key?(key)
|
109
|
-
super(convert_key(key))
|
110
|
-
end
|
111
|
-
|
112
|
-
alias_method :include?, :key?
|
113
|
-
alias_method :has_key?, :key?
|
114
|
-
alias_method :member?, :key?
|
115
|
-
|
116
|
-
# Fetches the value for the specified key, same as doing hash[key]
|
117
|
-
def fetch(key, *extras)
|
118
|
-
super(convert_key(key), *extras)
|
119
|
-
end
|
120
|
-
|
121
|
-
# Returns an array of the values at the specified indices:
|
122
|
-
#
|
123
|
-
# hash = HashWithIndifferentAccess.new
|
124
|
-
# hash[:a] = "x"
|
125
|
-
# hash[:b] = "y"
|
126
|
-
# hash.values_at("a", "b") # => ["x", "y"]
|
127
|
-
#
|
128
|
-
def values_at(*indices)
|
129
|
-
indices.collect {|key| self[convert_key(key)]}
|
130
|
-
end
|
131
|
-
|
132
|
-
# Returns an exact copy of the hash.
|
133
|
-
def dup
|
134
|
-
HashWithIndifferentAccess.new(self)
|
135
|
-
end
|
136
|
-
|
137
|
-
# Merges the instantized and the specified hashes together, giving precedence to the values from the second hash
|
138
|
-
# Does not overwrite the existing hash.
|
139
|
-
def merge(hash)
|
140
|
-
self.dup.update(hash)
|
141
|
-
end
|
142
|
-
|
143
|
-
# Performs the opposite of merge, with the keys and values from the first hash taking precedence over the second.
|
144
|
-
# This overloaded definition prevents returning a regular hash, if reverse_merge is called on a HashWithDifferentAccess.
|
145
|
-
def reverse_merge(other_hash)
|
146
|
-
super self.class.new_from_hash_copying_default(other_hash)
|
147
|
-
end
|
148
|
-
|
149
|
-
def reverse_merge!(other_hash)
|
150
|
-
replace(reverse_merge( other_hash ))
|
151
|
-
end
|
152
|
-
|
153
|
-
# Removes a specified key from the hash.
|
154
|
-
def delete(key)
|
155
|
-
super(convert_key(key))
|
156
|
-
end
|
157
|
-
|
158
|
-
def stringify_keys!; self end
|
159
|
-
def stringify_keys; dup end
|
160
|
-
def symbolize_keys; to_hash.symbolize_keys end
|
161
|
-
def to_options!; self end
|
162
|
-
|
163
|
-
# Convert to a Hash with String keys.
|
164
|
-
def to_hash
|
165
|
-
Hash.new(default).merge!(self)
|
166
|
-
end
|
167
|
-
|
168
|
-
protected
|
169
|
-
def convert_key(key)
|
170
|
-
key.kind_of?(Symbol) ? key.to_s : key
|
171
|
-
end
|
172
|
-
|
173
|
-
def convert_value(value)
|
174
|
-
case value
|
175
|
-
when Hash
|
176
|
-
self.class.new_from_hash_copying_default(value)
|
177
|
-
when Array
|
178
|
-
value.collect { |e| e.is_a?(Hash) ? self.class.new_from_hash_copying_default(e) : e }
|
179
|
-
else
|
180
|
-
value
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
#HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess
|
data/test/support/keys.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
class Hash
|
2
|
-
# Return a new hash with all keys converted to strings.
|
3
|
-
def stringify_keys
|
4
|
-
dup.stringify_keys!
|
5
|
-
end
|
6
|
-
|
7
|
-
# Destructively convert all keys to strings.
|
8
|
-
def stringify_keys!
|
9
|
-
keys.each do |key|
|
10
|
-
self[key.to_s] = delete(key)
|
11
|
-
end
|
12
|
-
self
|
13
|
-
end
|
14
|
-
|
15
|
-
# Return a new hash with all keys converted to symbols, as long as
|
16
|
-
# they respond to +to_sym+.
|
17
|
-
def symbolize_keys
|
18
|
-
dup.symbolize_keys!
|
19
|
-
end
|
20
|
-
|
21
|
-
# Destructively convert all keys to symbols, as long as they respond
|
22
|
-
# to +to_sym+.
|
23
|
-
def symbolize_keys!
|
24
|
-
keys.each do |key|
|
25
|
-
self[(key.to_sym rescue key) || key] = delete(key)
|
26
|
-
end
|
27
|
-
self
|
28
|
-
end
|
29
|
-
|
30
|
-
alias_method :to_options, :symbolize_keys
|
31
|
-
#alias_method :to_options!, :symbolize_keys!
|
32
|
-
|
33
|
-
# Validate all keys in a hash match *valid keys, raising ArgumentError on a mismatch.
|
34
|
-
# Note that keys are NOT treated indifferently, meaning if you use strings for keys but assert symbols
|
35
|
-
# as keys, this will fail.
|
36
|
-
#
|
37
|
-
# ==== Examples
|
38
|
-
# { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key(s): years"
|
39
|
-
# { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key(s): name, age"
|
40
|
-
# { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing
|
41
|
-
def assert_valid_keys(*valid_keys)
|
42
|
-
unknown_keys = keys - [valid_keys].flatten
|
43
|
-
raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
|
44
|
-
end
|
45
|
-
end
|
@@ -1,90 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
# Essentialy the same as test_threading.rb but with an expanded pool for
|
4
|
-
# testing multiple connections.
|
5
|
-
class TestThreadingLargePool < Test::Unit::TestCase
|
6
|
-
|
7
|
-
include Mongo
|
8
|
-
|
9
|
-
@@client = standard_connection(:pool_size => 50, :pool_timeout => 60)
|
10
|
-
@@db = @@client.db(MONGO_TEST_DB)
|
11
|
-
@@coll = @@db.collection('thread-test-collection')
|
12
|
-
|
13
|
-
def set_up_safe_data
|
14
|
-
@@db.drop_collection('duplicate')
|
15
|
-
@@db.drop_collection('unique')
|
16
|
-
@duplicate = @@db.collection('duplicate')
|
17
|
-
@unique = @@db.collection('unique')
|
18
|
-
|
19
|
-
@duplicate.insert("test" => "insert")
|
20
|
-
@duplicate.insert("test" => "update")
|
21
|
-
@unique.insert("test" => "insert")
|
22
|
-
@unique.insert("test" => "update")
|
23
|
-
@unique.create_index("test", :unique => true)
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_safe_update
|
27
|
-
set_up_safe_data
|
28
|
-
threads = []
|
29
|
-
300.times do |i|
|
30
|
-
threads[i] = Thread.new do
|
31
|
-
if i % 2 == 0
|
32
|
-
assert_raise Mongo::OperationFailure do
|
33
|
-
@unique.update({"test" => "insert"}, {"$set" => {"test" => "update"}})
|
34
|
-
end
|
35
|
-
else
|
36
|
-
@duplicate.update({"test" => "insert"}, {"$set" => {"test" => "update"}})
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
300.times do |i|
|
42
|
-
threads[i].join
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def test_safe_insert
|
47
|
-
set_up_safe_data
|
48
|
-
threads = []
|
49
|
-
300.times do |i|
|
50
|
-
threads[i] = Thread.new do
|
51
|
-
if i % 2 == 0
|
52
|
-
assert_raise Mongo::OperationFailure do
|
53
|
-
@unique.insert({"test" => "insert"})
|
54
|
-
end
|
55
|
-
else
|
56
|
-
@duplicate.insert({"test" => "insert"})
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
300.times do |i|
|
62
|
-
threads[i].join
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_threading
|
67
|
-
@@coll.drop
|
68
|
-
@@coll = @@db.collection('thread-test-collection')
|
69
|
-
|
70
|
-
1000.times do |i|
|
71
|
-
@@coll.insert({ "x" => i })
|
72
|
-
end
|
73
|
-
|
74
|
-
threads = []
|
75
|
-
|
76
|
-
10.times do |i|
|
77
|
-
threads[i] = Thread.new do
|
78
|
-
sum = 0
|
79
|
-
@@coll.find().each do |document|
|
80
|
-
sum += document["x"]
|
81
|
-
end
|
82
|
-
assert_equal 499500, sum
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
10.times do |i|
|
87
|
-
threads[i].join
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|