cassandra-driver 3.0.0.beta.1 → 3.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 +8 -8
- data/README.md +90 -38
- data/ext/cassandra_murmur3/cassandra_murmur3.c +1 -1
- data/lib/cassandra.rb +327 -130
- data/lib/cassandra/address_resolution.rb +1 -1
- data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +1 -1
- data/lib/cassandra/address_resolution/policies/none.rb +1 -1
- data/lib/cassandra/aggregate.rb +21 -7
- data/lib/cassandra/argument.rb +2 -2
- data/lib/cassandra/auth.rb +4 -4
- data/lib/cassandra/auth/providers.rb +1 -1
- data/lib/cassandra/auth/providers/password.rb +9 -5
- data/lib/cassandra/cassandra_logger.rb +80 -0
- data/lib/cassandra/cluster.rb +38 -9
- data/lib/cassandra/cluster/client.rb +801 -205
- data/lib/cassandra/cluster/connection_pool.rb +2 -2
- data/lib/cassandra/cluster/connector.rb +74 -25
- data/lib/cassandra/cluster/control_connection.rb +217 -82
- data/lib/cassandra/cluster/failed_connection.rb +1 -1
- data/lib/cassandra/cluster/metadata.rb +12 -4
- data/lib/cassandra/cluster/options.rb +60 -11
- data/lib/cassandra/cluster/registry.rb +69 -16
- data/lib/cassandra/cluster/schema.rb +25 -7
- data/lib/cassandra/cluster/schema/cql_type_parser.rb +15 -10
- data/lib/cassandra/cluster/schema/fetchers.rb +263 -106
- data/lib/cassandra/cluster/schema/fqcn_type_parser.rb +41 -36
- data/lib/cassandra/cluster/schema/partitioners.rb +1 -1
- data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +3 -3
- data/lib/cassandra/cluster/schema/partitioners/ordered.rb +1 -1
- data/lib/cassandra/cluster/schema/partitioners/random.rb +1 -1
- data/lib/cassandra/cluster/schema/replication_strategies.rb +1 -1
- data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +19 -18
- data/lib/cassandra/cluster/schema/replication_strategies/none.rb +1 -1
- data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +1 -1
- data/lib/cassandra/column.rb +3 -3
- data/lib/cassandra/compression.rb +1 -1
- data/lib/cassandra/compression/compressors/lz4.rb +4 -3
- data/lib/cassandra/compression/compressors/snappy.rb +4 -3
- data/lib/cassandra/driver.rb +103 -41
- data/lib/cassandra/errors.rb +265 -30
- data/lib/cassandra/execution/info.rb +16 -5
- data/lib/cassandra/execution/options.rb +99 -54
- data/lib/cassandra/execution/trace.rb +16 -9
- data/lib/cassandra/executors.rb +1 -1
- data/lib/cassandra/function.rb +19 -13
- data/lib/cassandra/function_collection.rb +85 -0
- data/lib/cassandra/future.rb +106 -48
- data/lib/cassandra/host.rb +10 -4
- data/lib/cassandra/keyspace.rb +90 -33
- data/lib/cassandra/listener.rb +1 -1
- data/lib/cassandra/load_balancing.rb +2 -2
- data/lib/cassandra/load_balancing/policies.rb +1 -1
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +18 -18
- data/lib/cassandra/load_balancing/policies/round_robin.rb +1 -1
- data/lib/cassandra/load_balancing/policies/token_aware.rb +15 -13
- data/lib/cassandra/load_balancing/policies/white_list.rb +11 -5
- data/lib/cassandra/null_logger.rb +27 -6
- data/lib/cassandra/protocol.rb +1 -1
- data/lib/cassandra/protocol/coder.rb +78 -39
- data/lib/cassandra/protocol/cql_byte_buffer.rb +50 -33
- data/lib/cassandra/protocol/cql_protocol_handler.rb +44 -45
- data/lib/cassandra/protocol/request.rb +2 -2
- data/lib/cassandra/protocol/requests/auth_response_request.rb +3 -3
- data/lib/cassandra/protocol/requests/batch_request.rb +16 -7
- data/lib/cassandra/protocol/requests/credentials_request.rb +3 -3
- data/lib/cassandra/protocol/requests/execute_request.rb +41 -20
- data/lib/cassandra/protocol/requests/options_request.rb +1 -1
- data/lib/cassandra/protocol/requests/prepare_request.rb +5 -5
- data/lib/cassandra/protocol/requests/query_request.rb +27 -22
- data/lib/cassandra/protocol/requests/register_request.rb +2 -2
- data/lib/cassandra/protocol/requests/startup_request.rb +6 -4
- data/lib/cassandra/protocol/requests/void_query_request.rb +1 -1
- data/lib/cassandra/protocol/response.rb +2 -2
- data/lib/cassandra/protocol/responses/already_exists_error_response.rb +12 -2
- data/lib/cassandra/protocol/responses/auth_challenge_response.rb +1 -1
- data/lib/cassandra/protocol/responses/auth_success_response.rb +1 -1
- data/lib/cassandra/protocol/responses/authenticate_response.rb +1 -1
- data/lib/cassandra/protocol/responses/error_response.rb +101 -13
- data/lib/cassandra/protocol/responses/event_response.rb +1 -1
- data/lib/cassandra/protocol/responses/function_failure_error_response.rb +13 -2
- data/lib/cassandra/protocol/responses/prepared_result_response.rb +11 -5
- data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +14 -9
- data/lib/cassandra/protocol/responses/read_failure_error_response.rb +26 -4
- data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +22 -3
- data/lib/cassandra/protocol/responses/ready_response.rb +3 -3
- data/lib/cassandra/protocol/responses/result_response.rb +4 -2
- data/lib/cassandra/protocol/responses/rows_result_response.rb +5 -3
- data/lib/cassandra/protocol/responses/schema_change_event_response.rb +5 -4
- data/lib/cassandra/protocol/responses/schema_change_result_response.rb +16 -9
- data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +2 -2
- data/lib/cassandra/protocol/responses/status_change_event_response.rb +2 -2
- data/lib/cassandra/protocol/responses/supported_response.rb +1 -1
- data/lib/cassandra/protocol/responses/topology_change_event_response.rb +1 -1
- data/lib/cassandra/protocol/responses/unavailable_error_response.rb +20 -3
- data/lib/cassandra/protocol/responses/unprepared_error_response.rb +11 -2
- data/lib/cassandra/protocol/responses/void_result_response.rb +1 -1
- data/lib/cassandra/protocol/responses/write_failure_error_response.rb +26 -4
- data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +22 -3
- data/lib/cassandra/protocol/v1.rb +101 -36
- data/lib/cassandra/protocol/v3.rb +124 -51
- data/lib/cassandra/protocol/v4.rb +172 -68
- data/lib/cassandra/reconnection.rb +1 -1
- data/lib/cassandra/reconnection/policies.rb +1 -1
- data/lib/cassandra/reconnection/policies/constant.rb +2 -4
- data/lib/cassandra/reconnection/policies/exponential.rb +6 -6
- data/lib/cassandra/result.rb +53 -19
- data/lib/cassandra/retry.rb +8 -8
- data/lib/cassandra/retry/policies.rb +1 -1
- data/lib/cassandra/retry/policies/default.rb +1 -1
- data/lib/cassandra/retry/policies/downgrading_consistency.rb +7 -3
- data/lib/cassandra/retry/policies/fallthrough.rb +1 -1
- data/lib/cassandra/session.rb +22 -16
- data/lib/cassandra/statement.rb +1 -1
- data/lib/cassandra/statements.rb +1 -1
- data/lib/cassandra/statements/batch.rb +16 -10
- data/lib/cassandra/statements/bound.rb +10 -3
- data/lib/cassandra/statements/prepared.rb +59 -15
- data/lib/cassandra/statements/simple.rb +23 -10
- data/lib/cassandra/statements/void.rb +1 -1
- data/lib/cassandra/table.rb +79 -30
- data/lib/cassandra/time.rb +11 -6
- data/lib/cassandra/time_uuid.rb +7 -7
- data/lib/cassandra/tuple.rb +16 -8
- data/lib/cassandra/types.rb +20 -9
- data/lib/cassandra/udt.rb +32 -36
- data/lib/cassandra/util.rb +20 -13
- data/lib/cassandra/uuid.rb +22 -15
- data/lib/cassandra/uuid/generator.rb +7 -5
- data/lib/cassandra/version.rb +2 -2
- data/lib/datastax/cassandra.rb +1 -1
- metadata +5 -3
data/lib/cassandra/aggregate.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright 2013-
|
4
|
+
# Copyright 2013-2016 DataStax, Inc.
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -40,7 +40,14 @@ module Cassandra
|
|
40
40
|
attr_reader :final_function
|
41
41
|
|
42
42
|
# @private
|
43
|
-
def initialize(keyspace,
|
43
|
+
def initialize(keyspace,
|
44
|
+
name,
|
45
|
+
type,
|
46
|
+
argument_types,
|
47
|
+
state_type,
|
48
|
+
initial_state,
|
49
|
+
state_function,
|
50
|
+
final_function)
|
44
51
|
@keyspace = keyspace
|
45
52
|
@name = name
|
46
53
|
@type = type
|
@@ -63,7 +70,7 @@ module Cassandra
|
|
63
70
|
@state_function == other.state_function && \
|
64
71
|
@final_function == other.final_function
|
65
72
|
end
|
66
|
-
alias
|
73
|
+
alias == eql?
|
67
74
|
|
68
75
|
# @private
|
69
76
|
def hash
|
@@ -83,12 +90,19 @@ module Cassandra
|
|
83
90
|
|
84
91
|
# @private
|
85
92
|
def inspect
|
86
|
-
"#<Cassandra::Aggregate:0x#{
|
93
|
+
"#<Cassandra::Aggregate:0x#{object_id.to_s(16)} " \
|
94
|
+
"@keyspace=#{@keyspace.inspect}, " \
|
95
|
+
"@name=#{@name.inspect}, " \
|
96
|
+
"@type=#{@type.inspect}, " \
|
97
|
+
"@argument_types=#{@argument_types.inspect}, " \
|
98
|
+
"@initial_state=#{@initial_state.inspect}, " \
|
99
|
+
"@state_function=#{@state_function.inspect}, " \
|
100
|
+
"@final_function=#{@final_function.inspect}>"
|
87
101
|
end
|
88
102
|
|
89
103
|
# @return [String] a cql representation of this aggregate
|
90
104
|
def to_cql
|
91
|
-
cql =
|
105
|
+
cql = 'CREATE AGGREGATE simplex.average('
|
92
106
|
first = true
|
93
107
|
@argument_types.each do |type|
|
94
108
|
if first
|
@@ -98,12 +112,12 @@ module Cassandra
|
|
98
112
|
end
|
99
113
|
cql << type.to_s
|
100
114
|
end
|
101
|
-
cql <<
|
115
|
+
cql << ')'
|
102
116
|
cql << "\n SFUNC #{@state_function.name}"
|
103
117
|
cql << "\n STYPE #{@state_type}"
|
104
118
|
cql << "\n FINALFUNC #{@final_function.name}" if @final_function
|
105
119
|
cql << "\n INITCOND #{@initial_state}"
|
106
|
-
cql <<
|
120
|
+
cql << ';'
|
107
121
|
end
|
108
122
|
end
|
109
123
|
end
|
data/lib/cassandra/argument.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright 2013-
|
4
|
+
# Copyright 2013-2016 DataStax, Inc.
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -36,7 +36,7 @@ module Cassandra
|
|
36
36
|
@name == other.name && \
|
37
37
|
@type == other.type
|
38
38
|
end
|
39
|
-
alias
|
39
|
+
alias == eql?
|
40
40
|
|
41
41
|
# @private
|
42
42
|
def hash
|
data/lib/cassandra/auth.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright 2013-
|
4
|
+
# Copyright 2013-2016 DataStax, Inc.
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -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 authenticator}
|
22
|
-
#
|
23
|
-
# requires authentication.
|
21
|
+
# An auth provider is a factory for {Cassandra::Auth::Authenticator authenticator}
|
22
|
+
# instances (or objects matching that interface). Its {#create_authenticator} will
|
23
|
+
# be called once for each connection that 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.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright 2013-
|
4
|
+
# Copyright 2013-2016 DataStax, Inc.
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -53,9 +53,12 @@ module Cassandra
|
|
53
53
|
@password = password
|
54
54
|
end
|
55
55
|
|
56
|
-
# Returns a Password Authenticator only if
|
57
|
-
#
|
58
|
-
# @
|
56
|
+
# Returns a Password Authenticator only if
|
57
|
+
# `org.apache.cassandra.auth.PasswordAuthenticator` is given.
|
58
|
+
# @param authentication_class [String] must equal to
|
59
|
+
# `org.apache.cassandra.auth.PasswordAuthenticator`
|
60
|
+
# @return [Cassandra::Auth::Authenticator] when `authentication_class ==
|
61
|
+
# "org.apache.cassandra.auth.PasswordAuthenticator"`
|
59
62
|
# @return [nil] for all other values of `authentication_class`
|
60
63
|
def create_authenticator(authentication_class)
|
61
64
|
if authentication_class == PASSWORD_AUTHENTICATOR_FQCN
|
@@ -66,7 +69,8 @@ module Cassandra
|
|
66
69
|
private
|
67
70
|
|
68
71
|
# @private
|
69
|
-
PASSWORD_AUTHENTICATOR_FQCN =
|
72
|
+
PASSWORD_AUTHENTICATOR_FQCN =
|
73
|
+
'org.apache.cassandra.auth.PasswordAuthenticator'.freeze
|
70
74
|
end
|
71
75
|
end
|
72
76
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright 2013-2016 DataStax, Inc.
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#++
|
18
|
+
|
19
|
+
require 'logger'
|
20
|
+
module Cassandra
|
21
|
+
# This class is a logger that may be used by the client to log the driver's actions.
|
22
|
+
# It is a subclass of the standard Ruby Logger class, so it is instantiated the
|
23
|
+
# same way.
|
24
|
+
#
|
25
|
+
# The format of log output is set to include the timestamp, thread-id, log severity,
|
26
|
+
# and message. <b>This format may change in newer versions of the driver to account
|
27
|
+
# for new/deprecated metadata.</b>
|
28
|
+
#
|
29
|
+
# @example Configuring {Cassandra::Cluster} to use a logger.
|
30
|
+
# cluster = Cassandra.cluster(logger: Cassandra::Logger.new($stderr))
|
31
|
+
#
|
32
|
+
# @example The log format may be changed the same way as in the standard Ruby Logger class
|
33
|
+
# logger = Cassandra::Logger.new($stderr)
|
34
|
+
# logger.formatter = proc { |severity, time, program_name, message|
|
35
|
+
# "[%s]: %s\n" % [severity, message]
|
36
|
+
# }
|
37
|
+
#
|
38
|
+
# @example Create a logger and use it in your own business logic
|
39
|
+
# logger = Cassandra::Logger.new($stderr)
|
40
|
+
# cluster = Cassandra.cluster(logger: logger)
|
41
|
+
# <various logic>
|
42
|
+
# logger.debug("something interesting happened.")
|
43
|
+
|
44
|
+
class Logger < ::Logger
|
45
|
+
# @private
|
46
|
+
# This class is mostly copied from the Ruby Logger::Format class.
|
47
|
+
class Formatter
|
48
|
+
Format = "[%s#%d] %5s: %s\n".freeze
|
49
|
+
|
50
|
+
def call(severity, time, _, msg)
|
51
|
+
format(Format,
|
52
|
+
format_datetime(time),
|
53
|
+
Thread.current.object_id,
|
54
|
+
severity,
|
55
|
+
msg2str(msg))
|
56
|
+
end
|
57
|
+
|
58
|
+
def format_datetime(time)
|
59
|
+
time.strftime('%H:%M:%S.') << format('%06d ', time.usec)
|
60
|
+
end
|
61
|
+
|
62
|
+
def msg2str(msg)
|
63
|
+
case msg
|
64
|
+
when ::String
|
65
|
+
msg
|
66
|
+
when ::Exception
|
67
|
+
"#{msg.message} (#{msg.class})\n" <<
|
68
|
+
(msg.backtrace || []).join("\n")
|
69
|
+
else
|
70
|
+
msg.inspect
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def initialize(*args)
|
76
|
+
super(*args)
|
77
|
+
self.formatter = Formatter.new
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/cassandra/cluster.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright 2013-
|
4
|
+
# Copyright 2013-2016 DataStax, Inc.
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -17,7 +17,8 @@
|
|
17
17
|
#++
|
18
18
|
|
19
19
|
module Cassandra
|
20
|
-
# Cluster represents a cassandra cluster. It serves as a
|
20
|
+
# Cluster represents a cassandra cluster. It serves as a
|
21
|
+
# {Cassandra::Session session factory} factory and a collection of metadata.
|
21
22
|
#
|
22
23
|
# @see Cassandra::Cluster#connect Creating a new session
|
23
24
|
# @see Cassandra::Cluster#each_host Getting all peers in the cluster
|
@@ -26,7 +27,21 @@ module Cassandra
|
|
26
27
|
extend Forwardable
|
27
28
|
|
28
29
|
# @private
|
29
|
-
def initialize(logger,
|
30
|
+
def initialize(logger,
|
31
|
+
io_reactor,
|
32
|
+
executor,
|
33
|
+
control_connection,
|
34
|
+
cluster_registry,
|
35
|
+
cluster_schema,
|
36
|
+
cluster_metadata,
|
37
|
+
execution_options,
|
38
|
+
connection_options,
|
39
|
+
load_balancing_policy,
|
40
|
+
reconnection_policy,
|
41
|
+
retry_policy,
|
42
|
+
address_resolution_policy,
|
43
|
+
connector,
|
44
|
+
futures_factory)
|
30
45
|
@logger = logger
|
31
46
|
@io_reactor = io_reactor
|
32
47
|
@executor = executor
|
@@ -43,8 +58,12 @@ module Cassandra
|
|
43
58
|
@connector = connector
|
44
59
|
@futures = futures_factory
|
45
60
|
|
46
|
-
@control_connection.on_close do |
|
47
|
-
|
61
|
+
@control_connection.on_close do |_cause|
|
62
|
+
begin
|
63
|
+
@load_balancing_policy.teardown(self)
|
64
|
+
rescue
|
65
|
+
nil
|
66
|
+
end
|
48
67
|
end
|
49
68
|
end
|
50
69
|
|
@@ -95,7 +114,7 @@ module Cassandra
|
|
95
114
|
return self if r == @registry
|
96
115
|
r
|
97
116
|
end
|
98
|
-
alias
|
117
|
+
alias hosts each_host
|
99
118
|
|
100
119
|
# @!method host(address)
|
101
120
|
# Find a host by its address
|
@@ -119,7 +138,7 @@ module Cassandra
|
|
119
138
|
return self if r == @schema
|
120
139
|
r
|
121
140
|
end
|
122
|
-
alias
|
141
|
+
alias keyspaces each_keyspace
|
123
142
|
|
124
143
|
# @!method keyspace(name)
|
125
144
|
# Find a keyspace by name
|
@@ -175,7 +194,17 @@ module Cassandra
|
|
175
194
|
return @futures.error(::ArgumentError.new("keyspace must be a string, #{keyspace.inspect} given"))
|
176
195
|
end
|
177
196
|
|
178
|
-
client = Client.new(@logger,
|
197
|
+
client = Client.new(@logger,
|
198
|
+
@registry,
|
199
|
+
@schema,
|
200
|
+
@io_reactor,
|
201
|
+
@connector,
|
202
|
+
@load_balancing_policy,
|
203
|
+
@reconnection_policy,
|
204
|
+
@retry_policy,
|
205
|
+
@address_resolver,
|
206
|
+
@connection_options,
|
207
|
+
@futures)
|
179
208
|
session = Session.new(client, @execution_options, @futures)
|
180
209
|
promise = @futures.promise
|
181
210
|
|
@@ -246,7 +275,7 @@ module Cassandra
|
|
246
275
|
|
247
276
|
# @private
|
248
277
|
def inspect
|
249
|
-
"#<#{self.class.name}:0x#{
|
278
|
+
"#<#{self.class.name}:0x#{object_id.to_s(16)}>"
|
250
279
|
end
|
251
280
|
end
|
252
281
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright 2013-
|
4
|
+
# Copyright 2013-2016 DataStax, Inc.
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -24,7 +24,17 @@ module Cassandra
|
|
24
24
|
|
25
25
|
attr_reader :keyspace
|
26
26
|
|
27
|
-
def initialize(logger,
|
27
|
+
def initialize(logger,
|
28
|
+
cluster_registry,
|
29
|
+
cluster_schema,
|
30
|
+
io_reactor,
|
31
|
+
connector,
|
32
|
+
load_balancing_policy,
|
33
|
+
reconnection_policy,
|
34
|
+
retry_policy,
|
35
|
+
address_resolution_policy,
|
36
|
+
connection_options,
|
37
|
+
futures_factory)
|
28
38
|
@logger = logger
|
29
39
|
@registry = cluster_registry
|
30
40
|
@schema = cluster_schema
|
@@ -65,7 +75,9 @@ module Cassandra
|
|
65
75
|
when :remote
|
66
76
|
pool_size = @connection_options.connections_per_remote_node
|
67
77
|
else
|
68
|
-
@logger.error("Not connecting to #{host.ip} - invalid load balancing
|
78
|
+
@logger.error("Not connecting to #{host.ip} - invalid load balancing " \
|
79
|
+
'distance. Distance must be one of ' \
|
80
|
+
"#{LoadBalancing::DISTANCES.inspect}, #{distance.inspect} given")
|
69
81
|
next
|
70
82
|
end
|
71
83
|
|
@@ -101,7 +113,9 @@ module Cassandra
|
|
101
113
|
raise Errors::NoHostsAvailable.new(errors)
|
102
114
|
else
|
103
115
|
failed_connections.each do |f|
|
104
|
-
connect_to_host_with_retry(f.host,
|
116
|
+
connect_to_host_with_retry(f.host,
|
117
|
+
connecting_hosts[f.host],
|
118
|
+
@reconnection_policy.schedule)
|
105
119
|
end
|
106
120
|
end
|
107
121
|
|
@@ -119,18 +133,19 @@ module Cassandra
|
|
119
133
|
return CLIENT_NOT_CONNECTED if @state == :idle
|
120
134
|
return @closed_future if @state == :closed || @state == :closing
|
121
135
|
|
122
|
-
state
|
136
|
+
state = @state
|
137
|
+
@state = :closing
|
123
138
|
end
|
124
139
|
|
125
140
|
@closed_future = begin
|
126
141
|
@registry.remove_listener(self)
|
127
142
|
@schema.remove_listener(self)
|
128
143
|
|
129
|
-
if state == :connecting
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
144
|
+
f = if state == :connecting
|
145
|
+
@connected_future.recover.flat_map { close_connections }
|
146
|
+
else
|
147
|
+
close_connections
|
148
|
+
end
|
134
149
|
|
135
150
|
f.map(self)
|
136
151
|
end
|
@@ -160,7 +175,9 @@ module Cassandra
|
|
160
175
|
when :remote
|
161
176
|
pool_size = @connection_options.connections_per_remote_node
|
162
177
|
else
|
163
|
-
@logger.error("Not connecting to #{host.ip} -
|
178
|
+
@logger.error("Not connecting to #{host.ip} - " \
|
179
|
+
'invalid load balancing distance. Distance must be one of ' \
|
180
|
+
"#{LoadBalancing::DISTANCES.inspect}, #{distance.inspect} given")
|
164
181
|
return Ione::Future.resolved
|
165
182
|
end
|
166
183
|
|
@@ -177,7 +194,7 @@ module Cassandra
|
|
177
194
|
pool = nil
|
178
195
|
|
179
196
|
synchronize do
|
180
|
-
return Ione::Future.resolved unless @connections.
|
197
|
+
return Ione::Future.resolved unless @connections.key?(host)
|
181
198
|
|
182
199
|
@pending_connections.delete(host) unless @pending_connections[host] > 0
|
183
200
|
@prepared_statements.delete(host)
|
@@ -186,7 +203,7 @@ module Cassandra
|
|
186
203
|
end
|
187
204
|
|
188
205
|
if pool
|
189
|
-
Ione::Future.all(*pool.snapshot.map!
|
206
|
+
Ione::Future.all(*pool.snapshot.map!(&:close)).map(nil)
|
190
207
|
else
|
191
208
|
Ione::Future.resolved
|
192
209
|
end
|
@@ -203,29 +220,52 @@ module Cassandra
|
|
203
220
|
nil
|
204
221
|
end
|
205
222
|
|
206
|
-
|
207
223
|
def query(statement, options)
|
208
|
-
|
224
|
+
if !statement.params.empty? && @connection_options.protocol_version == 1
|
225
|
+
return @futures.error(
|
226
|
+
Errors::ClientError.new(
|
227
|
+
'Positional arguments are not supported by the current version of ' \
|
228
|
+
'Apache Cassandra'))
|
229
|
+
end
|
209
230
|
|
210
231
|
timestamp = nil
|
211
|
-
|
232
|
+
if @connection_options.client_timestamps? &&
|
233
|
+
@connection_options.protocol_version > 2
|
234
|
+
timestamp = ::Time.now
|
235
|
+
end
|
212
236
|
payload = nil
|
213
|
-
payload = options.payload if
|
214
|
-
request = Protocol::QueryRequest.new(statement.cql,
|
237
|
+
payload = options.payload if @connection_options.protocol_version >= 4
|
238
|
+
request = Protocol::QueryRequest.new(statement.cql,
|
239
|
+
statement.params,
|
240
|
+
statement.params_types,
|
241
|
+
options.consistency,
|
242
|
+
options.serial_consistency,
|
243
|
+
options.page_size,
|
244
|
+
options.paging_state,
|
245
|
+
options.trace?,
|
246
|
+
statement.params_names,
|
247
|
+
timestamp,
|
248
|
+
payload)
|
215
249
|
timeout = options.timeout
|
216
250
|
promise = @futures.promise
|
217
251
|
|
218
252
|
keyspace = @keyspace
|
219
253
|
plan = @load_balancing_policy.plan(keyspace, statement, options)
|
220
254
|
|
221
|
-
send_request_by_plan(promise,
|
255
|
+
send_request_by_plan(promise,
|
256
|
+
keyspace,
|
257
|
+
statement,
|
258
|
+
options,
|
259
|
+
request,
|
260
|
+
plan,
|
261
|
+
timeout)
|
222
262
|
|
223
263
|
promise.future
|
224
264
|
end
|
225
265
|
|
226
266
|
def prepare(cql, options)
|
227
267
|
payload = nil
|
228
|
-
payload = options.payload if
|
268
|
+
payload = options.payload if @connection_options.protocol_version >= 4
|
229
269
|
request = Protocol::PrepareRequest.new(cql, options.trace?, payload)
|
230
270
|
timeout = options.timeout
|
231
271
|
promise = @futures.promise
|
@@ -234,19 +274,38 @@ module Cassandra
|
|
234
274
|
statement = VOID_STATEMENT
|
235
275
|
plan = @load_balancing_policy.plan(keyspace, statement, options)
|
236
276
|
|
237
|
-
send_request_by_plan(promise,
|
277
|
+
send_request_by_plan(promise,
|
278
|
+
keyspace,
|
279
|
+
statement,
|
280
|
+
options,
|
281
|
+
request,
|
282
|
+
plan,
|
283
|
+
timeout)
|
238
284
|
|
239
285
|
promise.future
|
240
286
|
end
|
241
287
|
|
242
288
|
def execute(statement, options)
|
243
|
-
timestamp
|
244
|
-
|
289
|
+
timestamp = nil
|
290
|
+
if @connection_options.client_timestamps? &&
|
291
|
+
@connection_options.protocol_version > 2
|
292
|
+
timestamp = ::Time.now
|
293
|
+
end
|
245
294
|
payload = nil
|
246
|
-
payload = options.payload if
|
295
|
+
payload = options.payload if @connection_options.protocol_version >= 4
|
247
296
|
timeout = options.timeout
|
248
297
|
result_metadata = statement.result_metadata
|
249
|
-
request = Protocol::ExecuteRequest.new(nil,
|
298
|
+
request = Protocol::ExecuteRequest.new(nil,
|
299
|
+
statement.params_types,
|
300
|
+
statement.params,
|
301
|
+
result_metadata.nil?,
|
302
|
+
options.consistency,
|
303
|
+
options.serial_consistency,
|
304
|
+
options.page_size,
|
305
|
+
options.paging_state,
|
306
|
+
options.trace?,
|
307
|
+
timestamp,
|
308
|
+
payload)
|
250
309
|
promise = @futures.promise
|
251
310
|
|
252
311
|
keyspace = @keyspace
|
@@ -258,14 +317,27 @@ module Cassandra
|
|
258
317
|
end
|
259
318
|
|
260
319
|
def batch(statement, options)
|
261
|
-
|
320
|
+
if @connection_options.protocol_version < 2
|
321
|
+
return @futures.error(
|
322
|
+
Errors::ClientError.new(
|
323
|
+
'Batch statements are not supported by the current version of ' \
|
324
|
+
'Apache Cassandra'))
|
325
|
+
end
|
262
326
|
|
263
327
|
timestamp = nil
|
264
|
-
|
328
|
+
if @connection_options.client_timestamps? &&
|
329
|
+
@connection_options.protocol_version > 2
|
330
|
+
timestamp = ::Time.now
|
331
|
+
end
|
265
332
|
payload = nil
|
266
|
-
payload = options.payload if
|
333
|
+
payload = options.payload if @connection_options.protocol_version >= 4
|
267
334
|
timeout = options.timeout
|
268
|
-
request = Protocol::BatchRequest.new(BATCH_TYPES[statement.type],
|
335
|
+
request = Protocol::BatchRequest.new(BATCH_TYPES[statement.type],
|
336
|
+
options.consistency,
|
337
|
+
options.trace?,
|
338
|
+
options.serial_consistency,
|
339
|
+
timestamp,
|
340
|
+
payload)
|
269
341
|
keyspace = @keyspace
|
270
342
|
plan = @load_balancing_policy.plan(keyspace, statement, options)
|
271
343
|
promise = @futures.promise
|
@@ -276,16 +348,16 @@ module Cassandra
|
|
276
348
|
end
|
277
349
|
|
278
350
|
def inspect
|
279
|
-
"#<#{self.class.name}:0x#{
|
351
|
+
"#<#{self.class.name}:0x#{object_id.to_s(16)}>"
|
280
352
|
end
|
281
353
|
|
282
354
|
private
|
283
355
|
|
284
356
|
NO_CONNECTIONS = Ione::Future.resolved([])
|
285
357
|
BATCH_TYPES = {
|
286
|
-
:
|
287
|
-
:
|
288
|
-
:
|
358
|
+
logged: Protocol::BatchRequest::LOGGED_TYPE,
|
359
|
+
unlogged: Protocol::BatchRequest::UNLOGGED_TYPE,
|
360
|
+
counter: Protocol::BatchRequest::COUNTER_TYPE
|
289
361
|
}.freeze
|
290
362
|
CLIENT_CLOSED = Ione::Future.failed(Errors::ClientError.new('Client closed'))
|
291
363
|
NOT_CONNECTED = Errors::ClientError.new('Client not connected')
|
@@ -299,8 +371,18 @@ module Cassandra
|
|
299
371
|
BOOTSTRAPPING_ERROR_CODE = 0x1002
|
300
372
|
UNPREPARED_ERROR_CODE = 0x2500
|
301
373
|
|
302
|
-
SELECT_SCHEMA_PEERS =
|
303
|
-
|
374
|
+
SELECT_SCHEMA_PEERS =
|
375
|
+
Protocol::QueryRequest.new(
|
376
|
+
'SELECT peer, rpc_address, schema_version FROM system.peers',
|
377
|
+
EMPTY_LIST,
|
378
|
+
EMPTY_LIST,
|
379
|
+
:one)
|
380
|
+
SELECT_SCHEMA_LOCAL =
|
381
|
+
Protocol::QueryRequest.new(
|
382
|
+
"SELECT schema_version FROM system.local WHERE key='local'",
|
383
|
+
EMPTY_LIST,
|
384
|
+
EMPTY_LIST,
|
385
|
+
:one)
|
304
386
|
|
305
387
|
def connected(f)
|
306
388
|
if f.resolved?
|
@@ -339,7 +421,7 @@ module Cassandra
|
|
339
421
|
def close_connections
|
340
422
|
futures = []
|
341
423
|
synchronize do
|
342
|
-
@connections.each do |
|
424
|
+
@connections.each do |_host, connections|
|
343
425
|
connections.snapshot.each do |c|
|
344
426
|
futures << c.close
|
345
427
|
end
|
@@ -351,7 +433,8 @@ module Cassandra
|
|
351
433
|
|
352
434
|
def connect_to_host_maybe_retry(host, pool_size)
|
353
435
|
connect_to_host(host, pool_size).fallback do |e|
|
354
|
-
@logger.error(
|
436
|
+
@logger.error('Scheduling initial connection retry to ' \
|
437
|
+
"#{host.ip} (#{e.class.name}: #{e.message})")
|
355
438
|
connect_to_host_with_retry(host, pool_size, @reconnection_policy.schedule)
|
356
439
|
end.map(nil)
|
357
440
|
end
|
@@ -364,7 +447,8 @@ module Cassandra
|
|
364
447
|
f = @reactor.schedule_timer(interval)
|
365
448
|
f.flat_map do
|
366
449
|
connect_to_host(host, pool_size).fallback do |e|
|
367
|
-
@logger.error(
|
450
|
+
@logger.error('Scheduling connection retry to ' \
|
451
|
+
"#{host.ip} (#{e.class.name}: #{e.message})")
|
368
452
|
connect_to_host_with_retry(host, pool_size, schedule)
|
369
453
|
end
|
370
454
|
end
|
@@ -390,7 +474,8 @@ module Cassandra
|
|
390
474
|
size -= @pending_connections[host]
|
391
475
|
|
392
476
|
if size <= 0
|
393
|
-
@logger.info("Not connecting to #{host.ip} -
|
477
|
+
@logger.info("Not connecting to #{host.ip} - " \
|
478
|
+
'host is already pending connections')
|
394
479
|
return NO_CONNECTIONS
|
395
480
|
end
|
396
481
|
|
@@ -439,7 +524,7 @@ module Cassandra
|
|
439
524
|
end
|
440
525
|
end
|
441
526
|
else
|
442
|
-
connections.each
|
527
|
+
connections.each(&:close)
|
443
528
|
end
|
444
529
|
|
445
530
|
if error
|
@@ -450,7 +535,15 @@ module Cassandra
|
|
450
535
|
end
|
451
536
|
end
|
452
537
|
|
453
|
-
def execute_by_plan(promise,
|
538
|
+
def execute_by_plan(promise,
|
539
|
+
keyspace,
|
540
|
+
statement,
|
541
|
+
options,
|
542
|
+
request,
|
543
|
+
plan,
|
544
|
+
timeout,
|
545
|
+
errors = nil,
|
546
|
+
hosts = [])
|
454
547
|
unless plan.has_next?
|
455
548
|
promise.break(Errors::NoHostsAvailable.new(errors))
|
456
549
|
return
|
@@ -463,7 +556,15 @@ module Cassandra
|
|
463
556
|
unless pool
|
464
557
|
errors ||= {}
|
465
558
|
errors[host] = NOT_CONNECTED
|
466
|
-
return execute_by_plan(promise,
|
559
|
+
return execute_by_plan(promise,
|
560
|
+
keyspace,
|
561
|
+
statement,
|
562
|
+
options,
|
563
|
+
request,
|
564
|
+
plan,
|
565
|
+
timeout,
|
566
|
+
errors,
|
567
|
+
hosts)
|
467
568
|
end
|
468
569
|
|
469
570
|
connection = pool.random_connection
|
@@ -472,13 +573,32 @@ module Cassandra
|
|
472
573
|
switch = switch_keyspace(connection, keyspace, timeout)
|
473
574
|
switch.on_complete do |s|
|
474
575
|
if s.resolved?
|
475
|
-
prepare_and_send_request_by_plan(host,
|
576
|
+
prepare_and_send_request_by_plan(host,
|
577
|
+
connection,
|
578
|
+
promise,
|
579
|
+
keyspace,
|
580
|
+
statement,
|
581
|
+
options,
|
582
|
+
request,
|
583
|
+
plan,
|
584
|
+
timeout,
|
585
|
+
errors,
|
586
|
+
hosts)
|
476
587
|
else
|
477
588
|
s.on_failure do |e|
|
478
|
-
if e.is_a?(Errors::HostError) ||
|
589
|
+
if e.is_a?(Errors::HostError) ||
|
590
|
+
(e.is_a?(Errors::TimeoutError) && statement.idempotent?)
|
479
591
|
errors ||= {}
|
480
592
|
errors[host] = e
|
481
|
-
execute_by_plan(promise,
|
593
|
+
execute_by_plan(promise,
|
594
|
+
keyspace,
|
595
|
+
statement,
|
596
|
+
options,
|
597
|
+
request,
|
598
|
+
plan,
|
599
|
+
timeout,
|
600
|
+
errors,
|
601
|
+
hosts)
|
482
602
|
else
|
483
603
|
promise.break(e)
|
484
604
|
end
|
@@ -486,33 +606,90 @@ module Cassandra
|
|
486
606
|
end
|
487
607
|
end
|
488
608
|
else
|
489
|
-
prepare_and_send_request_by_plan(host,
|
609
|
+
prepare_and_send_request_by_plan(host,
|
610
|
+
connection,
|
611
|
+
promise,
|
612
|
+
keyspace,
|
613
|
+
statement,
|
614
|
+
options,
|
615
|
+
request,
|
616
|
+
plan,
|
617
|
+
timeout,
|
618
|
+
errors,
|
619
|
+
hosts)
|
490
620
|
end
|
491
621
|
rescue => e
|
492
622
|
errors ||= {}
|
493
623
|
errors[host] = e
|
494
|
-
execute_by_plan(promise,
|
624
|
+
execute_by_plan(promise,
|
625
|
+
keyspace,
|
626
|
+
statement,
|
627
|
+
options,
|
628
|
+
request,
|
629
|
+
plan,
|
630
|
+
timeout,
|
631
|
+
errors,
|
632
|
+
hosts)
|
495
633
|
end
|
496
634
|
|
497
|
-
def prepare_and_send_request_by_plan(host,
|
635
|
+
def prepare_and_send_request_by_plan(host,
|
636
|
+
connection,
|
637
|
+
promise,
|
638
|
+
keyspace,
|
639
|
+
statement,
|
640
|
+
options,
|
641
|
+
request,
|
642
|
+
plan,
|
643
|
+
timeout,
|
644
|
+
errors,
|
645
|
+
hosts)
|
498
646
|
cql = statement.cql
|
499
647
|
id = synchronize { @prepared_statements[host][cql] }
|
500
648
|
|
501
649
|
if id
|
502
650
|
request.id = id
|
503
|
-
do_send_request_by_plan(host,
|
651
|
+
do_send_request_by_plan(host,
|
652
|
+
connection,
|
653
|
+
promise,
|
654
|
+
keyspace,
|
655
|
+
statement,
|
656
|
+
options,
|
657
|
+
request,
|
658
|
+
plan,
|
659
|
+
timeout,
|
660
|
+
errors,
|
661
|
+
hosts)
|
504
662
|
else
|
505
663
|
prepare = prepare_statement(host, connection, cql, timeout)
|
506
664
|
prepare.on_complete do |_|
|
507
665
|
if prepare.resolved?
|
508
666
|
request.id = prepare.value
|
509
|
-
do_send_request_by_plan(host,
|
667
|
+
do_send_request_by_plan(host,
|
668
|
+
connection,
|
669
|
+
promise,
|
670
|
+
keyspace,
|
671
|
+
statement,
|
672
|
+
options,
|
673
|
+
request,
|
674
|
+
plan,
|
675
|
+
timeout,
|
676
|
+
errors,
|
677
|
+
hosts)
|
510
678
|
else
|
511
679
|
prepare.on_failure do |e|
|
512
|
-
if e.is_a?(Errors::HostError) ||
|
680
|
+
if e.is_a?(Errors::HostError) ||
|
681
|
+
(e.is_a?(Errors::TimeoutError) && statement.idempotent?)
|
513
682
|
errors ||= {}
|
514
683
|
errors[host] = e
|
515
|
-
execute_by_plan(promise,
|
684
|
+
execute_by_plan(promise,
|
685
|
+
keyspace,
|
686
|
+
statement,
|
687
|
+
options,
|
688
|
+
request,
|
689
|
+
plan,
|
690
|
+
timeout,
|
691
|
+
errors,
|
692
|
+
hosts)
|
516
693
|
else
|
517
694
|
promise.break(e)
|
518
695
|
end
|
@@ -524,7 +701,15 @@ module Cassandra
|
|
524
701
|
promise.break(e)
|
525
702
|
end
|
526
703
|
|
527
|
-
def batch_by_plan(promise,
|
704
|
+
def batch_by_plan(promise,
|
705
|
+
keyspace,
|
706
|
+
statement,
|
707
|
+
options,
|
708
|
+
request,
|
709
|
+
plan,
|
710
|
+
timeout,
|
711
|
+
errors = nil,
|
712
|
+
hosts = [])
|
528
713
|
unless plan.has_next?
|
529
714
|
promise.break(Errors::NoHostsAvailable.new(errors))
|
530
715
|
return
|
@@ -537,7 +722,15 @@ module Cassandra
|
|
537
722
|
unless pool
|
538
723
|
errors ||= {}
|
539
724
|
errors[host] = NOT_CONNECTED
|
540
|
-
return batch_by_plan(promise,
|
725
|
+
return batch_by_plan(promise,
|
726
|
+
keyspace,
|
727
|
+
statement,
|
728
|
+
options,
|
729
|
+
request,
|
730
|
+
plan,
|
731
|
+
timeout,
|
732
|
+
errors,
|
733
|
+
hosts)
|
541
734
|
end
|
542
735
|
|
543
736
|
connection = pool.random_connection
|
@@ -546,13 +739,32 @@ module Cassandra
|
|
546
739
|
switch = switch_keyspace(connection, keyspace, timeout)
|
547
740
|
switch.on_complete do |s|
|
548
741
|
if s.resolved?
|
549
|
-
batch_and_send_request_by_plan(host,
|
742
|
+
batch_and_send_request_by_plan(host,
|
743
|
+
connection,
|
744
|
+
promise,
|
745
|
+
keyspace,
|
746
|
+
statement,
|
747
|
+
request,
|
748
|
+
options,
|
749
|
+
plan,
|
750
|
+
timeout,
|
751
|
+
errors,
|
752
|
+
hosts)
|
550
753
|
else
|
551
754
|
s.on_failure do |e|
|
552
|
-
if e.is_a?(Errors::HostError) ||
|
755
|
+
if e.is_a?(Errors::HostError) ||
|
756
|
+
(e.is_a?(Errors::TimeoutError) && statement.idempotent?)
|
553
757
|
errors ||= {}
|
554
758
|
errors[host] = e
|
555
|
-
batch_by_plan(promise,
|
759
|
+
batch_by_plan(promise,
|
760
|
+
keyspace,
|
761
|
+
statement,
|
762
|
+
options,
|
763
|
+
request,
|
764
|
+
plan,
|
765
|
+
timeout,
|
766
|
+
errors,
|
767
|
+
hosts)
|
556
768
|
else
|
557
769
|
promise.break(e)
|
558
770
|
end
|
@@ -560,19 +772,47 @@ module Cassandra
|
|
560
772
|
end
|
561
773
|
end
|
562
774
|
else
|
563
|
-
batch_and_send_request_by_plan(host,
|
775
|
+
batch_and_send_request_by_plan(host,
|
776
|
+
connection,
|
777
|
+
promise,
|
778
|
+
keyspace,
|
779
|
+
statement,
|
780
|
+
request,
|
781
|
+
options,
|
782
|
+
plan,
|
783
|
+
timeout,
|
784
|
+
errors,
|
785
|
+
hosts)
|
564
786
|
end
|
565
787
|
rescue => e
|
566
788
|
errors ||= {}
|
567
789
|
errors[host] = e
|
568
|
-
batch_by_plan(promise,
|
790
|
+
batch_by_plan(promise,
|
791
|
+
keyspace,
|
792
|
+
statement,
|
793
|
+
options,
|
794
|
+
request,
|
795
|
+
plan,
|
796
|
+
timeout,
|
797
|
+
errors,
|
798
|
+
hosts)
|
569
799
|
end
|
570
800
|
|
571
|
-
def batch_and_send_request_by_plan(host,
|
801
|
+
def batch_and_send_request_by_plan(host,
|
802
|
+
connection,
|
803
|
+
promise,
|
804
|
+
keyspace,
|
805
|
+
batch_statement,
|
806
|
+
request,
|
807
|
+
options,
|
808
|
+
plan,
|
809
|
+
timeout,
|
810
|
+
errors,
|
811
|
+
hosts)
|
572
812
|
request.clear
|
573
813
|
unprepared = Hash.new {|hash, cql| hash[cql] = []}
|
574
814
|
|
575
|
-
|
815
|
+
batch_statement.statements.each do |statement|
|
576
816
|
cql = statement.cql
|
577
817
|
|
578
818
|
if statement.is_a?(Statements::Bound)
|
@@ -589,7 +829,17 @@ module Cassandra
|
|
589
829
|
end
|
590
830
|
|
591
831
|
if unprepared.empty?
|
592
|
-
do_send_request_by_plan(host,
|
832
|
+
do_send_request_by_plan(host,
|
833
|
+
connection,
|
834
|
+
promise,
|
835
|
+
keyspace,
|
836
|
+
batch_statement,
|
837
|
+
options,
|
838
|
+
request,
|
839
|
+
plan,
|
840
|
+
timeout,
|
841
|
+
errors,
|
842
|
+
hosts)
|
593
843
|
else
|
594
844
|
to_prepare = unprepared.to_a
|
595
845
|
futures = to_prepare.map do |cql, _|
|
@@ -601,17 +851,38 @@ module Cassandra
|
|
601
851
|
prepared_ids = f.value
|
602
852
|
to_prepare.each_with_index do |(_, statements), i|
|
603
853
|
statements.each do |statement|
|
604
|
-
request.add_prepared(prepared_ids[i],
|
854
|
+
request.add_prepared(prepared_ids[i],
|
855
|
+
statement.params,
|
856
|
+
statement.params_types)
|
605
857
|
end
|
606
858
|
end
|
607
859
|
|
608
|
-
do_send_request_by_plan(host,
|
860
|
+
do_send_request_by_plan(host,
|
861
|
+
connection,
|
862
|
+
promise,
|
863
|
+
keyspace,
|
864
|
+
batch_statement,
|
865
|
+
options,
|
866
|
+
request,
|
867
|
+
plan,
|
868
|
+
timeout,
|
869
|
+
errors,
|
870
|
+
hosts)
|
609
871
|
else
|
610
872
|
f.on_failure do |e|
|
611
|
-
if e.is_a?(Errors::HostError) ||
|
873
|
+
if e.is_a?(Errors::HostError) ||
|
874
|
+
(e.is_a?(Errors::TimeoutError) && batch_statement.idempotent?)
|
612
875
|
errors ||= {}
|
613
876
|
errors[host] = e
|
614
|
-
batch_by_plan(promise,
|
877
|
+
batch_by_plan(promise,
|
878
|
+
keyspace,
|
879
|
+
batch_statement,
|
880
|
+
options,
|
881
|
+
request,
|
882
|
+
plan,
|
883
|
+
timeout,
|
884
|
+
errors,
|
885
|
+
hosts)
|
615
886
|
else
|
616
887
|
promise.break(e)
|
617
888
|
end
|
@@ -621,7 +892,15 @@ module Cassandra
|
|
621
892
|
end
|
622
893
|
end
|
623
894
|
|
624
|
-
def send_request_by_plan(promise,
|
895
|
+
def send_request_by_plan(promise,
|
896
|
+
keyspace,
|
897
|
+
statement,
|
898
|
+
options,
|
899
|
+
request,
|
900
|
+
plan,
|
901
|
+
timeout,
|
902
|
+
errors = nil,
|
903
|
+
hosts = [])
|
625
904
|
unless plan.has_next?
|
626
905
|
promise.break(Errors::NoHostsAvailable.new(errors))
|
627
906
|
return
|
@@ -634,7 +913,15 @@ module Cassandra
|
|
634
913
|
unless pool
|
635
914
|
errors ||= {}
|
636
915
|
errors[host] = NOT_CONNECTED
|
637
|
-
return send_request_by_plan(promise,
|
916
|
+
return send_request_by_plan(promise,
|
917
|
+
keyspace,
|
918
|
+
statement,
|
919
|
+
options,
|
920
|
+
request,
|
921
|
+
plan,
|
922
|
+
timeout,
|
923
|
+
errors,
|
924
|
+
hosts)
|
638
925
|
end
|
639
926
|
|
640
927
|
connection = pool.random_connection
|
@@ -643,13 +930,32 @@ module Cassandra
|
|
643
930
|
switch = switch_keyspace(connection, keyspace, timeout)
|
644
931
|
switch.on_complete do |s|
|
645
932
|
if s.resolved?
|
646
|
-
do_send_request_by_plan(host,
|
933
|
+
do_send_request_by_plan(host,
|
934
|
+
connection,
|
935
|
+
promise,
|
936
|
+
keyspace,
|
937
|
+
statement,
|
938
|
+
options,
|
939
|
+
request,
|
940
|
+
plan,
|
941
|
+
timeout,
|
942
|
+
errors,
|
943
|
+
hosts)
|
647
944
|
else
|
648
945
|
s.on_failure do |e|
|
649
|
-
if e.is_a?(Errors::HostError) ||
|
946
|
+
if e.is_a?(Errors::HostError) ||
|
947
|
+
(e.is_a?(Errors::TimeoutError) && statement.idempotent?)
|
650
948
|
errors ||= {}
|
651
949
|
errors[host] = e
|
652
|
-
send_request_by_plan(promise,
|
950
|
+
send_request_by_plan(promise,
|
951
|
+
keyspace,
|
952
|
+
statement,
|
953
|
+
options,
|
954
|
+
request,
|
955
|
+
plan,
|
956
|
+
timeout,
|
957
|
+
errors,
|
958
|
+
hosts)
|
653
959
|
else
|
654
960
|
promise.break(e)
|
655
961
|
end
|
@@ -657,166 +963,447 @@ module Cassandra
|
|
657
963
|
end
|
658
964
|
end
|
659
965
|
else
|
660
|
-
do_send_request_by_plan(host,
|
966
|
+
do_send_request_by_plan(host,
|
967
|
+
connection,
|
968
|
+
promise,
|
969
|
+
keyspace,
|
970
|
+
statement,
|
971
|
+
options,
|
972
|
+
request,
|
973
|
+
plan,
|
974
|
+
timeout,
|
975
|
+
errors,
|
976
|
+
hosts)
|
661
977
|
end
|
662
978
|
rescue => e
|
663
979
|
errors ||= {}
|
664
980
|
errors[host] = e
|
665
|
-
send_request_by_plan(promise,
|
981
|
+
send_request_by_plan(promise,
|
982
|
+
keyspace,
|
983
|
+
statement,
|
984
|
+
options,
|
985
|
+
request,
|
986
|
+
plan,
|
987
|
+
timeout,
|
988
|
+
errors,
|
989
|
+
hosts)
|
666
990
|
end
|
667
991
|
|
668
|
-
def do_send_request_by_plan(host,
|
992
|
+
def do_send_request_by_plan(host,
|
993
|
+
connection,
|
994
|
+
promise,
|
995
|
+
keyspace,
|
996
|
+
statement,
|
997
|
+
options,
|
998
|
+
request,
|
999
|
+
plan,
|
1000
|
+
timeout,
|
1001
|
+
errors,
|
1002
|
+
hosts,
|
1003
|
+
retries = 0)
|
669
1004
|
request.retries = retries
|
670
1005
|
|
671
1006
|
f = connection.send_request(request, timeout)
|
672
|
-
f.on_complete do |
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
@prepared_statements[host].delete(cql)
|
692
|
-
end
|
1007
|
+
f.on_complete do |response_future|
|
1008
|
+
errors ||= {}
|
1009
|
+
handle_response(response_future,
|
1010
|
+
host,
|
1011
|
+
connection,
|
1012
|
+
promise,
|
1013
|
+
keyspace,
|
1014
|
+
statement,
|
1015
|
+
options,
|
1016
|
+
request,
|
1017
|
+
plan,
|
1018
|
+
timeout,
|
1019
|
+
errors,
|
1020
|
+
hosts,
|
1021
|
+
retries)
|
1022
|
+
end
|
1023
|
+
rescue => e
|
1024
|
+
promise.break(e)
|
1025
|
+
end
|
693
1026
|
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
1027
|
+
def handle_response(response_future,
|
1028
|
+
host,
|
1029
|
+
connection,
|
1030
|
+
promise,
|
1031
|
+
keyspace,
|
1032
|
+
statement,
|
1033
|
+
options,
|
1034
|
+
request,
|
1035
|
+
plan,
|
1036
|
+
timeout,
|
1037
|
+
errors,
|
1038
|
+
hosts,
|
1039
|
+
retries)
|
1040
|
+
if response_future.resolved?
|
1041
|
+
r = response_future.value
|
1042
|
+
|
1043
|
+
begin
|
1044
|
+
decision = nil
|
1045
|
+
|
1046
|
+
case r
|
1047
|
+
when Protocol::UnavailableErrorResponse
|
1048
|
+
decision = @retry_policy.unavailable(statement,
|
1049
|
+
r.consistency,
|
1050
|
+
r.required,
|
1051
|
+
r.alive,
|
1052
|
+
retries)
|
1053
|
+
when Protocol::WriteTimeoutErrorResponse
|
1054
|
+
decision = @retry_policy.write_timeout(statement,
|
1055
|
+
r.consistency,
|
1056
|
+
r.write_type,
|
1057
|
+
r.blockfor,
|
1058
|
+
r.received,
|
1059
|
+
retries)
|
1060
|
+
when Protocol::ReadTimeoutErrorResponse
|
1061
|
+
decision = @retry_policy.read_timeout(statement,
|
1062
|
+
r.consistency,
|
1063
|
+
r.blockfor,
|
1064
|
+
r.received,
|
1065
|
+
r.data_present,
|
1066
|
+
retries)
|
1067
|
+
when Protocol::UnpreparedErrorResponse
|
1068
|
+
cql = statement.cql
|
1069
|
+
|
1070
|
+
synchronize do
|
1071
|
+
@preparing_statements[host].delete(cql)
|
1072
|
+
@prepared_statements[host].delete(cql)
|
1073
|
+
end
|
713
1074
|
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
1075
|
+
prepare = prepare_statement(host, connection, cql, timeout)
|
1076
|
+
prepare.on_complete do |_|
|
1077
|
+
if prepare.resolved?
|
1078
|
+
request.id = prepare.value
|
1079
|
+
do_send_request_by_plan(host,
|
1080
|
+
connection,
|
1081
|
+
promise,
|
1082
|
+
keyspace,
|
1083
|
+
statement,
|
1084
|
+
options,
|
1085
|
+
request,
|
1086
|
+
plan,
|
1087
|
+
timeout,
|
1088
|
+
errors,
|
1089
|
+
hosts)
|
726
1090
|
else
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
promise.fulfill(Statements::Prepared.new(r.custom_payload, r.warnings, cql, metadata, r.result_metadata, pk_idx, r.trace_id, keyspace, statement, options, hosts, request.consistency, retries, self, @connection_options))
|
744
|
-
when Protocol::RawRowsResultResponse
|
745
|
-
r.materialize(statement.result_metadata)
|
746
|
-
promise.fulfill(Results::Paged.new(r.custom_payload, r.warnings, r.rows, r.paging_state, r.trace_id, keyspace, statement, options, hosts, request.consistency, retries, self, @futures))
|
747
|
-
when Protocol::RowsResultResponse
|
748
|
-
promise.fulfill(Results::Paged.new(r.custom_payload, r.warnings, r.rows, r.paging_state, r.trace_id, keyspace, statement, options, hosts, request.consistency, retries, self, @futures))
|
749
|
-
when Protocol::SchemaChangeResultResponse
|
750
|
-
@schema.delete_keyspace(r.keyspace) if r.change == 'DROPPED' && r.target == Protocol::Constants::SCHEMA_CHANGE_TARGET_KEYSPACE
|
751
|
-
|
752
|
-
@logger.debug('Waiting for schema to propagate to all hosts after a change')
|
753
|
-
wait_for_schema_agreement(connection, @reconnection_policy.schedule).on_complete do |f|
|
754
|
-
unless f.resolved?
|
755
|
-
f.on_failure do |e|
|
756
|
-
@logger.error("Schema agreement failure (#{e.class.name}: #{e.message})")
|
1091
|
+
prepare.on_failure do |e|
|
1092
|
+
if e.is_a?(Errors::HostError) ||
|
1093
|
+
(e.is_a?(Errors::TimeoutError) && statement.idempotent?)
|
1094
|
+
errors[host] = e
|
1095
|
+
execute_by_plan(promise,
|
1096
|
+
keyspace,
|
1097
|
+
statement,
|
1098
|
+
options,
|
1099
|
+
request,
|
1100
|
+
plan,
|
1101
|
+
timeout,
|
1102
|
+
errors,
|
1103
|
+
hosts)
|
1104
|
+
else
|
1105
|
+
promise.break(e)
|
757
1106
|
end
|
758
1107
|
end
|
759
|
-
|
1108
|
+
end
|
1109
|
+
end
|
1110
|
+
when Protocol::ErrorResponse
|
1111
|
+
error = r.to_error(keyspace,
|
1112
|
+
statement,
|
1113
|
+
options,
|
1114
|
+
hosts,
|
1115
|
+
request.consistency,
|
1116
|
+
retries)
|
1117
|
+
|
1118
|
+
if error.is_a?(Errors::HostError) ||
|
1119
|
+
(error.is_a?(Errors::TimeoutError) && statement.idempotent?)
|
1120
|
+
errors[host] = error
|
1121
|
+
|
1122
|
+
case request
|
1123
|
+
when Protocol::QueryRequest, Protocol::PrepareRequest
|
1124
|
+
send_request_by_plan(promise,
|
1125
|
+
keyspace,
|
1126
|
+
statement,
|
1127
|
+
options,
|
1128
|
+
request,
|
1129
|
+
plan,
|
1130
|
+
timeout,
|
1131
|
+
errors,
|
1132
|
+
hosts)
|
1133
|
+
when Protocol::ExecuteRequest
|
1134
|
+
execute_by_plan(promise,
|
1135
|
+
keyspace,
|
1136
|
+
statement,
|
1137
|
+
options,
|
1138
|
+
request,
|
1139
|
+
plan,
|
1140
|
+
timeout,
|
1141
|
+
errors,
|
1142
|
+
hosts)
|
1143
|
+
when Protocol::BatchRequest
|
1144
|
+
batch_by_plan(promise,
|
1145
|
+
keyspace,
|
1146
|
+
statement,
|
1147
|
+
options,
|
1148
|
+
request,
|
1149
|
+
plan,
|
1150
|
+
timeout,
|
1151
|
+
errors,
|
1152
|
+
hosts)
|
760
1153
|
end
|
761
1154
|
else
|
762
|
-
promise.
|
1155
|
+
promise.break(error)
|
1156
|
+
end
|
1157
|
+
when Protocol::SetKeyspaceResultResponse
|
1158
|
+
@keyspace = r.keyspace
|
1159
|
+
promise.fulfill(Results::Void.new(r.custom_payload,
|
1160
|
+
r.warnings,
|
1161
|
+
r.trace_id,
|
1162
|
+
keyspace,
|
1163
|
+
statement,
|
1164
|
+
options,
|
1165
|
+
hosts,
|
1166
|
+
request.consistency,
|
1167
|
+
retries,
|
1168
|
+
self,
|
1169
|
+
@futures))
|
1170
|
+
when Protocol::PreparedResultResponse
|
1171
|
+
cql = request.cql
|
1172
|
+
synchronize do
|
1173
|
+
@prepared_statements[host][cql] = r.id
|
1174
|
+
@preparing_statements[host].delete(cql)
|
763
1175
|
end
|
764
1176
|
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
1177
|
+
metadata = r.metadata
|
1178
|
+
pk_idx = r.pk_idx
|
1179
|
+
pk_idx ||= @schema.get_pk_idx(metadata)
|
1180
|
+
|
1181
|
+
promise.fulfill(
|
1182
|
+
Statements::Prepared.new(r.custom_payload,
|
1183
|
+
r.warnings,
|
1184
|
+
cql,
|
1185
|
+
metadata,
|
1186
|
+
r.result_metadata,
|
1187
|
+
pk_idx,
|
1188
|
+
r.trace_id,
|
1189
|
+
keyspace,
|
1190
|
+
statement,
|
1191
|
+
options,
|
1192
|
+
hosts,
|
1193
|
+
request.consistency,
|
1194
|
+
retries,
|
1195
|
+
self,
|
1196
|
+
@connection_options))
|
1197
|
+
when Protocol::RawRowsResultResponse
|
1198
|
+
r.materialize(statement.result_metadata)
|
1199
|
+
promise.fulfill(
|
1200
|
+
Results::Paged.new(r.custom_payload,
|
1201
|
+
r.warnings,
|
1202
|
+
r.rows,
|
1203
|
+
r.paging_state,
|
1204
|
+
r.trace_id,
|
1205
|
+
keyspace,
|
1206
|
+
statement,
|
1207
|
+
options,
|
1208
|
+
hosts,
|
1209
|
+
request.consistency,
|
1210
|
+
retries,
|
1211
|
+
self,
|
1212
|
+
@futures))
|
1213
|
+
when Protocol::RowsResultResponse
|
1214
|
+
promise.fulfill(
|
1215
|
+
Results::Paged.new(r.custom_payload,
|
1216
|
+
r.warnings,
|
1217
|
+
r.rows,
|
1218
|
+
r.paging_state,
|
1219
|
+
r.trace_id,
|
1220
|
+
keyspace,
|
1221
|
+
statement,
|
1222
|
+
options,
|
1223
|
+
hosts,
|
1224
|
+
request.consistency,
|
1225
|
+
retries,
|
1226
|
+
self,
|
1227
|
+
@futures))
|
1228
|
+
when Protocol::SchemaChangeResultResponse
|
1229
|
+
if r.change == 'DROPPED' &&
|
1230
|
+
r.target == Protocol::Constants::SCHEMA_CHANGE_TARGET_KEYSPACE
|
1231
|
+
@schema.delete_keyspace(r.keyspace)
|
1232
|
+
end
|
1233
|
+
|
1234
|
+
@logger.debug('Waiting for schema to propagate to all hosts after a change')
|
1235
|
+
wait_for_schema_agreement(connection,
|
1236
|
+
@reconnection_policy.schedule).on_complete do |f|
|
1237
|
+
unless f.resolved?
|
1238
|
+
f.on_failure do |e|
|
1239
|
+
@logger.error(
|
1240
|
+
"Schema agreement failure (#{e.class.name}: #{e.message})")
|
782
1241
|
end
|
783
|
-
when Retry::Decisions::Ignore
|
784
|
-
promise.fulfill(Results::Void.new(r.custom_payload, r.warnings, r.trace_id, keyspace, statement, options, hosts, request.consistency, retries, self, @futures))
|
785
|
-
when Retry::Decisions::Reraise
|
786
|
-
promise.break(r.to_error(keyspace, statement, options, hosts, request.consistency, retries))
|
787
|
-
else
|
788
|
-
promise.break(r.to_error(keyspace, statement, options, hosts, request.consistency, retries))
|
789
1242
|
end
|
1243
|
+
promise.fulfill(
|
1244
|
+
Results::Void.new(r.custom_payload,
|
1245
|
+
r.warnings,
|
1246
|
+
r.trace_id,
|
1247
|
+
keyspace,
|
1248
|
+
statement,
|
1249
|
+
options,
|
1250
|
+
hosts,
|
1251
|
+
request.consistency,
|
1252
|
+
retries,
|
1253
|
+
self,
|
1254
|
+
@futures))
|
790
1255
|
end
|
791
|
-
|
792
|
-
promise.
|
1256
|
+
else
|
1257
|
+
promise.fulfill(Results::Void.new(r.custom_payload,
|
1258
|
+
r.warnings,
|
1259
|
+
r.trace_id,
|
1260
|
+
keyspace,
|
1261
|
+
statement,
|
1262
|
+
options,
|
1263
|
+
hosts,
|
1264
|
+
request.consistency,
|
1265
|
+
retries,
|
1266
|
+
self,
|
1267
|
+
@futures))
|
793
1268
|
end
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
1269
|
+
|
1270
|
+
if decision
|
1271
|
+
case decision
|
1272
|
+
when Retry::Decisions::Retry
|
1273
|
+
request.consistency = decision.consistency
|
1274
|
+
do_send_request_by_plan(host,
|
1275
|
+
connection,
|
1276
|
+
promise,
|
1277
|
+
keyspace,
|
1278
|
+
statement,
|
1279
|
+
options,
|
1280
|
+
request,
|
1281
|
+
plan,
|
1282
|
+
timeout,
|
1283
|
+
errors,
|
1284
|
+
hosts,
|
1285
|
+
retries + 1)
|
1286
|
+
when Retry::Decisions::TryNextHost
|
1287
|
+
errors[host] = r.to_error(keyspace,
|
1288
|
+
statement,
|
1289
|
+
options,
|
1290
|
+
hosts,
|
1291
|
+
request.consistency,
|
1292
|
+
retries)
|
1293
|
+
case request
|
1294
|
+
when Protocol::QueryRequest, Protocol::PrepareRequest
|
1295
|
+
send_request_by_plan(promise,
|
1296
|
+
keyspace,
|
1297
|
+
statement,
|
1298
|
+
options,
|
1299
|
+
request,
|
1300
|
+
plan,
|
1301
|
+
timeout,
|
1302
|
+
errors,
|
1303
|
+
hosts)
|
1304
|
+
when Protocol::ExecuteRequest
|
1305
|
+
execute_by_plan(promise,
|
1306
|
+
keyspace,
|
1307
|
+
statement,
|
1308
|
+
options,
|
1309
|
+
request,
|
1310
|
+
plan,
|
1311
|
+
timeout,
|
1312
|
+
errors,
|
1313
|
+
hosts)
|
1314
|
+
when Protocol::BatchRequest
|
1315
|
+
batch_by_plan(promise,
|
1316
|
+
keyspace,
|
1317
|
+
statement,
|
1318
|
+
options,
|
1319
|
+
request,
|
1320
|
+
plan,
|
1321
|
+
timeout,
|
1322
|
+
errors,
|
1323
|
+
hosts)
|
1324
|
+
else
|
1325
|
+
promise.break(e)
|
1326
|
+
end
|
1327
|
+
when Retry::Decisions::Ignore
|
1328
|
+
promise.fulfill(
|
1329
|
+
Results::Void.new(r.custom_payload,
|
1330
|
+
r.warnings,
|
1331
|
+
r.trace_id,
|
1332
|
+
keyspace,
|
1333
|
+
statement,
|
1334
|
+
options,
|
1335
|
+
hosts,
|
1336
|
+
request.consistency,
|
1337
|
+
retries,
|
1338
|
+
self,
|
1339
|
+
@futures))
|
1340
|
+
when Retry::Decisions::Reraise
|
1341
|
+
promise.break(
|
1342
|
+
r.to_error(keyspace,
|
1343
|
+
statement,
|
1344
|
+
options,
|
1345
|
+
hosts,
|
1346
|
+
request.consistency,
|
1347
|
+
retries))
|
805
1348
|
else
|
806
|
-
promise.break(
|
1349
|
+
promise.break(
|
1350
|
+
r.to_error(keyspace,
|
1351
|
+
statement,
|
1352
|
+
options,
|
1353
|
+
hosts,
|
1354
|
+
request.consistency,
|
1355
|
+
retries))
|
807
1356
|
end
|
808
1357
|
end
|
1358
|
+
rescue => e
|
1359
|
+
promise.break(e)
|
1360
|
+
end
|
1361
|
+
else
|
1362
|
+
response_future.on_failure do |ex|
|
1363
|
+
errors[host] = ex
|
1364
|
+
case request
|
1365
|
+
when Protocol::QueryRequest, Protocol::PrepareRequest
|
1366
|
+
send_request_by_plan(promise,
|
1367
|
+
keyspace,
|
1368
|
+
statement,
|
1369
|
+
options,
|
1370
|
+
request,
|
1371
|
+
plan,
|
1372
|
+
timeout,
|
1373
|
+
errors,
|
1374
|
+
hosts)
|
1375
|
+
when Protocol::ExecuteRequest
|
1376
|
+
execute_by_plan(promise,
|
1377
|
+
keyspace,
|
1378
|
+
statement,
|
1379
|
+
options,
|
1380
|
+
request,
|
1381
|
+
plan,
|
1382
|
+
timeout,
|
1383
|
+
errors,
|
1384
|
+
hosts)
|
1385
|
+
when Protocol::BatchRequest
|
1386
|
+
batch_by_plan(promise,
|
1387
|
+
keyspace,
|
1388
|
+
statement,
|
1389
|
+
options,
|
1390
|
+
request,
|
1391
|
+
plan,
|
1392
|
+
timeout,
|
1393
|
+
errors,
|
1394
|
+
hosts)
|
1395
|
+
else
|
1396
|
+
promise.break(ex)
|
1397
|
+
end
|
809
1398
|
end
|
810
1399
|
end
|
811
|
-
rescue => e
|
812
|
-
promise.break(e)
|
813
1400
|
end
|
814
1401
|
|
815
1402
|
def wait_for_schema_agreement(connection, schedule)
|
816
|
-
|
817
|
-
|
1403
|
+
peers_future = send_select_request(connection, SELECT_SCHEMA_PEERS)
|
1404
|
+
local_future = send_select_request(connection, SELECT_SCHEMA_LOCAL)
|
818
1405
|
|
819
|
-
Ione::Future.all(
|
1406
|
+
Ione::Future.all(peers_future, local_future).flat_map do |(peers, local)|
|
820
1407
|
versions = ::Set.new
|
821
1408
|
|
822
1409
|
unless local.empty?
|
@@ -841,7 +1428,8 @@ module Cassandra
|
|
841
1428
|
Ione::Future.resolved
|
842
1429
|
else
|
843
1430
|
interval = schedule.next
|
844
|
-
@logger.info(
|
1431
|
+
@logger.info('Hosts have different schema versions: ' \
|
1432
|
+
"#{versions.to_a.inspect}, retrying in #{interval} seconds")
|
845
1433
|
@reactor.schedule_timer(interval).flat_map do
|
846
1434
|
wait_for_schema_agreement(connection, schedule)
|
847
1435
|
end
|
@@ -862,7 +1450,10 @@ module Cassandra
|
|
862
1450
|
|
863
1451
|
return pending_switch || Ione::Future.resolved if pending_keyspace == keyspace
|
864
1452
|
|
865
|
-
request = Protocol::QueryRequest.new("USE #{Util.escape_name(keyspace)}",
|
1453
|
+
request = Protocol::QueryRequest.new("USE #{Util.escape_name(keyspace)}",
|
1454
|
+
EMPTY_LIST,
|
1455
|
+
EMPTY_LIST,
|
1456
|
+
:one)
|
866
1457
|
|
867
1458
|
f = connection.send_request(request, timeout).map do |r|
|
868
1459
|
case r
|
@@ -870,7 +1461,12 @@ module Cassandra
|
|
870
1461
|
@keyspace = r.keyspace
|
871
1462
|
nil
|
872
1463
|
when Protocol::ErrorResponse
|
873
|
-
raise r.to_error(nil,
|
1464
|
+
raise r.to_error(nil,
|
1465
|
+
Statements::Simple.new("USE #{Util.escape_name(keyspace)}"),
|
1466
|
+
VOID_OPTIONS,
|
1467
|
+
EMPTY_LIST,
|
1468
|
+
:one,
|
1469
|
+
0)
|
874
1470
|
else
|
875
1471
|
raise Errors::InternalError, "Unexpected response #{r.inspect}"
|
876
1472
|
end
|
@@ -879,7 +1475,7 @@ module Cassandra
|
|
879
1475
|
connection[:pending_keyspace] = keyspace
|
880
1476
|
connection[:pending_switch] = f
|
881
1477
|
|
882
|
-
f.on_complete do |
|
1478
|
+
f.on_complete do |_f|
|
883
1479
|
connection[:pending_switch] = nil
|
884
1480
|
connection[:pending_keyspace] = nil
|
885
1481
|
end
|
@@ -891,7 +1487,7 @@ module Cassandra
|
|
891
1487
|
synchronize do
|
892
1488
|
pending = @preparing_statements[host]
|
893
1489
|
|
894
|
-
return pending[cql] if pending.
|
1490
|
+
return pending[cql] if pending.key?(cql)
|
895
1491
|
end
|
896
1492
|
|
897
1493
|
request = Protocol::PrepareRequest.new(cql, false)
|