mongo 1.8.5 → 1.8.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b8b721f436d16c55388789c19bd0c03b99812702
4
- data.tar.gz: b43de3ec9c986727abd9d4bf181e038ce3ddbe02
3
+ metadata.gz: 5bdb78ad2291ea3ecb387526ccdbd162ffd51687
4
+ data.tar.gz: 6b3ec42fadc3f0beea953a08fe07a2d2ff206cba
5
5
  SHA512:
6
- metadata.gz: d0c55e5a9968be883c92acb53676b6ae8d08a77578dbaaec4cca2d71bf1c535d981d63f4f1377712819bae39733f6bde8781f8af860f5469e172bf4c2a14acb6
7
- data.tar.gz: 241ccee8c30eadb597252c4fea0a599b920551c4f77dea15fbf747eea2abf7e0270788f496d6df657f8d88cb98728fae20a956977a285086c7f25a161bc8c89b
6
+ metadata.gz: 83bb86f711779590a47d0d8d83fea4d844cd8ebdcde6617109c9172dd9d6961688d3faf03c1c7d0c0601575ed1a253522aecc2b26f2e81fb7980079ca3dff9fd
7
+ data.tar.gz: 880a70826f29e9e60fff3d26ede30390da593e78ad095f635743ffec711ce22af34da2d89318fd48f7825e2583bbec02da80c78899d4388386a76c769ee1e80e
Binary file
data.tar.gz.sig CHANGED
Binary file
data/Rakefile CHANGED
@@ -8,10 +8,10 @@ rescue LoadError
8
8
  raise '[FAIL] Bundler not found! Install it with `gem install bundler; bundle install`.'
9
9
  end
10
10
 
11
- if ENV['TEST']
11
+ if ENV.has_key?('TEST') || ENV.has_key?('TRAVIS_TEST')
12
12
  Bundler.require(:default, :testing)
13
13
  else
14
- Bundler.require(:default, :deploy, :testing)
14
+ Bundler.require(:default, :testing, :deploy, :development)
15
15
  end
16
16
 
17
17
  Dir.glob(File.join('tasks', '**', '*.rake')).sort.each { |rake| load File.expand_path(rake) }
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.8.5
1
+ 1.8.6
@@ -192,7 +192,12 @@ module Mongo
192
192
  user = users.find_one({:user => username}) || {:user => username}
193
193
  user['pwd'] = Mongo::Support.hash_password(username, password)
194
194
  user['readOnly'] = true if read_only;
195
- users.save(user)
195
+ begin
196
+ users.save(user)
197
+ rescue OperationFailure => ex
198
+ # adding first admin user fails GLE in MongoDB 2.2
199
+ raise ex unless ex.message =~ /login/
200
+ end
196
201
  user
197
202
  end
198
203
 
@@ -160,7 +160,7 @@ module Mongo
160
160
 
161
161
  # Initialize a connection to MongoDB using the MongoDB URI spec.
162
162
  #
163
- # Since MongoClient.new cannot be used with any <code>ENV["MONGODB_URI"]</code> that has multiple hosts (implying a replicaset),
163
+ # Since MongoClient.new cannot be used with any <code>ENV["MONGODB_URI"]</code> that has multiple hosts (implying a replicaset),
164
164
  # you may use this when the type of your connection varies by environment and should be determined solely from <code>ENV["MONGODB_URI"]</code>.
165
165
  #
166
166
  # @param uri [String]
@@ -469,7 +469,7 @@ module Mongo
469
469
  # NOTE: Do check if this needs to be more stringent.
470
470
  # Probably not since if any node raises a connection failure, all nodes will be closed.
471
471
  def connected?
472
- @primary_pool && !@primary_pool.closed?
472
+ !!(@primary_pool && !@primary_pool.closed?)
473
473
  end
474
474
 
475
475
  # Determine if the connection is active. In a normal case the *server_info* operation
@@ -545,6 +545,32 @@ module Mongo
545
545
  end
546
546
  end
547
547
 
548
+ # Internal method for checking isMaster() on a given node.
549
+ #
550
+ # @param node [Array] Port and host for the target node
551
+ # @return [Hash] Response from isMaster()
552
+ #
553
+ # @private
554
+ def check_is_master(node)
555
+ begin
556
+ host, port = *node
557
+ config = nil
558
+ socket = @socket_class.new(host, port, @op_timeout, @connect_timeout)
559
+ if @connect_timeout
560
+ Timeout::timeout(@connect_timeout, OperationTimeout) do
561
+ config = self['admin'].command({:ismaster => 1}, :socket => socket)
562
+ end
563
+ else
564
+ config = self['admin'].command({:ismaster => 1}, :socket => socket)
565
+ end
566
+ rescue OperationFailure, SocketError, SystemCallError, IOError
567
+ close
568
+ ensure
569
+ socket.close unless socket.nil? || socket.closed?
570
+ end
571
+ config
572
+ end
573
+
548
574
  protected
549
575
 
550
576
  def valid_opts
@@ -621,31 +647,6 @@ module Mongo
621
647
 
622
648
  private
623
649
 
624
- def check_is_master(node)
625
- begin
626
- host, port = *node
627
- socket = nil
628
- config = nil
629
-
630
- socket = @socket_class.new(host, port, @op_timeout, @connect_timeout)
631
- if(@connect_timeout)
632
- Timeout::timeout(@connect_timeout, OperationTimeout) do
633
- config = self['admin'].command({:ismaster => 1}, :socket => socket)
634
- end
635
- else
636
- config = self['admin'].command({:ismaster => 1}, :socket => socket)
637
- end
638
- rescue OperationFailure, SocketError, SystemCallError, IOError
639
- close
640
- ensure
641
- if socket
642
- socket.close unless socket.closed?
643
- end
644
- end
645
-
646
- config
647
- end
648
-
649
650
  # Set the specified node as primary.
650
651
  def set_primary(node)
651
652
  host, port = *node
@@ -137,14 +137,9 @@ module Mongo
137
137
  # Lock for request ids.
138
138
  @id_lock = Mutex.new
139
139
 
140
- @pool_mutex = Mutex.new
141
140
  @connected = false
142
141
 
143
- @safe_mutex_lock = Mutex.new
144
- @safe_mutexes = Hash.new {|hash, key| hash[key] = Mutex.new}
145
-
146
142
  @connect_mutex = Mutex.new
147
- @refresh_mutex = Mutex.new
148
143
 
149
144
  @mongos = false
150
145
 
@@ -162,7 +157,8 @@ module Mongo
162
157
  end
163
158
 
164
159
  # Initiate a connection to the replica set.
165
- def connect
160
+ def connect(force = !connected?)
161
+ return unless force
166
162
  log(:info, "Connecting...")
167
163
 
168
164
  # Prevent recursive connection attempts from the same thread.
@@ -170,15 +166,18 @@ module Mongo
170
166
  # infinitely while attempting to connect and continually failing. Instead, fail fast.
171
167
  raise ConnectionFailure, "Failed to get node data." if thread_local[:locks][:connecting] == true
172
168
 
169
+ current_version = @refresh_version
173
170
  @connect_mutex.synchronize do
174
- return if @connected
171
+ # don't try to connect if another thread has done so while we were waiting for the lock
172
+ return unless current_version == @refresh_version
175
173
  begin
176
174
  thread_local[:locks][:connecting] = true
177
175
  if @manager
178
- @manager.refresh! @seeds
176
+ ensure_manager
177
+ @manager.refresh!(@seeds)
179
178
  else
180
179
  @manager = PoolManager.new(self, @seeds)
181
- thread_local[:managers][self] = @manager
180
+ ensure_manager
182
181
  @manager.connect
183
182
  end
184
183
  ensure
@@ -210,6 +209,7 @@ module Mongo
210
209
  end
211
210
 
212
211
  log(:debug, "Checking replica set connection health...")
212
+ ensure_manager
213
213
  @manager.check_connection_health
214
214
 
215
215
  if @manager.refresh_required?
@@ -227,9 +227,7 @@ module Mongo
227
227
  # to get the refresh lock.
228
228
  def hard_refresh!
229
229
  log(:info, "Initiating hard refresh...")
230
- @manager.refresh! @seeds
231
-
232
- @refresh_version += 1
230
+ connect(true)
233
231
  return true
234
232
  end
235
233
 
@@ -420,6 +418,10 @@ module Mongo
420
418
  local_manager ? local_manager.secondary_pools : []
421
419
  end
422
420
 
421
+ def pools
422
+ local_manager ? local_manager.pools : []
423
+ end
424
+
423
425
  def tag_map
424
426
  local_manager ? local_manager.tag_map : {}
425
427
  end
@@ -475,16 +477,8 @@ module Mongo
475
477
  def sync_refresh
476
478
  if @refresh_mode == :sync &&
477
479
  ((Time.now - @last_refresh) > @refresh_interval)
478
-
479
480
  @last_refresh = Time.now
480
-
481
- if @refresh_mutex.try_lock
482
- begin
483
- refresh
484
- ensure
485
- @refresh_mutex.unlock
486
- end
487
- end
481
+ refresh
488
482
  end
489
483
  end
490
484
  end
@@ -41,14 +41,9 @@ module Mongo
41
41
  # Lock for request ids.
42
42
  @id_lock = Mutex.new
43
43
 
44
- @pool_mutex = Mutex.new
45
44
  @connected = false
46
45
 
47
- @safe_mutex_lock = Mutex.new
48
- @safe_mutexes = Hash.new {|hash, key| hash[key] = Mutex.new}
49
-
50
46
  @connect_mutex = Mutex.new
51
- @refresh_mutex = Mutex.new
52
47
 
53
48
  @mongos = true
54
49
 
@@ -66,7 +61,7 @@ module Mongo
66
61
  end
67
62
 
68
63
  # Initiate a connection to the sharded cluster.
69
- def connect(force = !@connected)
64
+ def connect(force = !connected?)
70
65
  return unless force
71
66
  log(:info, "Connecting...")
72
67
 
@@ -79,10 +74,11 @@ module Mongo
79
74
  begin
80
75
  thread_local[:locks][:connecting] = true
81
76
  if @manager
77
+ thread_local[:managers][self] = @manager
82
78
  @manager.refresh! @seeds
83
79
  else
84
80
  @manager = ShardingPoolManager.new(self, @seeds)
85
- thread_local[:managers][self] = @manager
81
+ ensure_manager
86
82
  @manager.connect
87
83
  end
88
84
  ensure
@@ -108,7 +104,7 @@ module Mongo
108
104
  end
109
105
 
110
106
  def connected?
111
- @connected && @manager.primary_pool
107
+ !!(@connected && @manager.primary_pool)
112
108
  end
113
109
 
114
110
  # Returns +true+ if it's okay to read from a secondary node.
@@ -140,7 +136,8 @@ module Mongo
140
136
  # @param opts [ Hash ] Any of the options available for MongoShardedClient.new
141
137
  #
142
138
  # @return [ Mongo::MongoShardedClient ] The sharded client.
143
- def self.from_uri(uri = ENV['MONGODB_URI'], options = {})
139
+ def self.from_uri(uri, options = {})
140
+ uri ||= ENV['MONGODB_URI']
144
141
  URIParser.new(uri).connection(options, false, true)
145
142
  end
146
143
  end
@@ -90,6 +90,7 @@ module Mongo
90
90
  end
91
91
 
92
92
  @config = @client['admin'].command({:ismaster => 1}, :socket => @socket)
93
+ update_max_sizes
93
94
 
94
95
  if @config['msg']
95
96
  @client.log(:warn, "#{config['msg']}")
@@ -106,7 +107,6 @@ module Mongo
106
107
  close
107
108
  end
108
109
  end
109
- @manager.update_max_sizes
110
110
  end
111
111
 
112
112
  # Return a list of replica set nodes from the config.
@@ -151,11 +151,11 @@ module Mongo
151
151
  end
152
152
 
153
153
  def max_bson_size
154
- max = config['maxBsonObjectSize'] || DEFAULT_MAX_BSON_SIZE
154
+ @max_bson_size || DEFAULT_MAX_BSON_SIZE
155
155
  end
156
156
 
157
157
  def max_message_size
158
- max = config['maxMessageSizeBytes'] || max_bson_size * MESSAGE_SIZE_FACTOR
158
+ @max_message_size || max_bson_size * MESSAGE_SIZE_FACTOR
159
159
  end
160
160
 
161
161
  protected
@@ -186,5 +186,12 @@ module Mongo
186
186
  end
187
187
  end
188
188
  end
189
+
190
+ private
191
+
192
+ def update_max_sizes
193
+ @max_bson_size = config['maxBsonObjectSize'] || DEFAULT_MAX_BSON_SIZE
194
+ @max_message_size = config['maxMessageSizeBytes'] || @max_bson_size * MESSAGE_SIZE_FACTOR
195
+ end
189
196
  end
190
197
  end
@@ -9,8 +9,6 @@ module Mongo
9
9
  :primary_pool,
10
10
  :secondary_pools,
11
11
  :hosts,
12
- :nodes,
13
- :members,
14
12
  :seeds,
15
13
  :pools,
16
14
  :max_bson_size,
@@ -24,19 +22,21 @@ module Mongo
24
22
  # time. The union of these lists will be used when attempting to connect,
25
23
  # with the newly-discovered nodes being used first.
26
24
  def initialize(client, seeds=[])
27
- @client = client
28
- @seeds = seeds
29
-
30
- @pools = Set.new
31
- @primary = nil
32
- @primary_pool = nil
33
- @secondaries = Set.new
34
- @secondary_pools = []
35
- @hosts = Set.new
36
- @members = Set.new
37
- @refresh_required = false
38
- @max_bson_size = DEFAULT_MAX_BSON_SIZE
39
- @max_message_size = @max_bson_size * MESSAGE_SIZE_FACTOR
25
+ @client = client
26
+ @seeds = seeds
27
+
28
+ @pools = Set.new
29
+ @primary = nil
30
+ @primary_pool = nil
31
+ @secondaries = Set.new
32
+ @secondary_pools = []
33
+ @hosts = Set.new
34
+ @members = Set.new
35
+ @refresh_required = false
36
+ @max_bson_size = DEFAULT_MAX_BSON_SIZE
37
+ @max_message_size = @max_bson_size * MESSAGE_SIZE_FACTOR
38
+ @connect_mutex = Mutex.new
39
+ thread_local[:locks][:connecting_manager] = false
40
40
  end
41
41
 
42
42
  def inspect
@@ -44,11 +44,19 @@ module Mongo
44
44
  end
45
45
 
46
46
  def connect
47
- @refresh_required = false
48
- disconnect_old_members
49
- connect_to_members
50
- initialize_pools(@members)
51
- @seeds = discovered_seeds
47
+ @connect_mutex.synchronize do
48
+ begin
49
+ thread_local[:locks][:connecting_manager] = true
50
+ @refresh_required = false
51
+ disconnect_old_members
52
+ connect_to_members
53
+ initialize_pools(@members)
54
+ update_max_sizes
55
+ @seeds = discovered_seeds
56
+ ensure
57
+ thread_local[:locks][:connecting_manager] = false
58
+ end
59
+ end
52
60
  end
53
61
 
54
62
  def refresh!(additional_seeds)
@@ -61,6 +69,8 @@ module Mongo
61
69
  # to our view. If any of these isn't the case,
62
70
  # set @refresh_required to true, and return.
63
71
  def check_connection_health
72
+ return if thread_local[:locks][:connecting_manager]
73
+ members = copy_members
64
74
  begin
65
75
  seed = get_valid_seed_node
66
76
  rescue ConnectionFailure
@@ -74,14 +84,14 @@ module Mongo
74
84
  return
75
85
  end
76
86
 
77
- if current_config['hosts'].length != @members.length
87
+ if current_config['hosts'].length != members.length
78
88
  @refresh_required = true
79
89
  seed.close
80
90
  return
81
91
  end
82
92
 
83
93
  current_config['hosts'].each do |host|
84
- member = @members.detect do |m|
94
+ member = members.detect do |m|
85
95
  m.address == host
86
96
  end
87
97
 
@@ -90,7 +100,7 @@ module Mongo
90
100
  else
91
101
  @refresh_required = true
92
102
  seed.close
93
- return false
103
+ return
94
104
  end
95
105
  end
96
106
 
@@ -117,6 +127,8 @@ module Mongo
117
127
  read_pool.host_port
118
128
  end
119
129
 
130
+ private
131
+
120
132
  def update_max_sizes
121
133
  unless @members.size == 0
122
134
  @max_bson_size = @members.map(&:max_bson_size).min
@@ -124,8 +136,6 @@ module Mongo
124
136
  end
125
137
  end
126
138
 
127
- private
128
-
129
139
  def validate_existing_member(current_config, member)
130
140
  if current_config['ismaster'] && member.last_state != :primary
131
141
  return false
@@ -152,13 +162,13 @@ module Mongo
152
162
  existing.set_config
153
163
  # If we are unhealthy after refreshing our config, drop from the set.
154
164
  if !existing.healthy?
155
- @members.delete existing
165
+ @members.delete(existing)
156
166
  else
157
167
  next
158
168
  end
159
169
  else
160
170
  existing.close
161
- @members.delete existing
171
+ @members.delete(existing)
162
172
  end
163
173
  end
164
174
 
@@ -242,11 +252,19 @@ module Mongo
242
252
  "#{@seeds.map {|s| "#{s[0]}:#{s[1]}" }.join(', ')}"
243
253
  end
244
254
 
245
- private
246
-
247
255
  def discovered_seeds
248
256
  @members.map(&:host_port)
249
257
  end
250
258
 
259
+ def copy_members
260
+ members = Set.new
261
+ @connect_mutex.synchronize do
262
+ @members.map do |m|
263
+ members << m.dup
264
+ end
265
+ end
266
+ members
267
+ end
268
+
251
269
  end
252
270
  end
@@ -9,11 +9,11 @@ module Mongo
9
9
  ]
10
10
 
11
11
  MONGOS_MODES = {
12
- :primary => :primary,
13
- :primary_preferred => :primaryPreferred,
14
- :secondary => :secondary,
15
- :secondary_preferred => :secondaryPreferred,
16
- :nearest => :nearest
12
+ :primary => 'primary',
13
+ :primary_preferred => 'primaryPreferred',
14
+ :secondary => 'secondary',
15
+ :secondary_preferred => 'secondaryPreferred',
16
+ :nearest => 'nearest'
17
17
  }
18
18
 
19
19
  def self.mongos(mode, tag_sets)
@@ -77,7 +77,7 @@ module Mongo
77
77
  when :secondary_preferred
78
78
  select_secondary_pool(secondary_pools, read_pref) || primary_pool
79
79
  when :nearest
80
- select_secondary_pool(pools, read_pref)
80
+ select_near_pool(pools, read_pref)
81
81
  end
82
82
  end
83
83
 
@@ -12,30 +12,43 @@ module Mongo
12
12
  end
13
13
 
14
14
  def connect
15
- @refresh_required = false
16
- disconnect_old_members
17
- connect_to_members
18
- initialize_pools best(@members)
19
- @seeds = discovered_seeds
15
+ @connect_mutex.synchronize do
16
+ begin
17
+ thread_local[:locks][:connecting_manager] = true
18
+ @refresh_required = false
19
+ disconnect_old_members
20
+ connect_to_members
21
+ initialize_pools best(@members)
22
+ update_max_sizes
23
+ @seeds = discovered_seeds
24
+ ensure
25
+ thread_local[:locks][:connecting_manager] = false
26
+ end
27
+ end
20
28
  end
21
29
 
22
- # We want to refresh to the member with the fastest ping time
23
- # but also want to minimize refreshes
24
- # We're healthy if the primary is pingable. If this isn't the case,
25
- # or the members have changed, set @refresh_required to true, and return.
26
- # The config.mongos find can't be part of the connect call chain due to infinite recursion
30
+ # Checks that each node is healthy (via check_is_master) and that each
31
+ # node is in fact a mongos. If either criteria are not true, a refresh is
32
+ # set to be triggered and close() is called on the node.
33
+ #
34
+ # @return [Boolean] indicating if a refresh is required.
27
35
  def check_connection_health
28
- begin
29
- seeds = @client['config']['mongos'].find.map do |mongos|
30
- Support.normalize_seeds(mongos['_id'])
31
- end
32
- if discovered_seeds != seeds
33
- @seeds = seeds
36
+ @refresh_required = false
37
+ @members.each do |member|
38
+ begin
39
+ config = @client.check_is_master([member.host, member.port])
40
+ unless config && config.has_key?('msg')
41
+ @refresh_required = true
42
+ member.close
43
+ end
44
+ rescue OperationTimeout
34
45
  @refresh_required = true
46
+ member.close
35
47
  end
36
- rescue Mongo::OperationFailure
37
- @refresh_required = true
48
+ break if @refresh_required
38
49
  end
50
+ @refresh_required
39
51
  end
52
+
40
53
  end
41
54
  end
@@ -8,10 +8,7 @@ class AuthenticationTest < Test::Unit::TestCase
8
8
  def setup
9
9
  @client = MongoClient.new
10
10
  @db = @client[MONGO_TEST_DB]
11
- end
12
-
13
- def teardown
14
- @db['system.users'].remove
11
+ init_auth
15
12
  end
16
13
 
17
14
  def test_authenticate_with_connection_uri
@@ -8,11 +8,8 @@ class ReplicaSetAuthenticationTest < Test::Unit::TestCase
8
8
  def setup
9
9
  ensure_cluster(:rs)
10
10
  @client = MongoReplicaSetClient.new(@rs.repl_set_seeds, :name => @rs.repl_set_name, :connect_timeout => 60)
11
- @db = @client[MONGO_TEST_DB]
12
- end
13
-
14
- def teardown
15
- @db['system.users'].remove
11
+ @db = @client[MONGO_TEST_DB]
12
+ init_auth
16
13
  end
17
14
 
18
15
  def test_authenticate_with_connection_uri
@@ -11,6 +11,21 @@ class ClientTest < Test::Unit::TestCase
11
11
  @client.close if @client
12
12
  end
13
13
 
14
+ def test_reconnection
15
+ @client = MongoReplicaSetClient.new @rs.repl_set_seeds
16
+ assert @client.connected?
17
+
18
+ manager = @client.local_manager
19
+
20
+ @client.close
21
+ assert !@client.connected?
22
+ assert !@client.local_manager
23
+
24
+ @client.connect
25
+ assert @client.connected?
26
+ assert_equal @client.local_manager, manager
27
+ end
28
+
14
29
  # TODO: test connect timeout.
15
30
 
16
31
  def test_connect_with_deprecated_multi
@@ -7,6 +7,12 @@ class MaxValuesTest < Test::Unit::TestCase
7
7
  def setup
8
8
  ensure_cluster(:rs)
9
9
  @client = MongoReplicaSetClient.new(@rs.repl_set_seeds, :name => @rs.repl_set_name)
10
+ @db = new_mock_db
11
+ @client.stubs(:[]).returns(@db)
12
+ @ismaster = {
13
+ 'hosts' => @client.local_manager.hosts.to_a,
14
+ 'arbiters' => @client.local_manager.arbiters
15
+ }
10
16
  end
11
17
 
12
18
  def test_initial_max_sizes
@@ -15,43 +21,52 @@ class MaxValuesTest < Test::Unit::TestCase
15
21
  end
16
22
 
17
23
  def test_updated_max_sizes_after_node_config_change
18
- # stub max sizes for one member
19
- @client.local_manager.members.each_with_index do |m, i|
20
- if i % 2 == 0
21
- m.stubs(:config).returns({'maxMessageSizeBytes' => 1024 * MESSAGE_SIZE_FACTOR, 'maxBsonObjectSize' => 1024})
22
- m.set_config
23
- end
24
- end
24
+ @db.stubs(:command).returns(
25
+ @ismaster.merge({'ismaster' => true}),
26
+ @ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 1024 * MESSAGE_SIZE_FACTOR}),
27
+ @ismaster.merge({'secondary' => true, 'maxBsonObjectSize' => 1024})
28
+ )
29
+ @client.local_manager.stubs(:refresh_required?).returns(true)
30
+ @client.refresh
25
31
 
26
32
  assert_equal 1024, @client.max_bson_size
27
33
  assert_equal 1024 * MESSAGE_SIZE_FACTOR, @client.max_message_size
28
34
  end
29
35
 
30
36
  def test_neither_max_sizes_in_config
31
- @client.local_manager.members.each do |m|
32
- m.stubs(:config).returns({})
33
- m.set_config
34
- end
37
+ @db.stubs(:command).returns(
38
+ @ismaster.merge({'ismaster' => true}),
39
+ @ismaster.merge({'secondary' => true}),
40
+ @ismaster.merge({'secondary' => true})
41
+ )
42
+ @client.local_manager.stubs(:refresh_required?).returns(true)
43
+ @client.refresh
35
44
 
36
45
  assert_equal DEFAULT_MAX_BSON_SIZE, @client.max_bson_size
37
46
  assert_equal DEFAULT_MAX_BSON_SIZE * MESSAGE_SIZE_FACTOR, @client.max_message_size
38
47
  end
39
48
 
40
49
  def test_only_bson_size_in_config
41
- @client.local_manager.members.each do |m|
42
- m.stubs(:config).returns({'maxBsonObjectSize' => 1024})
43
- m.set_config
44
- end
50
+ @db.stubs(:command).returns(
51
+ @ismaster.merge({'ismaster' => true}),
52
+ @ismaster.merge({'secondary' => true}),
53
+ @ismaster.merge({'secondary' => true, 'maxBsonObjectSize' => 1024})
54
+ )
55
+ @client.local_manager.stubs(:refresh_required?).returns(true)
56
+ @client.refresh
57
+
45
58
  assert_equal 1024, @client.max_bson_size
46
59
  assert_equal 1024 * MESSAGE_SIZE_FACTOR, @client.max_message_size
47
60
  end
48
61
 
49
62
  def test_both_sizes_in_config
50
- @client.local_manager.members.each do |m|
51
- m.stubs(:config).returns({'maxMessageSizeBytes' => 1024 * 2 * MESSAGE_SIZE_FACTOR,
52
- 'maxBsonObjectSize' => 1024})
53
- m.set_config
54
- end
63
+ @db.stubs(:command).returns(
64
+ @ismaster.merge({'ismaster' => true, 'maxMessageSizeBytes' => 1024 * 2 * MESSAGE_SIZE_FACTOR, 'maxBsonObjectSize' => 1024}),
65
+ @ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 1024 * 2 * MESSAGE_SIZE_FACTOR, 'maxBsonObjectSize' => 1024}),
66
+ @ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 1024 * 2 * MESSAGE_SIZE_FACTOR, 'maxBsonObjectSize' => 1024})
67
+ )
68
+ @client.local_manager.stubs(:refresh_required?).returns(true)
69
+ @client.refresh
55
70
 
56
71
  assert_equal 1024, @client.max_bson_size
57
72
  assert_equal 1024 * 2 * MESSAGE_SIZE_FACTOR, @client.max_message_size
@@ -78,6 +78,37 @@ class ReplicaSetRefreshTest < Test::Unit::TestCase
78
78
  "No secondaries have been added."
79
79
  assert_equal num_secondaries, client.secondary_pools.size
80
80
  end
81
+
82
+ def test_concurrent_refreshes
83
+ factor = 5
84
+ nthreads = factor * 10
85
+ threads = []
86
+ client = MongoReplicaSetClient.new(@rs.repl_set_seeds, :refresh_mode => :sync, :refresh_interval => 1)
87
+
88
+ nthreads.times do |i|
89
+ threads << Thread.new do
90
+ # force a connection failure every couple of threads that causes a refresh
91
+ if i % factor == 0
92
+ cursor = client['foo']['bar'].find
93
+ cursor.stubs(:checkout_socket_from_connection).raises(ConnectionFailure)
94
+ begin
95
+ cursor.next
96
+ rescue => ex
97
+ raise ex unless ex.class == ConnectionFailure
98
+ next
99
+ end
100
+ else
101
+ # synchronous refreshes will happen every couple of find_ones
102
+ cursor = client['foo']['bar'].find_one
103
+ end
104
+ end
105
+ end
106
+
107
+ threads.each do |t|
108
+ t.join
109
+ end
110
+ end
111
+
81
112
  =begin
82
113
  def test_automated_refresh_with_removed_node
83
114
  client = MongoReplicaSetClient.new(@rs.repl_set_seeds,
@@ -36,7 +36,7 @@ class BasicTest < Test::Unit::TestCase
36
36
  @client = MongoClient.new(host, port, {:read => :secondary, :tag_sets => tags})
37
37
  assert @client.connected?
38
38
  cursor = Cursor.new(@client[MONGO_TEST_DB]['whatever'], {})
39
- assert_equal cursor.construct_query_spec['$readPreference'], {:mode => :secondary, :tags => tags}
39
+ assert_equal cursor.construct_query_spec['$readPreference'], {:mode => 'secondary', :tags => tags}
40
40
  end
41
41
 
42
42
  def test_find_one_with_read_secondary
@@ -68,7 +68,7 @@ class BasicTest < Test::Unit::TestCase
68
68
  @client = MongoShardedClient.new(@seeds, {:read => :secondary, :tag_sets => tags})
69
69
  assert @client.connected?
70
70
  cursor = Cursor.new(@client[MONGO_TEST_DB]['whatever'], {})
71
- assert_equal cursor.construct_query_spec['$readPreference'], {:mode => :secondary, :tags => tags}
71
+ assert_equal cursor.construct_query_spec['$readPreference'], {:mode => 'secondary', :tags => tags}
72
72
  end
73
73
 
74
74
  def test_hard_refresh
@@ -1,4 +1,21 @@
1
1
  module AuthenticationTests
2
+
3
+ def init_auth
4
+ # enable authentication by creating and logging in as admin user
5
+ @admin = @client['admin']
6
+ @admin.add_user('admin', 'password')
7
+ @admin.authenticate('admin', 'password')
8
+ end
9
+
10
+ def teardown
11
+ @admin.logout
12
+ @admin.authenticate('admin','password')
13
+ @admin['system.users'].remove
14
+ @db['system.users'].remove
15
+ @db['test'].remove
16
+ @admin.logout
17
+ end
18
+
2
19
  def test_add_user
3
20
  @db.add_user('bob','user')
4
21
  assert @db['system.users'].find_one({:user => 'bob'})
@@ -1,4 +1,10 @@
1
- require 'rubygems'
1
+ begin
2
+ require 'pry-rescue'
3
+ require 'pry-nav'
4
+ rescue LoadError
5
+ # failed to load, skipping pry
6
+ end
7
+
2
8
  # SimpleCov must load before our code - A coverage report summary line will print after each test suite
3
9
  if RUBY_VERSION >= '1.9.0' && RUBY_ENGINE == 'ruby'
4
10
  if ENV.key?('COVERAGE')
@@ -35,7 +35,7 @@ module Mongo
35
35
  MONGODS_OPT_KEYS = [:mongods]
36
36
  CLUSTER_OPT_KEYS = SHARDING_OPT_KEYS + REPLICA_OPT_KEYS + MONGODS_OPT_KEYS
37
37
 
38
- FLAGS = [:noprealloc, :smallfiles, :logappend, :configsvr, :shardsvr, :quiet, :fastsync]
38
+ FLAGS = [:noprealloc, :smallfiles, :logappend, :configsvr, :shardsvr, :quiet, :fastsync, :auth]
39
39
 
40
40
  DEFAULT_VERIFIES = 60
41
41
  BASE_PORT = 3000
@@ -108,18 +108,24 @@ module Mongo
108
108
  :smallfiles => smallfiles,
109
109
  :noprealloc => noprealloc,
110
110
  :quiet => quiet,
111
- :fastsync => fast_sync)
111
+ :fastsync => fast_sync,
112
+ :auth => auth)
112
113
  end
113
114
 
114
- def self.make_replica(opts, count)
115
+ def self.make_replica(opts, id)
115
116
  params = make_mongod('replicas', opts)
116
117
 
117
118
  replSet = opts[:replSet] || 'ruby-driver-test'
118
- oplog_size = opts[:oplog_size] || 5
119
+ oplogSize = opts[:oplog_size] || 5
120
+ keyFile = opts[:key_file] || '/test/tools/keyfile.txt'
119
121
 
120
- params.merge(:_id => count,
122
+ keyFile = Dir.pwd << keyFile
123
+ system "chmod 600 #{keyFile}"
124
+
125
+ params.merge(:_id => id,
121
126
  :replSet => replSet,
122
- :oplogSize => oplog_size)
127
+ :oplogSize => oplogSize,
128
+ :keyFile => keyFile)
123
129
  end
124
130
 
125
131
  def self.make_config(opts)
@@ -187,7 +193,7 @@ module Mongo
187
193
  if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
188
194
  @pid = Process.spawn(*@cmd)
189
195
  else
190
- cmd_and_opts = [@cmd, {:out => :close}].flatten
196
+ cmd_and_opts = [@cmd, {:out => '/dev/null'}].flatten
191
197
  @pid = Process.spawn(*cmd_and_opts)
192
198
  end
193
199
  verify(verifies) if verifies > 0
@@ -124,7 +124,7 @@ class CursorTest < Test::Unit::TestCase
124
124
 
125
125
  spec = cursor.construct_query_spec
126
126
  assert spec.has_key?('$readPreference')
127
- assert_equal :secondary, spec['$readPreference'][:mode]
127
+ assert_equal 'secondary', spec['$readPreference'][:mode]
128
128
  assert !spec['$readPreference'].has_key?(:tags)
129
129
 
130
130
  # secondary preferred with tags
@@ -132,7 +132,7 @@ class CursorTest < Test::Unit::TestCase
132
132
 
133
133
  spec = cursor.construct_query_spec
134
134
  assert spec.has_key?('$readPreference')
135
- assert_equal :secondaryPreferred, spec['$readPreference'][:mode]
135
+ assert_equal 'secondaryPreferred', spec['$readPreference'][:mode]
136
136
  assert_equal @tag_sets, spec['$readPreference'][:tags]
137
137
 
138
138
  # primary preferred
@@ -140,7 +140,7 @@ class CursorTest < Test::Unit::TestCase
140
140
 
141
141
  spec = cursor.construct_query_spec
142
142
  assert spec.has_key?('$readPreference')
143
- assert_equal :primaryPreferred, spec['$readPreference'][:mode]
143
+ assert_equal 'primaryPreferred', spec['$readPreference'][:mode]
144
144
  assert !spec['$readPreference'].has_key?(:tags)
145
145
 
146
146
  # primary preferred with tags
@@ -148,7 +148,7 @@ class CursorTest < Test::Unit::TestCase
148
148
 
149
149
  spec = cursor.construct_query_spec
150
150
  assert spec.has_key?('$readPreference')
151
- assert_equal :primaryPreferred, spec['$readPreference'][:mode]
151
+ assert_equal 'primaryPreferred', spec['$readPreference'][:mode]
152
152
  assert_equal @tag_sets, spec['$readPreference'][:tags]
153
153
 
154
154
  # nearest
@@ -156,7 +156,7 @@ class CursorTest < Test::Unit::TestCase
156
156
 
157
157
  spec = cursor.construct_query_spec
158
158
  assert spec.has_key?('$readPreference')
159
- assert_equal :nearest, spec['$readPreference'][:mode]
159
+ assert_equal 'nearest', spec['$readPreference'][:mode]
160
160
  assert !spec['$readPreference'].has_key?(:tags)
161
161
 
162
162
  # nearest with tags
@@ -164,7 +164,7 @@ class CursorTest < Test::Unit::TestCase
164
164
 
165
165
  spec = cursor.construct_query_spec
166
166
  assert spec.has_key?('$readPreference')
167
- assert_equal :nearest, spec['$readPreference'][:mode]
167
+ assert_equal 'nearest', spec['$readPreference'][:mode]
168
168
  assert_equal @tag_sets, spec['$readPreference'][:tags]
169
169
  end
170
170
 
@@ -9,24 +9,24 @@ class MongoShardedClientTest < Test::Unit::TestCase
9
9
 
10
10
  def test_initialize_with_single_mongos_uri
11
11
  ENV["MONGODB_URI"] = "mongodb://localhost:27017"
12
- client = MongoShardedClient.new
12
+ client = MongoShardedClient.new(:connect => false)
13
13
  assert_equal [[ "localhost", 27017 ]], client.seeds
14
14
  end
15
15
 
16
16
  def test_initialize_with_multiple_mongos_uris
17
17
  ENV["MONGODB_URI"] = "mongodb://localhost:27017,localhost:27018"
18
- client = MongoShardedClient.new
18
+ client = MongoShardedClient.new(:connect => false)
19
19
  assert_equal [[ "localhost", 27017 ], [ "localhost", 27018 ]], client.seeds
20
20
  end
21
21
 
22
22
  def test_from_uri_with_string
23
- client = MongoShardedClient.from_uri("mongodb://localhost:27017,localhost:27018")
23
+ client = MongoShardedClient.from_uri("mongodb://localhost:27017,localhost:27018", :connect => false)
24
24
  assert_equal [[ "localhost", 27017 ], [ "localhost", 27018 ]], client.seeds
25
25
  end
26
26
 
27
27
  def test_from_uri_with_env_variable
28
28
  ENV["MONGODB_URI"] = "mongodb://localhost:27017,localhost:27018"
29
- client = MongoShardedClient.from_uri
29
+ client = MongoShardedClient.from_uri(nil, :connect => false)
30
30
  assert_equal [[ "localhost", 27017 ], [ "localhost", 27018 ]], client.seeds
31
31
  end
32
32
  end
@@ -0,0 +1,21 @@
1
+ require 'test_helper'
2
+
3
+ class ReadPrefTest < Test::Unit::TestCase
4
+ include ReadPreference
5
+
6
+ def setup
7
+ mock_pool = mock()
8
+ mock_pool.stubs(:ping_time).returns(Pool::MAX_PING_TIME)
9
+
10
+ stubs(:primary_pool).returns(mock_pool)
11
+ stubs(:secondary_pools).returns([mock_pool])
12
+ stubs(:pools).returns([mock_pool])
13
+ end
14
+
15
+ def test_select_pool
16
+ ReadPreference::READ_PREFERENCES.map do |rp|
17
+ assert select_pool({:mode => rp, :tags => [], :latency => 15})
18
+ end
19
+ end
20
+
21
+ end
@@ -59,30 +59,5 @@ class ShardingPoolManagerTest < Test::Unit::TestCase
59
59
  assert_equal 500, manager.max_bson_size
60
60
  assert_equal 700 , manager.max_message_size
61
61
  end
62
-
63
- should "maintain seed format when checking connection health" do
64
-
65
- @db.stubs(:command).returns(
66
- # First call to get a socket.
67
- @ismaster.merge({'ismaster' => true}),
68
-
69
- # Subsequent calls to configure pools.
70
- @ismaster.merge({'ismaster' => true}),
71
- @ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 700}),
72
- @ismaster.merge({'secondary' => true, 'maxBsonObjectSize' => 500}),
73
- @ismaster.merge({'arbiterOnly' => true})
74
- )
75
-
76
- config_db = new_mock_db
77
- mongos_coll = mock('collection')
78
- mongos_coll.stubs(:find).returns(@hosts.map{|h| {'_id' => h}})
79
- config_db.stubs(:[]).with('mongos').returns(mongos_coll)
80
- @client.stubs(:[]).with('config').returns(config_db)
81
-
82
- manager = Mongo::ShardingPoolManager.new(@client, @hosts)
83
- manager.check_connection_health
84
-
85
- assert manager.seeds.all? {|s| s.is_a?(Array) && s[0].is_a?(String) && s[1].is_a?(Integer)}
86
- end
87
62
  end
88
63
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.5
4
+ version: 1.8.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tyler Brock
@@ -33,7 +33,7 @@ cert_chain:
33
33
  8v7zLF2XliYbfurYIwkcXs8yPn8ggApBIy9bX6VJxRs/l2+UvqzaHIFaFy/F8/GP
34
34
  RNTuXsVG5NDACo7Q
35
35
  -----END CERTIFICATE-----
36
- date: 2013-04-11 00:00:00.000000000 Z
36
+ date: 2013-05-16 00:00:00.000000000 Z
37
37
  dependencies:
38
38
  - !ruby/object:Gem::Dependency
39
39
  name: bson
@@ -41,14 +41,14 @@ dependencies:
41
41
  requirements:
42
42
  - - ~>
43
43
  - !ruby/object:Gem::Version
44
- version: 1.8.5
44
+ version: 1.8.6
45
45
  type: :runtime
46
46
  prerelease: false
47
47
  version_requirements: !ruby/object:Gem::Requirement
48
48
  requirements:
49
49
  - - ~>
50
50
  - !ruby/object:Gem::Version
51
- version: 1.8.5
51
+ version: 1.8.6
52
52
  description: A Ruby driver for MongoDB. For more information about Mongo, see http://www.mongodb.org.
53
53
  email: mongodb-dev@googlegroups.com
54
54
  executables:
@@ -143,6 +143,7 @@ files:
143
143
  - test/unit/node_test.rb
144
144
  - test/unit/pool_manager_test.rb
145
145
  - test/unit/pool_test.rb
146
+ - test/unit/read_pref_test.rb
146
147
  - test/unit/read_test.rb
147
148
  - test/unit/safe_test.rb
148
149
  - test/unit/sharding_pool_manager_test.rb
@@ -223,6 +224,7 @@ test_files:
223
224
  - test/unit/node_test.rb
224
225
  - test/unit/pool_manager_test.rb
225
226
  - test/unit/pool_test.rb
227
+ - test/unit/read_pref_test.rb
226
228
  - test/unit/read_test.rb
227
229
  - test/unit/safe_test.rb
228
230
  - test/unit/sharding_pool_manager_test.rb
metadata.gz.sig CHANGED
@@ -1 +1 @@
1
- �4������i[ 8�[��1׈�#Y,t�[1Y�^Rar��:�*�1��iؒ�o���vT�M�L������^����>A3�P< ����_&��;k�tخ��Sz�v������B'���HU* +�z�N]@��ȳ��ϣ~2��Ul����h�>���8�]�7����߾�����r�����<
1
+ ;cJ�g����H�#~������Ç���������J�.� ۞(T�.7{��<�!����:ݬ���T;�S���RJ��y��A��x��D8ʒ�=k���nL7�пk�Y�[>�����1*+>)5 ���i�qJ3��^*q&��f��