cassandra-driver 1.2.0 → 2.0.0
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 +8 -8
- data/README.md +4 -4
- data/lib/cassandra.rb +5 -3
- data/lib/cassandra/cluster/client.rb +88 -95
- data/lib/cassandra/cluster/control_connection.rb +14 -13
- data/lib/cassandra/column.rb +1 -9
- data/lib/cassandra/execution/options.rb +24 -1
- data/lib/cassandra/executors.rb +2 -0
- data/lib/cassandra/load_balancing.rb +0 -2
- data/lib/cassandra/protocol.rb +7 -5
- data/lib/cassandra/protocol/coder.rb +509 -0
- data/lib/cassandra/protocol/cql_byte_buffer.rb +4 -0
- data/lib/cassandra/protocol/cql_protocol_handler.rb +38 -57
- data/lib/cassandra/protocol/requests/auth_response_request.rb +1 -1
- data/lib/cassandra/protocol/requests/batch_request.rb +35 -19
- data/lib/cassandra/protocol/requests/credentials_request.rb +1 -1
- data/lib/cassandra/protocol/requests/execute_request.rb +3 -16
- data/lib/cassandra/protocol/requests/options_request.rb +1 -1
- data/lib/cassandra/protocol/requests/prepare_request.rb +1 -1
- data/lib/cassandra/protocol/requests/query_request.rb +5 -61
- data/lib/cassandra/protocol/requests/register_request.rb +1 -1
- data/lib/cassandra/protocol/requests/startup_request.rb +1 -1
- data/lib/cassandra/protocol/response.rb +0 -9
- data/lib/cassandra/protocol/responses/already_exists_error_response.rb +40 -0
- data/lib/cassandra/protocol/responses/auth_challenge_response.rb +0 -4
- data/lib/cassandra/protocol/responses/auth_success_response.rb +1 -5
- data/lib/cassandra/protocol/responses/authenticate_response.rb +0 -4
- data/lib/cassandra/protocol/responses/error_response.rb +0 -12
- data/lib/cassandra/protocol/responses/event_response.rb +0 -8
- data/lib/cassandra/protocol/responses/prepared_result_response.rb +0 -10
- data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +1 -1
- data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +42 -0
- data/lib/cassandra/protocol/responses/ready_response.rb +0 -4
- data/lib/cassandra/protocol/responses/result_response.rb +0 -7
- data/lib/cassandra/protocol/responses/rows_result_response.rb +0 -101
- data/lib/cassandra/protocol/responses/schema_change_event_response.rb +0 -3
- data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +0 -4
- data/lib/cassandra/protocol/responses/status_change_event_response.rb +0 -4
- data/lib/cassandra/protocol/responses/supported_response.rb +0 -4
- data/lib/cassandra/protocol/responses/unavailable_error_response.rb +41 -0
- data/lib/cassandra/protocol/responses/unprepared_error_response.rb +39 -0
- data/lib/cassandra/protocol/responses/void_result_response.rb +0 -4
- data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +44 -0
- data/lib/cassandra/protocol/v1.rb +238 -0
- data/lib/cassandra/session.rb +95 -16
- data/lib/cassandra/statements/batch.rb +33 -6
- data/lib/cassandra/statements/bound.rb +3 -3
- data/lib/cassandra/statements/prepared.rb +38 -10
- data/lib/cassandra/statements/simple.rb +72 -3
- data/lib/cassandra/table.rb +2 -3
- data/lib/cassandra/util.rb +18 -0
- data/lib/cassandra/version.rb +1 -1
- metadata +8 -5
- data/lib/cassandra/protocol/frame_decoder.rb +0 -128
- data/lib/cassandra/protocol/frame_encoder.rb +0 -48
- data/lib/cassandra/protocol/responses/detailed_error_response.rb +0 -75
- data/lib/cassandra/protocol/type_converter.rb +0 -389
@@ -30,7 +30,6 @@ module Cassandra
|
|
30
30
|
# future = protocol_handler.send_request(Cassandra::Protocol::OptionsRequest.new)
|
31
31
|
# response = future.get
|
32
32
|
# puts "These options are supported: #{response.options}"
|
33
|
-
#
|
34
33
|
class CqlProtocolHandler
|
35
34
|
# @return [String] the current keyspace for the underlying connection
|
36
35
|
attr_reader :keyspace
|
@@ -42,10 +41,8 @@ module Cassandra
|
|
42
41
|
@connection.on_data(&method(:receive_data))
|
43
42
|
@connection.on_closed(&method(:socket_closed))
|
44
43
|
@promises = Array.new(128) { nil }
|
45
|
-
@
|
46
|
-
@
|
47
|
-
@frame_decoder = FrameDecoder.new(@compressor)
|
48
|
-
@current_frame = FrameDecoder::NULL_FRAME
|
44
|
+
@frame_encoder = V1::Encoder.new(@compressor, protocol_version)
|
45
|
+
@frame_decoder = V1::Decoder.new(self, @compressor)
|
49
46
|
@request_queue_in = []
|
50
47
|
@request_queue_out = []
|
51
48
|
@event_listeners = []
|
@@ -145,7 +142,7 @@ module Cassandra
|
|
145
142
|
def send_request(request, timeout=nil, with_heartbeat = true)
|
146
143
|
return Ione::Future.failed(Errors::IOError.new('Connection closed')) if closed?
|
147
144
|
schedule_heartbeat if with_heartbeat
|
148
|
-
promise = RequestPromise.new(request
|
145
|
+
promise = RequestPromise.new(request)
|
149
146
|
id = nil
|
150
147
|
@lock.lock
|
151
148
|
begin
|
@@ -157,12 +154,11 @@ module Cassandra
|
|
157
154
|
end
|
158
155
|
if id
|
159
156
|
@connection.write do |buffer|
|
160
|
-
@frame_encoder.
|
157
|
+
@frame_encoder.encode(buffer, request, id)
|
161
158
|
end
|
162
159
|
else
|
163
160
|
@lock.lock
|
164
161
|
begin
|
165
|
-
promise.encode_frame
|
166
162
|
@request_queue_in << promise
|
167
163
|
ensure
|
168
164
|
@lock.unlock
|
@@ -197,50 +193,6 @@ module Cassandra
|
|
197
193
|
@closed_promise.future
|
198
194
|
end
|
199
195
|
|
200
|
-
private
|
201
|
-
|
202
|
-
# @private
|
203
|
-
class RequestPromise < Ione::Promise
|
204
|
-
attr_reader :request, :frame
|
205
|
-
|
206
|
-
def initialize(request, frame_encoder)
|
207
|
-
@request = request
|
208
|
-
@frame_encoder = frame_encoder
|
209
|
-
@timed_out = false
|
210
|
-
super()
|
211
|
-
end
|
212
|
-
|
213
|
-
def timed_out?
|
214
|
-
@timed_out
|
215
|
-
end
|
216
|
-
|
217
|
-
def time_out!
|
218
|
-
unless future.completed?
|
219
|
-
@timed_out = true
|
220
|
-
fail(Errors::TimeoutError.new('Timed out'))
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
def encode_frame
|
225
|
-
@frame = @frame_encoder.encode_frame(@request)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
def receive_data(data)
|
230
|
-
reschedule_termination
|
231
|
-
@read_buffer << data
|
232
|
-
@current_frame = @frame_decoder.decode_frame(@read_buffer, @current_frame)
|
233
|
-
while @current_frame.complete?
|
234
|
-
id = @current_frame.stream_id
|
235
|
-
if id == -1
|
236
|
-
notify_event_listeners(@current_frame.body)
|
237
|
-
else
|
238
|
-
complete_request(id, @current_frame.body)
|
239
|
-
end
|
240
|
-
@current_frame = @frame_decoder.decode_frame(@read_buffer)
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
196
|
def notify_event_listeners(event_response)
|
245
197
|
event_listeners = nil
|
246
198
|
@lock.lock
|
@@ -251,7 +203,7 @@ module Cassandra
|
|
251
203
|
@lock.unlock
|
252
204
|
end
|
253
205
|
event_listeners.each do |listener|
|
254
|
-
listener.call(
|
206
|
+
listener.call(event_response)
|
255
207
|
end
|
256
208
|
end
|
257
209
|
|
@@ -276,6 +228,35 @@ module Cassandra
|
|
276
228
|
end
|
277
229
|
end
|
278
230
|
|
231
|
+
private
|
232
|
+
|
233
|
+
# @private
|
234
|
+
class RequestPromise < Ione::Promise
|
235
|
+
attr_reader :request
|
236
|
+
|
237
|
+
def initialize(request)
|
238
|
+
@request = request
|
239
|
+
@timed_out = false
|
240
|
+
super()
|
241
|
+
end
|
242
|
+
|
243
|
+
def timed_out?
|
244
|
+
@timed_out
|
245
|
+
end
|
246
|
+
|
247
|
+
def time_out!
|
248
|
+
unless future.completed?
|
249
|
+
@timed_out = true
|
250
|
+
fail(Errors::TimeoutError.new('Timed out'))
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def receive_data(data)
|
256
|
+
reschedule_termination
|
257
|
+
@frame_decoder << data
|
258
|
+
end
|
259
|
+
|
279
260
|
def flush_request_queue
|
280
261
|
@lock.lock
|
281
262
|
begin
|
@@ -288,7 +269,7 @@ module Cassandra
|
|
288
269
|
end
|
289
270
|
while true
|
290
271
|
id = nil
|
291
|
-
|
272
|
+
promise = nil
|
292
273
|
@lock.lock
|
293
274
|
begin
|
294
275
|
if @request_queue_out.any? && (id = next_stream_id)
|
@@ -296,7 +277,6 @@ module Cassandra
|
|
296
277
|
if promise.timed_out?
|
297
278
|
next
|
298
279
|
else
|
299
|
-
frame = promise.frame
|
300
280
|
@promises[id] = promise
|
301
281
|
end
|
302
282
|
end
|
@@ -304,8 +284,9 @@ module Cassandra
|
|
304
284
|
@lock.unlock
|
305
285
|
end
|
306
286
|
if id
|
307
|
-
@
|
308
|
-
|
287
|
+
@connection.write do |buffer|
|
288
|
+
@frame_encoder.encode(buffer, promise.request, id)
|
289
|
+
end
|
309
290
|
else
|
310
291
|
break
|
311
292
|
end
|
@@ -23,38 +23,43 @@ module Cassandra
|
|
23
23
|
UNLOGGED_TYPE = 1
|
24
24
|
COUNTER_TYPE = 2
|
25
25
|
|
26
|
-
attr_reader :type
|
26
|
+
attr_reader :type
|
27
27
|
attr_accessor :consistency, :retries
|
28
28
|
|
29
29
|
def initialize(type, consistency, trace=false)
|
30
30
|
super(0x0D, trace)
|
31
|
-
@type
|
32
|
-
@
|
33
|
-
@encoded_queries = CqlByteBuffer.new
|
31
|
+
@type = type
|
32
|
+
@parts = []
|
34
33
|
@consistency = consistency
|
35
34
|
end
|
36
35
|
|
37
|
-
def add_query(cql, values
|
38
|
-
@
|
39
|
-
@encoded_queries.append_long_string(cql)
|
40
|
-
QueryRequest.encode_values(@encoded_queries, values, type_hints)
|
41
|
-
@part_count += 1
|
36
|
+
def add_query(cql, values, types)
|
37
|
+
@parts << [:simple, cql, values, types]
|
42
38
|
nil
|
43
39
|
end
|
44
40
|
|
45
|
-
def add_prepared(id,
|
46
|
-
@
|
47
|
-
@encoded_queries.append_short_bytes(id)
|
48
|
-
ExecuteRequest.encode_values(@encoded_queries, metadata, values)
|
49
|
-
@part_count += 1
|
41
|
+
def add_prepared(id, values, types)
|
42
|
+
@parts << [:prepared, id, values, types]
|
50
43
|
nil
|
51
44
|
end
|
52
45
|
|
53
|
-
def write(protocol_version,
|
46
|
+
def write(buffer, protocol_version, encoder)
|
54
47
|
buffer.append(@type.chr)
|
55
|
-
buffer.append_short(@
|
56
|
-
|
48
|
+
buffer.append_short(@parts.size)
|
49
|
+
|
50
|
+
@parts.each do |(statement_kind, *arguments)|
|
51
|
+
__send__(:"write_#{statement_kind}", buffer, protocol_version, encoder, *arguments)
|
52
|
+
end
|
53
|
+
|
57
54
|
buffer.append_consistency(@consistency)
|
55
|
+
|
56
|
+
if protocol_version > 2
|
57
|
+
flags = 0
|
58
|
+
|
59
|
+
buffer.append(flags.chr)
|
60
|
+
end
|
61
|
+
|
62
|
+
buffer
|
58
63
|
end
|
59
64
|
|
60
65
|
def to_s
|
@@ -63,14 +68,25 @@ module Cassandra
|
|
63
68
|
when UNLOGGED_TYPE then 'UNLOGGED'
|
64
69
|
when COUNTER_TYPE then 'COUNTER'
|
65
70
|
end
|
66
|
-
%(BATCH #{type_str} #{@
|
71
|
+
%(BATCH #{type_str} #{@parts.size} #{@consistency.to_s.upcase})
|
67
72
|
end
|
68
73
|
|
69
74
|
private
|
70
75
|
|
71
|
-
TYPE_CONVERTER = TypeConverter.new
|
72
76
|
QUERY_KIND = "\x00".freeze
|
73
77
|
PREPARED_KIND = "\x01".freeze
|
78
|
+
|
79
|
+
def write_simple(buffer, protocol_version, encoder, cql, values, types)
|
80
|
+
buffer.append(QUERY_KIND)
|
81
|
+
buffer.append_long_string(cql)
|
82
|
+
encoder.write_parameters(buffer, values, types)
|
83
|
+
end
|
84
|
+
|
85
|
+
def write_prepared(buffer, protocol_version, encoder, id, values, types)
|
86
|
+
buffer.append(PREPARED_KIND)
|
87
|
+
buffer.append_short_bytes(id)
|
88
|
+
encoder.write_parameters(buffer, values, types)
|
89
|
+
end
|
74
90
|
end
|
75
91
|
end
|
76
92
|
end
|
@@ -36,10 +36,9 @@ module Cassandra
|
|
36
36
|
@serial_consistency = serial_consistency
|
37
37
|
@page_size = page_size
|
38
38
|
@paging_state = paging_state
|
39
|
-
@encoded_values = self.class.encode_values(CqlByteBuffer.new, @metadata, @values)
|
40
39
|
end
|
41
40
|
|
42
|
-
def write(protocol_version,
|
41
|
+
def write(buffer, protocol_version, encoder)
|
43
42
|
buffer.append_short_bytes(@id)
|
44
43
|
if protocol_version > 1
|
45
44
|
buffer.append_consistency(@consistency)
|
@@ -51,13 +50,13 @@ module Cassandra
|
|
51
50
|
flags |= 0x10 if @serial_consistency
|
52
51
|
buffer.append(flags.chr)
|
53
52
|
if @values.size > 0
|
54
|
-
|
53
|
+
encoder.write_parameters(buffer, @values, @metadata)
|
55
54
|
end
|
56
55
|
buffer.append_int(@page_size) if @page_size
|
57
56
|
buffer.append_bytes(@paging_state) if @paging_state
|
58
57
|
buffer.append_consistency(@serial_consistency) if @serial_consistency
|
59
58
|
else
|
60
|
-
|
59
|
+
encoder.write_parameters(buffer, @values, @metadata)
|
61
60
|
buffer.append_consistency(@consistency)
|
62
61
|
end
|
63
62
|
buffer
|
@@ -86,18 +85,6 @@ module Cassandra
|
|
86
85
|
h
|
87
86
|
end
|
88
87
|
end
|
89
|
-
|
90
|
-
def self.encode_values(buffer, metadata, values)
|
91
|
-
buffer.append_short(metadata.size)
|
92
|
-
metadata.each_with_index do |(_, _, _, type), index|
|
93
|
-
TYPE_CONVERTER.to_bytes(buffer, type, values[index])
|
94
|
-
end
|
95
|
-
buffer
|
96
|
-
end
|
97
|
-
|
98
|
-
private
|
99
|
-
|
100
|
-
TYPE_CONVERTER = TypeConverter.new
|
101
88
|
end
|
102
89
|
end
|
103
90
|
end
|
@@ -22,23 +22,18 @@ module Cassandra
|
|
22
22
|
attr_reader :cql, :values, :type_hints, :serial_consistency, :page_size, :paging_state
|
23
23
|
attr_accessor :consistency, :retries
|
24
24
|
|
25
|
-
def initialize(cql, values, type_hints, consistency, serial_consistency=nil, page_size=nil, paging_state=nil, trace=false)
|
26
|
-
raise ArgumentError, %(No CQL given!) unless cql
|
27
|
-
raise ArgumentError, %(No such consistency: #{consistency.inspect}) if consistency.nil? || !CONSISTENCIES.include?(consistency)
|
28
|
-
raise ArgumentError, %(No such consistency: #{serial_consistency.inspect}) unless serial_consistency.nil? || CONSISTENCIES.include?(serial_consistency)
|
29
|
-
raise ArgumentError, %(Bound values and type hints must have the same number of elements (got #{values.size} values and #{type_hints.size} hints)) if values && type_hints && values.size != type_hints.size
|
30
|
-
raise ArgumentError, %(Paging state given but no page size) if paging_state && !page_size
|
25
|
+
def initialize(cql, values, type_hints, consistency, serial_consistency = nil, page_size = nil, paging_state = nil, trace = false)
|
31
26
|
super(7, trace)
|
32
27
|
@cql = cql
|
33
|
-
@values = values
|
34
|
-
@type_hints = type_hints
|
28
|
+
@values = values
|
29
|
+
@type_hints = type_hints
|
35
30
|
@consistency = consistency
|
36
31
|
@serial_consistency = serial_consistency
|
37
32
|
@page_size = page_size
|
38
33
|
@paging_state = paging_state
|
39
34
|
end
|
40
35
|
|
41
|
-
def write(protocol_version,
|
36
|
+
def write(buffer, protocol_version, encoder)
|
42
37
|
buffer.append_long_string(@cql)
|
43
38
|
buffer.append_consistency(@consistency)
|
44
39
|
if protocol_version > 1
|
@@ -49,7 +44,7 @@ module Cassandra
|
|
49
44
|
if @values && @values.size > 0
|
50
45
|
flags |= 0x01
|
51
46
|
buffer.append(flags.chr)
|
52
|
-
|
47
|
+
encoder.write_parameters(buffer, @values, @type_hints)
|
53
48
|
else
|
54
49
|
buffer.append(flags.chr)
|
55
50
|
end
|
@@ -87,57 +82,6 @@ module Cassandra
|
|
87
82
|
h = 0xffffffffffffffff & (0x100000001b3 * (h ^ @paging_state.hash))
|
88
83
|
h
|
89
84
|
end
|
90
|
-
|
91
|
-
def self.encode_values(buffer, values, hints)
|
92
|
-
if values && values.size > 0
|
93
|
-
buffer.append_short(values.size)
|
94
|
-
values.each_with_index do |value, index|
|
95
|
-
type = (hints && hints[index]) || guess_type(value)
|
96
|
-
raise EncodingError, "Could not guess a suitable type for #{value.inspect}" unless type
|
97
|
-
TYPE_CONVERTER.to_bytes(buffer, type, value)
|
98
|
-
end
|
99
|
-
buffer
|
100
|
-
else
|
101
|
-
buffer.append_short(0)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
private
|
106
|
-
|
107
|
-
def self.guess_type(value)
|
108
|
-
type = TYPE_GUESSES[value.class]
|
109
|
-
if type == :map
|
110
|
-
pair = value.first
|
111
|
-
[type, guess_type(pair[0]), guess_type(pair[1])]
|
112
|
-
elsif type == :list
|
113
|
-
[type, guess_type(value.first)]
|
114
|
-
elsif type == :set
|
115
|
-
[type, guess_type(value.first)]
|
116
|
-
else
|
117
|
-
type
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
TYPE_GUESSES = {
|
122
|
-
String => :varchar,
|
123
|
-
Fixnum => :bigint,
|
124
|
-
Float => :double,
|
125
|
-
Bignum => :varint,
|
126
|
-
BigDecimal => :decimal,
|
127
|
-
TrueClass => :boolean,
|
128
|
-
FalseClass => :boolean,
|
129
|
-
NilClass => :bigint,
|
130
|
-
Uuid => :uuid,
|
131
|
-
TimeUuid => :uuid,
|
132
|
-
IPAddr => :inet,
|
133
|
-
Time => :timestamp,
|
134
|
-
Hash => :map,
|
135
|
-
Array => :list,
|
136
|
-
Set => :set,
|
137
|
-
}.freeze
|
138
|
-
TYPE_CONVERTER = TypeConverter.new
|
139
|
-
EMPTY_LIST = [].freeze
|
140
|
-
NO_FLAGS = "\x00".freeze
|
141
85
|
end
|
142
86
|
end
|
143
87
|
end
|