cassandra-driver 1.0.0.rc.1-java → 1.1.0-java
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 +4 -4
- data/README.md +58 -18
- data/lib/cassandra.rb +132 -93
- data/lib/cassandra/auth.rb +3 -3
- data/lib/cassandra/cluster.rb +65 -39
- data/lib/cassandra/cluster/client.rb +67 -28
- data/lib/cassandra/{client/connection_manager.rb → cluster/connection_pool.rb} +9 -3
- data/lib/cassandra/cluster/connector.rb +101 -30
- data/lib/cassandra/cluster/control_connection.rb +160 -96
- data/lib/cassandra/{client/null_logger.rb → cluster/failed_connection.rb} +12 -14
- data/lib/cassandra/cluster/options.rb +26 -11
- data/lib/cassandra/cluster/schema.rb +22 -1
- data/lib/cassandra/column.rb +5 -0
- data/lib/cassandra/driver.rb +46 -12
- data/lib/cassandra/errors.rb +5 -5
- data/lib/cassandra/execution/options.rb +42 -8
- data/lib/cassandra/execution/trace.rb +4 -4
- data/lib/cassandra/executors.rb +111 -0
- data/lib/cassandra/future.rb +88 -64
- data/lib/cassandra/keyspace.rb +12 -0
- data/lib/cassandra/load_balancing.rb +10 -0
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +10 -5
- data/lib/cassandra/load_balancing/policies/round_robin.rb +7 -5
- data/lib/cassandra/load_balancing/policies/token_aware.rb +31 -10
- data/lib/cassandra/load_balancing/policies/white_list.rb +4 -7
- data/lib/cassandra/null_logger.rb +35 -0
- data/lib/cassandra/protocol/cql_protocol_handler.rb +8 -1
- data/lib/cassandra/protocol/requests/query_request.rb +1 -11
- data/lib/cassandra/result.rb +34 -9
- data/lib/cassandra/session.rb +6 -0
- data/lib/cassandra/statements/prepared.rb +5 -1
- data/lib/cassandra/table.rb +5 -0
- data/lib/cassandra/util.rb +130 -0
- data/lib/cassandra/version.rb +1 -1
- metadata +40 -50
- data/lib/cassandra/client.rb +0 -144
- data/lib/cassandra/client/batch.rb +0 -212
- data/lib/cassandra/client/client.rb +0 -591
- data/lib/cassandra/client/column_metadata.rb +0 -54
- data/lib/cassandra/client/connector.rb +0 -273
- data/lib/cassandra/client/execute_options_decoder.rb +0 -59
- data/lib/cassandra/client/peer_discovery.rb +0 -50
- data/lib/cassandra/client/prepared_statement.rb +0 -314
- data/lib/cassandra/client/query_result.rb +0 -230
- data/lib/cassandra/client/request_runner.rb +0 -70
- data/lib/cassandra/client/result_metadata.rb +0 -48
- data/lib/cassandra/client/void_result.rb +0 -78
@@ -22,7 +22,7 @@ module Cassandra
|
|
22
22
|
class ControlConnection
|
23
23
|
include MonitorMixin
|
24
24
|
|
25
|
-
def initialize(logger, io_reactor, cluster_registry, cluster_schema, cluster_metadata, load_balancing_policy, reconnection_policy, address_resolution_policy, connector)
|
25
|
+
def initialize(logger, io_reactor, cluster_registry, cluster_schema, cluster_metadata, load_balancing_policy, reconnection_policy, address_resolution_policy, connector, connection_options)
|
26
26
|
@logger = logger
|
27
27
|
@io_reactor = io_reactor
|
28
28
|
@registry = cluster_registry
|
@@ -32,17 +32,24 @@ module Cassandra
|
|
32
32
|
@reconnection_policy = reconnection_policy
|
33
33
|
@address_resolver = address_resolution_policy
|
34
34
|
@connector = connector
|
35
|
-
@
|
35
|
+
@connection_options = connection_options
|
36
|
+
@refreshing_statuses = ::Hash.new(false)
|
36
37
|
@status = :closed
|
37
|
-
@refreshing_schema = false
|
38
|
-
@refreshing_keyspaces = Hash.new(false)
|
39
|
-
@refreshing_tables = Hash.new
|
40
38
|
@refreshing_hosts = false
|
41
|
-
@refreshing_host = Hash.new(false)
|
39
|
+
@refreshing_host = ::Hash.new(false)
|
40
|
+
@closed_promise = Ione::Promise.new
|
41
|
+
@schema_changes = ::Array.new
|
42
|
+
@schema_refresh_timer = nil
|
43
|
+
@schema_refresh_window = nil
|
42
44
|
|
43
45
|
mon_initialize
|
44
46
|
end
|
45
47
|
|
48
|
+
def on_close(&block)
|
49
|
+
@closed_promise.future.on_value(&block)
|
50
|
+
@closed_promise.future.on_failure(&block)
|
51
|
+
end
|
52
|
+
|
46
53
|
def connect_async
|
47
54
|
synchronize do
|
48
55
|
return Ione::Future.resolved if @status == :connecting || @status == :connected
|
@@ -110,10 +117,33 @@ module Cassandra
|
|
110
117
|
|
111
118
|
def close_async
|
112
119
|
synchronize do
|
113
|
-
return
|
120
|
+
return @closed_promise.future if @status == :closing || @status == :closed
|
114
121
|
@status = :closing
|
115
122
|
end
|
116
|
-
@io_reactor.stop
|
123
|
+
f = @io_reactor.stop
|
124
|
+
|
125
|
+
f.on_value(&method(:connection_closed))
|
126
|
+
f.on_failure(&method(:connection_closed))
|
127
|
+
|
128
|
+
@closed_promise.future
|
129
|
+
end
|
130
|
+
|
131
|
+
def connection_closed(cause)
|
132
|
+
@closed_promise.fulfill
|
133
|
+
end
|
134
|
+
|
135
|
+
def refresh_schema_async_maybe_retry
|
136
|
+
refresh_schema_async.fallback do |e|
|
137
|
+
case e
|
138
|
+
when Errors::HostError
|
139
|
+
refresh_schema_async_retry(e, @reconnection_policy.schedule)
|
140
|
+
else
|
141
|
+
connection = @connection
|
142
|
+
connection && connection.close(e)
|
143
|
+
|
144
|
+
Ione::Future.failed(e)
|
145
|
+
end
|
146
|
+
end
|
117
147
|
end
|
118
148
|
|
119
149
|
def inspect
|
@@ -127,11 +157,6 @@ module Cassandra
|
|
127
157
|
SELECT_KEYSPACES = Protocol::QueryRequest.new('SELECT * FROM system.schema_keyspaces', nil, nil, :one)
|
128
158
|
SELECT_TABLES = Protocol::QueryRequest.new('SELECT * FROM system.schema_columnfamilies', nil, nil, :one)
|
129
159
|
SELECT_COLUMNS = Protocol::QueryRequest.new('SELECT * FROM system.schema_columns', nil, nil, :one)
|
130
|
-
REGISTER = Protocol::RegisterRequest.new(
|
131
|
-
Protocol::TopologyChangeEventResponse::TYPE,
|
132
|
-
Protocol::StatusChangeEventResponse::TYPE,
|
133
|
-
Protocol::SchemaChangeEventResponse::TYPE
|
134
|
-
)
|
135
160
|
|
136
161
|
def reconnect_async(schedule)
|
137
162
|
timeout = schedule.next
|
@@ -163,7 +188,14 @@ module Cassandra
|
|
163
188
|
|
164
189
|
return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
|
165
190
|
|
166
|
-
|
191
|
+
request = Protocol::RegisterRequest.new(
|
192
|
+
Protocol::TopologyChangeEventResponse::TYPE,
|
193
|
+
Protocol::StatusChangeEventResponse::TYPE
|
194
|
+
)
|
195
|
+
|
196
|
+
request.events << Protocol::SchemaChangeEventResponse::TYPE if @connection_options.synchronize_schema?
|
197
|
+
|
198
|
+
f = connection.send_request(request)
|
167
199
|
f = f.map do |r|
|
168
200
|
case r
|
169
201
|
when Protocol::ReadyResponse
|
@@ -179,26 +211,7 @@ module Cassandra
|
|
179
211
|
@logger.debug("Event received #{event}")
|
180
212
|
|
181
213
|
if event.type == 'SCHEMA_CHANGE'
|
182
|
-
|
183
|
-
when 'CREATED'
|
184
|
-
if event.table.empty?
|
185
|
-
refresh_schema_async_maybe_retry
|
186
|
-
else
|
187
|
-
refresh_keyspace_async_maybe_retry(event.keyspace)
|
188
|
-
end
|
189
|
-
when 'DROPPED'
|
190
|
-
if event.table.empty?
|
191
|
-
refresh_schema_async_maybe_retry
|
192
|
-
else
|
193
|
-
refresh_keyspace_async_maybe_retry(event.keyspace)
|
194
|
-
end
|
195
|
-
when 'UPDATED'
|
196
|
-
if event.table.empty?
|
197
|
-
refresh_keyspace_async_maybe_retry(event.keyspace)
|
198
|
-
else
|
199
|
-
refresh_table_async_maybe_retry(event.keyspace, event.table)
|
200
|
-
end
|
201
|
-
end
|
214
|
+
handle_schema_change(event)
|
202
215
|
else
|
203
216
|
case event.change
|
204
217
|
when 'UP'
|
@@ -242,29 +255,6 @@ module Cassandra
|
|
242
255
|
end
|
243
256
|
end
|
244
257
|
|
245
|
-
def refresh_schema_async_maybe_retry
|
246
|
-
synchronize do
|
247
|
-
return Ione::Future.resolved if @refreshing_schema
|
248
|
-
@refreshing_schema = true
|
249
|
-
end
|
250
|
-
|
251
|
-
refresh_schema_async.fallback do |e|
|
252
|
-
case e
|
253
|
-
when Errors::HostError
|
254
|
-
refresh_schema_async_retry(e, @reconnection_policy.schedule)
|
255
|
-
else
|
256
|
-
connection = @connection
|
257
|
-
connection && connection.close(e)
|
258
|
-
|
259
|
-
Ione::Future.resolved
|
260
|
-
end
|
261
|
-
end.map do
|
262
|
-
synchronize do
|
263
|
-
@refreshing_schema = false
|
264
|
-
end
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
258
|
def refresh_schema_async_retry(error, schedule)
|
269
259
|
timeout = schedule.next
|
270
260
|
@logger.info("Failed to refresh schema (#{error.class.name}: #{error.message}), retrying in #{timeout}")
|
@@ -279,18 +269,13 @@ module Cassandra
|
|
279
269
|
connection = @connection
|
280
270
|
connection && connection.close(e)
|
281
271
|
|
282
|
-
Ione::Future.
|
272
|
+
Ione::Future.failed(e)
|
283
273
|
end
|
284
274
|
end
|
285
275
|
end
|
286
276
|
end
|
287
277
|
|
288
278
|
def refresh_keyspace_async_maybe_retry(keyspace)
|
289
|
-
synchronize do
|
290
|
-
return Ione::Future.resolved if @refreshing_schema || @refreshing_keyspaces[keyspace]
|
291
|
-
@refreshing_keyspaces[keyspace] = true
|
292
|
-
end
|
293
|
-
|
294
279
|
refresh_keyspace_async(keyspace).fallback do |e|
|
295
280
|
case e
|
296
281
|
when Errors::HostError
|
@@ -299,11 +284,7 @@ module Cassandra
|
|
299
284
|
connection = @connection
|
300
285
|
connection && connection.close(e)
|
301
286
|
|
302
|
-
Ione::Future.
|
303
|
-
end
|
304
|
-
end.map do
|
305
|
-
synchronize do
|
306
|
-
@refreshing_keyspaces.delete(host)
|
287
|
+
Ione::Future.failed(e)
|
307
288
|
end
|
308
289
|
end
|
309
290
|
end
|
@@ -322,7 +303,7 @@ module Cassandra
|
|
322
303
|
connection = @connection
|
323
304
|
connection && connection.close(e)
|
324
305
|
|
325
|
-
Ione::Future.
|
306
|
+
Ione::Future.failed(e)
|
326
307
|
end
|
327
308
|
end
|
328
309
|
end
|
@@ -333,25 +314,22 @@ module Cassandra
|
|
333
314
|
|
334
315
|
return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
|
335
316
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
columns = send_select_request(connection, Protocol::QueryRequest.new("SELECT * FROM system.schema_columns WHERE keyspace_name = ?", params, nil, :one))
|
317
|
+
keyspaces = send_select_request(connection, Protocol::QueryRequest.new("SELECT * FROM system.schema_keyspaces WHERE keyspace_name = '%s'" % keyspace, nil, nil, :one))
|
318
|
+
tables = send_select_request(connection, Protocol::QueryRequest.new("SELECT * FROM system.schema_columnfamilies WHERE keyspace_name = '%s'" % keyspace, nil, nil, :one))
|
319
|
+
columns = send_select_request(connection, Protocol::QueryRequest.new("SELECT * FROM system.schema_columns WHERE keyspace_name = '%s'" % keyspace, nil, nil, :one))
|
340
320
|
|
341
321
|
Ione::Future.all(keyspaces, tables, columns).map do |(keyspaces, tables, columns)|
|
342
322
|
host = @registry.host(connection.host)
|
343
323
|
|
344
|
-
|
324
|
+
if keyspaces.empty?
|
325
|
+
@schema.delete_keyspace(keyspace)
|
326
|
+
else
|
327
|
+
@schema.update_keyspace(host, keyspaces.first, tables, columns)
|
328
|
+
end
|
345
329
|
end
|
346
330
|
end
|
347
331
|
|
348
332
|
def refresh_table_async_maybe_retry(keyspace, table)
|
349
|
-
synchronize do
|
350
|
-
return Ione::Future.resolved if @refreshing_schema || @refreshing_keyspaces[keyspace] || @refreshing_tables[keyspace][table]
|
351
|
-
@refreshing_tables[keyspace] ||= ::Hash.new(false)
|
352
|
-
@refreshing_tables[keyspace][table] = true
|
353
|
-
end
|
354
|
-
|
355
333
|
refresh_table_async(keyspace, table).fallback do |e|
|
356
334
|
case e
|
357
335
|
when Errors::HostError
|
@@ -360,12 +338,7 @@ module Cassandra
|
|
360
338
|
connection = @connection
|
361
339
|
connection && connection.close(e)
|
362
340
|
|
363
|
-
Ione::Future.
|
364
|
-
end
|
365
|
-
end.map do
|
366
|
-
synchronize do
|
367
|
-
@refreshing_tables[keyspace].delete(table)
|
368
|
-
@refreshing_tables.delete(keyspace) if @refreshing_tables[keyspace].empty?
|
341
|
+
Ione::Future.failed(e)
|
369
342
|
end
|
370
343
|
end
|
371
344
|
end
|
@@ -384,7 +357,7 @@ module Cassandra
|
|
384
357
|
connection = @connection
|
385
358
|
connection && connection.close(e)
|
386
359
|
|
387
|
-
Ione::Future.
|
360
|
+
Ione::Future.failed(e)
|
388
361
|
end
|
389
362
|
end
|
390
363
|
end
|
@@ -396,13 +369,17 @@ module Cassandra
|
|
396
369
|
return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
|
397
370
|
|
398
371
|
params = [keyspace, table]
|
399
|
-
|
400
|
-
columns = send_select_request(connection, Protocol::QueryRequest.new("SELECT * FROM system.schema_columns WHERE keyspace_name =
|
372
|
+
tables = send_select_request(connection, Protocol::QueryRequest.new("SELECT * FROM system.schema_columnfamilies WHERE keyspace_name = '%s' AND columnfamily_name = '%s'" % params, nil, nil, :one))
|
373
|
+
columns = send_select_request(connection, Protocol::QueryRequest.new("SELECT * FROM system.schema_columns WHERE keyspace_name = '%s' AND columnfamily_name = '%s'" % params, nil, nil, :one))
|
401
374
|
|
402
|
-
Ione::Future.all(
|
375
|
+
Ione::Future.all(tables, columns).map do |(tables, columns)|
|
403
376
|
host = @registry.host(connection.host)
|
404
377
|
|
405
|
-
|
378
|
+
if tables.empty?
|
379
|
+
@schema.delete_table(keyspace, table)
|
380
|
+
else
|
381
|
+
@schema.udpate_table(host, keyspace, tables.first, columns)
|
382
|
+
end
|
406
383
|
end
|
407
384
|
end
|
408
385
|
|
@@ -420,7 +397,7 @@ module Cassandra
|
|
420
397
|
connection = @connection
|
421
398
|
connection && connection.close(e)
|
422
399
|
|
423
|
-
Ione::Future.
|
400
|
+
Ione::Future.failed(e)
|
424
401
|
end
|
425
402
|
end.map do
|
426
403
|
synchronize do
|
@@ -443,7 +420,7 @@ module Cassandra
|
|
443
420
|
connection = @connection
|
444
421
|
connection && connection.close(e)
|
445
422
|
|
446
|
-
Ione::Future.
|
423
|
+
Ione::Future.failed(e)
|
447
424
|
end
|
448
425
|
end
|
449
426
|
end
|
@@ -469,6 +446,7 @@ module Cassandra
|
|
469
446
|
@metadata.update(data)
|
470
447
|
end
|
471
448
|
|
449
|
+
peers.shuffle!
|
472
450
|
peers.each do |data|
|
473
451
|
ip = peer_ip(data)
|
474
452
|
next unless ip
|
@@ -525,7 +503,7 @@ module Cassandra
|
|
525
503
|
connection = @connection
|
526
504
|
connection && connection.close(e)
|
527
505
|
|
528
|
-
Ione::Future.
|
506
|
+
Ione::Future.failed(e)
|
529
507
|
end
|
530
508
|
end.map do
|
531
509
|
synchronize do
|
@@ -548,7 +526,7 @@ module Cassandra
|
|
548
526
|
connection = @connection
|
549
527
|
connection && connection.close(e)
|
550
528
|
|
551
|
-
Ione::Future.
|
529
|
+
Ione::Future.failed(e)
|
552
530
|
end
|
553
531
|
end
|
554
532
|
end
|
@@ -563,7 +541,7 @@ module Cassandra
|
|
563
541
|
if ip == connection.host
|
564
542
|
request = SELECT_LOCAL
|
565
543
|
else
|
566
|
-
request = Protocol::QueryRequest.new(
|
544
|
+
request = Protocol::QueryRequest.new("SELECT rack, data_center, host_id, rpc_address, release_version, tokens FROM system.peers WHERE peer = '%s'" % address, nil, nil, :one)
|
567
545
|
end
|
568
546
|
|
569
547
|
send_select_request(connection, request).map do |rows|
|
@@ -662,6 +640,92 @@ Control connection failed and is unlikely to recover.
|
|
662
640
|
@address_resolver.resolve(ip)
|
663
641
|
end
|
664
642
|
|
643
|
+
def process_schema_changes(schema_changes)
|
644
|
+
refresh_keyspaces = ::Hash.new
|
645
|
+
refresh_tables = ::Hash.new
|
646
|
+
|
647
|
+
schema_changes.each do |change|
|
648
|
+
keyspace = change.keyspace
|
649
|
+
table = change.table
|
650
|
+
|
651
|
+
next if refresh_keyspaces.has_key?(keyspace)
|
652
|
+
|
653
|
+
if table.empty?
|
654
|
+
refresh_tables.delete(keyspace)
|
655
|
+
refresh_keyspaces[keyspace] = true
|
656
|
+
else
|
657
|
+
tables = refresh_tables[keyspace] ||= ::Hash.new
|
658
|
+
tables[table] = true
|
659
|
+
end
|
660
|
+
end
|
661
|
+
|
662
|
+
futures = ::Array.new
|
663
|
+
|
664
|
+
refresh_keyspaces.each do |(keyspace, _)|
|
665
|
+
futures << refresh_keyspace_async_maybe_retry(keyspace)
|
666
|
+
end
|
667
|
+
|
668
|
+
refresh_tables.each do |(keyspace, tables)|
|
669
|
+
tables.each do |(table, _)|
|
670
|
+
futures << refresh_table_async_maybe_retry(keyspace, table)
|
671
|
+
end
|
672
|
+
end
|
673
|
+
|
674
|
+
Ione::Future.all(*futures)
|
675
|
+
end
|
676
|
+
|
677
|
+
def handle_schema_change(change)
|
678
|
+
timer = nil
|
679
|
+
expiration_timer = nil
|
680
|
+
|
681
|
+
synchronize do
|
682
|
+
@schema_changes << change
|
683
|
+
|
684
|
+
@io_reactor.cancel_timer(@schema_refresh_timer) if @schema_refresh_timer
|
685
|
+
timer = @schema_refresh_timer = @io_reactor.schedule_timer(@connection_options.schema_refresh_delay)
|
686
|
+
|
687
|
+
unless @schema_refresh_window
|
688
|
+
expiration_timer = @schema_refresh_window = @io_reactor.schedule_timer(@connection_options.schema_refresh_timeout)
|
689
|
+
end
|
690
|
+
end
|
691
|
+
|
692
|
+
if expiration_timer
|
693
|
+
expiration_timer.on_value do
|
694
|
+
schema_changes = nil
|
695
|
+
|
696
|
+
synchronize do
|
697
|
+
@io_reactor.cancel_timer(@schema_refresh_timer)
|
698
|
+
|
699
|
+
@schema_refresh_window = nil
|
700
|
+
@schema_refresh_timer = nil
|
701
|
+
|
702
|
+
schema_changes = @schema_changes
|
703
|
+
@schema_changes = ::Array.new
|
704
|
+
end
|
705
|
+
|
706
|
+
process_schema_changes(schema_changes)
|
707
|
+
end
|
708
|
+
end
|
709
|
+
|
710
|
+
timer.on_value do
|
711
|
+
schema_changes = nil
|
712
|
+
|
713
|
+
synchronize do
|
714
|
+
@io_reactor.cancel_timer(@schema_refresh_window)
|
715
|
+
|
716
|
+
@schema_refresh_window = nil
|
717
|
+
@schema_refresh_timer = nil
|
718
|
+
|
719
|
+
schema_changes = @schema_changes
|
720
|
+
@schema_changes = ::Array.new
|
721
|
+
end
|
722
|
+
|
723
|
+
process_schema_changes(schema_changes)
|
724
|
+
end
|
725
|
+
|
726
|
+
nil
|
727
|
+
end
|
728
|
+
|
665
729
|
def send_select_request(connection, request)
|
666
730
|
connection.send_request(request).map do |r|
|
667
731
|
case r
|
@@ -17,21 +17,19 @@
|
|
17
17
|
#++
|
18
18
|
|
19
19
|
module Cassandra
|
20
|
-
|
20
|
+
class Cluster
|
21
21
|
# @private
|
22
|
-
class
|
23
|
-
|
24
|
-
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
def warn(*); end
|
34
|
-
def warn?; false end
|
22
|
+
class FailedConnection
|
23
|
+
attr_reader :error, :host
|
24
|
+
|
25
|
+
def initialize(error, host)
|
26
|
+
@error = error
|
27
|
+
@host = host
|
28
|
+
end
|
29
|
+
|
30
|
+
def connected?
|
31
|
+
false
|
32
|
+
end
|
35
33
|
end
|
36
34
|
end
|
37
35
|
end
|