cassandra-driver 1.0.0.beta.1 → 1.0.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +20 -12
- data/ext/cassandra_murmur3/cassandra_murmur3.c +178 -0
- data/ext/cassandra_murmur3/extconf.rb +2 -0
- data/lib/cassandra.rb +132 -24
- data/lib/cassandra/auth.rb +5 -5
- data/lib/cassandra/client/connector.rb +11 -6
- data/lib/cassandra/cluster.rb +47 -23
- data/lib/cassandra/cluster/client.rb +5 -4
- data/lib/cassandra/cluster/connector.rb +17 -4
- data/lib/cassandra/cluster/control_connection.rb +21 -16
- data/lib/cassandra/cluster/metadata.rb +124 -0
- data/lib/cassandra/cluster/options.rb +5 -3
- data/lib/cassandra/cluster/registry.rb +26 -9
- data/lib/cassandra/cluster/schema.rb +23 -4
- data/lib/cassandra/cluster/schema/partitioners.rb +21 -0
- data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +47 -0
- data/lib/cassandra/cluster/schema/partitioners/ordered.rb +37 -0
- data/lib/cassandra/cluster/schema/partitioners/random.rb +37 -0
- data/lib/cassandra/cluster/schema/replication_strategies.rb +21 -0
- data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +92 -0
- data/lib/cassandra/cluster/schema/replication_strategies/none.rb +39 -0
- data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +44 -0
- data/lib/cassandra/cluster/schema/type_parser.rb +1 -1
- data/lib/cassandra/compression.rb +1 -1
- data/lib/cassandra/driver.rb +29 -4
- data/lib/cassandra/execution/options.rb +3 -0
- data/lib/cassandra/host.rb +9 -5
- data/lib/cassandra/keyspace.rb +17 -4
- data/lib/cassandra/listener.rb +3 -3
- data/lib/cassandra/load_balancing.rb +12 -11
- data/lib/cassandra/load_balancing/policies.rb +2 -1
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +1 -1
- data/lib/cassandra/load_balancing/policies/round_robin.rb +37 -0
- data/lib/cassandra/load_balancing/policies/token_aware.rb +119 -0
- data/lib/cassandra/protocol/cql_protocol_handler.rb +2 -2
- data/lib/cassandra/reconnection.rb +5 -5
- data/lib/cassandra/retry.rb +3 -3
- data/lib/cassandra/session.rb +7 -0
- data/lib/cassandra/statements/bound.rb +4 -2
- data/lib/cassandra/statements/prepared.rb +28 -6
- data/lib/cassandra/table.rb +49 -4
- data/lib/cassandra/time_uuid.rb +1 -0
- data/lib/cassandra/util.rb +0 -2
- data/lib/cassandra/version.rb +1 -1
- metadata +50 -45
data/lib/cassandra/auth.rb
CHANGED
@@ -46,7 +46,7 @@ module Cassandra
|
|
46
46
|
# @param authentication_class [String] the authentication class used by
|
47
47
|
# the server.
|
48
48
|
# @return [Cassandra::Auth::Authenticator, nil] an object with an
|
49
|
-
# interface matching {Cassandra::Auth::Authenticator} or nil if the
|
49
|
+
# interface matching {Cassandra::Auth::Authenticator} or `nil` if the
|
50
50
|
# authentication class is not supported.
|
51
51
|
end
|
52
52
|
|
@@ -55,12 +55,12 @@ module Cassandra
|
|
55
55
|
# block. If any of the method calls block, the whole connection process
|
56
56
|
# will be blocked.
|
57
57
|
#
|
58
|
-
# @
|
59
|
-
# of this class, but need to implement the same methods. This
|
60
|
-
# only for documentation purposes.
|
58
|
+
# @abstract Authenticators created by auth providers don't need to be
|
59
|
+
# subclasses of this class, but need to implement the same methods. This
|
60
|
+
# class exists only for documentation purposes.
|
61
61
|
#
|
62
62
|
# @see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v2.spec#L257-L273 Cassandra native protocol v2 SASL authentication
|
63
|
-
# @see Cassandra::Auth::Provider
|
63
|
+
# @see Cassandra::Auth::Provider#create_authenticator
|
64
64
|
class Authenticator
|
65
65
|
# @!method initial_response
|
66
66
|
#
|
@@ -88,16 +88,16 @@ module Cassandra
|
|
88
88
|
|
89
89
|
# @private
|
90
90
|
class ConnectStep
|
91
|
-
def initialize(io_reactor, protocol_handler_factory, port,
|
91
|
+
def initialize(io_reactor, protocol_handler_factory, port, connection_options, logger)
|
92
92
|
@io_reactor = io_reactor
|
93
93
|
@protocol_handler_factory = protocol_handler_factory
|
94
94
|
@port = port
|
95
|
-
@
|
95
|
+
@connection_options = connection_options
|
96
96
|
@logger = logger
|
97
97
|
end
|
98
98
|
|
99
99
|
def run(pending_connection)
|
100
|
-
@io_reactor.connect(pending_connection.host, @port, @
|
100
|
+
@io_reactor.connect(pending_connection.host, @port, @connection_options, &@protocol_handler_factory).map do |connection|
|
101
101
|
pending_connection.with_connection(connection)
|
102
102
|
end
|
103
103
|
end
|
@@ -105,12 +105,17 @@ module Cassandra
|
|
105
105
|
|
106
106
|
# @private
|
107
107
|
class CacheOptionsStep
|
108
|
+
def initialize(timeout = nil)
|
109
|
+
@timeout = timeout
|
110
|
+
end
|
111
|
+
|
108
112
|
def run(pending_connection)
|
109
|
-
f = pending_connection.execute(Protocol::OptionsRequest.new)
|
113
|
+
f = pending_connection.execute(Protocol::OptionsRequest.new, @timeout)
|
110
114
|
f.on_value do |supported_options|
|
111
115
|
pending_connection[:cql_version] = supported_options['CQL_VERSION']
|
112
116
|
pending_connection[:compression] = supported_options['COMPRESSION']
|
113
117
|
end
|
118
|
+
|
114
119
|
f.map(pending_connection)
|
115
120
|
end
|
116
121
|
end
|
@@ -250,8 +255,8 @@ module Cassandra
|
|
250
255
|
@connection[key] = value
|
251
256
|
end
|
252
257
|
|
253
|
-
def execute(request, &block)
|
254
|
-
@request_runner.execute(@connection, request,
|
258
|
+
def execute(request, timeout = nil, &block)
|
259
|
+
@request_runner.execute(@connection, request, timeout, nil, &block)
|
255
260
|
end
|
256
261
|
end
|
257
262
|
|
data/lib/cassandra/cluster.rb
CHANGED
@@ -26,15 +26,6 @@ module Cassandra
|
|
26
26
|
class Cluster
|
27
27
|
extend Forwardable
|
28
28
|
|
29
|
-
# @!method each_host
|
30
|
-
# Yield or enumerate each member of this cluster
|
31
|
-
# @overload each_host
|
32
|
-
# @yieldparam host [Cassandra::Host] current host
|
33
|
-
# @return [Array<Cassandra::Host>] a list of hosts
|
34
|
-
# @overload each_host
|
35
|
-
# @return [Enumerator<Cassandra::Host>] an enumerator
|
36
|
-
# @!parse alias :hosts :each_host
|
37
|
-
#
|
38
29
|
# @!method host(address)
|
39
30
|
# Find a host by its address
|
40
31
|
# @param address [IPAddr, String] ip address
|
@@ -44,17 +35,8 @@ module Cassandra
|
|
44
35
|
# Determine if a host by a given address exists
|
45
36
|
# @param address [IPAddr, String] ip address
|
46
37
|
# @return [Boolean] true or false
|
47
|
-
def_delegators :@registry, :
|
48
|
-
|
49
|
-
# @!method each_keyspace
|
50
|
-
# Yield or enumerate each keyspace defined in this cluster
|
51
|
-
# @overload each_keyspace
|
52
|
-
# @yieldparam keyspace [Cassandra::Keyspace] current keyspace
|
53
|
-
# @return [Array<Cassandra::Keyspace>] a list of keyspaces
|
54
|
-
# @overload each_keyspace
|
55
|
-
# @return [Enumerator<Cassandra::Keyspace>] an enumerator
|
56
|
-
# @!parse alias :keyspaces :each_keyspace
|
57
|
-
#
|
38
|
+
def_delegators :@registry, :host, :has_host?
|
39
|
+
|
58
40
|
# @!method keyspace(name)
|
59
41
|
# Find a keyspace by name
|
60
42
|
# @param name [String] keyspace name
|
@@ -64,15 +46,30 @@ module Cassandra
|
|
64
46
|
# Determine if a keyspace by a given name exists
|
65
47
|
# @param name [String] keyspace name
|
66
48
|
# @return [Boolean] true or false
|
67
|
-
def_delegators :@schema, :
|
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
|
68
64
|
|
69
65
|
# @private
|
70
|
-
def initialize(logger, io_reactor, control_connection, cluster_registry, cluster_schema, execution_options, connection_options, load_balancing_policy, reconnection_policy, retry_policy, connector, futures_factory)
|
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, connector, futures_factory)
|
71
67
|
@logger = logger
|
72
68
|
@io_reactor = io_reactor
|
73
69
|
@control_connection = control_connection
|
74
70
|
@registry = cluster_registry
|
75
71
|
@schema = cluster_schema
|
72
|
+
@metadata = cluster_metadata
|
76
73
|
@execution_options = execution_options
|
77
74
|
@connection_options = connection_options
|
78
75
|
@load_balancing_policy = load_balancing_policy
|
@@ -104,6 +101,32 @@ module Cassandra
|
|
104
101
|
self
|
105
102
|
end
|
106
103
|
|
104
|
+
# Yield or enumerate each member of this cluster
|
105
|
+
# @overload each_host
|
106
|
+
# @yieldparam host [Cassandra::Host] current host
|
107
|
+
# @return [Cassandra::Cluster] self
|
108
|
+
# @overload each_host
|
109
|
+
# @return [Array<Cassandra::Host>] a list of hosts
|
110
|
+
def each_host(&block)
|
111
|
+
r = @registry.each_host(&block)
|
112
|
+
return self if r == @registry
|
113
|
+
r
|
114
|
+
end
|
115
|
+
alias :hosts :each_host
|
116
|
+
|
117
|
+
# Yield or enumerate each keyspace defined in this cluster
|
118
|
+
# @overload each_keyspace
|
119
|
+
# @yieldparam keyspace [Cassandra::Keyspace] current keyspace
|
120
|
+
# @return [Cassandra::Cluster] self
|
121
|
+
# @overload each_keyspace
|
122
|
+
# @return [Array<Cassandra::Keyspace>] a list of keyspaces
|
123
|
+
def each_keyspace(&block)
|
124
|
+
r = @schema.each_keyspace(&block)
|
125
|
+
return self if r == @schema
|
126
|
+
r
|
127
|
+
end
|
128
|
+
alias :keyspaces :each_keyspace
|
129
|
+
|
107
130
|
# Asynchronously create a new session, optionally scoped to a keyspace
|
108
131
|
#
|
109
132
|
# @param keyspace [String] optional keyspace to scope session to
|
@@ -115,7 +138,7 @@ module Cassandra
|
|
115
138
|
return @futures.error(::ArgumentError.new("keyspace must be a string, #{keyspace.inspect} given"))
|
116
139
|
end
|
117
140
|
|
118
|
-
client = Client.new(@logger, @registry, @io_reactor, @connector, @load_balancing_policy, @reconnection_policy, @retry_policy, @connection_options, @futures)
|
141
|
+
client = Client.new(@logger, @registry, @schema, @io_reactor, @connector, @load_balancing_policy, @reconnection_policy, @retry_policy, @connection_options, @futures)
|
119
142
|
session = Session.new(client, @execution_options, @futures)
|
120
143
|
promise = @futures.promise
|
121
144
|
|
@@ -186,6 +209,7 @@ end
|
|
186
209
|
require 'cassandra/cluster/client'
|
187
210
|
require 'cassandra/cluster/connector'
|
188
211
|
require 'cassandra/cluster/control_connection'
|
212
|
+
require 'cassandra/cluster/metadata'
|
189
213
|
require 'cassandra/cluster/options'
|
190
214
|
require 'cassandra/cluster/registry'
|
191
215
|
require 'cassandra/cluster/schema'
|
@@ -22,9 +22,12 @@ module Cassandra
|
|
22
22
|
class Client
|
23
23
|
include MonitorMixin
|
24
24
|
|
25
|
-
|
25
|
+
attr_reader :keyspace
|
26
|
+
|
27
|
+
def initialize(logger, cluster_registry, cluster_schema, io_reactor, connector, load_balancing_policy, reconnection_policy, retry_policy, connection_options, futures_factory)
|
26
28
|
@logger = logger
|
27
29
|
@registry = cluster_registry
|
30
|
+
@schema = cluster_schema
|
28
31
|
@reactor = io_reactor
|
29
32
|
@connector = connector
|
30
33
|
@load_balancing_policy = load_balancing_policy
|
@@ -597,9 +600,7 @@ module Cassandra
|
|
597
600
|
@preparing_statements[host].delete(cql)
|
598
601
|
end
|
599
602
|
|
600
|
-
|
601
|
-
|
602
|
-
promise.fulfill(Statements::Prepared.new(cql, r.metadata, r.result_metadata, execution_info))
|
603
|
+
promise.fulfill(Statements::Prepared.new(cql, r.metadata, r.result_metadata, r.trace_id, keyspace, statement, options, hosts, request.consistency, retries, self, @futures, @schema))
|
603
604
|
when Protocol::RawRowsResultResponse
|
604
605
|
r.materialize(statement.result_metadata)
|
605
606
|
promise.fulfill(Results::Paged.new(r.rows, r.paging_state, r.trace_id, keyspace, statement, options, hosts, request.consistency, retries, self, @futures))
|
@@ -69,7 +69,11 @@ module Cassandra
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def refresh_status(host)
|
72
|
-
|
72
|
+
if synchronize { @connections[host] }
|
73
|
+
@registry.host_up(host.ip)
|
74
|
+
|
75
|
+
return Future.resolved
|
76
|
+
end
|
73
77
|
|
74
78
|
@logger.info("Refreshing host status ip=#{host.ip}")
|
75
79
|
f = do_connect(host)
|
@@ -130,11 +134,20 @@ module Cassandra
|
|
130
134
|
|
131
135
|
def create_connector
|
132
136
|
authentication_step = @options.protocol_version == 1 ? Cassandra::Client::CredentialsAuthenticationStep.new(@options.credentials) : Cassandra::Client::SaslAuthenticationStep.new(@options.auth_provider)
|
133
|
-
protocol_handler_factory = lambda
|
137
|
+
protocol_handler_factory = lambda do |connection|
|
138
|
+
raise "no connection given" unless connection
|
139
|
+
Protocol::CqlProtocolHandler.new(connection, @reactor, @options.protocol_version, @options.compressor)
|
140
|
+
end
|
134
141
|
|
135
142
|
Cassandra::Client::Connector.new([
|
136
|
-
Cassandra::Client::ConnectStep.new(
|
137
|
-
|
143
|
+
Cassandra::Client::ConnectStep.new(
|
144
|
+
@reactor,
|
145
|
+
protocol_handler_factory,
|
146
|
+
@options.port,
|
147
|
+
{:timeout => @options.connect_timeout, :ssl => @options.ssl},
|
148
|
+
@logger
|
149
|
+
),
|
150
|
+
Cassandra::Client::CacheOptionsStep.new(@options.connect_timeout),
|
138
151
|
Cassandra::Client::InitializeStep.new(@options.compressor, @logger),
|
139
152
|
authentication_step,
|
140
153
|
Cassandra::Client::CachePropertiesStep.new,
|
@@ -22,11 +22,12 @@ module Cassandra
|
|
22
22
|
class ControlConnection
|
23
23
|
include MonitorMixin
|
24
24
|
|
25
|
-
def initialize(logger, io_reactor, cluster_registry, cluster_schema, load_balancing_policy, reconnection_policy, connector)
|
25
|
+
def initialize(logger, io_reactor, cluster_registry, cluster_schema, cluster_metadata, load_balancing_policy, reconnection_policy, connector)
|
26
26
|
@logger = logger
|
27
27
|
@io_reactor = io_reactor
|
28
28
|
@registry = cluster_registry
|
29
29
|
@schema = cluster_schema
|
30
|
+
@metadata = cluster_metadata
|
30
31
|
@load_balancing_policy = load_balancing_policy
|
31
32
|
@reconnection_policy = reconnection_policy
|
32
33
|
@connector = connector
|
@@ -96,8 +97,8 @@ module Cassandra
|
|
96
97
|
|
97
98
|
private
|
98
99
|
|
99
|
-
SELECT_LOCAL = Protocol::QueryRequest.new('SELECT rack, data_center, host_id, release_version FROM system.local', nil, nil, :one)
|
100
|
-
SELECT_PEERS = Protocol::QueryRequest.new('SELECT peer, rack, data_center, host_id, rpc_address, release_version FROM system.peers', nil, nil, :one)
|
100
|
+
SELECT_LOCAL = Protocol::QueryRequest.new('SELECT rack, data_center, host_id, release_version, tokens, partitioner FROM system.local', nil, nil, :one)
|
101
|
+
SELECT_PEERS = Protocol::QueryRequest.new('SELECT peer, rack, data_center, host_id, rpc_address, release_version, tokens FROM system.peers', nil, nil, :one)
|
101
102
|
SELECT_KEYSPACES = Protocol::QueryRequest.new('SELECT * FROM system.schema_keyspaces', nil, nil, :one)
|
102
103
|
SELECT_TABLES = Protocol::QueryRequest.new('SELECT * FROM system.schema_columnfamilies', nil, nil, :one)
|
103
104
|
SELECT_COLUMNS = Protocol::QueryRequest.new('SELECT * FROM system.schema_columns', nil, nil, :one)
|
@@ -178,9 +179,13 @@ module Cassandra
|
|
178
179
|
when 'NEW_NODE'
|
179
180
|
address = event.address
|
180
181
|
|
181
|
-
|
182
|
+
unless @registry.has_host?(address)
|
183
|
+
refresh_host_async(address)
|
184
|
+
refresh_schema_async
|
185
|
+
end
|
182
186
|
when 'REMOVED_NODE'
|
183
187
|
@registry.host_lost(event.address)
|
188
|
+
refresh_schema_async
|
184
189
|
end
|
185
190
|
end
|
186
191
|
end
|
@@ -206,6 +211,7 @@ module Cassandra
|
|
206
211
|
host = @registry.host(connection.host)
|
207
212
|
|
208
213
|
@schema.update_keyspaces(host, keyspaces.rows, tables.rows, columns.rows)
|
214
|
+
@metadata.rebuild_token_map
|
209
215
|
end
|
210
216
|
end
|
211
217
|
|
@@ -268,32 +274,31 @@ module Cassandra
|
|
268
274
|
|
269
275
|
raise NO_HOSTS if local.empty? && peers.empty?
|
270
276
|
|
271
|
-
|
272
|
-
ips = ::Set.new
|
273
|
-
|
274
|
-
unless local.empty?
|
275
|
-
ips << local_ip
|
276
|
-
@registry.host_found(IPAddr.new(local_ip), local.first)
|
277
|
-
end
|
277
|
+
ips = ::Set.new
|
278
278
|
|
279
279
|
peers.each do |data|
|
280
|
-
ip = peer_ip(data)
|
281
|
-
ips << ip.to_s
|
280
|
+
ips << ip = peer_ip(data)
|
282
281
|
@registry.host_found(ip, data)
|
283
282
|
end
|
284
283
|
|
284
|
+
ips << ip = IPAddr.new(connection.host)
|
285
|
+
data = local.first
|
286
|
+
@registry.host_found(ip, data)
|
287
|
+
|
285
288
|
futures = []
|
286
289
|
|
287
290
|
@registry.each_host do |host|
|
288
|
-
if ips.include?(host.ip
|
291
|
+
if ips.include?(host.ip)
|
289
292
|
futures << refresh_host_status(host) if host.down?
|
290
293
|
else
|
291
294
|
@registry.host_lost(host.ip)
|
292
295
|
end
|
293
296
|
end
|
294
297
|
|
298
|
+
@metadata.update(data)
|
299
|
+
|
295
300
|
if futures.empty?
|
296
|
-
Ione::Future.resolved
|
301
|
+
Ione::Future.resolved
|
297
302
|
else
|
298
303
|
Ione::Future.all(*futures)
|
299
304
|
end
|
@@ -332,7 +337,7 @@ module Cassandra
|
|
332
337
|
if ip == connection.host
|
333
338
|
request = SELECT_LOCAL
|
334
339
|
else
|
335
|
-
request = Protocol::QueryRequest.new('SELECT rack, data_center, host_id, rpc_address, release_version FROM system.peers WHERE peer = ?', [address], nil, :one)
|
340
|
+
request = Protocol::QueryRequest.new('SELECT rack, data_center, host_id, rpc_address, release_version, tokens FROM system.peers WHERE peer = ?', [address], nil, :one)
|
336
341
|
end
|
337
342
|
|
338
343
|
connection.send_request(request).map do |response|
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright 2013-2014 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
|
+
module Cassandra
|
20
|
+
class Cluster
|
21
|
+
# @private
|
22
|
+
class Metadata
|
23
|
+
include MonitorMixin
|
24
|
+
|
25
|
+
attr_reader :name
|
26
|
+
|
27
|
+
def initialize(cluster_registry, cluster_schema, schema_partitioners, replication_strategies, default_replication_strategy)
|
28
|
+
@registry = cluster_registry
|
29
|
+
@schema = cluster_schema
|
30
|
+
@partitioners = schema_partitioners
|
31
|
+
@strategies = replication_strategies
|
32
|
+
@default_strategy = default_replication_strategy
|
33
|
+
end
|
34
|
+
|
35
|
+
def find_replicas(keyspace, statement)
|
36
|
+
unless statement.respond_to?(:partition_key) && statement.respond_to?(:keyspace)
|
37
|
+
return EMPTY_LIST
|
38
|
+
end
|
39
|
+
|
40
|
+
keyspace = String(statement.keyspace || keyspace)
|
41
|
+
partition_key = statement.partition_key
|
42
|
+
return EMPTY_LIST unless keyspace && partition_key
|
43
|
+
|
44
|
+
partitioner = @partitioner
|
45
|
+
return EMPTY_LIST unless partitioner
|
46
|
+
|
47
|
+
keyspace_hosts = @token_replicas[keyspace]
|
48
|
+
return EMPTY_LIST if keyspace_hosts.nil? || keyspace_hosts.empty?
|
49
|
+
|
50
|
+
token = partitioner.create_token(partition_key)
|
51
|
+
index = insertion_point(@token_ring, token)
|
52
|
+
index = 0 if index >= @token_ring.size
|
53
|
+
hosts = keyspace_hosts[@token_ring[index]]
|
54
|
+
return EMPTY_LIST unless hosts
|
55
|
+
|
56
|
+
hosts
|
57
|
+
end
|
58
|
+
|
59
|
+
def update(data)
|
60
|
+
@name = data['name']
|
61
|
+
@partitioner = @partitioners[data['partitioner']]
|
62
|
+
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
def rebuild_token_map
|
67
|
+
partitioner = @partitioner
|
68
|
+
return self unless partitioner
|
69
|
+
|
70
|
+
tokens = ::SortedSet.new
|
71
|
+
token_to_host = ::Hash.new
|
72
|
+
|
73
|
+
@registry.each_host do |host|
|
74
|
+
host.tokens.each do |token|
|
75
|
+
token = partitioner.parse_token(token) rescue next
|
76
|
+
tokens.add(token)
|
77
|
+
token_to_host[token] = host
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
token_ring = tokens.to_a
|
82
|
+
token_replicas = ::Hash.new
|
83
|
+
|
84
|
+
@schema.each_keyspace do |keyspace|
|
85
|
+
replication = keyspace.replication
|
86
|
+
strategy = @strategies[replication.klass] || @default_strategy
|
87
|
+
|
88
|
+
token_replicas[keyspace.name] = strategy.replication_map(
|
89
|
+
token_to_host,
|
90
|
+
token_ring,
|
91
|
+
replication.options
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
95
|
+
@token_replicas = token_replicas
|
96
|
+
@token_ring = token_ring
|
97
|
+
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def insertion_point(list, item)
|
104
|
+
min = 0
|
105
|
+
max = list.size - 1
|
106
|
+
|
107
|
+
while min <= max do
|
108
|
+
idx = (min + max) / 2
|
109
|
+
val = list[idx]
|
110
|
+
|
111
|
+
if val < item
|
112
|
+
min = idx + 1
|
113
|
+
elsif val > item
|
114
|
+
max = idx - 1
|
115
|
+
else
|
116
|
+
return idx # item found
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
min # item not found.
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|