mongo 2.11.0.rc0 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +2 -0
  5. data/lib/mongo/auth.rb +11 -2
  6. data/lib/mongo/auth/cr/conversation.rb +1 -1
  7. data/lib/mongo/auth/ldap/conversation.rb +1 -1
  8. data/lib/mongo/auth/scram/conversation.rb +4 -1
  9. data/lib/mongo/auth/user.rb +15 -1
  10. data/lib/mongo/auth/user/view.rb +10 -4
  11. data/lib/mongo/auth/x509.rb +11 -1
  12. data/lib/mongo/auth/x509/conversation.rb +15 -6
  13. data/lib/mongo/background_thread.rb +28 -13
  14. data/lib/mongo/client.rb +23 -15
  15. data/lib/mongo/collection/view/change_stream.rb +5 -1
  16. data/lib/mongo/collection/view/readable.rb +5 -2
  17. data/lib/mongo/collection/view/writable.rb +3 -1
  18. data/lib/mongo/cursor/builder/get_more_command.rb +4 -1
  19. data/lib/mongo/cursor/builder/kill_cursors_command.rb +16 -5
  20. data/lib/mongo/cursor/builder/op_get_more.rb +2 -2
  21. data/lib/mongo/cursor/builder/op_kill_cursors.rb +17 -5
  22. data/lib/mongo/error/operation_failure.rb +3 -3
  23. data/lib/mongo/monitoring/command_log_subscriber.rb +5 -3
  24. data/lib/mongo/monitoring/event/command_started.rb +13 -3
  25. data/lib/mongo/monitoring/publishable.rb +4 -2
  26. data/lib/mongo/operation/create_user/command.rb +1 -0
  27. data/lib/mongo/operation/remove_user/command.rb +1 -0
  28. data/lib/mongo/operation/update_user/command.rb +1 -0
  29. data/lib/mongo/protocol/get_more.rb +2 -1
  30. data/lib/mongo/protocol/kill_cursors.rb +6 -13
  31. data/lib/mongo/protocol/serializers.rb +10 -4
  32. data/lib/mongo/retryable.rb +1 -1
  33. data/lib/mongo/server/connection.rb +6 -2
  34. data/lib/mongo/server/connection_base.rb +2 -1
  35. data/lib/mongo/server/monitor.rb +1 -1
  36. data/lib/mongo/server/pending_connection.rb +6 -0
  37. data/lib/mongo/socket/ssl.rb +1 -1
  38. data/lib/mongo/uri.rb +5 -41
  39. data/lib/mongo/version.rb +1 -1
  40. data/mongo.gemspec +11 -2
  41. data/spec/README.md +105 -9
  42. data/spec/USERS.md +72 -0
  43. data/spec/integration/auth_spec.rb +20 -6
  44. data/spec/integration/client_construction_spec.rb +3 -1
  45. data/spec/integration/client_options_spec.rb +437 -0
  46. data/spec/integration/command_monitoring_spec.rb +4 -1
  47. data/spec/integration/connection_pool_populator_spec.rb +4 -0
  48. data/spec/integration/connection_spec.rb +4 -2
  49. data/spec/integration/cursor_reaping_spec.rb +1 -1
  50. data/spec/integration/get_more_spec.rb +32 -0
  51. data/spec/integration/retryable_errors_spec.rb +99 -0
  52. data/spec/integration/retryable_writes_errors_spec.rb +11 -10
  53. data/spec/lite_spec_helper.rb +2 -1
  54. data/spec/mongo/auth/scram_spec.rb +1 -0
  55. data/spec/mongo/auth/user/view_spec.rb +102 -1
  56. data/spec/mongo/auth/user_spec.rb +56 -15
  57. data/spec/mongo/auth/x509_spec.rb +31 -1
  58. data/spec/mongo/bulk_write_spec.rb +2 -2
  59. data/spec/mongo/collection/view/change_stream_spec.rb +2 -2
  60. data/spec/mongo/collection/view/readable_spec.rb +8 -4
  61. data/spec/mongo/cursor/builder/get_more_command_spec.rb +4 -2
  62. data/spec/mongo/cursor/builder/op_get_more_spec.rb +4 -2
  63. data/spec/mongo/cursor_spec.rb +3 -3
  64. data/spec/mongo/retryable_spec.rb +31 -52
  65. data/spec/mongo/server/connection_auth_spec.rb +3 -0
  66. data/spec/mongo/server/connection_pool_spec.rb +4 -0
  67. data/spec/mongo/server/connection_spec.rb +12 -4
  68. data/spec/mongo/server/monitor_spec.rb +19 -1
  69. data/spec/mongo/socket/ssl_spec.rb +1 -1
  70. data/spec/mongo/uri/srv_protocol_spec.rb +0 -13
  71. data/spec/mongo/uri_option_parsing_spec.rb +0 -8
  72. data/spec/mongo/uri_spec.rb +6 -20
  73. data/spec/runners/connection_string.rb +116 -0
  74. data/spec/runners/read_write_concern_document.rb +67 -0
  75. data/spec/spec_tests/change_streams_spec.rb +17 -2
  76. data/spec/spec_tests/connection_string_spec.rb +2 -59
  77. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +3 -3
  78. data/spec/spec_tests/data/change_streams/change-streams.yml +88 -20
  79. data/spec/spec_tests/data/cmap/connection-must-have-id.yml +6 -0
  80. data/spec/spec_tests/data/cmap/connection-must-order-ids.yml +6 -0
  81. data/spec/spec_tests/data/cmap/pool-checkin-destroy-closed.yml +3 -0
  82. data/spec/spec_tests/data/cmap/pool-checkin-destroy-stale.yml +3 -0
  83. data/spec/spec_tests/data/cmap/pool-checkin-make-available.yml +3 -0
  84. data/spec/spec_tests/data/cmap/pool-checkin.yml +1 -0
  85. data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +2 -0
  86. data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +5 -0
  87. data/spec/spec_tests/data/cmap/pool-checkout-multiple.yml +3 -0
  88. data/spec/spec_tests/data/cmap/pool-checkout-no-idle.yml +4 -0
  89. data/spec/spec_tests/data/cmap/pool-checkout-no-stale.yml +4 -0
  90. data/spec/spec_tests/data/cmap/pool-close-destroy-conns.yml +2 -0
  91. data/spec/spec_tests/data/cmap/pool-create-max-size.yml +15 -0
  92. data/spec/spec_tests/data/cmap/pool-create-min-size.yml +4 -0
  93. data/spec/spec_tests/data/cmap/wait-queue-fairness.yml +31 -1
  94. data/spec/spec_tests/data/cmap/wait-queue-timeout.yml +5 -0
  95. data/spec/spec_tests/data/read_write_concern/connection-string/read-concern.yml +32 -0
  96. data/spec/spec_tests/data/read_write_concern/connection-string/write-concern.yml +82 -0
  97. data/spec/spec_tests/data/read_write_concern/document/read-concern.yml +37 -0
  98. data/spec/spec_tests/data/read_write_concern/document/write-concern.yml +100 -0
  99. data/spec/spec_tests/data/retryable_reads/aggregate-merge.yml +39 -0
  100. data/spec/spec_tests/data/retryable_reads/aggregate-serverErrors.yml +1 -1
  101. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +2 -2
  102. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +1 -1
  103. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +2 -2
  104. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +1 -1
  105. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +2 -2
  106. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +1 -1
  107. data/spec/spec_tests/data/retryable_reads/count-serverErrors.yml +1 -1
  108. data/spec/spec_tests/data/retryable_reads/countDocuments-serverErrors.yml +1 -1
  109. data/spec/spec_tests/data/retryable_reads/distinct-serverErrors.yml +1 -1
  110. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-serverErrors.yml +1 -1
  111. data/spec/spec_tests/data/retryable_reads/find-serverErrors.yml +1 -1
  112. data/spec/spec_tests/data/retryable_reads/findOne-serverErrors.yml +1 -1
  113. data/spec/spec_tests/data/retryable_reads/gridfs-download-serverErrors.yml +1 -1
  114. data/spec/spec_tests/data/retryable_reads/gridfs-downloadByName-serverErrors.yml +1 -1
  115. data/spec/spec_tests/data/retryable_reads/listCollectionNames-serverErrors.yml +1 -1
  116. data/spec/spec_tests/data/retryable_reads/listCollectionObjects-serverErrors.yml +1 -1
  117. data/spec/spec_tests/data/retryable_reads/listCollections-serverErrors.yml +1 -1
  118. data/spec/spec_tests/data/retryable_reads/listDatabaseNames-serverErrors.yml +1 -1
  119. data/spec/spec_tests/data/retryable_reads/listDatabaseObjects-serverErrors.yml +1 -1
  120. data/spec/spec_tests/data/retryable_reads/listDatabases-serverErrors.yml +1 -1
  121. data/spec/spec_tests/data/retryable_reads/listIndexNames-serverErrors.yml +1 -1
  122. data/spec/spec_tests/data/retryable_reads/listIndexes-serverErrors.yml +1 -1
  123. data/spec/spec_tests/data/transactions/read-concern.yml +6 -6
  124. data/spec/spec_tests/data/transactions/transaction-options-repl.yml +117 -0
  125. data/spec/spec_tests/data/transactions/transaction-options.yml +14 -121
  126. data/spec/spec_tests/data/transactions/write-concern.yml +3 -0
  127. data/spec/spec_tests/data/transactions_api/transaction-options.yml +11 -12
  128. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +17 -7
  129. data/spec/spec_tests/read_write_concern_connection_string_spec.rb +8 -0
  130. data/spec/spec_tests/read_write_concern_document_spec.rb +74 -0
  131. data/spec/spec_tests/retryable_reads_spec.rb +32 -1
  132. data/spec/spec_tests/uri_options_spec.rb +4 -2
  133. data/spec/support/auth.rb +5 -14
  134. data/spec/support/certificates/client-x509.crt +78 -0
  135. data/spec/support/certificates/client-x509.key +27 -0
  136. data/spec/support/certificates/client-x509.pem +105 -0
  137. data/spec/support/change_streams.rb +8 -11
  138. data/spec/support/client_registry.rb +26 -12
  139. data/spec/support/cluster_tools.rb +2 -2
  140. data/spec/support/cmap.rb +11 -7
  141. data/spec/support/command_monitoring.rb +8 -8
  142. data/spec/support/connection_string.rb +56 -28
  143. data/spec/support/constraints.rb +8 -0
  144. data/spec/support/crud/spec.rb +5 -8
  145. data/spec/support/event_subscriber.rb +7 -0
  146. data/spec/support/gridfs.rb +4 -7
  147. data/spec/support/server_discovery_and_monitoring.rb +3 -8
  148. data/spec/support/server_selection.rb +4 -9
  149. data/spec/support/server_selection_rtt.rb +4 -7
  150. data/spec/support/spec_config.rb +47 -19
  151. data/spec/support/spec_setup.rb +5 -0
  152. data/spec/support/utils.rb +46 -8
  153. metadata +637 -597
  154. metadata.gz.sig +0 -0
@@ -129,7 +129,9 @@ module Mongo
129
129
  cmd[:new] = !!(opts[:return_document] && opts[:return_document] == :after)
130
130
  cmd[:upsert] = opts[:upsert] if opts[:upsert]
131
131
  cmd[:maxTimeMS] = max_time_ms if max_time_ms
132
- cmd[:bypassDocumentValidation] = !!opts[:bypass_document_validation]
132
+ if opts[:bypass_document_validation]
133
+ cmd[:bypassDocumentValidation] = true
134
+ end
133
135
 
134
136
  value = with_session(opts) do |session|
135
137
  applied_write_concern = applied_write_concern(opts[:session])
@@ -57,7 +57,10 @@ module Mongo
57
57
  private
58
58
 
59
59
  def get_more_command
60
- command = { :getMore => cursor.id, :collection => collection_name }
60
+ command = {
61
+ :getMore => BSON::Int64.new(cursor.id),
62
+ :collection => collection_name,
63
+ }
61
64
  command[:batchSize] = batch_size.abs if batch_size && batch_size != 0
62
65
  # If the max_await_time_ms option is set, then we set maxTimeMS on
63
66
  # the get more command.
@@ -54,7 +54,10 @@ module Mongo
54
54
  private
55
55
 
56
56
  def kill_cursors_command
57
- { :killCursors => collection_name, :cursors => [ cursor.id ] }
57
+ {
58
+ killCursors: collection_name,
59
+ cursors: [ BSON::Int64.new(cursor.id) ],
60
+ }
58
61
  end
59
62
 
60
63
  class << self
@@ -65,11 +68,19 @@ module Mongo
65
68
  # KillCursorsCommand.update_cursors(spec, ids)
66
69
  #
67
70
  # @return [ Hash ] The specification.
68
- # @return [ Array ] The ids to update with.
71
+ # @return [ Array<Integer> ] The ids to update with.
69
72
  #
70
73
  # @since 2.3.0
71
74
  def update_cursors(spec, ids)
72
- spec[:selector].merge!(cursors: spec[:selector][:cursors] & ids)
75
+ # Ruby 2.5+ can & BSON::Int64 instances.
76
+ # Ruby 2.4 and earlier cannot.
77
+ # Convert stored ids to Ruby integers for compatibility with
78
+ # older Rubies.
79
+ ids = get_cursors_list(spec) & ids
80
+ ids = ids.map do |cursor_id|
81
+ BSON::Int64.new(cursor_id)
82
+ end
83
+ spec[:selector].merge!(cursors: ids)
73
84
  end
74
85
 
75
86
  # Get the list of cursor ids from a spec generated by this Builder.
@@ -77,11 +88,11 @@ module Mongo
77
88
  # @example Get the list of cursor ids.
78
89
  # KillCursorsCommand.cursors(spec)
79
90
  #
80
- # @return [ Hash ] The specification.
91
+ # @return [ Array<Integer> ] The cursor ids.
81
92
  #
82
93
  # @since 2.3.0
83
94
  def get_cursors_list(spec)
84
- spec[:selector][:cursors]
95
+ spec[:selector][:cursors].map(&:value)
85
96
  end
86
97
  end
87
98
  end
@@ -50,9 +50,9 @@ module Mongo
50
50
  def specification
51
51
  {
52
52
  :to_return => to_return,
53
- :cursor_id => cursor.id,
53
+ :cursor_id => BSON::Int64.new(cursor.id),
54
54
  :db_name => database.name,
55
- :coll_name => collection_name
55
+ :coll_name => collection_name,
56
56
  }
57
57
  end
58
58
  end
@@ -48,7 +48,11 @@ module Mongo
48
48
  #
49
49
  # @since 2.2.0
50
50
  def specification
51
- { :coll_name => collection_name, :db_name => database.name, :cursor_ids => [ cursor.id ] }
51
+ {
52
+ coll_name: collection_name,
53
+ db_name: database.name,
54
+ cursor_ids: [ BSON::Int64.new(cursor.id) ],
55
+ }
52
56
  end
53
57
 
54
58
  class << self
@@ -59,11 +63,19 @@ module Mongo
59
63
  # OpKillCursors.update_cursors(spec, ids)
60
64
  #
61
65
  # @return [ Hash ] The specification.
62
- # @return [ Array ] The ids to update with.
66
+ # @return [ Array<Integer> ] The ids to update with.
63
67
  #
64
68
  # @since 2.3.0
65
69
  def update_cursors(spec, ids)
66
- spec.merge!(cursor_ids: spec[:cursor_ids] & ids)
70
+ # Ruby 2.5+ can & BSON::Int64 instances.
71
+ # Ruby 2.4 and earlier cannot.
72
+ # Convert stored ids to Ruby integers for compatibility with
73
+ # older Rubies.
74
+ ids = get_cursors_list(spec) & ids
75
+ ids = ids.map do |cursor_id|
76
+ BSON::Int64.new(cursor_id)
77
+ end
78
+ spec.merge!(cursor_ids: ids)
67
79
  end
68
80
 
69
81
  # Get the list of cursor ids from a spec generated by this Builder.
@@ -71,11 +83,11 @@ module Mongo
71
83
  # @example Get the list of cursor ids.
72
84
  # OpKillCursors.cursors(spec)
73
85
  #
74
- # @return [ Hash ] The specification.
86
+ # @return [ Array<Integer> ] The cursor ids.
75
87
  #
76
88
  # @since 2.3.0
77
89
  def get_cursors_list(spec)
78
- spec[:cursor_ids]
90
+ spec[:cursor_ids].map(&:value)
79
91
  end
80
92
  end
81
93
  end
@@ -80,15 +80,15 @@ module Mongo
80
80
  # @since 2.6.0
81
81
  attr_reader :code_name
82
82
 
83
- # Whether the error is a retryable error according to the legacy read retry
84
- # logic.
83
+ # Whether the error is a retryable error according to the legacy
84
+ # read retry logic.
85
85
  #
86
86
  # @return [ true, false ]
87
87
  #
88
88
  # @since 2.1.1
89
89
  # @deprecated
90
90
  def retryable?
91
- RETRY_MESSAGES.any?{ |m| message.include?(m) }
91
+ write_retryable? || RETRY_MESSAGES.any?{ |m| message.include?(m) }
92
92
  end
93
93
 
94
94
  # Whether the error is a retryable error according to the modern retryable
@@ -54,7 +54,8 @@ module Mongo
54
54
  # @since 2.1.0
55
55
  def started(event)
56
56
  if logger.debug?
57
- log_debug("#{prefix(event)} | STARTED | #{format_command(event.command)}")
57
+ log_debug("#{prefix(event, connection_id: event.connection_id)} | " +
58
+ "STARTED | #{format_command(event.command)}")
58
59
  end
59
60
  end
60
61
 
@@ -96,8 +97,9 @@ module Mongo
96
97
  end
97
98
  end
98
99
 
99
- def prefix(event)
100
- "#{event.address.to_s} | #{event.database_name}.#{event.command_name}"
100
+ def prefix(event, connection_id: nil)
101
+ "[#{event.request_id}] #{event.address.to_s}#{connection_id && " ##{connection_id}"} | " +
102
+ "#{event.database_name}.#{event.command_name}"
101
103
  end
102
104
 
103
105
  def truncate(command)
@@ -45,6 +45,12 @@ module Mongo
45
45
  # @api private
46
46
  attr_reader :socket_object_id
47
47
 
48
+ # @return [ Integer ] The ID for the connection over which the command
49
+ # is sent.
50
+ #
51
+ # @api private
52
+ attr_reader :connection_id
53
+
48
54
  # Create the new event.
49
55
  #
50
56
  # @example Create the event.
@@ -59,7 +65,7 @@ module Mongo
59
65
  # @since 2.1.0
60
66
  # @api private
61
67
  def initialize(command_name, database_name, address, request_id,
62
- operation_id, command, socket_object_id = nil
68
+ operation_id, command, socket_object_id: nil, connection_id: nil
63
69
  )
64
70
  @command_name = command_name.to_s
65
71
  @database_name = database_name
@@ -68,6 +74,7 @@ module Mongo
68
74
  @operation_id = operation_id
69
75
  @command = redacted(command_name, command)
70
76
  @socket_object_id = socket_object_id
77
+ @connection_id = connection_id
71
78
  end
72
79
 
73
80
  # Create the event from a wire protocol message payload.
@@ -83,7 +90,9 @@ module Mongo
83
90
  #
84
91
  # @since 2.1.0
85
92
  # @api private
86
- def self.generate(address, operation_id, payload, socket_object_id = nil)
93
+ def self.generate(address, operation_id, payload,
94
+ socket_object_id: nil, connection_id: nil
95
+ )
87
96
  new(
88
97
  payload[:command_name],
89
98
  payload[:database_name],
@@ -91,7 +100,8 @@ module Mongo
91
100
  payload[:request_id],
92
101
  operation_id,
93
102
  payload[:command],
94
- socket_object_id,
103
+ socket_object_id: socket_object_id,
104
+ connection_id: connection_id,
95
105
  )
96
106
  end
97
107
 
@@ -44,11 +44,13 @@ module Mongo
44
44
 
45
45
  private
46
46
 
47
- def command_started(address, operation_id, payload, socket_object_id = nil)
47
+ def command_started(address, operation_id, payload,
48
+ socket_object_id: nil, connection_id: nil
49
+ )
48
50
  monitoring.started(
49
51
  Monitoring::COMMAND,
50
52
  Event::CommandStarted.generate(address, operation_id, payload,
51
- socket_object_id)
53
+ socket_object_id: socket_object_id, connection_id: connection_id)
52
54
  )
53
55
  end
54
56
 
@@ -26,6 +26,7 @@ module Mongo
26
26
  include Executable
27
27
  include Limited
28
28
  include ReadPreferenceSupported
29
+ include WriteConcernSupported
29
30
 
30
31
  private
31
32
 
@@ -26,6 +26,7 @@ module Mongo
26
26
  include Executable
27
27
  include Limited
28
28
  include ReadPreferenceSupported
29
+ include WriteConcernSupported
29
30
 
30
31
  private
31
32
 
@@ -25,6 +25,7 @@ module Mongo
25
25
  include Specifiable
26
26
  include Executable
27
27
  include Limited
28
+ include WriteConcernSupported
28
29
 
29
30
  private
30
31
 
@@ -110,6 +110,7 @@ module Mongo
110
110
  # The get more constant.
111
111
  #
112
112
  # @since 2.2.0
113
+ # @deprecated
113
114
  GET_MORE = 'getMore'.freeze
114
115
 
115
116
  # @return [ String ] collection The name of the collection.
@@ -148,7 +149,7 @@ module Mongo
148
149
  # @since 2.1.0
149
150
  def command
150
151
  document = BSON::Document.new
151
- document.store(GET_MORE, cursor_id)
152
+ document.store('getMore', BSON::Int64.new(cursor_id))
152
153
  document.store(Message::BATCH_SIZE, number_to_return)
153
154
  document.store(Message::COLLECTION, collection)
154
155
  document
@@ -52,7 +52,7 @@ module Mongo
52
52
  command_name: 'killCursors',
53
53
  database_name: @database,
54
54
  command: upconverter.command,
55
- request_id: request_id
55
+ request_id: request_id,
56
56
  )
57
57
  end
58
58
 
@@ -85,16 +85,6 @@ module Mongo
85
85
  # @since 2.1.0
86
86
  class Upconverter
87
87
 
88
- # The kill cursors constant.
89
- #
90
- # @since 2.2.0
91
- KILL_CURSORS = 'killCursors'.freeze
92
-
93
- # The cursors constant.
94
- #
95
- # @since 2.2.0
96
- CURSORS = 'cursors'.freeze
97
-
98
88
  # @return [ String ] collection The name of the collection.
99
89
  attr_reader :collection
100
90
 
@@ -125,8 +115,11 @@ module Mongo
125
115
  # @since 2.1.0
126
116
  def command
127
117
  document = BSON::Document.new
128
- document.store(KILL_CURSORS, collection)
129
- document.store(CURSORS, cursor_ids)
118
+ document.store('killCursors', collection)
119
+ store_ids = cursor_ids.map do |cursor_id|
120
+ BSON::Int64.new(cursor_id)
121
+ end
122
+ document.store('cursors', store_ids)
130
123
  document
131
124
  end
132
125
  end
@@ -102,13 +102,16 @@ module Mongo
102
102
  # Serializes and de-serializes one 32-bit integer.
103
103
  module Int32
104
104
 
105
- # Serializes a fixnum to a 4-byte 32-bit integer
105
+ # Serializes a number to a 32-bit integer
106
106
  #
107
107
  # @param buffer [ String ] Buffer to receive the serialized Int32.
108
- # @param value [ Fixnum ] 32-bit integer to be serialized.
108
+ # @param value [ Integer | BSON::Int32 ] 32-bit integer to be serialized.
109
109
  #
110
110
  # @return [String] Buffer with serialized value.
111
111
  def self.serialize(buffer, value, validating_keys = BSON::Config.validating_keys?)
112
+ if value.is_a?(BSON::Int32)
113
+ value = value.value
114
+ end
112
115
  buffer.put_int32(value)
113
116
  end
114
117
 
@@ -127,13 +130,16 @@ module Mongo
127
130
  # Serializes and de-serializes one 64-bit integer.
128
131
  module Int64
129
132
 
130
- # Serializes a fixnum to an 8-byte 64-bit integer
133
+ # Serializes a number to a 64-bit integer
131
134
  #
132
135
  # @param buffer [ String ] Buffer to receive the serialized Int64.
133
- # @param value [ Fixnum ] 64-bit integer to be serialized.
136
+ # @param value [ Integer | BSON::Int64 ] 64-bit integer to be serialized.
134
137
  #
135
138
  # @return [ String ] Buffer with serialized value.
136
139
  def self.serialize(buffer, value, validating_keys = BSON::Config.validating_keys?)
140
+ if value.is_a?(BSON::Int64)
141
+ value = value.value
142
+ end
137
143
  buffer.put_int64(value)
138
144
  end
139
145
 
@@ -333,7 +333,7 @@ module Mongo
333
333
  retry
334
334
  rescue Error::OperationFailure => e
335
335
  e.add_note("attempt #{attempt + 1}")
336
- if cluster.sharded? && e.retryable? && !(session && session.in_transaction?)
336
+ if e.retryable? && !(session && session.in_transaction?)
337
337
  if attempt > client.max_read_retries
338
338
  raise e
339
339
  end
@@ -186,7 +186,7 @@ module Mongo
186
186
 
187
187
  begin
188
188
  handshake!(socket)
189
- pending_connection = PendingConnection.new(socket, @server, monitoring, options)
189
+ pending_connection = PendingConnection.new(socket, @server, monitoring, options.merge(id: id))
190
190
  authenticate!(pending_connection)
191
191
  rescue Exception
192
192
  socket.close
@@ -362,7 +362,11 @@ module Mongo
362
362
 
363
363
  def authenticate!(pending_connection)
364
364
  if options[:user] || options[:auth_mech]
365
- user = Auth::User.new(Options::Redacted.new(:auth_mech => default_mechanism).merge(options))
365
+ user_options = Options::Redacted.new(:auth_mech => default_mechanism).merge(options)
366
+ if user_options[:auth_mech] == :mongodb_x509
367
+ user_options[:auth_source] = '$external'
368
+ end
369
+ user = Auth::User.new(user_options)
366
370
  @server.handle_auth_failure! do
367
371
  begin
368
372
  Auth.get(user).login(pending_connection)
@@ -96,7 +96,8 @@ module Mongo
96
96
  buffer = serialize(message)
97
97
  ensure_connected do |socket|
98
98
  operation_id = Monitoring.next_operation_id
99
- command_started(address, operation_id, message.payload, socket.object_id)
99
+ command_started(address, operation_id, message.payload,
100
+ socket_object_id: socket.object_id, connection_id: id)
100
101
  start = Time.now
101
102
  result = nil
102
103
  begin
@@ -204,7 +204,7 @@ module Mongo
204
204
  connection.ismaster
205
205
  end
206
206
  if exc
207
- log_debug("Error running ismaster on #{server.address}: #{exc.message}")
207
+ log_debug("Error running ismaster on #{server.address}: #{exc.class}: #{exc.message}")
208
208
  if monitoring.monitoring?
209
209
  monitoring.failed(
210
210
  Monitoring::SERVER_HEARTBEAT,
@@ -26,8 +26,14 @@ module Mongo
26
26
  @options = options
27
27
  @server = server
28
28
  @monitoring = monitoring
29
+ @id = options[:id]
29
30
  end
30
31
 
32
+ # @return [ Integer ] The ID for the connection. This is the same ID
33
+ # as that of the regular Connection object for which this
34
+ # PendingConnection instance was created.
35
+ attr_reader :id
36
+
31
37
  def ensure_connected
32
38
  yield @socket
33
39
  end
@@ -112,7 +112,7 @@ module Mongo
112
112
 
113
113
  def verify_hostname?
114
114
  @verify_hostname ||=
115
- # If ssl_verify_hostname is not present, disable only if ssl_verify is
115
+ # If ssl_verify_hostname is not present, disable only if ssl_verify is
116
116
  # explicitly set to false.
117
117
  if options[:ssl_verify_hostname].nil?
118
118
  options[:ssl_verify] != false
@@ -241,7 +241,10 @@ module Mongo
241
241
  #
242
242
  # @since 2.0.0
243
243
  def client_options
244
- opts = default_client_options.merge(uri_options)
244
+ opts = uri_options.tap do |opts|
245
+ opts[:database] = @database if @database
246
+ end
247
+
245
248
  @user ? opts.merge(credentials) : opts
246
249
  end
247
250
 
@@ -442,35 +445,6 @@ module Mongo
442
445
  decode(string) if string.length > 0
443
446
  end
444
447
 
445
- def default_client_options
446
- opts = Options::Redacted.new(database: database)
447
-
448
- if @uri_options[:auth_mech] || @user
449
- opts[:auth_source] = default_auth_source
450
- end
451
-
452
- if @uri_options[:auth_mech] == :gssapi
453
- opts[:auth_mech_properties] = default_auth_mech_properties
454
- end
455
-
456
- opts
457
- end
458
-
459
- def default_auth_mech_properties
460
- { service_name: 'mongodb' }
461
- end
462
-
463
- def default_auth_source
464
- case @uri_options[:auth_mech]
465
- when :gssapi, :mongodb_x509
466
- :external
467
- when :plain
468
- @database || :external
469
- else
470
- @database || Database::ADMIN
471
- end
472
- end
473
-
474
448
  def raise_invalid_error!(details)
475
449
  raise Error::InvalidURI.new(@string, details, FORMAT)
476
450
  end
@@ -544,7 +518,7 @@ module Mongo
544
518
  uri_option 'connect', :connect, type: :symbol
545
519
 
546
520
  # Auth Options
547
- uri_option 'authsource', :auth_source, :type => :auth_source
521
+ uri_option 'authsource', :auth_source
548
522
  uri_option 'authmechanism', :auth_mech, :type => :auth_mech
549
523
  uri_option 'authmechanismproperties', :auth_mech_properties, :type => :auth_mech_props
550
524
 
@@ -632,16 +606,6 @@ module Mongo
632
606
  merge_uri_option(target, value, strategy[:name])
633
607
  end
634
608
 
635
- # Auth source transformation, either db string or :external.
636
- #
637
- # @param value [String] Authentication source.
638
- #
639
- # @return [String] If auth source is database name.
640
- # @return [:external] If auth source is external authentication.
641
- def auth_source(value)
642
- value == '$external' ? :external : value
643
- end
644
-
645
609
  # Authentication mechanism transformation.
646
610
  #
647
611
  # @param value [String] The authentication mechanism.