mongo 1.8.5 → 1.8.6

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