mongo 1.8.2 → 1.8.3.rc0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data.tar.gz.sig +0 -0
  2. data/LICENSE +1 -1
  3. data/README.md +2 -7
  4. data/VERSION +1 -1
  5. data/lib/mongo.rb +2 -18
  6. data/lib/mongo/collection.rb +20 -24
  7. data/lib/mongo/cursor.rb +30 -35
  8. data/lib/mongo/db.rb +1 -19
  9. data/lib/mongo/exceptions.rb +0 -19
  10. data/lib/mongo/gridfs/grid.rb +18 -29
  11. data/lib/mongo/gridfs/grid_ext.rb +0 -18
  12. data/lib/mongo/gridfs/grid_file_system.rb +17 -26
  13. data/lib/mongo/gridfs/grid_io.rb +0 -18
  14. data/lib/mongo/legacy.rb +0 -18
  15. data/lib/mongo/mongo_client.rb +11 -33
  16. data/lib/mongo/mongo_replica_set_client.rb +29 -56
  17. data/lib/mongo/mongo_sharded_client.rb +38 -50
  18. data/lib/mongo/networking.rb +5 -4
  19. data/lib/mongo/util/conversions.rb +0 -17
  20. data/lib/mongo/util/core_ext.rb +0 -18
  21. data/lib/mongo/util/node.rb +16 -3
  22. data/lib/mongo/util/pool.rb +46 -36
  23. data/lib/mongo/util/pool_manager.rb +102 -71
  24. data/lib/mongo/util/read_preference.rb +4 -2
  25. data/lib/mongo/util/server_version.rb +0 -17
  26. data/lib/mongo/util/sharding_pool_manager.rb +4 -23
  27. data/lib/mongo/util/socket_util.rb +20 -0
  28. data/lib/mongo/util/ssl_socket.rb +10 -19
  29. data/lib/mongo/util/support.rb +0 -18
  30. data/lib/mongo/util/tcp_socket.rb +1 -9
  31. data/lib/mongo/util/thread_local_variable_manager.rb +0 -18
  32. data/lib/mongo/util/uri_parser.rb +87 -82
  33. data/lib/mongo/util/write_concern.rb +0 -18
  34. data/mongo.gemspec +4 -1
  35. data/test/auxillary/pool_reuse_test.rb +65 -0
  36. data/test/functional/collection_test.rb +92 -3
  37. data/test/functional/connection_test.rb +30 -6
  38. data/test/functional/db_api_test.rb +11 -0
  39. data/test/functional/timeout_test.rb +23 -0
  40. data/test/functional/uri_test.rb +69 -0
  41. data/test/replica_set/client_test.rb +0 -22
  42. data/test/replica_set/cursor_test.rb +11 -5
  43. data/test/replica_set/refresh_test.rb +0 -0
  44. data/test/replica_set/z_cluster_shutdown.rb +13 -0
  45. data/test/sharded_cluster/basic_test.rb +46 -32
  46. data/test/test_helper.rb +26 -1
  47. data/test/threading/basic_test.rb +10 -9
  48. data/test/tools/mongo_config.rb +6 -2
  49. data/test/unit/collection_test.rb +1 -1
  50. data/test/unit/grid_test.rb +20 -13
  51. data/test/unit/mongo_sharded_client_test.rb +32 -0
  52. data/test/unit/pool_manager_test.rb +28 -14
  53. metadata +45 -12
  54. metadata.gz.sig +0 -0
@@ -34,8 +34,10 @@ module Mongo
34
34
  end
35
35
 
36
36
  def select_pool(mode, tags, latency)
37
+ return primary_pool if @client.mongos?
38
+
37
39
  if mode == :primary && !tags.empty?
38
- raise MongoArgumentError, "Read preferecy :primary cannot be combined with tags"
40
+ raise MongoArgumentError, "Read preference :primary cannot be combined with tags"
39
41
  end
40
42
 
41
43
  case mode
@@ -79,4 +81,4 @@ module Mongo
79
81
  near_pools[ rand(near_pools.length) ]
80
82
  end
81
83
  end
82
- end
84
+ end
@@ -1,20 +1,3 @@
1
- # encoding: UTF-8
2
-
3
- # --
4
- # Copyright (C) 2008-2012 10gen Inc.
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- # ++
18
1
  module Mongo
19
2
  # Simple class for comparing server versions.
20
3
  class ServerVersion
@@ -1,21 +1,6 @@
1
1
 
2
2
  module Mongo
3
3
  class ShardingPoolManager < PoolManager
4
-
5
- attr_reader :client, :primary, :primary_pool, :hosts, :nodes,
6
- :max_bson_size, :members
7
-
8
- # Create a new set of connection pools.
9
- #
10
- # The pool manager will by default use the original seed list passed
11
- # to the connection objects, accessible via connection.seeds. In addition,
12
- # the user may pass an additional list of seeds nodes discovered in real
13
- # time. The union of these lists will be used when attempting to connect,
14
- # with the newly-discovered nodes being used first.
15
- def initialize(client, seeds=[])
16
- super
17
- end
18
-
19
4
  def inspect
20
5
  "<Mongo::ShardingPoolManager:0x#{self.object_id.to_s(16)} @seeds=#{@seeds}>"
21
6
  end
@@ -27,14 +12,10 @@ module Mongo
27
12
  end
28
13
 
29
14
  def connect
30
- close if @previously_connected
31
-
32
- initialize_data
33
- members = connect_to_members
34
- initialize_pools(best(members))
35
-
36
- @members = members
37
- @previously_connected = true
15
+ @refresh_required = false
16
+ disconnect_old_members
17
+ connect_to_members
18
+ initialize_pools best(@members)
38
19
  end
39
20
 
40
21
  # We want to refresh to the member with the fastest ping time
@@ -0,0 +1,20 @@
1
+ module SocketUtil
2
+
3
+ attr_accessor :pool, :pid
4
+
5
+ def checkout
6
+ @pool.checkout if @pool
7
+ end
8
+
9
+ def checkin
10
+ @pool.checkin(self) if @pool
11
+ end
12
+
13
+ def close
14
+ @socket.close unless closed?
15
+ end
16
+
17
+ def closed?
18
+ @socket.closed?
19
+ end
20
+ end
@@ -8,19 +8,18 @@ module Mongo
8
8
  # a TCP connection over SSL and then provides an basic interface
9
9
  # mirroring Ruby's TCPSocket, vis., TCPSocket#send and TCPSocket#read.
10
10
  class SSLSocket
11
-
12
- attr_accessor :pool, :pid
11
+ include SocketUtil
13
12
 
14
13
  def initialize(host, port, op_timeout=nil, connect_timeout=nil)
15
14
  @op_timeout = op_timeout
16
15
  @connect_timeout = connect_timeout
17
16
  @pid = Process.pid
18
17
 
19
- @socket = ::TCPSocket.new(host, port)
20
- @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
18
+ @tcp_socket = ::TCPSocket.new(host, port)
19
+ @tcp_socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
21
20
 
22
- @ssl = OpenSSL::SSL::SSLSocket.new(@socket)
23
- @ssl.sync_close = true
21
+ @socket = OpenSSL::SSL::SSLSocket.new(@tcp_socket)
22
+ @socket.sync_close = true
24
23
 
25
24
  connect
26
25
  end
@@ -28,33 +27,25 @@ module Mongo
28
27
  def connect
29
28
  if @connect_timeout
30
29
  Timeout::timeout(@connect_timeout, ConnectionTimeoutError) do
31
- @ssl.connect
30
+ @socket.connect
32
31
  end
33
32
  else
34
- @ssl.connect
33
+ @socket.connect
35
34
  end
36
35
  end
37
36
 
38
37
  def send(data)
39
- @ssl.syswrite(data)
38
+ @socket.syswrite(data)
40
39
  end
41
40
 
42
41
  def read(length, buffer)
43
42
  if @op_timeout
44
43
  Timeout::timeout(@op_timeout, OperationTimeout) do
45
- @ssl.sysread(length, buffer)
44
+ @socket.sysread(length, buffer)
46
45
  end
47
46
  else
48
- @ssl.sysread(length, buffer)
47
+ @socket.sysread(length, buffer)
49
48
  end
50
49
  end
51
-
52
- def close
53
- @ssl.close
54
- end
55
-
56
- def closed?
57
- @ssl.closed?
58
- end
59
50
  end
60
51
  end
@@ -1,21 +1,3 @@
1
- # encoding: UTF-8
2
-
3
- # --
4
- # Copyright (C) 2008-2012 10gen Inc.
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- # ++
18
-
19
1
  require 'digest/md5'
20
2
 
21
3
  module Mongo
@@ -8,7 +8,7 @@ module Mongo
8
8
  # sans Timeout::timeout
9
9
  #
10
10
  class TCPSocket
11
- attr_accessor :pool, :pid
11
+ include SocketUtil
12
12
 
13
13
  def initialize(host, port, op_timeout=nil, connect_timeout=nil)
14
14
  @op_timeout = op_timeout
@@ -58,13 +58,5 @@ module Mongo
58
58
  raise ConnectionFailure, ex
59
59
  end
60
60
  end
61
-
62
- def close
63
- @socket.close
64
- end
65
-
66
- def closed?
67
- @socket.closed?
68
- end
69
61
  end
70
62
  end
@@ -1,21 +1,3 @@
1
- # encoding: UTF-8
2
-
3
- # --
4
- # Copyright (C) 2008-2012 10gen Inc.
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- # ++
18
-
19
1
  #:nodoc:
20
2
  module Mongo
21
3
  module ThreadLocalVariableManager
@@ -1,21 +1,3 @@
1
- # encoding: UTF-8
2
-
3
- # --
4
- # Copyright (C) 2008-2012 10gen Inc.
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- # ++
18
-
19
1
  require 'cgi'
20
2
 
21
3
  module Mongo
@@ -36,83 +18,100 @@ module Mongo
36
18
 
37
19
  SPEC_ATTRS = [:nodes, :auths]
38
20
 
21
+ READ_PREFERENCES = {
22
+ "primary" => :primary,
23
+ "primarypreferred" => :primary_preferred,
24
+ "secondary" => :secondary,
25
+ "secondarypreferred" => :secondary_preferred,
26
+ "nearest" => :nearest
27
+ }
28
+
39
29
  OPT_ATTRS = [
40
30
  :connect,
31
+ :connecttimeoutms,
32
+ :fsync,
33
+ :journal,
34
+ :pool_size,
35
+ :readpreference,
41
36
  :replicaset,
37
+ :safe,
42
38
  :slaveok,
39
+ :sockettimeoutms,
43
40
  :ssl,
44
- :safe,
45
41
  :w,
46
42
  :wtimeout,
47
- :fsync,
48
- :journal,
49
- :connecttimeoutms,
50
- :sockettimeoutms,
51
- :wtimeoutms,
52
- :pool_size
43
+ :wtimeoutms
53
44
  ]
54
45
 
55
- OPT_VALID = {:connect => lambda {|arg| ['direct', 'replicaset', 'true', 'false', true, false].include?(arg)},
56
- :replicaset => lambda {|arg| arg.length > 0},
57
- :slaveok => lambda {|arg| ['true', 'false'].include?(arg)},
58
- :ssl => lambda {|arg| ['true', 'false'].include?(arg)},
59
- :safe => lambda {|arg| ['true', 'false'].include?(arg)},
60
- :w => lambda {|arg| arg =~ /^\w+$/ },
61
- :wtimeout => lambda {|arg| arg =~ /^\d+$/ },
62
- :fsync => lambda {|arg| ['true', 'false'].include?(arg)},
63
- :journal => lambda {|arg| ['true', 'false'].include?(arg)},
64
- :connecttimeoutms => lambda {|arg| arg =~ /^\d+$/ },
65
- :sockettimeoutms => lambda {|arg| arg =~ /^\d+$/ },
66
- :wtimeoutms => lambda {|arg| arg =~ /^\d+$/ },
67
- :pool_size => lambda {|arg| arg.to_i > 0 }
68
- }
69
-
70
- OPT_ERR = {:connect => "must be 'direct', 'replicaset', 'true', or 'false'",
71
- :replicaset => "must be a string containing the name of the replica set to connect to",
72
- :slaveok => "must be 'true' or 'false'",
73
- :ssl => "must be 'true' or 'false'",
74
- :safe => "must be 'true' or 'false'",
75
- :w => "must be an integer indicating number of nodes to replicate to or a string specifying
76
- that replication is required to the majority or nodes with a particilar getLastErrorMode.",
77
- :wtimeout => "must be an integer specifying milliseconds",
78
- :fsync => "must be 'true' or 'false'",
79
- :journal => "must be 'true' or 'false'",
80
- :connecttimeoutms => "must be an integer specifying milliseconds",
81
- :sockettimeoutms => "must be an integer specifying milliseconds",
82
- :wtimeoutms => "must be an integer specifying milliseconds",
83
- :pool_size => "must be an integer greater than zero"
84
- }
85
-
86
- OPT_CONV = {:connect => lambda {|arg| arg == 'false' ? false : arg}, # be sure to convert 'false' to FalseClass
87
- :replicaset => lambda {|arg| arg},
88
- :slaveok => lambda {|arg| arg == 'true' ? true : false},
89
- :ssl => lambda {|arg| arg == 'true' ? true : false},
90
- :safe => lambda {|arg| arg == 'true' ? true : false},
91
- :w => lambda {|arg| Mongo::Support.is_i?(arg) ? arg.to_i : arg.to_sym },
92
- :wtimeout => lambda {|arg| arg.to_i},
93
- :fsync => lambda {|arg| arg == 'true' ? true : false},
94
- :journal => lambda {|arg| arg == 'true' ? true : false},
95
- :connecttimeoutms => lambda {|arg| arg.to_f / 1000 }, # stored as seconds
96
- :sockettimeoutms => lambda {|arg| arg.to_f / 1000 }, # stored as seconds
97
- :wtimeoutms => lambda {|arg| arg.to_i },
98
- :pool_size => lambda {|arg| arg.to_i }
99
- }
46
+ OPT_VALID = {
47
+ :connect => lambda { |arg| [ 'direct', 'replicaset', 'true', 'false', true, false ].include?(arg) },
48
+ :connecttimeoutms => lambda { |arg| arg =~ /^\d+$/ },
49
+ :fsync => lambda { |arg| ['true', 'false'].include?(arg) },
50
+ :journal => lambda { |arg| ['true', 'false'].include?(arg) },
51
+ :pool_size => lambda { |arg| arg.to_i > 0 },
52
+ :readpreference => lambda { |arg| READ_PREFERENCES.keys.include?(arg) },
53
+ :replicaset => lambda { |arg| arg.length > 0 },
54
+ :safe => lambda { |arg| ['true', 'false'].include?(arg) },
55
+ :slaveok => lambda { |arg| ['true', 'false'].include?(arg) },
56
+ :sockettimeoutms => lambda { |arg| arg =~ /^\d+$/ },
57
+ :ssl => lambda { |arg| ['true', 'false'].include?(arg) },
58
+ :w => lambda { |arg| arg =~ /^\w+$/ },
59
+ :wtimeout => lambda { |arg| arg =~ /^\d+$/ },
60
+ :wtimeoutms => lambda { |arg| arg =~ /^\d+$/ }
61
+ }
62
+
63
+ OPT_ERR = {
64
+ :connect => "must be 'direct', 'replicaset', 'true', or 'false'",
65
+ :connecttimeoutms => "must be an integer specifying milliseconds",
66
+ :fsync => "must be 'true' or 'false'",
67
+ :journal => "must be 'true' or 'false'",
68
+ :pool_size => "must be an integer greater than zero",
69
+ :readpreference => "must be on of #{READ_PREFERENCES.keys.map(&:inspect).join(",")}",
70
+ :replicaset => "must be a string containing the name of the replica set to connect to",
71
+ :safe => "must be 'true' or 'false'",
72
+ :slaveok => "must be 'true' or 'false'",
73
+ :sockettimeoutms => "must be an integer specifying milliseconds",
74
+ :ssl => "must be 'true' or 'false'",
75
+ :w => "must be an integer indicating number of nodes to replicate to or a string " +
76
+ "specifying that replication is required to the majority or nodes with a " +
77
+ "particilar getLastErrorMode.",
78
+ :wtimeout => "must be an integer specifying milliseconds",
79
+ :wtimeoutms => "must be an integer specifying milliseconds"
80
+ }
81
+
82
+ OPT_CONV = {
83
+ :connect => lambda { |arg| arg == 'false' ? false : arg }, # convert 'false' to FalseClass
84
+ :connecttimeoutms => lambda { |arg| arg.to_f / 1000 }, # stored as seconds
85
+ :fsync => lambda { |arg| arg == 'true' ? true : false },
86
+ :journal => lambda { |arg| arg == 'true' ? true : false },
87
+ :pool_size => lambda { |arg| arg.to_i },
88
+ :readpreference => lambda { |arg| READ_PREFERENCES[arg] },
89
+ :replicaset => lambda { |arg| arg },
90
+ :safe => lambda { |arg| arg == 'true' ? true : false },
91
+ :slaveok => lambda { |arg| arg == 'true' ? true : false },
92
+ :sockettimeoutms => lambda { |arg| arg.to_f / 1000 }, # stored as seconds
93
+ :ssl => lambda { |arg| arg == 'true' ? true : false },
94
+ :w => lambda { |arg| Mongo::Support.is_i?(arg) ? arg.to_i : arg.to_sym },
95
+ :wtimeout => lambda { |arg| arg.to_i },
96
+ :wtimeoutms => lambda { |arg| arg.to_i }
97
+ }
100
98
 
101
99
  attr_reader :auths,
102
100
  :connect,
101
+ :connecttimeoutms,
102
+ :fsync,
103
+ :journal,
104
+ :nodes,
105
+ :pool_size,
106
+ :readpreference,
103
107
  :replicaset,
108
+ :safe,
104
109
  :slaveok,
110
+ :sockettimeoutms,
105
111
  :ssl,
106
- :safe,
107
112
  :w,
108
113
  :wtimeout,
109
- :fsync,
110
- :journal,
111
- :connecttimeoutms,
112
- :sockettimeoutms,
113
- :wtimeoutms,
114
- :pool_size,
115
- :nodes
114
+ :wtimeoutms
116
115
 
117
116
  # Parse a MongoDB URI. This method is used by MongoClient.from_uri.
118
117
  # Returns an array of nodes and an array of db authorizations, if applicable.
@@ -141,8 +140,8 @@ module Mongo
141
140
  # @note Don't confuse this with attribute getter method #connect.
142
141
  #
143
142
  # @return [MongoClient,MongoReplicaSetClient]
144
- def connection(extra_opts, legacy=false)
145
- opts = connection_options.merge! extra_opts
143
+ def connection(extra_opts, legacy = false, sharded = false)
144
+ opts = connection_options.merge!(extra_opts)
146
145
  if(legacy)
147
146
  if replicaset?
148
147
  ReplSetConnection.new(node_strings, opts)
@@ -150,7 +149,9 @@ module Mongo
150
149
  Connection.new(host, port, opts)
151
150
  end
152
151
  else
153
- if replicaset?
152
+ if sharded
153
+ MongoShardedClient.new(node_strings, opts)
154
+ elsif replicaset?
154
155
  MongoReplicaSetClient.new(node_strings, opts)
155
156
  else
156
157
  MongoClient.new(host, port, opts)
@@ -219,7 +220,11 @@ module Mongo
219
220
  opts[:pool_size] = @pool_size
220
221
  end
221
222
 
222
- if @slaveok
223
+ if @readpreference && replicaset?
224
+ opts[:read] = @readpreference
225
+ end
226
+
227
+ if @slaveok && !@readpreference
223
228
  if direct?
224
229
  opts[:slave_ok] = true
225
230
  else