mongo 2.2.1 → 2.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +1 -0
- data/lib/mongo/bson.rb +1 -1
- data/lib/mongo/cluster/topology/replica_set.rb +21 -4
- data/lib/mongo/collection/view/readable.rb +0 -1
- data/lib/mongo/error/operation_failure.rb +3 -1
- data/lib/mongo/grid/file.rb +14 -11
- data/lib/mongo/grid/file/chunk.rb +12 -10
- data/lib/mongo/grid/fs_bucket.rb +2 -2
- data/lib/mongo/grid/stream/read.rb +1 -1
- data/lib/mongo/grid/stream/write.rb +5 -5
- data/lib/mongo/options/mapper.rb +17 -0
- data/lib/mongo/protocol/message.rb +1 -1
- data/lib/mongo/server/connection.rb +3 -25
- data/lib/mongo/server/description.rb +19 -2
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo/write_concern/normalizable.rb +2 -1
- data/spec/mongo/client_spec.rb +1 -1
- data/spec/mongo/collection/view/readable_spec.rb +18 -0
- data/spec/mongo/grid/file/chunk_spec.rb +1 -0
- data/spec/mongo/grid/file_spec.rb +25 -6
- data/spec/mongo/grid/stream/write_spec.rb +11 -0
- data/spec/mongo/protocol/reply_spec.rb +13 -0
- data/spec/mongo/server/connection_spec.rb +4 -4
- data/spec/mongo/write_concern_spec.rb +15 -0
- data/spec/support/command_monitoring.rb +3 -0
- data/spec/support/sdam/rs/equal_electionids.yml +4 -0
- data/spec/support/sdam/rs/new_primary_new_electionid.yml +7 -1
- data/spec/support/sdam/rs/new_primary_new_setversion.yml +101 -0
- data/spec/support/sdam/rs/null_election_id.yml +8 -1
- data/spec/support/sdam/rs/primary_disconnect_electionid.yml +37 -1
- data/spec/support/sdam/rs/primary_disconnect_setversion.yml +160 -0
- data/spec/support/sdam/rs/set_version_without_electionid.yml +69 -0
- data/spec/support/sdam/rs/setversion_without_electionid.yml +69 -0
- data/spec/support/sdam/rs/use_setversion_without_electionid.yml +99 -0
- metadata +36 -5
- metadata.gz.sig +1 -0
- data/lib/csasl/csasl.bundle +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72df9675f13de7a6111464ef0089ba64b4ef11af
|
4
|
+
data.tar.gz: 20832950dd436fb031938d2e164cca2c7fe5d84c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eaaf003581ddec08e424a7a8168917b4a971514029527229ffe0e1a5746715be52caf0eb8e1f3ef4af29e35d744b23240282fecfa157280f4e31cb4f8c03bfbf
|
7
|
+
data.tar.gz: 32dd69254433179769be7b7d030e230da1b499ce59da53ab1535b1d736cca6dd2a3bb8d1516323abdf3f8dbb7d2285356ef011c708f8a460cc2ffa1e4e88f015
|
checksums.yaml.gz.sig
ADDED
Binary file
|
data.tar.gz.sig
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
���Y;ht����S���~r�٘-��ZK���cu�̸x����=��\�w�JG��%@y�U�3x;�d�:IR"�^�i�\���<^;O�Y����H�,�;_1eH�����6���(�>�/�`zRІ|@N �&����b�lz�8r��jy�ѓ��C����i,JY(^Q�a�ydQ���"
_�k�94�J#*5���hi�F���'�����`~+�85�>q���Nl��|[]/��8&�no���v
|
data/lib/mongo/bson.rb
CHANGED
@@ -68,6 +68,7 @@ module Mongo
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
update_max_election_id(description)
|
71
|
+
update_max_set_version(description)
|
71
72
|
end
|
72
73
|
else
|
73
74
|
log_warn(
|
@@ -88,7 +89,8 @@ module Mongo
|
|
88
89
|
# @since 2.0.0
|
89
90
|
def initialize(options, seeds = [])
|
90
91
|
@options = options
|
91
|
-
@max_election_id =
|
92
|
+
@max_election_id = nil
|
93
|
+
@max_set_version = nil
|
92
94
|
end
|
93
95
|
|
94
96
|
# A replica set topology is a replica set.
|
@@ -222,14 +224,29 @@ module Mongo
|
|
222
224
|
private
|
223
225
|
|
224
226
|
def update_max_election_id(description)
|
225
|
-
if description.election_id &&
|
227
|
+
if description.election_id &&
|
228
|
+
(@max_election_id.nil? ||
|
229
|
+
description.election_id > @max_election_id)
|
226
230
|
@max_election_id = description.election_id
|
227
231
|
end
|
228
232
|
end
|
229
233
|
|
234
|
+
def update_max_set_version(description)
|
235
|
+
if description.set_version &&
|
236
|
+
(@max_set_version.nil? ||
|
237
|
+
description.set_version > @max_set_version)
|
238
|
+
@max_set_version = description.set_version
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
230
242
|
def detect_stale_primary!(description)
|
231
|
-
if description.election_id && description.
|
232
|
-
|
243
|
+
if description.election_id && description.set_version
|
244
|
+
if @max_set_version && @max_election_id &&
|
245
|
+
(description.set_version < @max_set_version ||
|
246
|
+
(description.set_version == @max_set_version &&
|
247
|
+
description.election_id < @max_election_id))
|
248
|
+
description.unknown!
|
249
|
+
end
|
233
250
|
end
|
234
251
|
end
|
235
252
|
|
@@ -120,7 +120,6 @@ module Mongo
|
|
120
120
|
# @option options :limit [ Integer ] Max number of docs to return.
|
121
121
|
# @option options :max_time_ms [ Integer ] The maximum amount of time to allow the
|
122
122
|
# command to run.
|
123
|
-
# @option options :read [ Hash ] The read preference for this command.
|
124
123
|
#
|
125
124
|
# @return [ Integer ] The document count.
|
126
125
|
#
|
@@ -37,7 +37,9 @@ module Mongo
|
|
37
37
|
'error querying',
|
38
38
|
'could not get last error',
|
39
39
|
'connection attempt failed',
|
40
|
-
'interrupted at shutdown'
|
40
|
+
'interrupted at shutdown',
|
41
|
+
'unknown replica set',
|
42
|
+
'dbclient error communicating with server'
|
41
43
|
].freeze
|
42
44
|
|
43
45
|
# Can the operation that caused the error be retried?
|
data/lib/mongo/grid/file.rb
CHANGED
@@ -30,9 +30,6 @@ module Mongo
|
|
30
30
|
# @return [ Array<Chunk> ] chunks The file chunks.
|
31
31
|
attr_reader :chunks
|
32
32
|
|
33
|
-
# @return [ IO ] data The raw data for the file.
|
34
|
-
attr_reader :data
|
35
|
-
|
36
33
|
# @return [ File::Info ] info The file information.
|
37
34
|
attr_reader :info
|
38
35
|
|
@@ -48,7 +45,7 @@ module Mongo
|
|
48
45
|
# @since 2.0.0
|
49
46
|
def ==(other)
|
50
47
|
return false unless other.is_a?(File)
|
51
|
-
chunks == other.chunks &&
|
48
|
+
chunks == other.chunks && info == other.info
|
52
49
|
end
|
53
50
|
|
54
51
|
# Initialize the file.
|
@@ -56,8 +53,8 @@ module Mongo
|
|
56
53
|
# @example Create the file.
|
57
54
|
# Grid::File.new(data, :filename => 'test.txt')
|
58
55
|
#
|
59
|
-
# @param [ IO, Array<BSON::Document> ] data The file
|
60
|
-
# chunks.
|
56
|
+
# @param [ IO, String, Array<BSON::Document> ] data The file object, file
|
57
|
+
# contents or chunks.
|
61
58
|
# @param [ BSON::Document, Hash ] options The info options.
|
62
59
|
#
|
63
60
|
# @option options [ String ] :filename Required name of the file.
|
@@ -71,10 +68,19 @@ module Mongo
|
|
71
68
|
#
|
72
69
|
# @since 2.0.0
|
73
70
|
def initialize(data, options = {})
|
74
|
-
@info = Info.new(options.merge(:length => data.
|
71
|
+
@info = Info.new(options.merge(:length => data.size))
|
75
72
|
initialize_chunks!(data)
|
76
73
|
end
|
77
74
|
|
75
|
+
# Joins chunks into a string.
|
76
|
+
#
|
77
|
+
# @return [ String ] The raw data for the file.
|
78
|
+
#
|
79
|
+
# @since 2.0.0
|
80
|
+
def data
|
81
|
+
@data ||= Chunk.assemble(chunks)
|
82
|
+
end
|
83
|
+
|
78
84
|
# Gets a pretty inspection of the file.
|
79
85
|
#
|
80
86
|
# @example Get the file inspection.
|
@@ -96,12 +102,9 @@ module Mongo
|
|
96
102
|
# the original data itself.
|
97
103
|
def initialize_chunks!(value)
|
98
104
|
if value.is_a?(Array)
|
99
|
-
|
100
|
-
@chunks = chks
|
101
|
-
@data = Chunk.assemble(chks)
|
105
|
+
@chunks = value.map{ |doc| Chunk.new(doc) }
|
102
106
|
else
|
103
107
|
@chunks = Chunk.split(value, info)
|
104
|
-
@data = value
|
105
108
|
end
|
106
109
|
end
|
107
110
|
end
|
@@ -12,6 +12,8 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
require 'stringio'
|
16
|
+
|
15
17
|
module Mongo
|
16
18
|
module Grid
|
17
19
|
class File
|
@@ -159,23 +161,23 @@ module Mongo
|
|
159
161
|
# @example Split the data into chunks.
|
160
162
|
# Chunks.split(data)
|
161
163
|
#
|
162
|
-
# @param [ String ] data The raw bytes.
|
164
|
+
# @param [ String, IO ] data The raw bytes.
|
163
165
|
# @param [ File::Info ] file_info The files collection file doc.
|
164
166
|
#
|
165
167
|
# @return [ Array<Chunk> ] The chunks of the data.
|
166
168
|
#
|
167
169
|
# @since 2.0.0
|
168
|
-
def split(
|
169
|
-
|
170
|
-
|
171
|
-
|
170
|
+
def split(io, file_info, offset = 0)
|
171
|
+
io = StringIO.new(io) if io.is_a?(String)
|
172
|
+
parts = Enumerator.new { |y| y << io.read(file_info.chunk_size) until io.eof? }
|
173
|
+
parts.map.with_index do |bytes, n|
|
172
174
|
file_info.md5.update(bytes)
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
175
|
+
Chunk.new(
|
176
|
+
data: BSON::Binary.new(bytes),
|
177
|
+
files_id: file_info.id,
|
178
|
+
n: n + offset,
|
179
|
+
)
|
177
180
|
end
|
178
|
-
chunks
|
179
181
|
end
|
180
182
|
end
|
181
183
|
end
|
data/lib/mongo/grid/fs_bucket.rb
CHANGED
@@ -359,8 +359,8 @@ module Mongo
|
|
359
359
|
# chunks collection. After all the chunks have been uploaded, it creates a files collection
|
360
360
|
# document for the filename in the files collection.
|
361
361
|
#
|
362
|
-
# @example
|
363
|
-
# fs.
|
362
|
+
# @example Upload a file to the GridFS bucket.
|
363
|
+
# fs.upload_from_stream('a-file.txt')
|
364
364
|
#
|
365
365
|
# @param [ String ] filename The filename of the file to upload.
|
366
366
|
# @param [ IO ] io The source io stream to upload from.
|
@@ -74,7 +74,7 @@ module Mongo
|
|
74
74
|
view.each_with_index.reduce(0) do |length_read, (doc, index)|
|
75
75
|
chunk = Grid::File::Chunk.new(doc)
|
76
76
|
validate!(index, num_chunks, chunk, length_read)
|
77
|
-
data =
|
77
|
+
data = chunk.data.data
|
78
78
|
yield data
|
79
79
|
length_read += data.size
|
80
80
|
end if block_given?
|
@@ -82,9 +82,8 @@ module Mongo
|
|
82
82
|
def write(io)
|
83
83
|
ensure_open!
|
84
84
|
@indexes ||= ensure_indexes!
|
85
|
-
|
86
|
-
|
87
|
-
chunks = File::Chunk.split(data, file_info, @n)
|
85
|
+
@length += io.size
|
86
|
+
chunks = File::Chunk.split(io, file_info, @n)
|
88
87
|
@n += chunks.size
|
89
88
|
chunks_collection.insert_many(chunks) unless chunks.empty?
|
90
89
|
self
|
@@ -157,10 +156,11 @@ module Mongo
|
|
157
156
|
end
|
158
157
|
|
159
158
|
def with_write_concern(collection)
|
160
|
-
if
|
159
|
+
if write_concern.nil? || (collection.write_concern &&
|
160
|
+
collection.write_concern.options == write_concern.options)
|
161
161
|
collection
|
162
162
|
else
|
163
|
-
collection.
|
163
|
+
collection.with(write: write_concern.options)
|
164
164
|
end
|
165
165
|
end
|
166
166
|
|
data/lib/mongo/options/mapper.rb
CHANGED
@@ -81,6 +81,23 @@ module Mongo
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
+
# Coverts all the keys of the options to symbols.
|
85
|
+
#
|
86
|
+
# @example Convert all option keys to symbols.
|
87
|
+
# Mapper.transform({ 'name' => 1 })
|
88
|
+
#
|
89
|
+
# @param [ Hash ] options The options to transform.
|
90
|
+
#
|
91
|
+
# @return [ Hash ] The transformed options.
|
92
|
+
#
|
93
|
+
# @since 2.2.2
|
94
|
+
def transform_keys_to_symbols(options)
|
95
|
+
options.reduce({}) do |transformed, (key, value)|
|
96
|
+
transformed[key.to_sym] = value
|
97
|
+
transformed
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
84
101
|
# Coverts all the symbol values to strings.
|
85
102
|
#
|
86
103
|
# @example Convert all option symbol values to strings.
|
@@ -114,7 +114,7 @@ module Mongo
|
|
114
114
|
|
115
115
|
# Protection from potential DOS man-in-the-middle attacks. See
|
116
116
|
# DRIVERS-276.
|
117
|
-
if length > max_message_size
|
117
|
+
if length > (max_message_size || MAX_MESSAGE_SIZE)
|
118
118
|
raise Error::MaxMessageSize.new(max_message_size)
|
119
119
|
end
|
120
120
|
|
@@ -38,29 +38,12 @@ module Mongo
|
|
38
38
|
# @since 2.1.0
|
39
39
|
PING_BYTES = PING_MESSAGE.serialize.to_s.freeze
|
40
40
|
|
41
|
-
# @return [ Mongo::Auth::CR, Mongo::Auth::X509, Mongo::Auth:LDAP, Mongo::Auth::SCRAM ]
|
42
|
-
# authenticator The authentication strategy.
|
43
|
-
attr_reader :authenticator
|
44
|
-
|
45
41
|
def_delegators :@server,
|
46
42
|
:features,
|
47
43
|
:max_bson_object_size,
|
48
44
|
:max_message_size,
|
49
45
|
:mongos?
|
50
46
|
|
51
|
-
# Is this connection authenticated. Will return true if authorization
|
52
|
-
# details were provided and authentication passed.
|
53
|
-
#
|
54
|
-
# @example Is the connection authenticated?
|
55
|
-
# connection.authenticated?
|
56
|
-
#
|
57
|
-
# @return [ true, false ] If the connection is authenticated.
|
58
|
-
#
|
59
|
-
# @since 2.0.0
|
60
|
-
def authenticated?
|
61
|
-
!!@authenticated
|
62
|
-
end
|
63
|
-
|
64
47
|
# Tell the underlying socket to establish a connection to the host.
|
65
48
|
#
|
66
49
|
# @example Connect to the host.
|
@@ -76,10 +59,7 @@ module Mongo
|
|
76
59
|
unless socket
|
77
60
|
@socket = address.socket(timeout, ssl_options)
|
78
61
|
socket.connect!
|
79
|
-
|
80
|
-
authenticator.login(self)
|
81
|
-
@authenticated = true
|
82
|
-
end
|
62
|
+
authenticate!
|
83
63
|
end
|
84
64
|
true
|
85
65
|
end
|
@@ -99,7 +79,6 @@ module Mongo
|
|
99
79
|
if socket
|
100
80
|
socket.close
|
101
81
|
@socket = nil
|
102
|
-
@authenticated = false
|
103
82
|
end
|
104
83
|
true
|
105
84
|
end
|
@@ -151,7 +130,6 @@ module Mongo
|
|
151
130
|
@ssl_options = options.reject { |k, v| !k.to_s.start_with?(SSL) }
|
152
131
|
@socket = nil
|
153
132
|
@pid = Process.pid
|
154
|
-
setup_authentication!
|
155
133
|
end
|
156
134
|
|
157
135
|
# Ping the connection to see if the server is responding to commands.
|
@@ -180,11 +158,11 @@ module Mongo
|
|
180
158
|
messages.last.replyable? ? read : nil
|
181
159
|
end
|
182
160
|
|
183
|
-
def
|
161
|
+
def authenticate!
|
184
162
|
if options[:user]
|
185
163
|
default_mechanism = @server.features.scram_sha_1_enabled? ? :scram : :mongodb_cr
|
186
164
|
user = Auth::User.new(Options::Redacted.new(:auth_mech => default_mechanism).merge(options))
|
187
|
-
|
165
|
+
Auth.get(user).login(self)
|
188
166
|
end
|
189
167
|
end
|
190
168
|
|
@@ -129,11 +129,16 @@ module Mongo
|
|
129
129
|
# @since 2.0.0
|
130
130
|
TAGS = 'tags'.freeze
|
131
131
|
|
132
|
-
# Constant for reading
|
132
|
+
# Constant for reading electionId info from config.
|
133
133
|
#
|
134
134
|
# @since 2.1.0
|
135
135
|
ELECTION_ID = 'electionId'.freeze
|
136
136
|
|
137
|
+
# Constant for reading setVersion info from config.
|
138
|
+
#
|
139
|
+
# @since 2.2.2
|
140
|
+
SET_VERSION = 'setVersion'.freeze
|
141
|
+
|
137
142
|
# Constant for reading localTime info from config.
|
138
143
|
#
|
139
144
|
# @since 2.1.0
|
@@ -142,7 +147,7 @@ module Mongo
|
|
142
147
|
# Fields to exclude when comparing two descriptions.
|
143
148
|
#
|
144
149
|
# @since 2.0.6
|
145
|
-
EXCLUDE_FOR_COMPARISON = [ LOCAL_TIME, ELECTION_ID ].freeze
|
150
|
+
EXCLUDE_FOR_COMPARISON = [ LOCAL_TIME, ELECTION_ID, SET_VERSION ].freeze
|
146
151
|
|
147
152
|
# @return [ Address ] address The server's address.
|
148
153
|
attr_reader :address
|
@@ -343,6 +348,18 @@ module Mongo
|
|
343
348
|
config[ELECTION_ID]
|
344
349
|
end
|
345
350
|
|
351
|
+
# Get the setVersion from the config.
|
352
|
+
#
|
353
|
+
# @example Get the setVersion.
|
354
|
+
# description.set_version
|
355
|
+
#
|
356
|
+
# @return [ Integer ] The set version.
|
357
|
+
#
|
358
|
+
# @since 2.2.2
|
359
|
+
def set_version
|
360
|
+
config[SET_VERSION]
|
361
|
+
end
|
362
|
+
|
346
363
|
# Is the server a mongos?
|
347
364
|
#
|
348
365
|
# @example Is the server a mongos?
|
data/lib/mongo/version.rb
CHANGED
data/spec/mongo/client_spec.rb
CHANGED
@@ -688,7 +688,7 @@ describe Mongo::Client do
|
|
688
688
|
end
|
689
689
|
|
690
690
|
it 'returns a acknowledged write concern' do
|
691
|
-
expect(concern.get_last_error).to eq(:getlasterror => 1,
|
691
|
+
expect(concern.get_last_error).to eq(:getlasterror => 1, :j => true)
|
692
692
|
end
|
693
693
|
end
|
694
694
|
|
@@ -377,6 +377,17 @@ describe Mongo::Collection::View::Readable do
|
|
377
377
|
expect(distinct).to be_empty
|
378
378
|
end
|
379
379
|
end
|
380
|
+
|
381
|
+
context 'when the field does not exist' do
|
382
|
+
|
383
|
+
let(:distinct) do
|
384
|
+
view.distinct(:doesnotexist)
|
385
|
+
end
|
386
|
+
|
387
|
+
it 'returns an empty array' do
|
388
|
+
expect(distinct).to be_empty
|
389
|
+
end
|
390
|
+
end
|
380
391
|
end
|
381
392
|
|
382
393
|
context 'when no selector is provided' do
|
@@ -462,6 +473,13 @@ describe Mongo::Collection::View::Readable do
|
|
462
473
|
expect(view.distinct(:field, max_time_ms: 100)).to eq([ 'test' ])
|
463
474
|
end
|
464
475
|
end
|
476
|
+
|
477
|
+
context 'when the field does not exist' do
|
478
|
+
|
479
|
+
it 'returns an empty array' do
|
480
|
+
expect(view.distinct(:nofieldexists)).to be_empty
|
481
|
+
end
|
482
|
+
end
|
465
483
|
end
|
466
484
|
|
467
485
|
describe '#hint' do
|