mongo 1.1.5 → 1.3.0

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.
Files changed (76) hide show
  1. data/README.md +15 -15
  2. data/Rakefile +38 -17
  3. data/docs/FAQ.md +4 -0
  4. data/docs/HISTORY.md +59 -0
  5. data/docs/RELEASES.md +33 -0
  6. data/docs/REPLICA_SETS.md +13 -16
  7. data/lib/mongo/collection.rb +157 -69
  8. data/lib/mongo/connection.rb +189 -65
  9. data/lib/mongo/cursor.rb +43 -29
  10. data/lib/mongo/db.rb +63 -43
  11. data/lib/mongo/exceptions.rb +4 -1
  12. data/lib/mongo/gridfs/grid.rb +1 -1
  13. data/lib/mongo/gridfs/grid_ext.rb +1 -1
  14. data/lib/mongo/gridfs/grid_file_system.rb +1 -1
  15. data/lib/mongo/gridfs/grid_io.rb +89 -8
  16. data/lib/mongo/gridfs/grid_io_fix.rb +1 -1
  17. data/lib/mongo/repl_set_connection.rb +72 -20
  18. data/lib/mongo/test.rb +20 -0
  19. data/lib/mongo/util/conversions.rb +1 -1
  20. data/lib/mongo/util/core_ext.rb +11 -1
  21. data/lib/mongo/util/pool.rb +67 -15
  22. data/lib/mongo/util/server_version.rb +1 -1
  23. data/lib/mongo/util/support.rb +1 -1
  24. data/lib/mongo/util/uri_parser.rb +127 -13
  25. data/lib/mongo.rb +38 -2
  26. data/test/async/collection_test.rb +224 -0
  27. data/test/async/connection_test.rb +24 -0
  28. data/test/async/cursor_test.rb +162 -0
  29. data/test/async/worker_pool_test.rb +99 -0
  30. data/test/auxillary/fork_test.rb +30 -0
  31. data/test/auxillary/repl_set_auth_test.rb +58 -0
  32. data/test/auxillary/threaded_authentication_test.rb +101 -0
  33. data/test/bson/bson_test.rb +140 -28
  34. data/test/bson/byte_buffer_test.rb +18 -0
  35. data/test/bson/object_id_test.rb +14 -1
  36. data/test/bson/ordered_hash_test.rb +7 -0
  37. data/test/bson/timestamp_test.rb +24 -0
  38. data/test/collection_test.rb +104 -15
  39. data/test/connection_test.rb +78 -2
  40. data/test/conversions_test.rb +10 -11
  41. data/test/cursor_fail_test.rb +1 -1
  42. data/test/cursor_message_test.rb +1 -1
  43. data/test/cursor_test.rb +33 -4
  44. data/test/db_api_test.rb +30 -52
  45. data/test/db_test.rb +3 -3
  46. data/test/grid_file_system_test.rb +0 -1
  47. data/test/grid_io_test.rb +72 -1
  48. data/test/grid_test.rb +16 -16
  49. data/test/load/resque/load.rb +21 -0
  50. data/test/load/resque/processor.rb +26 -0
  51. data/test/load/thin/load.rb +24 -0
  52. data/test/load/unicorn/load.rb +23 -0
  53. data/test/load/unicorn/unicorn.rb +29 -0
  54. data/test/replica_sets/connect_test.rb +11 -1
  55. data/test/replica_sets/connection_string_test.rb +32 -0
  56. data/test/replica_sets/query_secondaries.rb +16 -0
  57. data/test/replica_sets/query_test.rb +10 -0
  58. data/test/replica_sets/replication_ack_test.rb +2 -0
  59. data/test/replica_sets/rs_test_helper.rb +9 -11
  60. data/test/support/hash_with_indifferent_access.rb +0 -13
  61. data/test/support_test.rb +0 -1
  62. data/test/test_helper.rb +27 -8
  63. data/test/tools/auth_repl_set_manager.rb +14 -0
  64. data/test/tools/load.rb +58 -0
  65. data/test/tools/repl_set_manager.rb +34 -9
  66. data/test/tools/sharding_manager.rb +202 -0
  67. data/test/tools/test.rb +3 -12
  68. data/test/unit/collection_test.rb +20 -24
  69. data/test/unit/connection_test.rb +4 -18
  70. data/test/unit/cursor_test.rb +16 -6
  71. data/test/unit/db_test.rb +10 -11
  72. data/test/unit/repl_set_connection_test.rb +0 -23
  73. data/test/unit/safe_test.rb +3 -3
  74. data/test/uri_test.rb +91 -0
  75. metadata +49 -12
  76. data/docs/1.0_UPGRADE.md +0 -21
@@ -16,8 +16,8 @@ class ConnectTest < Test::Unit::TestCase
16
16
 
17
17
  def test_connect_with_deprecated_multi
18
18
  @conn = Connection.multi([[RS.host, RS.ports[0]], [RS.host, RS.ports[1]]], :name => RS.name)
19
- assert @conn.connected?
20
19
  assert @conn.is_a?(ReplSetConnection)
20
+ assert @conn.connected?
21
21
  end
22
22
 
23
23
  def test_connect_bad_name
@@ -31,12 +31,22 @@ class ConnectTest < Test::Unit::TestCase
31
31
  @conn = ReplSetConnection.new([RS.host, RS.ports[0]], [RS.host, RS.ports[1]],
32
32
  [RS.host, RS.ports[2]], :name => RS.name)
33
33
  assert @conn.connected?
34
+ assert @conn.read_primary?
35
+ assert @conn.primary?
34
36
 
35
37
  assert_equal RS.primary, @conn.primary
36
38
  assert_equal RS.secondaries.sort, @conn.secondaries.sort
37
39
  assert_equal RS.arbiters.sort, @conn.arbiters.sort
38
40
  end
39
41
 
42
+ def test_host_port_accessors
43
+ @conn = ReplSetConnection.new([RS.host, RS.ports[0]], [RS.host, RS.ports[1]],
44
+ [RS.host, RS.ports[2]], :name => RS.name)
45
+
46
+ assert_equal @conn.host, RS.primary[0]
47
+ assert_equal @conn.port, RS.primary[1]
48
+ end
49
+
40
50
  def test_connect_with_primary_node_killed
41
51
  node = RS.kill_primary
42
52
 
@@ -0,0 +1,32 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require './test/replica_sets/rs_test_helper'
3
+
4
+ # NOTE: This test expects a replica set of three nodes to be running on RS.host,
5
+ # on ports TEST_PORT, RS.ports[1], and TEST + 2.
6
+ class ConnectionStringTest < Test::Unit::TestCase
7
+ include Mongo
8
+
9
+ def setup
10
+ RS.restart_killed_nodes
11
+ end
12
+
13
+ def teardown
14
+ RS.restart_killed_nodes
15
+ end
16
+
17
+ def test_connect_with_connection_string
18
+ @conn = Connection.from_uri("mongodb://#{RS.host}:#{RS.ports[0]},#{RS.host}:#{RS.ports[1]}?replicaset=#{RS.name}")
19
+ assert @conn.is_a?(ReplSetConnection)
20
+ assert @conn.connected?
21
+ end
22
+
23
+ def test_connect_with_full_connection_string
24
+ @conn = Connection.from_uri("mongodb://#{RS.host}:#{RS.ports[0]},#{RS.host}:#{RS.ports[1]}?replicaset=#{RS.name};safe=true;w=2;fsync=true;slaveok=true")
25
+ assert @conn.is_a?(ReplSetConnection)
26
+ assert @conn.connected?
27
+ assert_equal 2, @conn.safe[:w]
28
+ assert @conn.safe[:fsync]
29
+ assert @conn.read_pool
30
+ end
31
+
32
+ end
@@ -16,6 +16,13 @@ class ReplicaSetQuerySecondariesTest < Test::Unit::TestCase
16
16
  RS.restart_killed_nodes
17
17
  end
18
18
 
19
+ def test_read_primary
20
+ rescue_connection_failure do
21
+ assert !@conn.read_primary?
22
+ assert !@conn.primary?
23
+ end
24
+ end
25
+
19
26
  def test_con
20
27
  assert @conn.primary_pool, "No primary pool!"
21
28
  assert @conn.read_pool, "No read pool!"
@@ -54,6 +61,12 @@ class ReplicaSetQuerySecondariesTest < Test::Unit::TestCase
54
61
  # Should still be able to read immediately after killing master node
55
62
  RS.kill_primary
56
63
  assert_equal 2, @coll.find.to_a.length
64
+ rescue_connection_failure do
65
+ @coll.save({:a => 50}, :safe => {:w => 2, :wtimeout => 10000})
66
+ end
67
+ RS.restart_killed_nodes
68
+ @coll.save({:a => 50}, :safe => {:w => 2, :wtimeout => 10000})
69
+ assert_equal 4, @coll.find.to_a.length
57
70
  end
58
71
 
59
72
  def test_kill_secondary
@@ -66,6 +79,7 @@ class ReplicaSetQuerySecondariesTest < Test::Unit::TestCase
66
79
  RS.kill(read_node)
67
80
 
68
81
  # Should fail immediately on next read
82
+ old_read_pool_port = @conn.read_pool.port
69
83
  assert_raise ConnectionFailure do
70
84
  @coll.find.to_a.length
71
85
  end
@@ -75,6 +89,8 @@ class ReplicaSetQuerySecondariesTest < Test::Unit::TestCase
75
89
  length = @coll.find.to_a.length
76
90
  assert_equal 2, length
77
91
  end
92
+ new_read_pool_port = @conn.read_pool.port
93
+ assert old_read_pool != new_read_pool
78
94
  end
79
95
 
80
96
  end
@@ -27,6 +27,8 @@ class ReplicaSetQueryTest < Test::Unit::TestCase
27
27
  assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
28
28
  end
29
29
 
30
+ puts "Benchmark before failover: #{benchmark_queries}"
31
+
30
32
  RS.kill_primary
31
33
 
32
34
  results = []
@@ -35,7 +37,15 @@ class ReplicaSetQueryTest < Test::Unit::TestCase
35
37
  [20, 30, 40].each do |a|
36
38
  assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
37
39
  end
40
+
41
+ puts "Benchmark after failover: #{benchmark_queries}"
38
42
  end
39
43
  end
40
44
 
45
+ def benchmark_queries
46
+ t1 = Time.now
47
+ 10000.times { @coll.find_one }
48
+ Time.now - t1
49
+ end
50
+
41
51
  end
@@ -13,6 +13,8 @@ class ReplicaSetAckTest < Test::Unit::TestCase
13
13
  @slave1 = Connection.new(@conn.secondary_pools[0].host,
14
14
  @conn.secondary_pools[0].port, :slave_ok => true)
15
15
 
16
+ assert !@slave1.read_primary?
17
+
16
18
  @db = @conn.db(MONGO_TEST_DB)
17
19
  @db.drop_collection("test-sets")
18
20
  @col = @db.collection("test-sets")
@@ -12,17 +12,15 @@ class Test::Unit::TestCase
12
12
  # Generic code for rescuing connection failures and retrying operations.
13
13
  # This could be combined with some timeout functionality.
14
14
  def rescue_connection_failure(max_retries=60)
15
- success = false
16
- tries = 0
17
- while !success && tries < max_retries
18
- begin
19
- yield
20
- success = true
21
- rescue Mongo::ConnectionFailure
22
- puts "Rescue attempt #{tries}\n"
23
- tries += 1
24
- sleep(1)
25
- end
15
+ retries = 0
16
+ begin
17
+ yield
18
+ rescue Mongo::ConnectionFailure => ex
19
+ puts "Rescue attempt #{retries}: from #{ex}"
20
+ retries += 1
21
+ raise ex if retries > max_retries
22
+ sleep(1)
23
+ retry
26
24
  end
27
25
  end
28
26
 
@@ -38,19 +38,6 @@ class Hash
38
38
 
39
39
  alias_method :to_options, :symbolize_keys
40
40
  #alias_method :to_options!, :symbolize_keys!
41
-
42
- # Validate all keys in a hash match *valid keys, raising ArgumentError on a mismatch.
43
- # Note that keys are NOT treated indifferently, meaning if you use strings for keys but assert symbols
44
- # as keys, this will fail.
45
- #
46
- # ==== Examples
47
- # { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key(s): years"
48
- # { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key(s): name, age"
49
- # { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing
50
- def assert_valid_keys(*valid_keys)
51
- unknown_keys = keys - [valid_keys].flatten
52
- raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
53
- end
54
41
  end
55
42
 
56
43
  module ActiveSupport
data/test/support_test.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require './test/test_helper'
2
2
 
3
3
  class SupportTest < Test::Unit::TestCase
4
- include Mongo
5
4
 
6
5
  def test_command_response_succeeds
7
6
  assert Support.ok?('ok' => 1)
data/test/test_helper.rb CHANGED
@@ -1,14 +1,22 @@
1
1
  $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- require 'rubygems' if ENV['C_EXT']
2
+ require 'rubygems' if RUBY_VERSION < '1.9.0' && ENV['C_EXT']
3
3
  require 'mongo'
4
4
  require 'test/unit'
5
5
 
6
+ def silently
7
+ warn_level = $VERBOSE
8
+ $VERBOSE = nil
9
+ result = yield
10
+ $VERBOSE = warn_level
11
+ result
12
+ end
13
+
6
14
  begin
7
- require 'rubygems'
8
- require 'shoulda'
9
- require 'mocha'
10
- rescue LoadError
11
- puts <<MSG
15
+ require 'rubygems' if RUBY_VERSION < "1.9.0" && !ENV['C_EXT']
16
+ silently { require 'shoulda' }
17
+ silently { require 'mocha' }
18
+ rescue LoadError
19
+ puts <<MSG
12
20
 
13
21
  This test suite requires shoulda and mocha.
14
22
  You can install them as follows:
@@ -16,7 +24,8 @@ You can install them as follows:
16
24
  gem install mocha
17
25
 
18
26
  MSG
19
- exit
27
+
28
+ exit
20
29
  end
21
30
 
22
31
  require 'bson_ext/cbson' if !(RUBY_PLATFORM =~ /java/) && ENV['C_EXT']
@@ -69,7 +78,17 @@ class Test::Unit::TestCase
69
78
  self.class.mongo_port
70
79
  end
71
80
 
72
-
81
+ def new_mock_socket(host='localhost', port=27017)
82
+ socket = Object.new
83
+ socket.stubs(:setsockopt).with(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
84
+ socket.stubs(:close)
85
+ socket
86
+ end
87
+
88
+ def new_mock_db
89
+ db = Object.new
90
+ end
91
+
73
92
  def assert_raise_error(klass, message)
74
93
  begin
75
94
  yield
@@ -0,0 +1,14 @@
1
+ require File.join((File.expand_path(File.dirname(__FILE__))), 'repl_set_manager')
2
+
3
+ class AuthReplSetManager < ReplSetManager
4
+ def initialize(opts={})
5
+ super(opts)
6
+
7
+ @key_path = opts[:key_path] || File.join(File.expand_path(File.dirname(__FILE__)), "keyfile.txt")
8
+ system("chmod 600 #{@key_path}")
9
+ end
10
+
11
+ def start_cmd(n)
12
+ super + " --keyFile #{@key_path}"
13
+ end
14
+ end
@@ -0,0 +1,58 @@
1
+ require 'rubygems'
2
+ require 'mongo'
3
+ require 'sharding_manager'
4
+
5
+ class MongoLoader
6
+
7
+ def initialize
8
+ @mongo = Mongo::Connection.new("localhost", 50000)
9
+ @data = BSON::Binary.new(File.open("tools.gz").read)
10
+ @count = 0
11
+ @manager = ShardingManager.new(:config_count => 3)
12
+ @manager.start_cluster
13
+ end
14
+
15
+ def kill
16
+ @manager.kill_random
17
+ end
18
+
19
+ def restart
20
+ @manager.restart_killed_nodes
21
+ end
22
+
23
+ def run
24
+ Thread.new do
25
+ ("a".."z").each do |p|
26
+ seed(p)
27
+ end
28
+ end
29
+ end
30
+
31
+ def seed(prefix)
32
+ @queue = []
33
+ 1000.times do |n|
34
+ id = BSON::OrderedHash.new
35
+ id[:p] = prefix
36
+ id[:c] = n
37
+ @queue << {:tid => id, :data => @data}
38
+ end
39
+
40
+ while @queue.length > 0 do
41
+ begin
42
+ doc = @queue.pop
43
+ @mongo['app']['photos'].insert(doc, :safe => {:w => 3})
44
+ @count += 1
45
+ p @count
46
+ rescue StandardError => e
47
+ p e
48
+ p @count
49
+ @queue.push(doc)
50
+ @count -= 1
51
+ sleep(10)
52
+ retry
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ @m = MongoLoader.new
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/ruby
2
2
 
3
+ require 'thread'
4
+
3
5
  STDOUT.sync = true
4
6
 
5
7
  unless defined? Mongo
@@ -17,6 +19,7 @@ class ReplSetManager
17
19
  @host = opts[:host] || 'localhost'
18
20
  @retries = opts[:retries] || 60
19
21
  @config = {"_id" => @name, "members" => []}
22
+ @durable = opts.fetch(:durable, false)
20
23
  @path = File.join(File.expand_path(File.dirname(__FILE__)), "data")
21
24
 
22
25
  @arbiter_count = opts[:arbiter_count] || 2
@@ -61,6 +64,13 @@ class ReplSetManager
61
64
  ensure_up
62
65
  end
63
66
 
67
+ def cleanup_set
68
+ system("killall mongod")
69
+ @count.times do |n|
70
+ system("rm -rf #{@mongods[n]['db_path']}")
71
+ end
72
+ end
73
+
64
74
  def init_node(n)
65
75
  @mongods[n] ||= {}
66
76
  port = @start_port + n
@@ -71,9 +81,7 @@ class ReplSetManager
71
81
  system("rm -rf #{@mongods[n]['db_path']}")
72
82
  system("mkdir -p #{@mongods[n]['db_path']}")
73
83
 
74
- @mongods[n]['start'] = "mongod --replSet #{@name} --logpath '#{@mongods[n]['log_path']}' " +
75
- " --dbpath #{@mongods[n]['db_path']} --port #{@mongods[n]['port']} --fork"
76
-
84
+ @mongods[n]['start'] = start_cmd(n)
77
85
  start(n)
78
86
 
79
87
  member = {'_id' => n, 'host' => "#{@host}:#{@mongods[n]['port']}"}
@@ -88,17 +96,24 @@ class ReplSetManager
88
96
  @config['members'] << member
89
97
  end
90
98
 
91
- def kill(node)
99
+ def start_cmd(n)
100
+ @mongods[n]['start'] = "mongod --replSet #{@name} --logpath '#{@mongods[n]['log_path']}' " +
101
+ " --dbpath #{@mongods[n]['db_path']} --port #{@mongods[n]['port']} --fork"
102
+ @mongods[n]['start'] += " --dur" if @durable
103
+ @mongods[n]['start']
104
+ end
105
+
106
+ def kill(node, signal=2)
92
107
  pid = @mongods[node]['pid']
93
108
  puts "** Killing node with pid #{pid} at port #{@mongods[node]['port']}"
94
- system("kill -2 #{@mongods[node]['pid']}")
109
+ system("kill -#{signal} #{@mongods[node]['pid']}")
95
110
  @mongods[node]['up'] = false
96
111
  sleep(1)
97
112
  end
98
113
 
99
- def kill_primary
114
+ def kill_primary(signal=2)
100
115
  node = get_node_with_state(1)
101
- kill(node)
116
+ kill(node, signal)
102
117
  return node
103
118
  end
104
119
 
@@ -174,6 +189,16 @@ class ReplSetManager
174
189
  get_all_host_pairs_with_state(7)
175
190
  end
176
191
 
192
+ # String used for adding a shard via mongos
193
+ # using the addshard command.
194
+ def shard_string
195
+ str = "#{@name}/"
196
+ str << @mongods.map do |k, mongod|
197
+ "#{@host}:#{mongod['port']}"
198
+ end.join(',')
199
+ str
200
+ end
201
+
177
202
  private
178
203
 
179
204
  def initiate
@@ -229,13 +254,13 @@ class ReplSetManager
229
254
  while count < @retries do
230
255
  begin
231
256
  return yield
232
- rescue Mongo::OperationFailure, Mongo::ConnectionFailure
257
+ rescue Mongo::OperationFailure, Mongo::ConnectionFailure => ex
233
258
  sleep(1)
234
259
  count += 1
235
260
  end
236
261
  end
237
262
 
238
- raise exception
263
+ raise ex
239
264
  end
240
265
 
241
266
  end
@@ -0,0 +1,202 @@
1
+ require 'repl_set_manager'
2
+ require 'thread'
3
+
4
+ class ShardingManager
5
+
6
+ attr_accessor :shards
7
+
8
+ def initialize(opts={})
9
+ @durable = opts.fetch(:durable, true)
10
+ @host = "localhost"
11
+
12
+ @mongos_port = opts[:mongos_port] || 50000
13
+ @config_port = opts[:config_port] || 40000
14
+ @shard_start_port = opts[:start_shard_port] || 30000
15
+ @path = File.join(File.expand_path(File.dirname(__FILE__)), "data")
16
+ system("rm -rf #{@path}")
17
+
18
+ @shard_count = 2
19
+ @mongos_count = 1
20
+ @config_count = opts.fetch(:config_count, 1)
21
+ if ![1, 3].include?(@config_count)
22
+ raise ArgumentError, "Must specify 1 or 3 config servers."
23
+ end
24
+
25
+ @config_servers = {}
26
+ @mongos_servers = {}
27
+ @shards = []
28
+ @ports = []
29
+ end
30
+
31
+ def kill_random
32
+ shard_to_kill = rand(@shard_count)
33
+ @shards[shard_to_kill].kill_primary
34
+ end
35
+
36
+ def restart_killed
37
+ threads = []
38
+ @shards.each do |k, shard|
39
+ threads << Thread.new do
40
+ shard.restart_killed_nodes
41
+ end
42
+ end
43
+ end
44
+
45
+ def start_cluster
46
+ start_sharding_components
47
+ start_mongos_servers
48
+ configure_cluster
49
+ end
50
+
51
+ def configure_cluster
52
+ add_shards
53
+ enable_sharding
54
+ shard_collection
55
+ end
56
+
57
+ def enable_sharding
58
+ mongos['admin'].command({:enablesharding => "app"})
59
+ end
60
+
61
+ def shard_collection
62
+ cmd = BSON::OrderedHash.new
63
+ cmd[:shardcollection] = "app.photos"
64
+ cmd[:key] = {:tid => 1}
65
+ p mongos['admin'].command(cmd)
66
+ end
67
+
68
+ def add_shards
69
+ @shards.each do |shard|
70
+ cmd = {:addshard => shard.shard_string}
71
+ p cmd
72
+ p mongos['admin'].command(cmd)
73
+ end
74
+ p mongos['admin'].command({:listshards => 1})
75
+ end
76
+
77
+ def mongos
78
+ attempt do
79
+ @mongos ||= Mongo::Connection.new(@host, @mongos_servers[0]['port'])
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def start_sharding_components
86
+ system("killall mongos")
87
+
88
+ threads = []
89
+ threads << Thread.new do
90
+ start_shards
91
+ end
92
+
93
+ threads << Thread.new do
94
+ start_config_servers
95
+ end
96
+ threads.each {|t| t.join}
97
+ puts "\nShards and config servers up!"
98
+ end
99
+
100
+ def start_shards
101
+ threads = []
102
+ @shard_count.times do |n|
103
+ threads << Thread.new do
104
+ port = @shard_start_port + n * 100
105
+ shard = ReplSetManager.new(:arbiter_count => 0, :secondary_count => 2,
106
+ :passive_count => 0, :start_port => port, :durable => @durable,
107
+ :name => "shard-#{n}")
108
+ shard.start_set
109
+ shard.ensure_up
110
+ @shards << shard
111
+ end
112
+ end
113
+ threads.each {|t| t.join}
114
+ end
115
+
116
+ def start_config_servers
117
+ @config_count.times do |n|
118
+ @config_servers[n] ||= {}
119
+ port = @config_port + n
120
+ @ports << port
121
+ @config_servers[n]['port'] = port
122
+ @config_servers[n]['db_path'] = get_path("config-#{port}")
123
+ @config_servers[n]['log_path'] = get_path("log-config-#{port}")
124
+ system("rm -rf #{@config_servers[n]['db_path']}")
125
+ system("mkdir -p #{@config_servers[n]['db_path']}")
126
+
127
+ @config_servers[n]['start'] = start_config_cmd(n)
128
+
129
+ start(@config_servers, n)
130
+ end
131
+ end
132
+
133
+ def start_mongos_servers
134
+ @mongos_count.times do |n|
135
+ @mongos_servers[n] ||= {}
136
+ port = @mongos_port + n
137
+ @ports << port
138
+ @mongos_servers[n]['port'] = port
139
+ @mongos_servers[n]['db_path'] = get_path("mongos-#{port}")
140
+ @mongos_servers[n]['pidfile_path'] = File.join(@mongos_servers[n]['db_path'], "mongod.lock")
141
+ @mongos_servers[n]['log_path'] = get_path("log-mongos-#{port}")
142
+ system("rm -rf #{@mongos_servers[n]['db_path']}")
143
+ system("mkdir -p #{@mongos_servers[n]['db_path']}")
144
+
145
+ @mongos_servers[n]['start'] = start_mongos_cmd(n)
146
+
147
+ start(@mongos_servers, n)
148
+ end
149
+ end
150
+
151
+ def start_config_cmd(n)
152
+ cmd = "mongod --configsvr --logpath '#{@config_servers[n]['log_path']}' " +
153
+ " --dbpath #{@config_servers[n]['db_path']} --port #{@config_servers[n]['port']} --fork"
154
+ cmd += " --dur" if @durable
155
+ cmd
156
+ end
157
+
158
+ def start_mongos_cmd(n)
159
+ "mongos --configdb #{config_db_string} --logpath '#{@mongos_servers[n]['log_path']}' " +
160
+ "--pidfilepath #{@mongos_servers[n]['pidfile_path']} --port #{@mongos_servers[n]['port']} --fork"
161
+ end
162
+
163
+ def config_db_string
164
+ @config_servers.map do |k, v|
165
+ "#{@host}:#{v['port']}"
166
+ end.join(',')
167
+ end
168
+
169
+ def start(set, node)
170
+ system(set[node]['start'])
171
+ set[node]['up'] = true
172
+ sleep(0.5)
173
+ set[node]['pid'] = File.open(File.join(set[node]['db_path'], 'mongod.lock')).read.strip
174
+ end
175
+ alias :restart :start
176
+
177
+ private
178
+
179
+ def cleanup_config
180
+ end
181
+
182
+ def get_path(name)
183
+ File.join(@path, name)
184
+ end
185
+
186
+ # TODO: put this into a shared module
187
+ def attempt
188
+ raise "No block given!" unless block_given?
189
+ count = 0
190
+
191
+ while count < 50 do
192
+ begin
193
+ return yield
194
+ rescue Mongo::OperationFailure, Mongo::ConnectionFailure
195
+ sleep(1)
196
+ count += 1
197
+ end
198
+ end
199
+
200
+ raise exception
201
+ end
202
+ end
data/test/tools/test.rb CHANGED
@@ -1,13 +1,4 @@
1
- require 'repl_set_manager'
1
+ require 'sharding_manager'
2
2
 
3
- m = ReplSetManager.new
4
- m.start_set
5
-
6
- node = m.kill_secondary
7
- m.ensure_up
8
-
9
- puts "Pausing..."
10
- gets
11
-
12
- m.start(node)
13
- m.ensure_up
3
+ m = ShardingManager.new(:config_count => 3)
4
+ m.start_cluster