cassandra-driver 1.2.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|