mongo 1.8.4 → 1.8.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +6 -14
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +2 -0
  5. data/VERSION +1 -1
  6. data/lib/mongo.rb +11 -9
  7. data/lib/mongo/collection.rb +26 -19
  8. data/lib/mongo/cursor.rb +7 -2
  9. data/lib/mongo/db.rb +1 -1
  10. data/lib/mongo/mongo_client.rb +1 -1
  11. data/lib/mongo/mongo_replica_set_client.rb +2 -3
  12. data/lib/mongo/mongo_sharded_client.rb +1 -2
  13. data/lib/mongo/util/node.rb +12 -14
  14. data/lib/mongo/util/pool.rb +1 -1
  15. data/lib/mongo/util/pool_manager.rb +13 -15
  16. data/lib/mongo/util/sharding_pool_manager.rb +5 -2
  17. data/lib/mongo/util/support.rb +14 -0
  18. data/mongo.gemspec +7 -3
  19. data/test/functional/authentication_test.rb +21 -0
  20. data/test/functional/collection_test.rb +0 -1
  21. data/test/functional/connection_test.rb +1 -1
  22. data/test/functional/db_test.rb +1 -56
  23. data/test/functional/support_test.rb +30 -0
  24. data/test/replica_set/authentication_test.rb +23 -0
  25. data/test/replica_set/max_values_test.rb +61 -0
  26. data/test/sharded_cluster/basic_test.rb +18 -0
  27. data/test/shared/authentication.rb +49 -0
  28. data/test/tools/mongo_config.rb +21 -26
  29. data/test/unit/node_test.rb +3 -0
  30. data/test/unit/pool_manager_test.rb +3 -1
  31. data/test/unit/read_test.rb +4 -0
  32. data/test/unit/sharding_pool_manager_test.rb +88 -0
  33. metadata +38 -69
  34. metadata.gz.sig +0 -0
  35. data/test/auxillary/1.4_feature_test.rb +0 -165
  36. data/test/auxillary/authentication_test.rb +0 -74
  37. data/test/auxillary/autoreconnect_test.rb +0 -39
  38. data/test/auxillary/fork_test.rb +0 -28
  39. data/test/auxillary/pool_reuse_test.rb +0 -65
  40. data/test/auxillary/repl_set_auth_test.rb +0 -69
  41. data/test/auxillary/slave_connection_test.rb +0 -37
  42. data/test/auxillary/threaded_authentication_test.rb +0 -99
  43. data/test/bson/binary_test.rb +0 -13
  44. data/test/bson/bson_test.rb +0 -762
  45. data/test/bson/byte_buffer_test.rb +0 -215
  46. data/test/bson/hash_with_indifferent_access_test.rb +0 -48
  47. data/test/bson/json_test.rb +0 -16
  48. data/test/bson/object_id_test.rb +0 -153
  49. data/test/bson/ordered_hash_test.rb +0 -247
  50. data/test/bson/timestamp_test.rb +0 -51
  51. data/test/tools/auth_repl_set_manager.rb +0 -14
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MThmZWQ1YmJmNDFkNDNhMjY3MTcxZTQxNjRjZjI2YjYzMWE4MDRiOQ==
5
- data.tar.gz: !binary |-
6
- Njk3M2NhNmI2MWM1ZDE1ZGQ0MTZiYjNiYTgyNzRjYmZmM2E5MWExMg==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- NjYyM2MxZDQ3ZjRiMzliMjM3NDdhZmFmYTZmMTEwNjgwNzFiZmVmOTIwNzVh
10
- MDkxZWQ2ZmNiNDUxZjA1NWQzOGNmMDNkMjRkZThhM2RhMzZiNTRlOTA4ODQ0
11
- ZDAxMjg1ZmZlYWZhNzcyZTU0OWQ5M2RlZmMyMWNkMjgzMmU5NmM=
12
- data.tar.gz: !binary |-
13
- MDU0ZTI3MjA2MzVlYjc2MDFiZGM1MjUxZjRlZDFmNDE5ZTc0NzMyNzBhMDI2
14
- NjM5ZGE1NDYxYmY2MjM3NmQyMTg1ZmMxMjFlYWU1M2ExZDgyYTU2NjRkZjk4
15
- MjIxYTliNDRmNWIyODA5YmRmYTYxMWJmYzAwNTVkOTRkYTczMzg=
2
+ SHA1:
3
+ metadata.gz: b8b721f436d16c55388789c19bd0c03b99812702
4
+ data.tar.gz: b43de3ec9c986727abd9d4bf181e038ce3ddbe02
5
+ SHA512:
6
+ metadata.gz: d0c55e5a9968be883c92acb53676b6ae8d08a77578dbaaec4cca2d71bf1c535d981d63f4f1377712819bae39733f6bde8781f8af860f5469e172bf4c2a14acb6
7
+ data.tar.gz: 241ccee8c30eadb597252c4fea0a599b920551c4f77dea15fbf747eea2abf7e0270788f496d6df657f8d88cb98728fae20a956977a285086c7f25a161bc8c89b
Binary file
data.tar.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -241,6 +241,8 @@ for the first time.
241
241
 
242
242
  ### Strict mode
243
243
 
244
+ _**NOTE:** Support for strict mode has been deprecated and will be removed in version 2.0 of the driver._
245
+
244
246
  Each database has an optional strict mode. If strict mode is on, then asking
245
247
  for a collection that does not exist will raise an error, as will asking to
246
248
  create a collection that already exists. Note that both these operations are
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.8.4
1
+ 1.8.5
@@ -6,17 +6,19 @@ module Mongo
6
6
  GEOHAYSTACK = 'geoHaystack'
7
7
  TEXT = 'text'
8
8
  HASHED = 'hashed'
9
- INDEX_TYPES = [ ASCENDING,
10
- DESCENDING,
11
- GEO2D,
12
- GEO2DSPHERE,
13
- GEOHAYSTACK,
14
- TEXT,
15
- HASHED
16
- ]
9
+
10
+ INDEX_TYPES = {
11
+ 'ASCENDING' => ASCENDING,
12
+ 'DESCENDING' => DESCENDING,
13
+ 'GEO2D' => GEO2D,
14
+ 'GEO2DSPHERE' => GEO2DSPHERE,
15
+ 'GEOHAYSTACK' => GEOHAYSTACK,
16
+ 'TEXT' => TEXT,
17
+ 'HASHED' => HASHED
18
+ }
17
19
 
18
20
  DEFAULT_MAX_BSON_SIZE = 4 * 1024 * 1024
19
- DEFAULT_MAX_MESSAGE_SIZE = DEFAULT_MAX_BSON_SIZE * 2
21
+ MESSAGE_SIZE_FACTOR = 2
20
22
 
21
23
  module Constants
22
24
  OP_REPLY = 1
@@ -505,12 +505,15 @@ module Mongo
505
505
  # @option opts [Integer] :min (nil) specify the minimum longitude and latitude for a geo index.
506
506
  # @option opts [Integer] :max (nil) specify the maximum longitude and latitude for a geo index.
507
507
  #
508
- # @example Creating a compound index using a hash: (Ruby 1.9 and above)
508
+ # @example Creating a compound index using a hash: (Ruby 1.9+ Syntax)
509
509
  # @posts.create_index({'subject' => Mongo::ASCENDING, 'created_at' => Mongo::DESCENDING})
510
510
  #
511
511
  # @example Creating a compound index:
512
512
  # @posts.create_index([['subject', Mongo::ASCENDING], ['created_at', Mongo::DESCENDING]])
513
513
  #
514
+ # @example Creating a geospatial index using a hash: (Ruby 1.9+ Syntax)
515
+ # @restaurants.create_index(:location => Mongo::GEO2D)
516
+ #
514
517
  # @example Creating a geospatial index:
515
518
  # @restaurants.create_index([['location', Mongo::GEO2D]])
516
519
  #
@@ -542,13 +545,13 @@ module Mongo
542
545
  #
543
546
  # The parameters and options for this methods are the same as those for Collection#create_index.
544
547
  #
545
- # @example Call sequence:
546
- # Time t: @posts.ensure_index([['subject', Mongo::ASCENDING]) -- calls create_index and
548
+ # @example Call sequence (Ruby 1.9+ Syntax):
549
+ # Time t: @posts.ensure_index(:subject => Mongo::ASCENDING) -- calls create_index and
547
550
  # sets the 5 minute cache
548
- # Time t+2min : @posts.ensure_index([['subject', Mongo::ASCENDING]) -- doesn't do anything
549
- # Time t+3min : @posts.ensure_index([['something_else', Mongo::ASCENDING]) -- calls create_index
551
+ # Time t+2min : @posts.ensure_index(:subject => Mongo::ASCENDING) -- doesn't do anything
552
+ # Time t+3min : @posts.ensure_index(:something_else => Mongo::ASCENDING) -- calls create_index
550
553
  # and sets 5 minute cache
551
- # Time t+10min : @posts.ensure_index([['subject', Mongo::ASCENDING]) -- calls create_index and
554
+ # Time t+10min : @posts.ensure_index(:subject => Mongo::ASCENDING) -- calls create_index and
552
555
  # resets the 5 minute counter
553
556
  #
554
557
  # @return [String] the name of the index.
@@ -1013,21 +1016,15 @@ module Mongo
1013
1016
  if spec.is_a?(String) || spec.is_a?(Symbol)
1014
1017
  field_spec[spec.to_s] = 1
1015
1018
  elsif spec.is_a?(Hash)
1016
- if RUBY_VERSION < '1.9' && !spec.is_a?(BSON::OrderedHash)
1017
- raise MongoArgumentError, "Must use OrderedHash in Ruby < 1.9.0"
1018
- else
1019
- field_spec = spec.is_a?(BSON::OrderedHash) ? spec : BSON::OrderedHash.try_convert(spec)
1020
- end
1019
+ if RUBY_VERSION < '1.9' && !spec.is_a?(BSON::OrderedHash)
1020
+ raise MongoArgumentError, "Must use OrderedHash in Ruby < 1.9.0"
1021
+ end
1022
+ validate_index_types(spec.values)
1023
+ field_spec = spec.is_a?(BSON::OrderedHash) ? spec : BSON::OrderedHash.try_convert(spec)
1021
1024
  elsif spec.is_a?(Array) && spec.all? {|field| field.is_a?(Array) }
1022
1025
  spec.each do |f|
1023
- if Mongo::INDEX_TYPES.include?(f[1])
1024
- field_spec[f[0].to_s] = f[1]
1025
- else
1026
- raise MongoArgumentError, "Invalid index field #{f[1].inspect}; " +
1027
- "should be one of Mongo::ASCENDING (#{Mongo::ASCENDING}), Mongo::DESCENDING (#{Mongo::DESCENDING}), " +
1028
- "Mongo::GEOHAYSTACK ('#{Mongo::GEOHAYSTACK}'), Mongo::GEO2DSPHERE ('#{Mongo::GEO2DSPHERE}'), " +
1029
- "Mongo::TEXT ('#{Mongo::TEXT}'), or Mongo::HASHED ('#{Mongo::HASHED}')"
1030
- end
1026
+ validate_index_types(f[1])
1027
+ field_spec[f[0].to_s] = f[1]
1031
1028
  end
1032
1029
  else
1033
1030
  raise MongoArgumentError, "Invalid index specification #{spec.inspect}; " +
@@ -1036,6 +1033,16 @@ module Mongo
1036
1033
  field_spec
1037
1034
  end
1038
1035
 
1036
+ def validate_index_types(*types)
1037
+ types.flatten!
1038
+ types.each do |t|
1039
+ unless Mongo::INDEX_TYPES.values.include?(t)
1040
+ raise MongoArgumentError, "Invalid index field #{t.inspect}; " +
1041
+ "should be one of " + Mongo::INDEX_TYPES.map {|k,v| "Mongo::#{k} (#{v})"}.join(', ')
1042
+ end
1043
+ end
1044
+ end
1045
+
1039
1046
  def generate_indexes(field_spec, name, opts)
1040
1047
  selector = {
1041
1048
  :name => name,
@@ -472,6 +472,7 @@ module Mongo
472
472
  nil, @options & OP_QUERY_EXHAUST != 0)
473
473
  rescue ConnectionFailure => ex
474
474
  socket.close if socket
475
+ @pool = nil
475
476
  @connection.unpin_pool
476
477
  @connection.refresh
477
478
  if tries < 3 && !@socket && (!@command || Mongo::Support::secondary_ok?(@selector))
@@ -584,16 +585,20 @@ module Mongo
584
585
  spec['$returnKey'] = true if @return_key
585
586
  spec['$showDiskLoc'] = true if @show_disk_loc
586
587
  spec['$comment'] = @comment if @comment
587
- if @connection.mongos? && @read != :primary
588
+ if needs_read_pref?
588
589
  read_pref = Mongo::ReadPreference::mongos(@read, @tag_sets)
589
590
  spec['$readPreference'] = read_pref if read_pref
590
591
  end
591
592
  spec
592
593
  end
593
594
 
595
+ def needs_read_pref?
596
+ @connection.mongos? && @read != :primary
597
+ end
598
+
594
599
  def query_contains_special_fields?
595
600
  @order || @explain || @hint || @snapshot || @show_disk_loc ||
596
- @max_scan || @return_key || @comment || @connection.mongos?
601
+ @max_scan || @return_key || @comment || needs_read_pref?
597
602
  end
598
603
 
599
604
  def close_cursor_if_query_complete
@@ -123,7 +123,7 @@ module Mongo
123
123
  end
124
124
 
125
125
  begin
126
- socket = @connection.checkout_reader(:primary_preferred)
126
+ socket = @connection.checkout_reader(:mode => :primary_preferred)
127
127
  issue_authentication(username, password, save_auth, :socket => socket)
128
128
  ensure
129
129
  socket.checkin if socket
@@ -520,7 +520,7 @@ module Mongo
520
520
  end
521
521
 
522
522
  def max_message_size
523
- @max_message_size || DEFAULT_MAX_MESSAGE_SIZE
523
+ @max_message_size || max_bson_size * MESSAGE_SIZE_FACTOR
524
524
  end
525
525
 
526
526
  # Checkout a socket for reading (i.e., a secondary node).
@@ -105,8 +105,7 @@ module Mongo
105
105
  warn "Please specify hosts as an array of 'host:port' strings; the old format will be removed in v2.0"
106
106
  node
107
107
  elsif node.is_a?(String)
108
- host, port = node.split(":")
109
- [ host, port.to_i ]
108
+ Support.normalize_seeds(node)
110
109
  else
111
110
  raise MongoArgumentError "Bad seed format!"
112
111
  end
@@ -432,7 +431,7 @@ module Mongo
432
431
 
433
432
  def max_message_size
434
433
  return local_manager.max_message_size if local_manager
435
- DEFAULT_MAX_MESSAGE_SIZE
434
+ max_bson_size * MESSAGE_SIZE_FACTOR
436
435
  end
437
436
 
438
437
  private
@@ -25,8 +25,7 @@ module Mongo
25
25
  end
26
26
 
27
27
  @seeds = nodes.map do |host_port|
28
- host, port = host_port.split(":")
29
- [ host, port.to_i ]
28
+ Support.normalize_seeds(host_port)
30
29
  end
31
30
 
32
31
  # TODO: add a method for replacing this list of node.
@@ -5,7 +5,8 @@ module Mongo
5
5
 
6
6
  def initialize(client, host_port)
7
7
  @client = client
8
- @host, @port = split_node(host_port)
8
+ @manager = @client.local_manager
9
+ @host, @port = Support.normalize_seeds(host_port)
9
10
  @address = "#{@host}:#{@port}"
10
11
  @config = nil
11
12
  @socket = nil
@@ -19,7 +20,7 @@ module Mongo
19
20
 
20
21
  def =~(other)
21
22
  if other.is_a?(String)
22
- h, p = split_node(other)
23
+ h, p = Support.normalize_seeds(other)
23
24
  h == @host && p == @port
24
25
  else
25
26
  false
@@ -105,6 +106,7 @@ module Mongo
105
106
  close
106
107
  end
107
108
  end
109
+ @manager.update_max_sizes
108
110
  end
109
111
 
110
112
  # Return a list of replica set nodes from the config.
@@ -119,9 +121,8 @@ module Mongo
119
121
 
120
122
  def arbiters
121
123
  return [] unless config['arbiters']
122
-
123
124
  config['arbiters'].map do |arbiter|
124
- split_node(arbiter)
125
+ Support.normalize_seeds(arbiter)
125
126
  end
126
127
  end
127
128
 
@@ -149,19 +150,16 @@ module Mongo
149
150
  connected? && config
150
151
  end
151
152
 
152
- protected
153
-
154
- def split_node(host_port)
155
- if host_port.is_a?(String)
156
- host_port = host_port.split(":")
157
- end
158
-
159
- host = host_port[0]
160
- port = host_port[1].nil? ? MongoClient::DEFAULT_PORT : host_port[1].to_i
153
+ def max_bson_size
154
+ max = config['maxBsonObjectSize'] || DEFAULT_MAX_BSON_SIZE
155
+ end
161
156
 
162
- [host, port]
157
+ def max_message_size
158
+ max = config['maxMessageSizeBytes'] || max_bson_size * MESSAGE_SIZE_FACTOR
163
159
  end
164
160
 
161
+ protected
162
+
165
163
  # Ensure that this node is a healthy member of a replica set.
166
164
  def check_set_membership(config)
167
165
  if !config.has_key?('hosts')
@@ -165,8 +165,8 @@ module Mongo
165
165
  socket.pool = self
166
166
  rescue => ex
167
167
  socket.close if socket
168
- raise ConnectionFailure, "Failed to connect to host #{@host} and port #{@port}: #{ex}"
169
168
  @node.close if @node
169
+ raise ConnectionFailure, "Failed to connect to host #{@host} and port #{@port}: #{ex}"
170
170
  end
171
171
 
172
172
  # If any saved authentications exist, we want to apply those
@@ -12,7 +12,9 @@ module Mongo
12
12
  :nodes,
13
13
  :members,
14
14
  :seeds,
15
- :pools
15
+ :pools,
16
+ :max_bson_size,
17
+ :max_message_size
16
18
 
17
19
  # Create a new set of connection pools.
18
20
  #
@@ -33,6 +35,8 @@ module Mongo
33
35
  @hosts = Set.new
34
36
  @members = Set.new
35
37
  @refresh_required = false
38
+ @max_bson_size = DEFAULT_MAX_BSON_SIZE
39
+ @max_message_size = @max_bson_size * MESSAGE_SIZE_FACTOR
36
40
  end
37
41
 
38
42
  def inspect
@@ -44,7 +48,7 @@ module Mongo
44
48
  disconnect_old_members
45
49
  connect_to_members
46
50
  initialize_pools(@members)
47
- cache_discovered_seeds
51
+ @seeds = discovered_seeds
48
52
  end
49
53
 
50
54
  def refresh!(additional_seeds)
@@ -113,12 +117,11 @@ module Mongo
113
117
  read_pool.host_port
114
118
  end
115
119
 
116
- def max_bson_size
117
- @max_bson_size ||= config_min('maxBsonObjectSize', DEFAULT_MAX_BSON_SIZE)
118
- end
119
-
120
- def max_message_size
121
- @max_message_size ||= config_min('maxMessageSizeBytes', DEFAULT_MAX_MESSAGE_SIZE)
120
+ def update_max_sizes
121
+ unless @members.size == 0
122
+ @max_bson_size = @members.map(&:max_bson_size).min
123
+ @max_message_size = @members.map(&:max_message_size).min
124
+ end
122
125
  end
123
126
 
124
127
  private
@@ -192,11 +195,6 @@ module Mongo
192
195
  @arbiters = members.first.arbiters
193
196
  end
194
197
 
195
- def config_min(attribute, default)
196
- @members.reject {|m| !m.config[attribute]}
197
- @members.map {|m| m.config[attribute]}.min || default
198
- end
199
-
200
198
  def assign_primary(member)
201
199
  member.last_state = :primary
202
200
  @primary = member.host_port
@@ -246,8 +244,8 @@ module Mongo
246
244
 
247
245
  private
248
246
 
249
- def cache_discovered_seeds
250
- @seeds = @members.map &:host_port
247
+ def discovered_seeds
248
+ @members.map(&:host_port)
251
249
  end
252
250
 
253
251
  end
@@ -16,6 +16,7 @@ module Mongo
16
16
  disconnect_old_members
17
17
  connect_to_members
18
18
  initialize_pools best(@members)
19
+ @seeds = discovered_seeds
19
20
  end
20
21
 
21
22
  # We want to refresh to the member with the fastest ping time
@@ -25,8 +26,10 @@ module Mongo
25
26
  # The config.mongos find can't be part of the connect call chain due to infinite recursion
26
27
  def check_connection_health
27
28
  begin
28
- seeds = @client['config']['mongos'].find.to_a.map{|doc| doc['_id']}
29
- if @seeds != seeds
29
+ seeds = @client['config']['mongos'].find.map do |mongos|
30
+ Support.normalize_seeds(mongos['_id'])
31
+ end
32
+ if discovered_seeds != seeds
30
33
  @seeds = seeds
31
34
  @refresh_required = true
32
35
  end
@@ -82,6 +82,20 @@ module Mongo
82
82
  end
83
83
  end
84
84
 
85
+ def normalize_seeds(seeds)
86
+ pairs = Array(seeds)
87
+ pairs = [ seeds ] if pairs.last.is_a?(Fixnum)
88
+ pairs = pairs.collect do |hostport|
89
+ if hostport.is_a?(String)
90
+ host, port = hostport.split(':')
91
+ [ host, port && port.to_i || MongoClient::DEFAULT_PORT ]
92
+ else
93
+ hostport
94
+ end
95
+ end
96
+ pairs.length > 1 ? pairs : pairs.first
97
+ end
98
+
85
99
  def is_i?(value)
86
100
  return !!(value =~ /^\d+$/)
87
101
  end
@@ -11,14 +11,18 @@ Gem::Specification.new do |s|
11
11
  s.rubyforge_project = 'mongo'
12
12
  s.license = 'Apache License Version 2.0'
13
13
 
14
- s.signing_key = 'gem-private_key.pem'
15
- s.cert_chain = ['gem-public_cert.pem']
14
+ if File.exists?('gem-private_key.pem')
15
+ s.signing_key = 'gem-private_key.pem'
16
+ s.cert_chain = ['gem-public_cert.pem']
17
+ else
18
+ warn 'Warning: No private key present, creating unsigned gem.'
19
+ end
16
20
 
17
21
  s.files = ['mongo.gemspec', 'LICENSE', 'VERSION']
18
22
  s.files += ['README.md', 'Rakefile', 'bin/mongo_console']
19
23
  s.files += ['lib/mongo.rb'] + Dir['lib/mongo/**/*.rb']
20
24
 
21
- s.test_files = Dir['test/**/*.rb']
25
+ s.test_files = Dir['test/**/*.rb'] - Dir['test/bson/*']
22
26
  s.executables = ['mongo_console']
23
27
  s.require_paths = ['lib']
24
28
  s.has_rdoc = 'yard'
@@ -0,0 +1,21 @@
1
+ require 'test_helper'
2
+ require 'shared/authentication'
3
+
4
+ class AuthenticationTest < Test::Unit::TestCase
5
+ include Mongo
6
+ include AuthenticationTests
7
+
8
+ def setup
9
+ @client = MongoClient.new
10
+ @db = @client[MONGO_TEST_DB]
11
+ end
12
+
13
+ def teardown
14
+ @db['system.users'].remove
15
+ end
16
+
17
+ def test_authenticate_with_connection_uri
18
+ @db.add_user('eunice', 'uritest')
19
+ assert MongoClient.from_uri("mongodb://eunice:uritest@#{host_port}/#{@db.name}")
20
+ end
21
+ end