cassandra-driver 3.0.0.beta.1-java → 3.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +106 -39
  3. data/lib/cassandra.rb +396 -148
  4. data/lib/cassandra/address_resolution.rb +1 -1
  5. data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +1 -1
  6. data/lib/cassandra/address_resolution/policies/none.rb +1 -1
  7. data/lib/cassandra/aggregate.rb +21 -7
  8. data/lib/cassandra/argument.rb +2 -2
  9. data/lib/cassandra/attr_boolean.rb +33 -0
  10. data/lib/cassandra/auth.rb +6 -5
  11. data/lib/cassandra/auth/providers.rb +1 -1
  12. data/lib/cassandra/auth/providers/password.rb +5 -13
  13. data/lib/cassandra/cassandra_logger.rb +80 -0
  14. data/lib/cassandra/cluster.rb +49 -9
  15. data/lib/cassandra/cluster/client.rb +835 -209
  16. data/lib/cassandra/cluster/connection_pool.rb +2 -2
  17. data/lib/cassandra/cluster/connector.rb +86 -27
  18. data/lib/cassandra/cluster/control_connection.rb +222 -95
  19. data/lib/cassandra/cluster/failed_connection.rb +1 -1
  20. data/lib/cassandra/cluster/metadata.rb +14 -8
  21. data/lib/cassandra/cluster/options.rb +68 -22
  22. data/lib/cassandra/cluster/registry.rb +81 -17
  23. data/lib/cassandra/cluster/schema.rb +70 -8
  24. data/lib/cassandra/cluster/schema/cql_type_parser.rb +15 -10
  25. data/lib/cassandra/cluster/schema/fetchers.rb +601 -241
  26. data/lib/cassandra/cluster/schema/fqcn_type_parser.rb +39 -38
  27. data/lib/cassandra/cluster/schema/partitioners.rb +1 -1
  28. data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +6 -8
  29. data/lib/cassandra/cluster/schema/partitioners/ordered.rb +1 -1
  30. data/lib/cassandra/cluster/schema/partitioners/random.rb +1 -1
  31. data/lib/cassandra/cluster/schema/replication_strategies.rb +1 -1
  32. data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +19 -18
  33. data/lib/cassandra/cluster/schema/replication_strategies/none.rb +1 -1
  34. data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +1 -1
  35. data/lib/cassandra/column.rb +4 -23
  36. data/lib/cassandra/column_container.rb +322 -0
  37. data/lib/cassandra/compression.rb +1 -1
  38. data/lib/cassandra/compression/compressors/lz4.rb +7 -8
  39. data/lib/cassandra/compression/compressors/snappy.rb +4 -3
  40. data/lib/cassandra/driver.rb +107 -46
  41. data/lib/cassandra/errors.rb +303 -52
  42. data/lib/cassandra/execution/info.rb +16 -5
  43. data/lib/cassandra/execution/options.rb +102 -55
  44. data/lib/cassandra/execution/trace.rb +16 -9
  45. data/lib/cassandra/executors.rb +1 -1
  46. data/lib/cassandra/function.rb +19 -13
  47. data/lib/cassandra/function_collection.rb +85 -0
  48. data/lib/cassandra/future.rb +101 -49
  49. data/lib/cassandra/host.rb +25 -5
  50. data/lib/cassandra/index.rb +118 -0
  51. data/lib/cassandra/keyspace.rb +169 -33
  52. data/lib/cassandra/listener.rb +1 -1
  53. data/lib/cassandra/load_balancing.rb +2 -2
  54. data/lib/cassandra/load_balancing/policies.rb +1 -1
  55. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +39 -25
  56. data/lib/cassandra/load_balancing/policies/round_robin.rb +8 -1
  57. data/lib/cassandra/load_balancing/policies/token_aware.rb +22 -13
  58. data/lib/cassandra/load_balancing/policies/white_list.rb +18 -5
  59. data/lib/cassandra/materialized_view.rb +90 -0
  60. data/lib/cassandra/null_logger.rb +27 -6
  61. data/lib/cassandra/protocol.rb +1 -1
  62. data/lib/cassandra/protocol/coder.rb +81 -42
  63. data/lib/cassandra/protocol/cql_byte_buffer.rb +58 -44
  64. data/lib/cassandra/protocol/cql_protocol_handler.rb +57 -54
  65. data/lib/cassandra/protocol/request.rb +6 -7
  66. data/lib/cassandra/protocol/requests/auth_response_request.rb +3 -3
  67. data/lib/cassandra/protocol/requests/batch_request.rb +17 -8
  68. data/lib/cassandra/protocol/requests/credentials_request.rb +3 -3
  69. data/lib/cassandra/protocol/requests/execute_request.rb +39 -20
  70. data/lib/cassandra/protocol/requests/options_request.rb +1 -1
  71. data/lib/cassandra/protocol/requests/prepare_request.rb +5 -5
  72. data/lib/cassandra/protocol/requests/query_request.rb +28 -23
  73. data/lib/cassandra/protocol/requests/register_request.rb +2 -2
  74. data/lib/cassandra/protocol/requests/startup_request.rb +8 -8
  75. data/lib/cassandra/protocol/requests/void_query_request.rb +1 -1
  76. data/lib/cassandra/protocol/response.rb +3 -4
  77. data/lib/cassandra/protocol/responses/already_exists_error_response.rb +12 -2
  78. data/lib/cassandra/protocol/responses/auth_challenge_response.rb +4 -5
  79. data/lib/cassandra/protocol/responses/auth_success_response.rb +4 -5
  80. data/lib/cassandra/protocol/responses/authenticate_response.rb +4 -5
  81. data/lib/cassandra/protocol/responses/error_response.rb +104 -17
  82. data/lib/cassandra/protocol/responses/event_response.rb +3 -4
  83. data/lib/cassandra/protocol/responses/function_failure_error_response.rb +13 -2
  84. data/lib/cassandra/protocol/responses/prepared_result_response.rb +14 -9
  85. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +14 -9
  86. data/lib/cassandra/protocol/responses/read_failure_error_response.rb +26 -4
  87. data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +22 -3
  88. data/lib/cassandra/protocol/responses/ready_response.rb +6 -7
  89. data/lib/cassandra/protocol/responses/result_response.rb +11 -10
  90. data/lib/cassandra/protocol/responses/rows_result_response.rb +8 -7
  91. data/lib/cassandra/protocol/responses/schema_change_event_response.rb +8 -8
  92. data/lib/cassandra/protocol/responses/schema_change_result_response.rb +19 -13
  93. data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +5 -6
  94. data/lib/cassandra/protocol/responses/status_change_event_response.rb +5 -6
  95. data/lib/cassandra/protocol/responses/supported_response.rb +4 -5
  96. data/lib/cassandra/protocol/responses/topology_change_event_response.rb +4 -5
  97. data/lib/cassandra/protocol/responses/unavailable_error_response.rb +20 -3
  98. data/lib/cassandra/protocol/responses/unprepared_error_response.rb +11 -2
  99. data/lib/cassandra/protocol/responses/void_result_response.rb +4 -5
  100. data/lib/cassandra/protocol/responses/write_failure_error_response.rb +26 -4
  101. data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +22 -3
  102. data/lib/cassandra/protocol/v1.rb +98 -37
  103. data/lib/cassandra/protocol/v3.rb +121 -50
  104. data/lib/cassandra/protocol/v4.rb +172 -68
  105. data/lib/cassandra/reconnection.rb +1 -1
  106. data/lib/cassandra/reconnection/policies.rb +1 -1
  107. data/lib/cassandra/reconnection/policies/constant.rb +2 -4
  108. data/lib/cassandra/reconnection/policies/exponential.rb +6 -6
  109. data/lib/cassandra/result.rb +55 -20
  110. data/lib/cassandra/retry.rb +8 -8
  111. data/lib/cassandra/retry/policies.rb +1 -1
  112. data/lib/cassandra/retry/policies/default.rb +1 -1
  113. data/lib/cassandra/retry/policies/downgrading_consistency.rb +4 -2
  114. data/lib/cassandra/retry/policies/fallthrough.rb +1 -1
  115. data/lib/cassandra/session.rb +24 -16
  116. data/lib/cassandra/statement.rb +1 -1
  117. data/lib/cassandra/statements.rb +1 -1
  118. data/lib/cassandra/statements/batch.rb +16 -10
  119. data/lib/cassandra/statements/bound.rb +10 -3
  120. data/lib/cassandra/statements/prepared.rb +62 -18
  121. data/lib/cassandra/statements/simple.rb +23 -10
  122. data/lib/cassandra/statements/void.rb +1 -1
  123. data/lib/cassandra/table.rb +53 -185
  124. data/lib/cassandra/time.rb +11 -6
  125. data/lib/cassandra/time_uuid.rb +12 -14
  126. data/lib/cassandra/timestamp_generator.rb +37 -0
  127. data/lib/cassandra/timestamp_generator/simple.rb +38 -0
  128. data/lib/cassandra/timestamp_generator/ticking_on_duplicate.rb +58 -0
  129. data/lib/cassandra/tuple.rb +4 -4
  130. data/lib/cassandra/types.rb +109 -71
  131. data/lib/cassandra/udt.rb +66 -50
  132. data/lib/cassandra/util.rb +155 -15
  133. data/lib/cassandra/uuid.rb +20 -21
  134. data/lib/cassandra/uuid/generator.rb +7 -5
  135. data/lib/cassandra/version.rb +2 -2
  136. data/lib/cassandra_murmur3.jar +0 -0
  137. data/lib/datastax/cassandra.rb +1 -1
  138. metadata +27 -16
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -19,6 +19,9 @@
19
19
  module Cassandra
20
20
  module Protocol
21
21
  class VoidResultResponse < ResultResponse
22
+ # @private
23
+ RESULT_TYPES[0x01] = self
24
+
22
25
  def to_s
23
26
  %(RESULT VOID)
24
27
  end
@@ -26,10 +29,6 @@ module Cassandra
26
29
  def void?
27
30
  true
28
31
  end
29
-
30
- private
31
-
32
- RESULT_TYPES[0x01] = self
33
32
  end
34
33
  end
35
34
  end
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -21,7 +21,15 @@ module Cassandra
21
21
  class WriteFailureErrorResponse < ErrorResponse
22
22
  attr_reader :consistency, :received, :blockfor, :numfailures, :write_type
23
23
 
24
- def initialize(custom_payload, warnings, code, message, consistency, received, blockfor, numfailures, write_type)
24
+ def initialize(custom_payload,
25
+ warnings,
26
+ code,
27
+ message,
28
+ consistency,
29
+ received,
30
+ blockfor,
31
+ numfailures,
32
+ write_type)
25
33
  super(custom_payload, warnings, code, message)
26
34
 
27
35
  write_type.downcase!
@@ -34,11 +42,25 @@ module Cassandra
34
42
  end
35
43
 
36
44
  def to_error(keyspace, statement, options, hosts, consistency, retries)
37
- Errors::WriteError.new(@message, @custom_payload, @warnings, keyspace, statement, options, hosts, consistency, retries, @write_type, @consistency, @blockfor, @numfailures, @received)
45
+ Errors::WriteError.new(@message,
46
+ @custom_payload,
47
+ @warnings,
48
+ keyspace,
49
+ statement,
50
+ options,
51
+ hosts,
52
+ consistency,
53
+ retries,
54
+ @write_type,
55
+ @consistency,
56
+ @blockfor,
57
+ @numfailures,
58
+ @received)
38
59
  end
39
60
 
40
61
  def to_s
41
- "#{super} #{@write_type} #{@consistency} #{@blockfor} #{@numfailures} #{@received}"
62
+ "#{super} #{@write_type} #{@consistency} #{@blockfor} " \
63
+ "#{@numfailures} #{@received}"
42
64
  end
43
65
  end
44
66
  end
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -21,7 +21,14 @@ module Cassandra
21
21
  class WriteTimeoutErrorResponse < ErrorResponse
22
22
  attr_reader :consistency, :received, :blockfor, :write_type
23
23
 
24
- def initialize(custom_payload, warnings, code, message, consistency, received, blockfor, write_type)
24
+ def initialize(custom_payload,
25
+ warnings,
26
+ code,
27
+ message,
28
+ consistency,
29
+ received,
30
+ blockfor,
31
+ write_type)
25
32
  super(custom_payload, warnings, code, message)
26
33
 
27
34
  write_type.downcase!
@@ -33,7 +40,19 @@ module Cassandra
33
40
  end
34
41
 
35
42
  def to_error(keyspace, statement, options, hosts, consistency, retries)
36
- Errors::WriteTimeoutError.new(@message, @custom_payload, @warnings, keyspace, statement, options, hosts, consistency, retries, @write_type, @consistency, @blockfor, @received)
43
+ Errors::WriteTimeoutError.new(@message,
44
+ @custom_payload,
45
+ @warnings,
46
+ keyspace,
47
+ statement,
48
+ options,
49
+ hosts,
50
+ consistency,
51
+ retries,
52
+ @write_type,
53
+ @consistency,
54
+ @blockfor,
55
+ @received)
37
56
  end
38
57
 
39
58
  def to_s
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ module Cassandra
37
37
  body = @compressor.compress(body)
38
38
  end
39
39
 
40
- header = [@protocol_version, flags, stream_id, request.opcode, body.bytesize]
40
+ header = [@protocol_version, flags, stream_id, request.opcode, body.bytesize]
41
41
  buffer << header.pack(HEADER_FORMAT)
42
42
  buffer << body
43
43
  buffer
@@ -131,7 +131,8 @@ module Cassandra
131
131
  buffer = CqlByteBuffer.new(@compressor.decompress(buffer.read(size)))
132
132
  size = buffer.size
133
133
  else
134
- raise Errors::DecodingError, 'Compressed frame received, but no compressor configured'
134
+ raise Errors::DecodingError,
135
+ 'Compressed frame received, but no compressor configured'
135
136
  end
136
137
  end
137
138
 
@@ -145,9 +146,7 @@ module Cassandra
145
146
  extra_length = buffer.length - size
146
147
  response = decode_response(opcode, protocol_version, buffer, size, trace_id)
147
148
 
148
- if buffer.length > extra_length
149
- buffer.discard(buffer.length - extra_length)
150
- end
149
+ buffer.discard(buffer.length - extra_length) if buffer.length > extra_length
151
150
 
152
151
  if stream_id == -1
153
152
  @handler.notify_event_listeners(response)
@@ -156,8 +155,6 @@ module Cassandra
156
155
  end
157
156
  end
158
157
 
159
- private
160
-
161
158
  CODE_ERROR = 0x00
162
159
  CODE_READY = 0x02
163
160
  CODE_AUTHENTICATE = 0x03
@@ -168,22 +165,61 @@ module Cassandra
168
165
  CODE_AUTH_SUCCESS = 0x10
169
166
 
170
167
  def decode_response(opcode, protocol_version, buffer, size, trace_id)
171
- response = case opcode
172
- when CODE_READY then READY
173
- when CODE_AUTHENTICATE then AuthenticateResponse.new(buffer.read_string)
174
- when CODE_AUTH_CHALLENGE then AuthChallengeResponse.new(buffer.read_bytes)
175
- when CODE_AUTH_SUCCESS then AuthSuccessResponse.new(buffer.read_bytes)
176
- when CODE_SUPPORTED then SupportedResponse.new(buffer.read_string_multimap)
168
+ case opcode
169
+ when CODE_READY then
170
+ READY
171
+ when CODE_AUTHENTICATE then
172
+ AuthenticateResponse.new(buffer.read_string)
173
+ when CODE_AUTH_CHALLENGE then
174
+ AuthChallengeResponse.new(buffer.read_bytes)
175
+ when CODE_AUTH_SUCCESS then
176
+ AuthSuccessResponse.new(buffer.read_bytes)
177
+ when CODE_SUPPORTED then
178
+ SupportedResponse.new(buffer.read_string_multimap)
177
179
  when CODE_ERROR
178
- code = buffer.read_int
180
+ code = buffer.read_int
179
181
  message = buffer.read_string
180
182
 
181
183
  case code
182
- when 0x1000 then UnavailableErrorResponse.new(nil, nil, code, message, buffer.read_consistency, buffer.read_int, buffer.read_int)
183
- when 0x1100 then WriteTimeoutErrorResponse.new(nil, nil, code, message, buffer.read_consistency, buffer.read_int, buffer.read_int, buffer.read_string)
184
- when 0x1200 then ReadTimeoutErrorResponse.new(nil, nil, code, message, buffer.read_consistency, buffer.read_int, buffer.read_int, (buffer.read_byte != 0))
185
- when 0x2400 then AlreadyExistsErrorResponse.new(nil, nil, code, message, buffer.read_string, buffer.read_string)
186
- when 0x2500 then UnpreparedErrorResponse.new(nil, nil, code, message, buffer.read_short_bytes)
184
+ when 0x1000 then
185
+ UnavailableErrorResponse.new(nil,
186
+ nil,
187
+ code,
188
+ message,
189
+ buffer.read_consistency,
190
+ buffer.read_int,
191
+ buffer.read_int)
192
+ when 0x1100 then
193
+ WriteTimeoutErrorResponse.new(nil,
194
+ nil,
195
+ code,
196
+ message,
197
+ buffer.read_consistency,
198
+ buffer.read_int,
199
+ buffer.read_int,
200
+ buffer.read_string)
201
+ when 0x1200 then
202
+ ReadTimeoutErrorResponse.new(nil,
203
+ nil,
204
+ code,
205
+ message,
206
+ buffer.read_consistency,
207
+ buffer.read_int,
208
+ buffer.read_int,
209
+ (buffer.read_byte != 0))
210
+ when 0x2400 then
211
+ AlreadyExistsErrorResponse.new(nil,
212
+ nil,
213
+ code,
214
+ message,
215
+ buffer.read_string,
216
+ buffer.read_string)
217
+ when 0x2500 then
218
+ UnpreparedErrorResponse.new(nil,
219
+ nil,
220
+ code,
221
+ message,
222
+ buffer.read_short_bytes)
187
223
  else
188
224
  ErrorResponse.new(nil, nil, code, message)
189
225
  end
@@ -197,50 +233,75 @@ module Cassandra
197
233
  column_specs, paging_state = Coder.read_metadata_v1(buffer)
198
234
 
199
235
  if column_specs.nil?
200
- consumed_bytes = original_buffer_length - buffer.length
201
- remaining_bytes = CqlByteBuffer.new(buffer.read(size - consumed_bytes - 4))
202
- RawRowsResultResponse.new(nil, nil, protocol_version, remaining_bytes, paging_state, trace_id)
236
+ consumed_bytes = original_buffer_length - buffer.length
237
+ remaining_bytes =
238
+ CqlByteBuffer.new(buffer.read(size - consumed_bytes - 4))
239
+ RawRowsResultResponse.new(nil,
240
+ nil,
241
+ protocol_version,
242
+ remaining_bytes,
243
+ paging_state,
244
+ trace_id)
203
245
  else
204
- RowsResultResponse.new(nil, nil, Coder.read_values_v1(buffer, column_specs), column_specs, paging_state, trace_id)
246
+ RowsResultResponse.new(nil,
247
+ nil,
248
+ Coder.read_values_v1(buffer, column_specs),
249
+ column_specs,
250
+ paging_state,
251
+ trace_id)
205
252
  end
206
253
  when 0x0003 # SetKeyspace
207
254
  SetKeyspaceResultResponse.new(nil, nil, buffer.read_string, trace_id)
208
255
  when 0x0004 # Prepared
209
- id = buffer.read_short_bytes
256
+ id = buffer.read_short_bytes
210
257
  params_metadata = Coder.read_metadata_v1(buffer).first
211
258
  result_metadata = nil
212
259
  result_metadata = Coder.read_metadata_v1(buffer).first if protocol_version > 1
213
260
 
214
- PreparedResultResponse.new(nil, nil, id, params_metadata, result_metadata, nil, trace_id)
261
+ PreparedResultResponse.new(nil,
262
+ nil,
263
+ id,
264
+ params_metadata,
265
+ result_metadata,
266
+ nil,
267
+ trace_id)
215
268
  when 0x0005 # SchemaChange
216
- change = buffer.read_string
217
- keyspace = buffer.read_string
218
- name = buffer.read_string
269
+ change = buffer.read_string
270
+ keyspace = buffer.read_string
271
+ name = buffer.read_string
219
272
  arguments = EMPTY_LIST
220
- target = nil
273
+ target = nil
221
274
 
222
275
  if name.empty?
223
- name = nil
276
+ name = nil
224
277
  target = Constants::SCHEMA_CHANGE_TARGET_KEYSPACE
225
278
  else
226
279
  target = Constants::SCHEMA_CHANGE_TARGET_TABLE
227
280
  end
228
281
 
229
- SchemaChangeResultResponse.new(nil, nil, change, keyspace, name, target, arguments, nil)
282
+ SchemaChangeResultResponse.new(nil,
283
+ nil,
284
+ change,
285
+ keyspace,
286
+ name,
287
+ target,
288
+ arguments,
289
+ nil)
230
290
  else
231
- raise Errors::DecodingError, "Unsupported result type: #{result_type.inspect}"
291
+ raise Errors::DecodingError,
292
+ "Unsupported result type: #{result_type.inspect}"
232
293
  end
233
294
  when CODE_EVENT
234
295
  event_type = buffer.read_string
235
296
  case event_type
236
297
  when 'SCHEMA_CHANGE'
237
- change = buffer.read_string
238
- keyspace = buffer.read_string
239
- name = buffer.read_string
298
+ change = buffer.read_string
299
+ keyspace = buffer.read_string
300
+ name = buffer.read_string
240
301
  arguments = EMPTY_LIST
241
302
 
242
303
  if name.empty?
243
- name = nil
304
+ name = nil
244
305
  target = Constants::SCHEMA_CHANGE_TARGET_KEYSPACE
245
306
  else
246
307
  target = Constants::SCHEMA_CHANGE_TARGET_TABLE
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # Copyright 2013-2015 DataStax, Inc.
4
+ # Copyright 2013-2016 DataStax, Inc.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ module Cassandra
37
37
  body = @compressor.compress(body)
38
38
  end
39
39
 
40
- header = [@protocol_version, flags, stream_id, request.opcode, body.bytesize]
40
+ header = [@protocol_version, flags, stream_id, request.opcode, body.bytesize]
41
41
  buffer << header.pack(HEADER_FORMAT)
42
42
  buffer << body
43
43
 
@@ -81,7 +81,9 @@ module Cassandra
81
81
  stream_id = (frame_header >> 8) & 0xff
82
82
  stream_id = (stream_id & 0x7f) - (stream_id & 0x80)
83
83
 
84
- @handler.complete_request(stream_id, ErrorResponse.new(nil, nil, 0x000A, "Invalid or unsupported protocol version"))
84
+ error_response = ErrorResponse.new(nil, nil, 0x000A,
85
+ 'Invalid or unsupported protocol version')
86
+ @handler.complete_request(stream_id, error_response)
85
87
 
86
88
  return
87
89
  end
@@ -150,7 +152,7 @@ module Cassandra
150
152
  nil
151
153
  end
152
154
 
153
- def actual_decode(buffer, fields, size, code)
155
+ def actual_decode(buffer, fields, frame_length, code)
154
156
  protocol_version = (fields >> 24) & 0x7f
155
157
  compression = (fields >> 16) & 0x01
156
158
  tracing = (fields >> 16) & 0x02
@@ -158,28 +160,40 @@ module Cassandra
158
160
  stream_id = (stream_id & 0x7fff) - (stream_id & 0x8000)
159
161
  opcode = code & 0xff
160
162
 
163
+ # If we're dealing with a compressed body, read the whole body, decompress,
164
+ # and treat the uncompressed body as if that's what we got in the first place.
165
+ # This means we must reset frame_length to that uncompressed size.
161
166
  if compression == 1
162
167
  if @compressor
163
- buffer = CqlByteBuffer.new(@compressor.decompress(buffer.read(size)))
164
- size = buffer.size
168
+ buffer = CqlByteBuffer.new(
169
+ @compressor.decompress(buffer.read(frame_length)))
170
+ frame_length = buffer.size
165
171
  else
166
- raise Errors::DecodingError, 'Compressed frame received, but no compressor configured'
172
+ raise Errors::DecodingError,
173
+ 'Compressed frame received, but no compressor configured'
167
174
  end
168
175
  end
169
176
 
170
- if tracing == 2
171
- trace_id = buffer.read_uuid
172
- size -= 16
173
- else
174
- trace_id = nil
175
- end
177
+ # We want to read one full frame; but after we read/parse chunks of the body
178
+ # there may be more cruft left in the frame that we don't care about. So,
179
+ # we save off the current size of the buffer, do all our reads for the
180
+ # frame, get the final remaining size, and based on that discard possible
181
+ # remaining bytes in the frame. In particular, we account for the possibility
182
+ # that the buffer contains some/all of a subsequent frame as well, and we
183
+ # don't want to mess with that.
176
184
 
177
- extra_length = buffer.length - size
178
- response = decode_response(opcode, protocol_version, buffer, size, trace_id)
185
+ buffer_starting_length = buffer.length
179
186
 
180
- if buffer.length > extra_length
181
- buffer.discard(buffer.length - extra_length)
182
- end
187
+ trace_id = (buffer.read_uuid if tracing == 2)
188
+
189
+ remaining_frame_length = frame_length -
190
+ (buffer_starting_length - buffer.length)
191
+ response = decode_response(opcode, protocol_version, buffer,
192
+ remaining_frame_length, trace_id)
193
+
194
+ # Calculate and discard remaining cruft in the frame.
195
+ extra_length = frame_length - (buffer_starting_length - buffer.length)
196
+ buffer.discard(extra_length) if extra_length > 0
183
197
 
184
198
  if stream_id == -1
185
199
  @handler.notify_event_listeners(response)
@@ -191,15 +205,49 @@ module Cassandra
191
205
  def decode_response(opcode, protocol_version, buffer, size, trace_id)
192
206
  case opcode
193
207
  when 0x00 # ERROR
194
- code = buffer.read_int
208
+ code = buffer.read_int
195
209
  message = buffer.read_string
196
210
 
197
211
  case code
198
- when 0x1000 then UnavailableErrorResponse.new(nil, nil, code, message, buffer.read_consistency, buffer.read_int, buffer.read_int)
199
- when 0x1100 then WriteTimeoutErrorResponse.new(nil, nil, code, message, buffer.read_consistency, buffer.read_int, buffer.read_int, buffer.read_string)
200
- when 0x1200 then ReadTimeoutErrorResponse.new(nil, nil, code, message, buffer.read_consistency, buffer.read_int, buffer.read_int, (buffer.read_byte != 0))
201
- when 0x2400 then AlreadyExistsErrorResponse.new(nil, nil, code, message, buffer.read_string, buffer.read_string)
202
- when 0x2500 then UnpreparedErrorResponse.new(nil, nil, code, message, buffer.read_short_bytes)
212
+ when 0x1000
213
+ UnavailableErrorResponse.new(nil,
214
+ nil,
215
+ code,
216
+ message,
217
+ buffer.read_consistency,
218
+ buffer.read_int,
219
+ buffer.read_int)
220
+ when 0x1100
221
+ WriteTimeoutErrorResponse.new(nil,
222
+ nil,
223
+ code,
224
+ message,
225
+ buffer.read_consistency,
226
+ buffer.read_int,
227
+ buffer.read_int,
228
+ buffer.read_string)
229
+ when 0x1200
230
+ ReadTimeoutErrorResponse.new(nil,
231
+ nil,
232
+ code,
233
+ message,
234
+ buffer.read_consistency,
235
+ buffer.read_int,
236
+ buffer.read_int,
237
+ (buffer.read_byte != 0))
238
+ when 0x2400
239
+ AlreadyExistsErrorResponse.new(nil,
240
+ nil,
241
+ code,
242
+ message,
243
+ buffer.read_string,
244
+ buffer.read_string)
245
+ when 0x2500
246
+ UnpreparedErrorResponse.new(nil,
247
+ nil,
248
+ code,
249
+ message,
250
+ buffer.read_short_bytes)
203
251
  else
204
252
  ErrorResponse.new(nil, nil, code, message)
205
253
  end
@@ -219,49 +267,70 @@ module Cassandra
219
267
  column_specs, paging_state = Coder.read_metadata_v3(buffer)
220
268
 
221
269
  if column_specs.nil?
222
- consumed_bytes = original_buffer_length - buffer.length
223
- remaining_bytes = CqlByteBuffer.new(buffer.read(size - consumed_bytes - 4))
224
- RawRowsResultResponse.new(nil, nil, protocol_version, remaining_bytes, paging_state, trace_id)
270
+ consumed_bytes = original_buffer_length - buffer.length
271
+ remaining_bytes =
272
+ CqlByteBuffer.new(buffer.read(size - consumed_bytes - 4))
273
+ RawRowsResultResponse.new(nil,
274
+ nil,
275
+ protocol_version,
276
+ remaining_bytes,
277
+ paging_state,
278
+ trace_id)
225
279
  else
226
- RowsResultResponse.new(nil, nil, Coder.read_values_v3(buffer, column_specs), column_specs, paging_state, trace_id)
280
+ RowsResultResponse.new(nil,
281
+ nil,
282
+ Coder.read_values_v3(buffer, column_specs),
283
+ column_specs,
284
+ paging_state,
285
+ trace_id)
227
286
  end
228
287
  when 0x0003 # SetKeyspace
229
288
  SetKeyspaceResultResponse.new(nil, nil, buffer.read_string, trace_id)
230
289
  when 0x0004 # Prepared
231
- id = buffer.read_short_bytes
290
+ id = buffer.read_short_bytes
232
291
  params_metadata = Coder.read_metadata_v3(buffer).first
233
292
  result_metadata = nil
234
293
  result_metadata = Coder.read_metadata_v3(buffer).first if protocol_version > 1
235
294
 
236
- PreparedResultResponse.new(nil, nil, id, params_metadata, result_metadata, nil, trace_id)
295
+ PreparedResultResponse.new(nil,
296
+ nil,
297
+ id,
298
+ params_metadata,
299
+ result_metadata,
300
+ nil,
301
+ trace_id)
237
302
  when 0x0005 # SchemaChange
238
- change = buffer.read_string
239
- target = buffer.read_string
240
- keyspace = buffer.read_string
303
+ change = buffer.read_string
304
+ target = buffer.read_string
305
+ keyspace = buffer.read_string
241
306
  arguments = EMPTY_LIST
242
- name = nil
243
-
244
- if target == Constants::SCHEMA_CHANGE_TARGET_TABLE
245
- name = buffer.read_string
246
- end
247
-
248
- SchemaChangeResultResponse.new(nil, nil, change, keyspace, name, target, arguments, nil)
307
+ name = nil
308
+
309
+ name = buffer.read_string if target == Constants::SCHEMA_CHANGE_TARGET_TABLE
310
+
311
+ SchemaChangeResultResponse.new(nil,
312
+ nil,
313
+ change,
314
+ keyspace,
315
+ name,
316
+ target,
317
+ arguments,
318
+ nil)
249
319
  else
250
- raise Errors::DecodingError, "Unsupported result type: #{result_type.inspect}"
320
+ raise Errors::DecodingError,
321
+ "Unsupported result type: #{result_type.inspect}"
251
322
  end
252
323
  when 0x0C # EVENT
253
324
  event_type = buffer.read_string
254
325
  case event_type
255
326
  when 'SCHEMA_CHANGE'
256
- change = buffer.read_string
257
- target = buffer.read_string
258
- keyspace = buffer.read_string
259
- name = nil
327
+ change = buffer.read_string
328
+ target = buffer.read_string
329
+ keyspace = buffer.read_string
330
+ name = nil
260
331
  arguments = EMPTY_LIST
261
332
 
262
- if target == Constants::SCHEMA_CHANGE_TARGET_TABLE
263
- name = buffer.read_string
264
- end
333
+ name = buffer.read_string if target == Constants::SCHEMA_CHANGE_TARGET_TABLE
265
334
 
266
335
  SchemaChangeEventResponse.new(change, keyspace, name, target, arguments)
267
336
  when 'STATUS_CHANGE'
@@ -269,14 +338,16 @@ module Cassandra
269
338
  when 'TOPOLOGY_CHANGE'
270
339
  TopologyChangeEventResponse.new(buffer.read_string, *buffer.read_inet)
271
340
  else
272
- raise Errors::DecodingError, "Unsupported event type: #{event_type.inspect}"
341
+ raise Errors::DecodingError,
342
+ "Unsupported event type: #{event_type.inspect}"
273
343
  end
274
344
  when 0x0E # AUTH_CHALLENGE
275
345
  AuthChallengeResponse.new(buffer.read_bytes)
276
346
  when 0x10 # AUTH_SUCCESS
277
347
  AuthSuccessResponse.new(buffer.read_bytes)
278
348
  else
279
- raise Errors::DecodingError, "Unsupported response opcode: #{opcode.inspect}"
349
+ raise Errors::DecodingError,
350
+ "Unsupported response opcode: #{opcode.inspect}"
280
351
  end
281
352
  end
282
353
  end