cassandra-driver 1.0.0.beta.3 → 1.0.0.rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +13 -5
- data/README.md +8 -6
- data/lib/cassandra.rb +99 -13
- data/lib/cassandra/address_resolution.rb +36 -0
- data/lib/cassandra/address_resolution/policies.rb +2 -0
- data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +56 -0
- data/lib/cassandra/address_resolution/policies/none.rb +35 -0
- data/lib/cassandra/auth.rb +1 -1
- data/lib/cassandra/auth/providers/password.rb +1 -1
- data/lib/cassandra/client.rb +2 -2
- data/lib/cassandra/client/batch.rb +3 -3
- data/lib/cassandra/client/client.rb +12 -12
- data/lib/cassandra/client/connection_manager.rb +2 -2
- data/lib/cassandra/client/connector.rb +6 -10
- data/lib/cassandra/client/prepared_statement.rb +4 -4
- data/lib/cassandra/client/request_runner.rb +1 -2
- data/lib/cassandra/cluster.rb +15 -5
- data/lib/cassandra/cluster/client.rb +158 -96
- data/lib/cassandra/cluster/connector.rb +42 -27
- data/lib/cassandra/cluster/control_connection.rb +384 -132
- data/lib/cassandra/cluster/options.rb +5 -2
- data/lib/cassandra/cluster/registry.rb +19 -9
- data/lib/cassandra/compression.rb +1 -1
- data/lib/cassandra/compression/compressors/lz4.rb +1 -1
- data/lib/cassandra/compression/compressors/snappy.rb +1 -1
- data/lib/cassandra/driver.rb +28 -20
- data/lib/cassandra/errors.rb +325 -35
- data/lib/cassandra/future.rb +3 -3
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +7 -3
- data/lib/cassandra/load_balancing/policies/token_aware.rb +1 -1
- data/lib/cassandra/protocol.rb +0 -16
- data/lib/cassandra/protocol/cql_byte_buffer.rb +18 -18
- data/lib/cassandra/protocol/cql_protocol_handler.rb +74 -8
- data/lib/cassandra/protocol/frame_decoder.rb +2 -2
- data/lib/cassandra/protocol/frame_encoder.rb +1 -1
- data/lib/cassandra/protocol/response.rb +1 -1
- data/lib/cassandra/protocol/responses/detailed_error_response.rb +16 -1
- data/lib/cassandra/protocol/responses/error_response.rb +17 -0
- data/lib/cassandra/protocol/responses/event_response.rb +1 -1
- data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +1 -1
- data/lib/cassandra/protocol/responses/result_response.rb +1 -1
- data/lib/cassandra/protocol/responses/rows_result_response.rb +1 -1
- data/lib/cassandra/protocol/type_converter.rb +4 -3
- data/lib/cassandra/reconnection.rb +1 -1
- data/lib/cassandra/retry.rb +3 -5
- data/lib/cassandra/session.rb +11 -5
- data/lib/cassandra/table.rb +1 -1
- data/lib/cassandra/time_uuid.rb +21 -83
- data/lib/cassandra/util.rb +1 -1
- data/lib/cassandra/uuid.rb +6 -4
- data/lib/cassandra/uuid/generator.rb +207 -0
- data/lib/cassandra/version.rb +1 -1
- metadata +24 -19
data/lib/cassandra/future.rb
CHANGED
@@ -188,7 +188,7 @@ module Cassandra
|
|
188
188
|
monitor = Monitor.new
|
189
189
|
promise = Promise.new
|
190
190
|
remaining = futures.length
|
191
|
-
values = Array.new(
|
191
|
+
values = Array.new(remaining)
|
192
192
|
|
193
193
|
futures.each_with_index do |future, i|
|
194
194
|
future.on_complete do |v, e|
|
@@ -390,11 +390,11 @@ module Cassandra
|
|
390
390
|
end
|
391
391
|
|
392
392
|
def success(value)
|
393
|
-
@block.call(
|
393
|
+
@block.call(value, nil)
|
394
394
|
end
|
395
395
|
|
396
396
|
def failure(error)
|
397
|
-
@block.call(
|
397
|
+
@block.call(nil, error)
|
398
398
|
end
|
399
399
|
end
|
400
400
|
|
@@ -56,11 +56,11 @@ module Cassandra
|
|
56
56
|
|
57
57
|
include MonitorMixin
|
58
58
|
|
59
|
-
def initialize(datacenter, max_remote_hosts_to_use = nil, use_remote_hosts_for_local_consistency = false)
|
60
|
-
datacenter = String(datacenter)
|
59
|
+
def initialize(datacenter = nil, max_remote_hosts_to_use = nil, use_remote_hosts_for_local_consistency = false)
|
60
|
+
datacenter = datacenter && String(datacenter)
|
61
61
|
max_remote_hosts_to_use = max_remote_hosts_to_use && Integer(max_remote_hosts_to_use)
|
62
62
|
|
63
|
-
raise ::ArgumentError, "datacenter cannot be
|
63
|
+
raise ::ArgumentError, "datacenter cannot be empty" if datacenter && datacenter.empty?
|
64
64
|
raise ::ArgumentError, "max_remote_hosts_to_use must be nil or >= 0" if max_remote_hosts_to_use && max_remote_hosts_to_use < 0
|
65
65
|
|
66
66
|
@datacenter = datacenter
|
@@ -75,6 +75,10 @@ module Cassandra
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def host_up(host)
|
78
|
+
if !@datacenter && host.datacenter
|
79
|
+
@datacenter = host.datacenter
|
80
|
+
end
|
81
|
+
|
78
82
|
if host.datacenter.nil? || host.datacenter == @datacenter
|
79
83
|
synchronize { @local = @local.dup.push(host) }
|
80
84
|
else
|
@@ -111,7 +111,7 @@ module Cassandra
|
|
111
111
|
replicas = @cluster.find_replicas(keyspace, statement)
|
112
112
|
return @policy.plan(keyspace, statement, options) if replicas.empty?
|
113
113
|
|
114
|
-
Plan.new(replicas.
|
114
|
+
Plan.new(replicas.shuffle, @policy, keyspace, statement, options)
|
115
115
|
end
|
116
116
|
end
|
117
117
|
end
|
data/lib/cassandra/protocol.rb
CHANGED
@@ -17,24 +17,8 @@
|
|
17
17
|
#++
|
18
18
|
|
19
19
|
module Cassandra
|
20
|
-
# @private
|
21
|
-
ProtocolError = Class.new(Error)
|
22
|
-
|
23
20
|
# @private
|
24
21
|
module Protocol
|
25
|
-
DecodingError = Class.new(ProtocolError)
|
26
|
-
EncodingError = Class.new(ProtocolError)
|
27
|
-
InvalidStreamIdError = Class.new(ProtocolError)
|
28
|
-
InvalidValueError = Class.new(ProtocolError)
|
29
|
-
UnsupportedOperationError = Class.new(ProtocolError)
|
30
|
-
UnsupportedFrameTypeError = Class.new(ProtocolError)
|
31
|
-
UnsupportedResultKindError = Class.new(ProtocolError)
|
32
|
-
UnsupportedColumnTypeError = Class.new(ProtocolError)
|
33
|
-
UnsupportedEventTypeError = Class.new(ProtocolError)
|
34
|
-
UnsupportedFeatureError = Class.new(ProtocolError)
|
35
|
-
UnexpectedCompressionError = Class.new(ProtocolError)
|
36
|
-
UnmaterializedRowsError = Class.new(ProtocolError)
|
37
|
-
|
38
22
|
module Formats
|
39
23
|
CHAR_FORMAT = 'c'.freeze
|
40
24
|
DOUBLE_FORMAT = 'G'.freeze
|
@@ -22,7 +22,7 @@ module Cassandra
|
|
22
22
|
def read_unsigned_byte
|
23
23
|
read_byte
|
24
24
|
rescue RangeError => e
|
25
|
-
raise DecodingError, e.message, e.backtrace
|
25
|
+
raise Errors::DecodingError, e.message, e.backtrace
|
26
26
|
end
|
27
27
|
|
28
28
|
def read_varint(len=bytesize, signed=true)
|
@@ -36,7 +36,7 @@ module Cassandra
|
|
36
36
|
end
|
37
37
|
n
|
38
38
|
rescue RangeError => e
|
39
|
-
raise DecodingError, e.message, e.backtrace
|
39
|
+
raise Errors::DecodingError, e.message, e.backtrace
|
40
40
|
end
|
41
41
|
|
42
42
|
def read_decimal(len=bytesize)
|
@@ -57,8 +57,8 @@ module Cassandra
|
|
57
57
|
fraction_string << number_string[number_string.length - size, number_string.length]
|
58
58
|
end
|
59
59
|
BigDecimal.new(fraction_string)
|
60
|
-
rescue DecodingError => e
|
61
|
-
raise DecodingError, e.message, e.backtrace
|
60
|
+
rescue Errors::DecodingError => e
|
61
|
+
raise Errors::DecodingError, e.message, e.backtrace
|
62
62
|
end
|
63
63
|
|
64
64
|
def read_long
|
@@ -68,19 +68,19 @@ module Cassandra
|
|
68
68
|
bottom ^= 0xffffffff
|
69
69
|
-((top << 32) | bottom) - 1
|
70
70
|
rescue RangeError => e
|
71
|
-
raise DecodingError, e.message, e.backtrace
|
71
|
+
raise Errors::DecodingError, e.message, e.backtrace
|
72
72
|
end
|
73
73
|
|
74
74
|
def read_double
|
75
75
|
read(8).unpack(Formats::DOUBLE_FORMAT).first
|
76
76
|
rescue RangeError => e
|
77
|
-
raise DecodingError, "Not enough bytes available to decode a double: #{e.message}", e.backtrace
|
77
|
+
raise Errors::DecodingError, "Not enough bytes available to decode a double: #{e.message}", e.backtrace
|
78
78
|
end
|
79
79
|
|
80
80
|
def read_float
|
81
81
|
read(4).unpack(Formats::FLOAT_FORMAT).first
|
82
82
|
rescue RangeError => e
|
83
|
-
raise DecodingError, "Not enough bytes available to decode a float: #{e.message}", e.backtrace
|
83
|
+
raise Errors::DecodingError, "Not enough bytes available to decode a float: #{e.message}", e.backtrace
|
84
84
|
end
|
85
85
|
|
86
86
|
def read_signed_int
|
@@ -88,13 +88,13 @@ module Cassandra
|
|
88
88
|
return n if n <= 0x7fffffff
|
89
89
|
n - 0xffffffff - 1
|
90
90
|
rescue RangeError => e
|
91
|
-
raise DecodingError, "Not enough bytes available to decode an int: #{e.message}", e.backtrace
|
91
|
+
raise Errors::DecodingError, "Not enough bytes available to decode an int: #{e.message}", e.backtrace
|
92
92
|
end
|
93
93
|
|
94
94
|
def read_unsigned_short
|
95
95
|
read_short
|
96
96
|
rescue RangeError => e
|
97
|
-
raise DecodingError, "Not enough bytes available to decode a short: #{e.message}", e.backtrace
|
97
|
+
raise Errors::DecodingError, "Not enough bytes available to decode a short: #{e.message}", e.backtrace
|
98
98
|
end
|
99
99
|
|
100
100
|
def read_string
|
@@ -103,7 +103,7 @@ module Cassandra
|
|
103
103
|
string.force_encoding(::Encoding::UTF_8)
|
104
104
|
string
|
105
105
|
rescue RangeError => e
|
106
|
-
raise DecodingError, "Not enough bytes available to decode a string: #{e.message}", e.backtrace
|
106
|
+
raise Errors::DecodingError, "Not enough bytes available to decode a string: #{e.message}", e.backtrace
|
107
107
|
end
|
108
108
|
|
109
109
|
def read_long_string
|
@@ -112,13 +112,13 @@ module Cassandra
|
|
112
112
|
string.force_encoding(::Encoding::UTF_8)
|
113
113
|
string
|
114
114
|
rescue RangeError => e
|
115
|
-
raise DecodingError, "Not enough bytes available to decode a long string: #{e.message}", e.backtrace
|
115
|
+
raise Errors::DecodingError, "Not enough bytes available to decode a long string: #{e.message}", e.backtrace
|
116
116
|
end
|
117
117
|
|
118
118
|
def read_uuid(impl=Uuid)
|
119
119
|
impl.new(read_varint(16, false))
|
120
|
-
rescue DecodingError => e
|
121
|
-
raise DecodingError, "Not enough bytes available to decode a UUID: #{e.message}", e.backtrace
|
120
|
+
rescue Errors::DecodingError => e
|
121
|
+
raise Errors::DecodingError, "Not enough bytes available to decode a UUID: #{e.message}", e.backtrace
|
122
122
|
end
|
123
123
|
|
124
124
|
def read_string_list
|
@@ -131,7 +131,7 @@ module Cassandra
|
|
131
131
|
return nil if size & 0x80000000 == 0x80000000
|
132
132
|
read(size)
|
133
133
|
rescue RangeError => e
|
134
|
-
raise DecodingError, "Not enough bytes available to decode a bytes: #{e.message}", e.backtrace
|
134
|
+
raise Errors::DecodingError, "Not enough bytes available to decode a bytes: #{e.message}", e.backtrace
|
135
135
|
end
|
136
136
|
|
137
137
|
def read_short_bytes
|
@@ -139,7 +139,7 @@ module Cassandra
|
|
139
139
|
return nil if size & 0x8000 == 0x8000
|
140
140
|
read(size)
|
141
141
|
rescue RangeError => e
|
142
|
-
raise DecodingError, "Not enough bytes available to decode a short bytes: #{e.message}", e.backtrace
|
142
|
+
raise Errors::DecodingError, "Not enough bytes available to decode a short bytes: #{e.message}", e.backtrace
|
143
143
|
end
|
144
144
|
|
145
145
|
def read_option
|
@@ -157,12 +157,12 @@ module Cassandra
|
|
157
157
|
port = read_int
|
158
158
|
[ip_addr, port]
|
159
159
|
rescue RangeError => e
|
160
|
-
raise DecodingError, "Not enough bytes available to decode an INET: #{e.message}", e.backtrace
|
160
|
+
raise Errors::DecodingError, "Not enough bytes available to decode an INET: #{e.message}", e.backtrace
|
161
161
|
end
|
162
162
|
|
163
163
|
def read_consistency
|
164
164
|
index = read_unsigned_short
|
165
|
-
raise DecodingError, "Unknown consistency index #{index}" if index >= CONSISTENCIES.size || CONSISTENCIES[index].nil?
|
165
|
+
raise Errors::DecodingError, "Unknown consistency index #{index}" if index >= CONSISTENCIES.size || CONSISTENCIES[index].nil?
|
166
166
|
CONSISTENCIES[index]
|
167
167
|
end
|
168
168
|
|
@@ -241,7 +241,7 @@ module Cassandra
|
|
241
241
|
|
242
242
|
def append_consistency(consistency)
|
243
243
|
index = CONSISTENCIES.index(consistency)
|
244
|
-
raise EncodingError, %(Unknown consistency "#{consistency}") if index.nil? || CONSISTENCIES[index].nil?
|
244
|
+
raise Errors::EncodingError, %(Unknown consistency "#{consistency}") if index.nil? || CONSISTENCIES[index].nil?
|
245
245
|
append_short(index)
|
246
246
|
end
|
247
247
|
|
@@ -35,7 +35,7 @@ module Cassandra
|
|
35
35
|
# @return [String] the current keyspace for the underlying connection
|
36
36
|
attr_reader :keyspace
|
37
37
|
|
38
|
-
def initialize(connection, scheduler, protocol_version, compressor=nil)
|
38
|
+
def initialize(connection, scheduler, protocol_version, compressor=nil, heartbeat_interval = 30, idle_timeout = 60)
|
39
39
|
@connection = connection
|
40
40
|
@scheduler = scheduler
|
41
41
|
@compressor = compressor
|
@@ -53,6 +53,10 @@ module Cassandra
|
|
53
53
|
@lock = Mutex.new
|
54
54
|
@closed_promise = Ione::Promise.new
|
55
55
|
@keyspace = nil
|
56
|
+
@heartbeat = nil
|
57
|
+
@terminate = nil
|
58
|
+
@heartbeat_interval = heartbeat_interval
|
59
|
+
@idle_timeout = idle_timeout
|
56
60
|
end
|
57
61
|
|
58
62
|
# Returns the hostname of the underlying connection
|
@@ -128,7 +132,7 @@ module Cassandra
|
|
128
132
|
# closes the futures of all active requests will be failed with the error
|
129
133
|
# that caused the connection to close, or nil.
|
130
134
|
#
|
131
|
-
# When `timeout` is specified the future will fail with {Cassandra::TimeoutError}
|
135
|
+
# When `timeout` is specified the future will fail with {Cassandra::Errors::TimeoutError}
|
132
136
|
# after that many seconds have passed. If a response arrives after that
|
133
137
|
# time it will be lost. If a response never arrives for the request the
|
134
138
|
# channel occupied by the request will _not_ be reused.
|
@@ -138,8 +142,9 @@ module Cassandra
|
|
138
142
|
# failing the request
|
139
143
|
# @return [Ione::Future<Cassandra::Protocol::Response>] a future that resolves to
|
140
144
|
# the response
|
141
|
-
def send_request(request, timeout=nil)
|
142
|
-
return Ione::Future.failed(Errors::
|
145
|
+
def send_request(request, timeout=nil, with_heartbeat = true)
|
146
|
+
return Ione::Future.failed(Errors::IOError.new('Connection closed')) if closed?
|
147
|
+
schedule_heartbeat if with_heartbeat
|
143
148
|
promise = RequestPromise.new(request, @frame_encoder)
|
144
149
|
id = nil
|
145
150
|
@lock.lock
|
@@ -174,8 +179,18 @@ module Cassandra
|
|
174
179
|
# Closes the underlying connection.
|
175
180
|
#
|
176
181
|
# @return [Ione::Future] a future that completes when the connection has closed
|
177
|
-
def close
|
178
|
-
@
|
182
|
+
def close(cause = nil)
|
183
|
+
if @heartbeat
|
184
|
+
@scheduler.cancel_timer(@heartbeat)
|
185
|
+
@heartbeat = nil
|
186
|
+
end
|
187
|
+
|
188
|
+
if @terminate
|
189
|
+
@scheduler.cancel_timer(@terminate)
|
190
|
+
@terminate = nil
|
191
|
+
end
|
192
|
+
|
193
|
+
@connection.close(cause)
|
179
194
|
@closed_promise.future
|
180
195
|
end
|
181
196
|
|
@@ -199,7 +214,7 @@ module Cassandra
|
|
199
214
|
def time_out!
|
200
215
|
unless future.completed?
|
201
216
|
@timed_out = true
|
202
|
-
fail(TimeoutError.new)
|
217
|
+
fail(Errors::TimeoutError.new('Timed out'))
|
203
218
|
end
|
204
219
|
end
|
205
220
|
|
@@ -209,6 +224,7 @@ module Cassandra
|
|
209
224
|
end
|
210
225
|
|
211
226
|
def receive_data(data)
|
227
|
+
reschedule_termination
|
212
228
|
@read_buffer << data
|
213
229
|
@current_frame = @frame_decoder.decode_frame(@read_buffer, @current_frame)
|
214
230
|
while @current_frame.complete?
|
@@ -248,6 +264,9 @@ module Cassandra
|
|
248
264
|
if response.is_a?(Protocol::SetKeyspaceResultResponse)
|
249
265
|
@keyspace = response.keyspace
|
250
266
|
end
|
267
|
+
if response.is_a?(Protocol::SchemaChangeResultResponse) && response.change == 'DROPPED' && response.keyspace == @keyspace && response.table.empty?
|
268
|
+
@keyspace = nil
|
269
|
+
end
|
251
270
|
flush_request_queue
|
252
271
|
unless promise.timed_out?
|
253
272
|
promise.fulfill(response)
|
@@ -291,9 +310,22 @@ module Cassandra
|
|
291
310
|
end
|
292
311
|
|
293
312
|
def socket_closed(cause)
|
294
|
-
|
313
|
+
if cause
|
314
|
+
e = Errors::IOError.new(cause.message)
|
315
|
+
e.set_backtrace(cause.backtrace)
|
316
|
+
|
317
|
+
cause = e
|
318
|
+
end
|
319
|
+
|
320
|
+
request_failure_cause = cause || Errors::IOError.new('Connection closed')
|
295
321
|
promises_to_fail = nil
|
296
322
|
@lock.synchronize do
|
323
|
+
@scheduler.cancel_timer(@heartbeat) if @heartbeat
|
324
|
+
@scheduler.cancel_timer(@terminate) if @terminate
|
325
|
+
|
326
|
+
@heartbeat = nil
|
327
|
+
@terminate = nil
|
328
|
+
|
297
329
|
promises_to_fail = @promises.compact
|
298
330
|
promises_to_fail.concat(@request_queue_in)
|
299
331
|
promises_to_fail.concat(@request_queue_out)
|
@@ -311,6 +343,37 @@ module Cassandra
|
|
311
343
|
end
|
312
344
|
end
|
313
345
|
|
346
|
+
def schedule_heartbeat
|
347
|
+
timer = nil
|
348
|
+
|
349
|
+
@lock.synchronize do
|
350
|
+
@scheduler.cancel_timer(@heartbeat) if @heartbeat && !@heartbeat.resolved?
|
351
|
+
|
352
|
+
@heartbeat = timer = @scheduler.schedule_timer(@heartbeat_interval)
|
353
|
+
end
|
354
|
+
|
355
|
+
timer.on_value do
|
356
|
+
send_request(HEARTBEAT, nil, false).on_value do
|
357
|
+
schedule_heartbeat
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
def reschedule_termination
|
363
|
+
timer = nil
|
364
|
+
|
365
|
+
@lock.synchronize do
|
366
|
+
@scheduler.cancel_timer(@terminate) if @terminate
|
367
|
+
|
368
|
+
@terminate = timer = @scheduler.schedule_timer(@idle_timeout)
|
369
|
+
end
|
370
|
+
|
371
|
+
timer.on_value do
|
372
|
+
@terminate = nil
|
373
|
+
@connection.close(TERMINATED)
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
314
377
|
def next_stream_id
|
315
378
|
if (stream_id = @promises.index(nil))
|
316
379
|
stream_id
|
@@ -318,6 +381,9 @@ module Cassandra
|
|
318
381
|
nil
|
319
382
|
end
|
320
383
|
end
|
384
|
+
|
385
|
+
HEARTBEAT = OptionsRequest.new
|
386
|
+
TERMINATED = Errors::TimeoutError.new('Terminated due to inactivity')
|
321
387
|
end
|
322
388
|
end
|
323
389
|
end
|
@@ -47,7 +47,7 @@ module Cassandra
|
|
47
47
|
|
48
48
|
def actual_decode(buffer, fields, size)
|
49
49
|
if (fields >> 24) & 0x80 == 0
|
50
|
-
raise
|
50
|
+
raise Errors::DecodingError, 'Request frames are not supported'
|
51
51
|
end
|
52
52
|
protocol_version = (fields >> 24) & 0x7f
|
53
53
|
compression = (fields >> 16) & 0x01
|
@@ -78,7 +78,7 @@ module Cassandra
|
|
78
78
|
compressed_body = buffer.read(size)
|
79
79
|
CqlByteBuffer.new(@compressor.decompress(compressed_body))
|
80
80
|
else
|
81
|
-
raise
|
81
|
+
raise Errors::DecodingError, 'Compressed frame received, but no compressor configured'
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
@@ -26,7 +26,7 @@ module Cassandra
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def encode_frame(request, stream_id=0, buffer=nil)
|
29
|
-
raise
|
29
|
+
raise EncodingError, 'The stream ID must be between 0 and 127' unless 0 <= stream_id && stream_id < 128
|
30
30
|
buffer ||= CqlByteBuffer.new
|
31
31
|
flags = request.trace? ? 2 : 0
|
32
32
|
body = request.write(@protocol_version, CqlByteBuffer.new)
|
@@ -24,7 +24,7 @@ module Cassandra
|
|
24
24
|
if response_class
|
25
25
|
response_class.decode(protocol_version, buffer, length, trace_id)
|
26
26
|
else
|
27
|
-
raise
|
27
|
+
raise Errors::DecodingError, "Unsupported opcode #{opcode.inspect}"
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -37,7 +37,10 @@ module Cassandra
|
|
37
37
|
details[:cl] = buffer.read_consistency
|
38
38
|
details[:received] = buffer.read_int
|
39
39
|
details[:blockfor] = buffer.read_int
|
40
|
-
|
40
|
+
write_type = buffer.read_string
|
41
|
+
write_type.downcase!
|
42
|
+
|
43
|
+
details[:write_type] = write_type.to_sym
|
41
44
|
when 0x1200 # read_timeout
|
42
45
|
details[:cl] = buffer.read_consistency
|
43
46
|
details[:received] = buffer.read_int
|
@@ -52,6 +55,18 @@ module Cassandra
|
|
52
55
|
new(code, message, details)
|
53
56
|
end
|
54
57
|
|
58
|
+
def to_error(statement = nil)
|
59
|
+
case code
|
60
|
+
when 0x1000 then Errors::UnavailableError.new(@message, statement, @details[:cl], @details[:required], @details[:alive])
|
61
|
+
when 0x1100 then Errors::WriteTimeoutError.new(@message, statement, @details[:write_type], @details[:cl], @details[:blockfor], @details[:received])
|
62
|
+
when 0x1200 then Errors::ReadTimeoutError.new(@message, statement, @details[:data_present], @details[:cl], @details[:blockfor], @details[:received])
|
63
|
+
when 0x2400 then Errors::AlreadyExistsError.new(@message, statement, @details[:ks], @details[:table])
|
64
|
+
when 0x2500 then Errors::UnpreparedError.new(@message, statement, @details[:id])
|
65
|
+
else
|
66
|
+
super
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
55
70
|
def to_s
|
56
71
|
"#{super} #{@details}"
|
57
72
|
end
|
@@ -42,6 +42,23 @@ module Cassandra
|
|
42
42
|
%(ERROR 0x#{hex_code} "#@message")
|
43
43
|
end
|
44
44
|
|
45
|
+
def to_error(statement = nil)
|
46
|
+
case @code
|
47
|
+
when 0x0000 then Errors::ServerError.new(@message)
|
48
|
+
when 0x000A then Errors::ProtocolError.new(@message)
|
49
|
+
when 0x0100 then Errors::AuthenticationError.new(@message)
|
50
|
+
when 0x1001 then Errors::OverloadedError.new(@message, statement)
|
51
|
+
when 0x1002 then Errors::IsBootstrappingError.new(@message, statement)
|
52
|
+
when 0x1003 then Errors::TruncateError.new(@message, statement)
|
53
|
+
when 0x2000 then Errors::SyntaxError.new(@message, statement)
|
54
|
+
when 0x2100 then Errors::UnauthorizedError.new(@message, statement)
|
55
|
+
when 0x2200 then Errors::InvalidError.new(@message, statement)
|
56
|
+
when 0x2300 then Errors::ConfigurationError.new(@message, statement)
|
57
|
+
else
|
58
|
+
Errors::ServerError.new(@message)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
45
62
|
private
|
46
63
|
|
47
64
|
RESPONSE_TYPES[0x00] = self
|