cassandra-driver 1.0.0.rc.1-java → 1.1.0-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/cassandra/auth.rb
CHANGED
@@ -18,9 +18,9 @@
|
|
18
18
|
|
19
19
|
module Cassandra
|
20
20
|
module Auth
|
21
|
-
# An auth provider is a factory for {Cassandra::Auth::Authenticator} instances
|
22
|
-
#
|
23
|
-
#
|
21
|
+
# An auth provider is a factory for {Cassandra::Auth::Authenticator authenticator} instances (or objects matching that interface). Its
|
22
|
+
# {#create_authenticator} will be called once for each connection that
|
23
|
+
# requires authentication.
|
24
24
|
#
|
25
25
|
# If the authentication requires keeping state, keep that in the
|
26
26
|
# authenticator instances, not in the auth provider.
|
data/lib/cassandra/cluster.rb
CHANGED
@@ -17,8 +17,7 @@
|
|
17
17
|
#++
|
18
18
|
|
19
19
|
module Cassandra
|
20
|
-
# Cluster represents a cassandra cluster. It serves as a {Cassandra::Session}
|
21
|
-
# factory and a collection of metadata.
|
20
|
+
# Cluster represents a cassandra cluster. It serves as a {Cassandra::Session session factory} factory and a collection of metadata.
|
22
21
|
#
|
23
22
|
# @see Cassandra::Cluster#connect Creating a new session
|
24
23
|
# @see Cassandra::Cluster#each_host Getting all peers in the cluster
|
@@ -26,46 +25,11 @@ module Cassandra
|
|
26
25
|
class Cluster
|
27
26
|
extend Forwardable
|
28
27
|
|
29
|
-
# @!method host(address)
|
30
|
-
# Find a host by its address
|
31
|
-
# @param address [IPAddr, String] ip address
|
32
|
-
# @return [Cassandra::Host, nil] host or nil
|
33
|
-
#
|
34
|
-
# @!method has_host?(address)
|
35
|
-
# Determine if a host by a given address exists
|
36
|
-
# @param address [IPAddr, String] ip address
|
37
|
-
# @return [Boolean] true or false
|
38
|
-
def_delegators :@registry, :host, :has_host?
|
39
|
-
|
40
|
-
# @!method keyspace(name)
|
41
|
-
# Find a keyspace by name
|
42
|
-
# @param name [String] keyspace name
|
43
|
-
# @return [Cassandra::Keyspace, nil] keyspace or nil
|
44
|
-
#
|
45
|
-
# @!method has_keyspace?(name)
|
46
|
-
# Determine if a keyspace by a given name exists
|
47
|
-
# @param name [String] keyspace name
|
48
|
-
# @return [Boolean] true or false
|
49
|
-
def_delegators :@schema, :keyspace, :has_keyspace?
|
50
|
-
|
51
|
-
# @!method name
|
52
|
-
# Return cluster's name
|
53
|
-
# @return [String] cluster's name
|
54
|
-
#
|
55
|
-
# @!method find_replicas(keyspace, statement)
|
56
|
-
# Return replicas for a given statement and keyspace
|
57
|
-
# @note an empty list is returned when statement/keyspace information is
|
58
|
-
# not enough to determine replica list.
|
59
|
-
# @param keyspace [String] keyspace name
|
60
|
-
# @param statement [Cassandra::Statement] statement for which to find
|
61
|
-
# replicas
|
62
|
-
# @return [Array<Cassandra::Host>] a list of replicas
|
63
|
-
def_delegators :@metadata, :name, :find_replicas
|
64
|
-
|
65
28
|
# @private
|
66
|
-
def initialize(logger, io_reactor, control_connection, cluster_registry, cluster_schema, cluster_metadata, execution_options, connection_options, load_balancing_policy, reconnection_policy, retry_policy, address_resolution_policy, connector, futures_factory)
|
29
|
+
def initialize(logger, io_reactor, executor, control_connection, cluster_registry, cluster_schema, cluster_metadata, execution_options, connection_options, load_balancing_policy, reconnection_policy, retry_policy, address_resolution_policy, connector, futures_factory)
|
67
30
|
@logger = logger
|
68
31
|
@io_reactor = io_reactor
|
32
|
+
@executor = executor
|
69
33
|
@control_connection = control_connection
|
70
34
|
@registry = cluster_registry
|
71
35
|
@schema = cluster_schema
|
@@ -78,8 +42,26 @@ module Cassandra
|
|
78
42
|
@address_resolver = address_resolution_policy
|
79
43
|
@connector = connector
|
80
44
|
@futures = futures_factory
|
45
|
+
|
46
|
+
@control_connection.on_close do |cause|
|
47
|
+
@load_balancing_policy.teardown(self) rescue nil
|
48
|
+
end
|
81
49
|
end
|
82
50
|
|
51
|
+
# @!method name
|
52
|
+
# Return cluster's name
|
53
|
+
# @return [String] cluster's name
|
54
|
+
#
|
55
|
+
# @!method find_replicas(keyspace, statement)
|
56
|
+
# Return replicas for a given statement and keyspace
|
57
|
+
# @note an empty list is returned when statement/keyspace information is
|
58
|
+
# not enough to determine replica list.
|
59
|
+
# @param keyspace [String] keyspace name
|
60
|
+
# @param statement [Cassandra::Statement] statement for which to find
|
61
|
+
# replicas
|
62
|
+
# @return [Array<Cassandra::Host>] a list of replicas
|
63
|
+
def_delegators :@metadata, :name, :find_replicas
|
64
|
+
|
83
65
|
# Register a cluster state listener. State listener will start receiving
|
84
66
|
# notifications about topology and schema changes
|
85
67
|
#
|
@@ -115,6 +97,17 @@ module Cassandra
|
|
115
97
|
end
|
116
98
|
alias :hosts :each_host
|
117
99
|
|
100
|
+
# @!method host(address)
|
101
|
+
# Find a host by its address
|
102
|
+
# @param address [IPAddr, String] ip address
|
103
|
+
# @return [Cassandra::Host, nil] host or nil
|
104
|
+
#
|
105
|
+
# @!method has_host?(address)
|
106
|
+
# Determine if a host by a given address exists
|
107
|
+
# @param address [IPAddr, String] ip address
|
108
|
+
# @return [Boolean] true or false
|
109
|
+
def_delegators :@registry, :host, :has_host?
|
110
|
+
|
118
111
|
# Yield or enumerate each keyspace defined in this cluster
|
119
112
|
# @overload each_keyspace
|
120
113
|
# @yieldparam keyspace [Cassandra::Keyspace] current keyspace
|
@@ -128,6 +121,35 @@ module Cassandra
|
|
128
121
|
end
|
129
122
|
alias :keyspaces :each_keyspace
|
130
123
|
|
124
|
+
# @!method keyspace(name)
|
125
|
+
# Find a keyspace by name
|
126
|
+
# @param name [String] keyspace name
|
127
|
+
# @return [Cassandra::Keyspace, nil] keyspace or nil
|
128
|
+
#
|
129
|
+
# @!method has_keyspace?(name)
|
130
|
+
# Determine if a keyspace by a given name exists
|
131
|
+
# @param name [String] keyspace name
|
132
|
+
# @return [Boolean] true or false
|
133
|
+
def_delegators :@schema, :keyspace, :has_keyspace?
|
134
|
+
|
135
|
+
# @!method refresh_schema_async
|
136
|
+
# Trigger an asynchronous schema metadata refresh
|
137
|
+
# @return [Cassandra::Future<nil>] a future that will be fulfilled when
|
138
|
+
# schema metadata has been refreshed
|
139
|
+
def_delegator :@control_connection, :refresh_schema_async_maybe_retry, \
|
140
|
+
:refresh_schema_async
|
141
|
+
|
142
|
+
# Synchronously refresh schema metadata
|
143
|
+
#
|
144
|
+
# @return [nil] nothing
|
145
|
+
# @raise [Cassandra::Errors::ClientError] when cluster is disconnected
|
146
|
+
# @raise [Cassandra::Error] other unexpected errors
|
147
|
+
#
|
148
|
+
# @see Cassandra::Cluster#refresh_schema_async
|
149
|
+
def refresh_schema
|
150
|
+
refresh_schema_async.get
|
151
|
+
end
|
152
|
+
|
131
153
|
# Asynchronously create a new session, optionally scoped to a keyspace
|
132
154
|
#
|
133
155
|
# @param keyspace [String] optional keyspace to scope session to
|
@@ -195,6 +217,8 @@ module Cassandra
|
|
195
217
|
else
|
196
218
|
f.on_failure {|e| promise.break(e)}
|
197
219
|
end
|
220
|
+
|
221
|
+
@executor.shutdown
|
198
222
|
end
|
199
223
|
|
200
224
|
promise.future
|
@@ -217,8 +241,10 @@ module Cassandra
|
|
217
241
|
end
|
218
242
|
|
219
243
|
require 'cassandra/cluster/client'
|
244
|
+
require 'cassandra/cluster/connection_pool'
|
220
245
|
require 'cassandra/cluster/connector'
|
221
246
|
require 'cassandra/cluster/control_connection'
|
247
|
+
require 'cassandra/cluster/failed_connection'
|
222
248
|
require 'cassandra/cluster/metadata'
|
223
249
|
require 'cassandra/cluster/options'
|
224
250
|
require 'cassandra/cluster/registry'
|
@@ -63,11 +63,12 @@ module Cassandra
|
|
63
63
|
@connected_future = begin
|
64
64
|
@logger.info('Creating session')
|
65
65
|
@registry.add_listener(self)
|
66
|
+
@schema.add_listener(self)
|
66
67
|
|
67
68
|
futures = @connecting_hosts.map do |(host, distance)|
|
68
69
|
f = connect_to_host(host, distance)
|
69
70
|
f.recover do |error|
|
70
|
-
|
71
|
+
FailedConnection.new(error, host)
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
@@ -100,6 +101,7 @@ module Cassandra
|
|
100
101
|
|
101
102
|
@closed_future = begin
|
102
103
|
@registry.remove_listener(self)
|
104
|
+
@schema.remove_listener(self)
|
103
105
|
|
104
106
|
if state == :connecting
|
105
107
|
f = @connected_future.recover.flat_map { close_connections }
|
@@ -138,7 +140,7 @@ module Cassandra
|
|
138
140
|
end
|
139
141
|
|
140
142
|
def host_down(host)
|
141
|
-
|
143
|
+
pool = nil
|
142
144
|
|
143
145
|
synchronize do
|
144
146
|
return Ione::Future.resolved if !@connections.has_key?(host) && !@connecting_hosts.include?(host)
|
@@ -147,18 +149,30 @@ module Cassandra
|
|
147
149
|
@prepared_statements.delete(host)
|
148
150
|
@preparing_statements.delete(host)
|
149
151
|
|
150
|
-
|
152
|
+
pool = @connections.delete(host)
|
151
153
|
end
|
152
154
|
|
153
|
-
if
|
154
|
-
Ione::Future.all(*
|
155
|
+
if pool
|
156
|
+
Ione::Future.all(*pool.snapshot.map! {|c| c.close}).map(nil)
|
155
157
|
else
|
156
158
|
Ione::Future.resolved
|
157
159
|
end
|
158
160
|
end
|
159
161
|
|
160
|
-
def
|
161
|
-
|
162
|
+
def keyspace_created(keyspace)
|
163
|
+
end
|
164
|
+
|
165
|
+
def keyspace_changed(keyspace)
|
166
|
+
end
|
167
|
+
|
168
|
+
def keyspace_dropped(keyspace)
|
169
|
+
@keyspace = nil if @keyspace == keyspace.name
|
170
|
+
nil
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
def query(statement, options)
|
175
|
+
request = Protocol::QueryRequest.new(statement.cql, statement.params, nil, options.consistency, options.serial_consistency, options.page_size, options.paging_state, options.trace?)
|
162
176
|
timeout = options.timeout
|
163
177
|
promise = @futures.promise
|
164
178
|
|
@@ -184,10 +198,10 @@ module Cassandra
|
|
184
198
|
promise.future
|
185
199
|
end
|
186
200
|
|
187
|
-
def execute(statement, options
|
201
|
+
def execute(statement, options)
|
188
202
|
timeout = options.timeout
|
189
203
|
result_metadata = statement.result_metadata
|
190
|
-
request = Protocol::ExecuteRequest.new(nil, statement.params_metadata, statement.params, result_metadata.nil?, options.consistency, options.serial_consistency, options.page_size, paging_state, options.trace?)
|
204
|
+
request = Protocol::ExecuteRequest.new(nil, statement.params_metadata, statement.params, result_metadata.nil?, options.consistency, options.serial_consistency, options.page_size, options.paging_state, options.trace?)
|
191
205
|
promise = @futures.promise
|
192
206
|
|
193
207
|
keyspace = @keyspace
|
@@ -331,19 +345,46 @@ module Cassandra
|
|
331
345
|
return NO_CONNECTIONS
|
332
346
|
end
|
333
347
|
|
334
|
-
|
348
|
+
pool = nil
|
349
|
+
existing_connections = 0
|
350
|
+
|
351
|
+
synchronize do
|
352
|
+
pool = @connections[host]
|
353
|
+
end
|
354
|
+
|
355
|
+
existing_connections = pool.size if pool
|
356
|
+
pool = nil
|
357
|
+
missing_connections = (pool_size - existing_connections)
|
358
|
+
return Ione::Future.resolved if missing_connections <= 0
|
359
|
+
|
360
|
+
f = @connector.connect_many(host, missing_connections)
|
335
361
|
|
336
362
|
f.on_value do |connections|
|
337
|
-
|
363
|
+
pool = nil
|
338
364
|
|
339
365
|
synchronize do
|
340
366
|
@connecting_hosts.delete(host)
|
341
367
|
@prepared_statements[host] = {}
|
342
368
|
@preparing_statements[host] = {}
|
343
|
-
|
369
|
+
pool = @connections[host] ||= ConnectionPool.new
|
344
370
|
end
|
345
371
|
|
346
|
-
|
372
|
+
pool.add_connections(connections)
|
373
|
+
|
374
|
+
connections.each do |connection|
|
375
|
+
connection.on_closed do
|
376
|
+
distance = nil
|
377
|
+
|
378
|
+
synchronize do
|
379
|
+
if !(@state == :closed || @state == :closing) && !@connecting_hosts.include?(host) && @connections.include?(host)
|
380
|
+
distance = @load_balancing_policy.distance(host)
|
381
|
+
@connecting_hosts[host] = distance unless distance == :ignore
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
connect_to_host_maybe_retry(host, distance).map(nil) if distance
|
386
|
+
end
|
387
|
+
end
|
347
388
|
end
|
348
389
|
|
349
390
|
f
|
@@ -356,16 +397,16 @@ module Cassandra
|
|
356
397
|
end
|
357
398
|
|
358
399
|
hosts << host = plan.next
|
359
|
-
|
360
|
-
synchronize {
|
400
|
+
pool = nil
|
401
|
+
synchronize { pool = @connections[host] }
|
361
402
|
|
362
|
-
unless
|
403
|
+
unless pool
|
363
404
|
errors ||= {}
|
364
405
|
errors[host] = NOT_CONNECTED
|
365
406
|
return execute_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
|
366
407
|
end
|
367
408
|
|
368
|
-
connection =
|
409
|
+
connection = pool.random_connection
|
369
410
|
|
370
411
|
if keyspace && connection.keyspace != keyspace
|
371
412
|
switch = switch_keyspace(connection, keyspace, timeout)
|
@@ -430,16 +471,16 @@ module Cassandra
|
|
430
471
|
end
|
431
472
|
|
432
473
|
hosts << host = plan.next
|
433
|
-
|
434
|
-
synchronize {
|
474
|
+
pool = nil
|
475
|
+
synchronize { pool = @connections[host] }
|
435
476
|
|
436
|
-
unless
|
477
|
+
unless pool
|
437
478
|
errors ||= {}
|
438
479
|
errors[host] = NOT_CONNECTED
|
439
480
|
return batch_by_plan(promise, keyspace, statement, options, plan, timeout, errors, hosts)
|
440
481
|
end
|
441
482
|
|
442
|
-
connection =
|
483
|
+
connection = pool.random_connection
|
443
484
|
|
444
485
|
if keyspace && connection.keyspace != keyspace
|
445
486
|
switch = switch_keyspace(connection, keyspace, timeout)
|
@@ -529,16 +570,16 @@ module Cassandra
|
|
529
570
|
end
|
530
571
|
|
531
572
|
hosts << host = plan.next
|
532
|
-
|
533
|
-
synchronize {
|
573
|
+
pool = nil
|
574
|
+
synchronize { pool = @connections[host] }
|
534
575
|
|
535
|
-
unless
|
576
|
+
unless pool
|
536
577
|
errors ||= {}
|
537
578
|
errors[host] = NOT_CONNECTED
|
538
579
|
return send_request_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
|
539
580
|
end
|
540
581
|
|
541
|
-
connection =
|
582
|
+
connection = pool.random_connection
|
542
583
|
|
543
584
|
if keyspace && connection.keyspace != keyspace
|
544
585
|
switch = switch_keyspace(connection, keyspace, timeout)
|
@@ -671,9 +712,7 @@ module Cassandra
|
|
671
712
|
when Protocol::RowsResultResponse
|
672
713
|
promise.fulfill(Results::Paged.new(r.rows, r.paging_state, r.trace_id, keyspace, statement, options, hosts, request.consistency, retries, self, @futures))
|
673
714
|
when Protocol::SchemaChangeResultResponse
|
674
|
-
if r.change == 'DROPPED' && r.
|
675
|
-
@keyspace = nil
|
676
|
-
end
|
715
|
+
@schema.delete_keyspace(r.keyspace) if r.change == 'DROPPED' && r.table.empty?
|
677
716
|
|
678
717
|
@logger.debug('Waiting for schema to propagate to all hosts after a change')
|
679
718
|
wait_for_schema_agreement(connection, @reconnection_policy.schedule).on_complete do |f|
|
@@ -17,14 +17,14 @@
|
|
17
17
|
#++
|
18
18
|
|
19
19
|
module Cassandra
|
20
|
-
|
20
|
+
class Cluster
|
21
21
|
# @private
|
22
|
-
class
|
22
|
+
class ConnectionPool
|
23
23
|
include Enumerable
|
24
24
|
|
25
25
|
def initialize
|
26
26
|
@connections = []
|
27
|
-
@lock = Mutex.new
|
27
|
+
@lock = ::Mutex.new
|
28
28
|
end
|
29
29
|
|
30
30
|
def add_connections(connections)
|
@@ -59,6 +59,12 @@ module Cassandra
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
+
def size
|
63
|
+
@lock.synchronize do
|
64
|
+
@connections.size
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
62
68
|
def each_connection(&callback)
|
63
69
|
return self unless block_given?
|
64
70
|
raise Errors::IOError, 'Not connected' unless connected?
|
@@ -22,13 +22,14 @@ module Cassandra
|
|
22
22
|
class Connector
|
23
23
|
include MonitorMixin
|
24
24
|
|
25
|
-
def initialize(logger, io_reactor, cluster_registry, connection_options)
|
26
|
-
@logger
|
27
|
-
@reactor
|
28
|
-
@registry
|
29
|
-
@
|
30
|
-
@
|
31
|
-
@
|
25
|
+
def initialize(logger, io_reactor, cluster_registry, connection_options, execution_options)
|
26
|
+
@logger = logger
|
27
|
+
@reactor = io_reactor
|
28
|
+
@registry = cluster_registry
|
29
|
+
@connection_options = connection_options
|
30
|
+
@execution_options = execution_options
|
31
|
+
@connections = ::Hash.new
|
32
|
+
@open_connections = ::Hash.new
|
32
33
|
|
33
34
|
mon_initialize
|
34
35
|
end
|
@@ -115,13 +116,33 @@ module Cassandra
|
|
115
116
|
UNCLAIMED_TIMEOUT = 5 # close unclaimed connections in five seconds
|
116
117
|
|
117
118
|
def do_connect(host)
|
118
|
-
|
119
|
+
f = @reactor.connect(host.ip.to_s, @connection_options.port, {:timeout => @connection_options.connect_timeout, :ssl => @connection_options.ssl}) do |connection|
|
120
|
+
raise Errors::ClientError, 'Not connected, reactor stopped' unless connection
|
121
|
+
Protocol::CqlProtocolHandler.new(connection, @reactor, @connection_options.protocol_version, @connection_options.compressor, @connection_options.heartbeat_interval, @connection_options.idle_timeout)
|
122
|
+
end
|
123
|
+
f = f.flat_map do |connection|
|
124
|
+
request_options(connection).flat_map do |options|
|
125
|
+
compression = @connection_options.compression
|
126
|
+
supported_algorithms = options['COMPRESSION']
|
127
|
+
|
128
|
+
if compression && !supported_algorithms.include?(compression)
|
129
|
+
@logger.warn("Compression with #{compression.inspect} is not supported by host at #{host.ip}, supported algorithms are #{supported_algorithms.inspect}")
|
130
|
+
compression = nil
|
131
|
+
end
|
132
|
+
|
133
|
+
supported_cql_versions = options['CQL_VERSION']
|
134
|
+
cql_version = (supported_cql_versions && !supported_cql_versions.empty?) ? supported_cql_versions.first : '3.1.0'
|
135
|
+
|
136
|
+
startup_connection(connection, cql_version, compression)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
f.fallback do |error|
|
119
140
|
case error
|
120
141
|
when Errors::ProtocolError
|
121
142
|
synchronize do
|
122
|
-
if @
|
123
|
-
@logger.info("Host #{host.ip} doesn't support protocol version #{@
|
124
|
-
@
|
143
|
+
if @connection_options.protocol_version > 1
|
144
|
+
@logger.info("Host #{host.ip} doesn't support protocol version #{@connection_options.protocol_version}, downgrading")
|
145
|
+
@connection_options.protocol_version -= 1
|
125
146
|
do_connect(host)
|
126
147
|
else
|
127
148
|
Ione::Future.failed(error)
|
@@ -137,32 +158,82 @@ module Cassandra
|
|
137
158
|
end
|
138
159
|
end
|
139
160
|
|
140
|
-
def
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
161
|
+
def startup_connection(connection, cql_version, compression)
|
162
|
+
connection.send_request(Protocol::StartupRequest.new(cql_version, compression), @execution_options.timeout).flat_map do |r|
|
163
|
+
case r
|
164
|
+
when Protocol::AuthenticateResponse
|
165
|
+
if @connection_options.protocol_version == 1
|
166
|
+
credentials = @connection_options.credentials
|
167
|
+
if credentials
|
168
|
+
send_credentials(connection, credentials)
|
169
|
+
else
|
170
|
+
Ione::Future.failed(Errors::AuthenticationError.new('Server requested authentication, but client was not configured to authenticate'))
|
171
|
+
end
|
172
|
+
else
|
173
|
+
authenticator = @connection_options.create_authenticator(r.authentication_class)
|
174
|
+
if authenticator
|
175
|
+
challenge_response_cycle(connection, authenticator, authenticator.initial_response)
|
176
|
+
else
|
177
|
+
Ione::Future.failed(Errors::AuthenticationError.new('Server requested authentication, but client was not configured to authenticate'))
|
178
|
+
end
|
179
|
+
end
|
180
|
+
when Protocol::ReadyResponse
|
181
|
+
::Ione::Future.resolved(connection)
|
182
|
+
when Protocol::ErrorResponse
|
183
|
+
::Ione::Future.failed(r.to_error(VOID_STATEMENT))
|
184
|
+
else
|
185
|
+
::Ione::Future.failed(Errors::InternalError.new("Unexpected response #{r.inspect}"))
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def request_options(connection)
|
191
|
+
connection.send_request(Protocol::OptionsRequest.new, @execution_options.timeout).map do |r|
|
192
|
+
case r
|
193
|
+
when Protocol::SupportedResponse
|
194
|
+
r.options
|
195
|
+
when Protocol::ErrorResponse
|
196
|
+
raise r.to_error(VOID_STATEMENT)
|
197
|
+
else
|
198
|
+
raise Errors::InternalError, "Unexpected response #{r.inspect}"
|
199
|
+
end
|
145
200
|
end
|
201
|
+
end
|
146
202
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
203
|
+
def send_credentials(connection, credentials)
|
204
|
+
connection.send_request(Protocol::CredentialsRequest.new(credentials), @execution_options.timeout).map do |r|
|
205
|
+
case r
|
206
|
+
when Protocol::ReadyResponse
|
207
|
+
connection
|
208
|
+
when Protocol::ErrorResponse
|
209
|
+
raise r.to_error(VOID_STATEMENT)
|
210
|
+
else
|
211
|
+
raise Errors::InternalError, "Unexpected response #{r.inspect}"
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def challenge_response_cycle(connection, authenticator, token)
|
217
|
+
connection.send_request(Protocol::AuthResponseRequest.new(token), @execution_options.timeout).flat_map do |r|
|
218
|
+
case r
|
219
|
+
when Protocol::AuthChallengeResponse
|
220
|
+
token = authenticator.challenge_response(r.token)
|
221
|
+
challenge_response_cycle(pending_connection, authenticator, token)
|
222
|
+
when Protocol::AuthSuccessResponse
|
223
|
+
authenticator.authentication_successful(r.token) rescue nil
|
224
|
+
::Ione::Future.resolved(connection)
|
225
|
+
when Protocol::ErrorResponse
|
226
|
+
::Ione::Future.failed(r.to_error(VOID_STATEMENT))
|
227
|
+
else
|
228
|
+
::Ione::Future.failed(Errors::InternalError.new("Unexpected response #{r.inspect}"))
|
229
|
+
end
|
230
|
+
end
|
160
231
|
end
|
161
232
|
|
162
233
|
def create_additional_connections(host, count, established_connections, error = nil)
|
163
234
|
futures = count.times.map do
|
164
235
|
connect(host).recover do |e|
|
165
|
-
|
236
|
+
FailedConnection.new(e, host)
|
166
237
|
end
|
167
238
|
end
|
168
239
|
|