mongo 1.8.2 → 1.8.3.rc0

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 (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