yugabyte-ycql-driver 3.2.3.1

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