cassandra-driver 1.0.0.beta.1 → 1.0.0.beta.2
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 +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
|