mongo-lyon 1.2.4

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 (87) hide show
  1. data/LICENSE.txt +190 -0
  2. data/README.md +344 -0
  3. data/Rakefile +202 -0
  4. data/bin/mongo_console +34 -0
  5. data/docs/1.0_UPGRADE.md +21 -0
  6. data/docs/CREDITS.md +123 -0
  7. data/docs/FAQ.md +116 -0
  8. data/docs/GridFS.md +158 -0
  9. data/docs/HISTORY.md +225 -0
  10. data/docs/REPLICA_SETS.md +72 -0
  11. data/docs/TUTORIAL.md +247 -0
  12. data/docs/WRITE_CONCERN.md +28 -0
  13. data/lib/mongo.rb +77 -0
  14. data/lib/mongo/collection.rb +872 -0
  15. data/lib/mongo/connection.rb +875 -0
  16. data/lib/mongo/cursor.rb +449 -0
  17. data/lib/mongo/db.rb +607 -0
  18. data/lib/mongo/exceptions.rb +68 -0
  19. data/lib/mongo/gridfs/grid.rb +106 -0
  20. data/lib/mongo/gridfs/grid_ext.rb +57 -0
  21. data/lib/mongo/gridfs/grid_file_system.rb +145 -0
  22. data/lib/mongo/gridfs/grid_io.rb +394 -0
  23. data/lib/mongo/gridfs/grid_io_fix.rb +38 -0
  24. data/lib/mongo/repl_set_connection.rb +342 -0
  25. data/lib/mongo/util/conversions.rb +89 -0
  26. data/lib/mongo/util/core_ext.rb +60 -0
  27. data/lib/mongo/util/pool.rb +185 -0
  28. data/lib/mongo/util/server_version.rb +71 -0
  29. data/lib/mongo/util/support.rb +82 -0
  30. data/lib/mongo/util/uri_parser.rb +181 -0
  31. data/lib/mongo/version.rb +3 -0
  32. data/mongo.gemspec +34 -0
  33. data/test/auxillary/1.4_features.rb +166 -0
  34. data/test/auxillary/authentication_test.rb +68 -0
  35. data/test/auxillary/autoreconnect_test.rb +41 -0
  36. data/test/auxillary/repl_set_auth_test.rb +58 -0
  37. data/test/auxillary/slave_connection_test.rb +36 -0
  38. data/test/auxillary/threaded_authentication_test.rb +101 -0
  39. data/test/bson/binary_test.rb +15 -0
  40. data/test/bson/bson_test.rb +614 -0
  41. data/test/bson/byte_buffer_test.rb +190 -0
  42. data/test/bson/hash_with_indifferent_access_test.rb +38 -0
  43. data/test/bson/json_test.rb +17 -0
  44. data/test/bson/object_id_test.rb +154 -0
  45. data/test/bson/ordered_hash_test.rb +197 -0
  46. data/test/collection_test.rb +893 -0
  47. data/test/connection_test.rb +303 -0
  48. data/test/conversions_test.rb +120 -0
  49. data/test/cursor_fail_test.rb +75 -0
  50. data/test/cursor_message_test.rb +43 -0
  51. data/test/cursor_test.rb +457 -0
  52. data/test/db_api_test.rb +715 -0
  53. data/test/db_connection_test.rb +15 -0
  54. data/test/db_test.rb +287 -0
  55. data/test/grid_file_system_test.rb +244 -0
  56. data/test/grid_io_test.rb +120 -0
  57. data/test/grid_test.rb +200 -0
  58. data/test/load/thin/load.rb +24 -0
  59. data/test/load/unicorn/load.rb +23 -0
  60. data/test/replica_sets/connect_test.rb +86 -0
  61. data/test/replica_sets/connection_string_test.rb +32 -0
  62. data/test/replica_sets/count_test.rb +35 -0
  63. data/test/replica_sets/insert_test.rb +53 -0
  64. data/test/replica_sets/pooled_insert_test.rb +55 -0
  65. data/test/replica_sets/query_secondaries.rb +96 -0
  66. data/test/replica_sets/query_test.rb +51 -0
  67. data/test/replica_sets/replication_ack_test.rb +66 -0
  68. data/test/replica_sets/rs_test_helper.rb +27 -0
  69. data/test/safe_test.rb +68 -0
  70. data/test/support/hash_with_indifferent_access.rb +199 -0
  71. data/test/support/keys.rb +45 -0
  72. data/test/support_test.rb +19 -0
  73. data/test/test_helper.rb +83 -0
  74. data/test/threading/threading_with_large_pool_test.rb +90 -0
  75. data/test/threading_test.rb +87 -0
  76. data/test/tools/auth_repl_set_manager.rb +14 -0
  77. data/test/tools/repl_set_manager.rb +266 -0
  78. data/test/unit/collection_test.rb +130 -0
  79. data/test/unit/connection_test.rb +98 -0
  80. data/test/unit/cursor_test.rb +99 -0
  81. data/test/unit/db_test.rb +96 -0
  82. data/test/unit/grid_test.rb +49 -0
  83. data/test/unit/pool_test.rb +9 -0
  84. data/test/unit/repl_set_connection_test.rb +72 -0
  85. data/test/unit/safe_test.rb +125 -0
  86. data/test/uri_test.rb +91 -0
  87. metadata +202 -0
@@ -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
@@ -0,0 +1,35 @@
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
5
+ # on the local host.
6
+ class ReplicaSetCountTest < Test::Unit::TestCase
7
+ include Mongo
8
+
9
+ def setup
10
+ @conn = ReplSetConnection.new([RS.host, RS.ports[0]], [RS.host, RS.ports[1]], [RS.host, RS.ports[2]])
11
+ @db = @conn.db(MONGO_TEST_DB)
12
+ @db.drop_collection("test-sets")
13
+ @coll = @db.collection("test-sets")
14
+ end
15
+
16
+ def teardown
17
+ RS.restart_killed_nodes
18
+ end
19
+
20
+ def test_correct_count_after_insertion_reconnect
21
+ @coll.insert({:a => 20}, :safe => {:w => 2, :wtimeout => 10000})
22
+ assert_equal 1, @coll.count
23
+
24
+ # Kill the current master node
25
+ @node = RS.kill_primary
26
+
27
+ rescue_connection_failure do
28
+ @coll.insert({:a => 30}, :safe => true)
29
+ end
30
+
31
+ @coll.insert({:a => 40}, :safe => true)
32
+ assert_equal 3, @coll.count, "Second count failed"
33
+ end
34
+
35
+ end
@@ -0,0 +1,53 @@
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
5
+ # on the local host.
6
+ class ReplicaSetInsertTest < Test::Unit::TestCase
7
+ include Mongo
8
+
9
+ def setup
10
+ @conn = ReplSetConnection.new([TEST_HOST, RS.ports[0]], [TEST_HOST, RS.ports[1]], [TEST_HOST, RS.ports[2]])
11
+ @db = @conn.db(MONGO_TEST_DB)
12
+ @db.drop_collection("test-sets")
13
+ @coll = @db.collection("test-sets")
14
+ end
15
+
16
+ def teardown
17
+ RS.restart_killed_nodes
18
+ end
19
+
20
+ def test_insert
21
+ @coll.save({:a => 20}, :safe => true)
22
+
23
+ RS.kill_primary
24
+
25
+ rescue_connection_failure do
26
+ @coll.save({:a => 30}, :safe => true)
27
+ end
28
+
29
+ @coll.save({:a => 40}, :safe => true)
30
+ @coll.save({:a => 50}, :safe => true)
31
+ @coll.save({:a => 60}, :safe => true)
32
+ @coll.save({:a => 70}, :safe => true)
33
+
34
+ # Restart the old master and wait for sync
35
+ RS.restart_killed_nodes
36
+ sleep(1)
37
+ results = []
38
+
39
+ rescue_connection_failure do
40
+ @coll.find.each {|r| results << r}
41
+ [20, 30, 40, 50, 60, 70].each do |a|
42
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
43
+ end
44
+ end
45
+
46
+ @coll.save({:a => 80}, :safe => true)
47
+ @coll.find.each {|r| results << r}
48
+ [20, 30, 40, 50, 60, 70, 80].each do |a|
49
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a} on second find"
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,55 @@
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
5
+ # on the local host.
6
+ class ReplicaSetPooledInsertTest < Test::Unit::TestCase
7
+ include Mongo
8
+
9
+ def setup
10
+ @conn = ReplSetConnection.new([RS.host, RS.ports[0]], [RS.host, RS.ports[1]],
11
+ [RS.host, RS.ports[2]], :pool_size => 10, :timeout => 5)
12
+ @db = @conn.db(MONGO_TEST_DB)
13
+ @db.drop_collection("test-sets")
14
+ @coll = @db.collection("test-sets")
15
+ end
16
+
17
+ def teardown
18
+ RS.restart_killed_nodes
19
+ end
20
+
21
+ def test_insert
22
+ expected_results = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
23
+ @coll.save({:a => -1}, :safe => true)
24
+
25
+ RS.kill_primary
26
+
27
+ threads = []
28
+ 10.times do |i|
29
+ threads[i] = Thread.new do
30
+ rescue_connection_failure do
31
+ @coll.save({:a => i}, :safe => true)
32
+ end
33
+ end
34
+ end
35
+
36
+ # Restart the old master and wait for sync
37
+ RS.restart_killed_nodes
38
+ sleep(1)
39
+ results = []
40
+
41
+ rescue_connection_failure do
42
+ @coll.find.each {|r| results << r}
43
+ expected_results.each do |a|
44
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
45
+ end
46
+ end
47
+
48
+ @coll.save({:a => 10}, :safe => true)
49
+ @coll.find.each {|r| results << r}
50
+ (expected_results + [10]).each do |a|
51
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a} on second find"
52
+ end
53
+ end
54
+
55
+ end
@@ -0,0 +1,96 @@
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
5
+ # on the local host.
6
+ class ReplicaSetQuerySecondariesTest < Test::Unit::TestCase
7
+ include Mongo
8
+
9
+ def setup
10
+ @conn = ReplSetConnection.new([RS.host, RS.ports[0]], :read_secondary => true)
11
+ @db = @conn.db(MONGO_TEST_DB)
12
+ @db.drop_collection("test-sets")
13
+ end
14
+
15
+ def teardown
16
+ RS.restart_killed_nodes
17
+ end
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
+
26
+ def test_con
27
+ assert @conn.primary_pool, "No primary pool!"
28
+ assert @conn.read_pool, "No read pool!"
29
+ assert @conn.primary_pool.port != @conn.read_pool.port,
30
+ "Primary port and read port at the same!"
31
+ end
32
+
33
+ def test_query_secondaries
34
+ @coll = @db.collection("test-sets", :safe => {:w => 3, :wtimeout => 10000})
35
+ @coll.save({:a => 20})
36
+ @coll.save({:a => 30})
37
+ @coll.save({:a => 40})
38
+ results = []
39
+ @coll.find.each {|r| results << r["a"]}
40
+ assert results.include?(20)
41
+ assert results.include?(30)
42
+ assert results.include?(40)
43
+
44
+ RS.kill_primary
45
+
46
+ results = []
47
+ rescue_connection_failure do
48
+ @coll.find.each {|r| results << r}
49
+ [20, 30, 40].each do |a|
50
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
51
+ end
52
+ end
53
+ end
54
+
55
+ def test_kill_primary
56
+ @coll = @db.collection("test-sets", :safe => {:w => 3, :wtimeout => 10000})
57
+ @coll.save({:a => 20})
58
+ @coll.save({:a => 30})
59
+ assert_equal 2, @coll.find.to_a.length
60
+
61
+ # Should still be able to read immediately after killing master node
62
+ RS.kill_primary
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
70
+ end
71
+
72
+ def test_kill_secondary
73
+ @coll = @db.collection("test-sets", {:safe => {:w => 3, :wtimeout => 10000}})
74
+ @coll.save({:a => 20})
75
+ @coll.save({:a => 30})
76
+ assert_equal 2, @coll.find.to_a.length
77
+
78
+ read_node = RS.get_node_from_port(@conn.read_pool.port)
79
+ RS.kill(read_node)
80
+
81
+ # Should fail immediately on next read
82
+ old_read_pool_port = @conn.read_pool.port
83
+ assert_raise ConnectionFailure do
84
+ @coll.find.to_a.length
85
+ end
86
+
87
+ # Should eventually reconnect and be able to read
88
+ rescue_connection_failure do
89
+ length = @coll.find.to_a.length
90
+ assert_equal 2, length
91
+ end
92
+ new_read_pool_port = @conn.read_pool.port
93
+ assert old_read_pool != new_read_pool
94
+ end
95
+
96
+ end
@@ -0,0 +1,51 @@
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
5
+ # on the local host.
6
+ class ReplicaSetQueryTest < Test::Unit::TestCase
7
+ include Mongo
8
+
9
+ def setup
10
+ @conn = ReplSetConnection.new([RS.host, RS.ports[0]])
11
+ @db = @conn.db(MONGO_TEST_DB)
12
+ @db.drop_collection("test-sets")
13
+ @coll = @db.collection("test-sets")
14
+ end
15
+
16
+ def teardown
17
+ RS.restart_killed_nodes
18
+ end
19
+
20
+ def test_query
21
+ @coll.save({:a => 20}, :safe => {:w => 3})
22
+ @coll.save({:a => 30}, :safe => {:w => 3})
23
+ @coll.save({:a => 40}, :safe => {:w => 3})
24
+ results = []
25
+ @coll.find.each {|r| results << r}
26
+ [20, 30, 40].each do |a|
27
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
28
+ end
29
+
30
+ puts "Benchmark before failover: #{benchmark_queries}"
31
+
32
+ RS.kill_primary
33
+
34
+ results = []
35
+ rescue_connection_failure do
36
+ @coll.find.each {|r| results << r}
37
+ [20, 30, 40].each do |a|
38
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
39
+ end
40
+
41
+ puts "Benchmark after failover: #{benchmark_queries}"
42
+ end
43
+ end
44
+
45
+ def benchmark_queries
46
+ t1 = Time.now
47
+ 10000.times { @coll.find_one }
48
+ Time.now - t1
49
+ end
50
+
51
+ end
@@ -0,0 +1,66 @@
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 local host.
5
+ class ReplicaSetAckTest < Test::Unit::TestCase
6
+ include Mongo
7
+
8
+ def setup
9
+ RS.ensure_up
10
+
11
+ @conn = ReplSetConnection.new([RS.host, RS.ports[0]])
12
+
13
+ @slave1 = Connection.new(@conn.secondary_pools[0].host,
14
+ @conn.secondary_pools[0].port, :slave_ok => true)
15
+
16
+ assert !@slave1.read_primary?
17
+
18
+ @db = @conn.db(MONGO_TEST_DB)
19
+ @db.drop_collection("test-sets")
20
+ @col = @db.collection("test-sets")
21
+ end
22
+
23
+ def test_safe_mode_with_w_failure
24
+ assert_raise_error OperationFailure, "timeout" do
25
+ @col.insert({:foo => 1}, :safe => {:w => 4, :wtimeout => 1, :fsync => true})
26
+ end
27
+ assert_raise_error OperationFailure, "timeout" do
28
+ @col.update({:foo => 1}, {:foo => 2}, :safe => {:w => 4, :wtimeout => 1, :fsync => true})
29
+ end
30
+ assert_raise_error OperationFailure, "timeout" do
31
+ @col.remove({:foo => 2}, :safe => {:w => 4, :wtimeout => 1, :fsync => true})
32
+ end
33
+ end
34
+
35
+ def test_safe_mode_replication_ack
36
+ @col.insert({:baz => "bar"}, :safe => {:w => 2, :wtimeout => 5000})
37
+
38
+ assert @col.insert({:foo => "0" * 5000}, :safe => {:w => 2, :wtimeout => 5000})
39
+ assert_equal 2, @slave1[MONGO_TEST_DB]["test-sets"].count
40
+
41
+ assert @col.update({:baz => "bar"}, {:baz => "foo"}, :safe => {:w => 2, :wtimeout => 5000})
42
+ assert @slave1[MONGO_TEST_DB]["test-sets"].find_one({:baz => "foo"})
43
+
44
+ assert @col.remove({}, :safe => {:w => 2, :wtimeout => 5000})
45
+ assert_equal 0, @slave1[MONGO_TEST_DB]["test-sets"].count
46
+ end
47
+
48
+ def test_last_error_responses
49
+ 20.times { @col.insert({:baz => "bar"}) }
50
+ response = @db.get_last_error(:w => 2, :wtimeout => 5000)
51
+ assert response['ok'] == 1
52
+ assert response['lastOp']
53
+
54
+ @col.update({}, {:baz => "foo"}, :multi => true)
55
+ response = @db.get_last_error(:w => 2, :wtimeout => 5000)
56
+ assert response['ok'] == 1
57
+ assert response['lastOp']
58
+
59
+ @col.remove({})
60
+ response = @db.get_last_error(:w => 2, :wtimeout => 5000)
61
+ assert response['ok'] == 1
62
+ assert response['n'] == 20
63
+ assert response['lastOp']
64
+ end
65
+
66
+ end
@@ -0,0 +1,27 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require './test/test_helper'
3
+ require './test/tools/repl_set_manager'
4
+
5
+ unless defined? RS
6
+ RS = ReplSetManager.new
7
+ RS.start_set
8
+ end
9
+
10
+ class Test::Unit::TestCase
11
+
12
+ # Generic code for rescuing connection failures and retrying operations.
13
+ # This could be combined with some timeout functionality.
14
+ def rescue_connection_failure(max_retries=60)
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
24
+ end
25
+ end
26
+
27
+ end
data/test/safe_test.rb ADDED
@@ -0,0 +1,68 @@
1
+ require './test/test_helper'
2
+ include Mongo
3
+
4
+ class SafeTest < Test::Unit::TestCase
5
+ context "Safe mode propogation: " do
6
+ setup do
7
+ @con = standard_connection(:safe => {:w => 1})
8
+ @db = @con[MONGO_TEST_DB]
9
+ @col = @db['test-safe']
10
+ @col.create_index([[:a, 1]], :unique => true)
11
+ @col.remove
12
+ end
13
+
14
+ should "propogate safe option on insert" do
15
+ @col.insert({:a => 1})
16
+
17
+ assert_raise_error(OperationFailure, "duplicate key") do
18
+ @col.insert({:a => 1})
19
+ end
20
+ end
21
+
22
+ should "allow safe override on insert" do
23
+ @col.insert({:a => 1})
24
+ @col.insert({:a => 1}, :safe => false)
25
+ end
26
+
27
+ should "propogate safe option on update" do
28
+ @col.insert({:a => 1})
29
+ @col.insert({:a => 2})
30
+
31
+ assert_raise_error(OperationFailure, "duplicate key") do
32
+ @col.update({:a => 2}, {:a => 1})
33
+ end
34
+ end
35
+
36
+ should "allow safe override on update" do
37
+ @col.insert({:a => 1})
38
+ @col.insert({:a => 2})
39
+ @col.update({:a => 2}, {:a => 1}, :safe => false)
40
+ end
41
+ end
42
+
43
+ context "Safe error objects" do
44
+ setup do
45
+ @con = standard_connection
46
+ @db = @con[MONGO_TEST_DB]
47
+ @col = @db['test']
48
+ @col.remove
49
+ @col.insert({:a => 1})
50
+ @col.insert({:a => 1})
51
+ @col.insert({:a => 1})
52
+ end
53
+
54
+ should "return object on update" do
55
+ response = @col.update({:a => 1}, {"$set" => {:a => 2}},
56
+ :multi => true, :safe => true)
57
+
58
+ assert response['updatedExisting']
59
+ assert_equal 3, response['n']
60
+ end
61
+
62
+ should "return object on remove" do
63
+ response = @col.remove({}, :safe => true)
64
+ assert_equal 3, response['n']
65
+ end
66
+ end
67
+
68
+ end