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
@@ -0,0 +1,39 @@
|
|
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
|
+
class Schema
|
22
|
+
# @private
|
23
|
+
module ReplicationStrategies
|
24
|
+
# @private
|
25
|
+
class None
|
26
|
+
def replication_map(token_hosts, token_ring, replication_options)
|
27
|
+
replication_map = ::Hash.new
|
28
|
+
|
29
|
+
token_hosts.each do |token, host|
|
30
|
+
replication_map[token] = [host].freeze
|
31
|
+
end
|
32
|
+
|
33
|
+
replication_map
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,44 @@
|
|
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
|
+
class Schema
|
22
|
+
# @private
|
23
|
+
module ReplicationStrategies
|
24
|
+
# @private
|
25
|
+
class Simple
|
26
|
+
def replication_map(token_hosts, token_ring, replication_options)
|
27
|
+
factor = Integer(replication_options['replication_factor'])
|
28
|
+
size = token_ring.size
|
29
|
+
factor = size if size < factor
|
30
|
+
replication_map = ::Hash.new
|
31
|
+
|
32
|
+
token_ring.each_with_index do |token, i|
|
33
|
+
replication_map[token] = factor.times.map do |j|
|
34
|
+
token_hosts[token_ring[(i + j) % size]]
|
35
|
+
end.freeze
|
36
|
+
end
|
37
|
+
|
38
|
+
replication_map
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -18,7 +18,7 @@
|
|
18
18
|
|
19
19
|
module Cassandra
|
20
20
|
module Compression
|
21
|
-
# @
|
21
|
+
# @abstract Compressors given to {Cassandra.connect} as the `:compressor`
|
22
22
|
# option don't need to be subclasses of this class, but need to implement
|
23
23
|
# the same methods. This class exists only for documentation purposes.
|
24
24
|
class Compressor
|
data/lib/cassandra/driver.rb
CHANGED
@@ -27,15 +27,38 @@ module Cassandra
|
|
27
27
|
let(:io_reactor) { Io::IoReactor.new }
|
28
28
|
let(:cluster_registry) { Cluster::Registry.new(logger) }
|
29
29
|
let(:cluster_schema) { Cluster::Schema.new(schema_type_parser) }
|
30
|
+
let(:cluster_metadata) { Cluster::Metadata.new(
|
31
|
+
cluster_registry,
|
32
|
+
cluster_schema,
|
33
|
+
{
|
34
|
+
'org.apache.cassandra.dht.Murmur3Partitioner' => murmur3_partitioner,
|
35
|
+
'org.apache.cassandra.dht.ByteOrderedPartitioner' => ordered_partitioner,
|
36
|
+
'org.apache.cassandra.dht.RandomPartitioner' => random_partitioner
|
37
|
+
}.freeze,
|
38
|
+
{
|
39
|
+
'org.apache.cassandra.locator.SimpleStrategy' => simple_replication_strategy,
|
40
|
+
'org.apache.cassandra.locator.NetworkTopologyStrategy' => network_topology_replication_strategy
|
41
|
+
}.freeze,
|
42
|
+
no_replication_strategy
|
43
|
+
)
|
44
|
+
}
|
30
45
|
let(:futures_factory) { Future }
|
31
46
|
|
32
47
|
let(:schema_type_parser) { Cluster::Schema::TypeParser.new }
|
33
48
|
|
49
|
+
let(:simple_replication_strategy) { Cluster::Schema::ReplicationStrategies::Simple.new }
|
50
|
+
let(:network_topology_replication_strategy) { Cluster::Schema::ReplicationStrategies::NetworkTopology.new }
|
51
|
+
let(:no_replication_strategy) { Cluster::Schema::ReplicationStrategies::None.new }
|
52
|
+
|
53
|
+
let(:murmur3_partitioner) { Cluster::Schema::Partitioners::Murmur3.new }
|
54
|
+
let(:ordered_partitioner) { Cluster::Schema::Partitioners::Ordered.new }
|
55
|
+
let(:random_partitioner) { Cluster::Schema::Partitioners::Random.new }
|
56
|
+
|
34
57
|
let(:connector) { Cluster::Connector.new(logger, io_reactor, cluster_registry, connection_options) }
|
35
58
|
|
36
|
-
let(:control_connection) { Cluster::ControlConnection.new(logger, io_reactor, cluster_registry, cluster_schema, load_balancing_policy, reconnection_policy, connector) }
|
59
|
+
let(:control_connection) { Cluster::ControlConnection.new(logger, io_reactor, cluster_registry, cluster_schema, cluster_metadata, load_balancing_policy, reconnection_policy, connector) }
|
37
60
|
|
38
|
-
let(:cluster) { Cluster.new(logger, io_reactor, control_connection, cluster_registry, cluster_schema, execution_options, connection_options, load_balancing_policy, reconnection_policy, retry_policy, connector, futures_factory) }
|
61
|
+
let(:cluster) { Cluster.new(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) }
|
39
62
|
|
40
63
|
let(:execution_options) do
|
41
64
|
Execution::Options.new({
|
@@ -45,11 +68,12 @@ module Cassandra
|
|
45
68
|
})
|
46
69
|
end
|
47
70
|
|
48
|
-
let(:connection_options) { Cluster::Options.new(protocol_version, credentials, auth_provider, compressor, port,
|
71
|
+
let(:connection_options) { Cluster::Options.new(protocol_version, credentials, auth_provider, compressor, port, connect_timeout, ssl, connections_per_local_node, connections_per_remote_node) }
|
49
72
|
|
50
73
|
let(:port) { 9042 }
|
51
74
|
let(:protocol_version) { 2 }
|
52
|
-
let(:
|
75
|
+
let(:connect_timeout) { 10 }
|
76
|
+
let(:ssl) { false }
|
53
77
|
let(:logger) { Client::NullLogger.new }
|
54
78
|
let(:compressor) { nil }
|
55
79
|
let(:credentials) { nil }
|
@@ -72,6 +96,7 @@ module Cassandra
|
|
72
96
|
end
|
73
97
|
|
74
98
|
def connect(addresses)
|
99
|
+
load_balancing_policy.setup(cluster)
|
75
100
|
cluster_registry.add_listener(load_balancing_policy)
|
76
101
|
cluster_registry.add_listener(control_connection)
|
77
102
|
listeners.each do |listener|
|
@@ -45,6 +45,9 @@ module Cassandra
|
|
45
45
|
page_size = page_size && Integer(page_size)
|
46
46
|
timeout = timeout && Integer(timeout)
|
47
47
|
|
48
|
+
raise ::ArgumentError, ":page_size must be greater than 0, #{page_size.inspect} given" if page_size && page_size <= 0
|
49
|
+
raise ::ArgumentError, ":timeout must be greater than 0, #{timeout.inspect} given" if timeout && timeout <= 0
|
50
|
+
|
48
51
|
@consistency = consistency
|
49
52
|
@page_size = page_size
|
50
53
|
@trace = !!trace
|
data/lib/cassandra/host.rb
CHANGED
@@ -20,28 +20,32 @@ module Cassandra
|
|
20
20
|
class Host
|
21
21
|
# @return [IPAddr] host ip
|
22
22
|
attr_reader :ip
|
23
|
-
# @note Host id can be `nil` before cluster connected.
|
23
|
+
# @note Host id can be `nil` before cluster has connected.
|
24
24
|
# @return [Cassandra::Uuid, nil] host id.
|
25
25
|
attr_reader :id
|
26
|
-
# @note Host datacenter can be `nil` before cluster connected.
|
26
|
+
# @note Host datacenter can be `nil` before cluster has connected.
|
27
27
|
# @return [String, nil] host datacenter
|
28
28
|
attr_reader :datacenter
|
29
|
-
# @note Host rack can be `nil` before cluster connected.
|
29
|
+
# @note Host rack can be `nil` before cluster has connected.
|
30
30
|
# @return [String, nil] host rack
|
31
31
|
attr_reader :rack
|
32
|
-
# @note Host's cassandra version can be `nil` before cluster connected.
|
32
|
+
# @note Host's cassandra version can be `nil` before cluster has connected.
|
33
33
|
# @return [String, nil] version of cassandra that a host is running
|
34
34
|
attr_reader :release_version
|
35
|
+
# @note Host tokens will be empty before cluster has connected.
|
36
|
+
# @return [Array<String>] a list of tokens owned by this host
|
37
|
+
attr_reader :tokens
|
35
38
|
# @return [Symbol] host status. Must be `:up` or `:down`
|
36
39
|
attr_reader :status
|
37
40
|
|
38
41
|
# @private
|
39
|
-
def initialize(ip, id = nil, rack = nil, datacenter = nil, release_version = nil, status = :up)
|
42
|
+
def initialize(ip, id = nil, rack = nil, datacenter = nil, release_version = nil, tokens = EMPTY_LIST, status = :up)
|
40
43
|
@ip = ip
|
41
44
|
@id = id
|
42
45
|
@rack = rack
|
43
46
|
@datacenter = datacenter
|
44
47
|
@release_version = release_version
|
48
|
+
@tokens = tokens
|
45
49
|
@status = status
|
46
50
|
end
|
47
51
|
|
data/lib/cassandra/keyspace.rb
CHANGED
@@ -78,11 +78,16 @@ module Cassandra
|
|
78
78
|
# Yield or enumerate each table defined in this keyspace
|
79
79
|
# @overload each_table
|
80
80
|
# @yieldparam table [Cassandra::Table] current table
|
81
|
-
# @return [
|
81
|
+
# @return [Cassandra::Keyspace] self
|
82
82
|
# @overload each_table
|
83
|
-
# @return [
|
83
|
+
# @return [Array<Cassandra::Table>] a list of tables
|
84
84
|
def each_table(&block)
|
85
|
-
|
85
|
+
if block_given?
|
86
|
+
@tables.each_value(&block)
|
87
|
+
self
|
88
|
+
else
|
89
|
+
@tables.values
|
90
|
+
end
|
86
91
|
end
|
87
92
|
alias :tables :each_table
|
88
93
|
|
@@ -103,7 +108,15 @@ module Cassandra
|
|
103
108
|
|
104
109
|
# @private
|
105
110
|
def update_table(table)
|
106
|
-
|
111
|
+
tables = @tables.dup
|
112
|
+
tables[table.name] = table
|
113
|
+
Keyspace.new(@name, @durable_writes, @replication, tables)
|
114
|
+
end
|
115
|
+
|
116
|
+
# @private
|
117
|
+
def create_partition_key(table, values)
|
118
|
+
table = @tables[table]
|
119
|
+
table && table.create_partition_key(values)
|
107
120
|
end
|
108
121
|
|
109
122
|
# @private
|
data/lib/cassandra/listener.rb
CHANGED
@@ -19,9 +19,9 @@
|
|
19
19
|
module Cassandra
|
20
20
|
# Cassandra state listener.
|
21
21
|
#
|
22
|
-
# @
|
23
|
-
# class as long as they conform to its interface. This class exists
|
24
|
-
# for documentation purposes
|
22
|
+
# @abstract Actual state listener implementations don't need to inherit from
|
23
|
+
# this class as long as they conform to its interface. This class exists
|
24
|
+
# solely for documentation purposes
|
25
25
|
#
|
26
26
|
# @see Cassandra::Cluster#register
|
27
27
|
class Listener
|
@@ -22,34 +22,36 @@ module Cassandra
|
|
22
22
|
# {Cassandra::LoadBalancing::Policy#distance} must return
|
23
23
|
DISTANCES = [:ignore, :local, :remote].freeze
|
24
24
|
|
25
|
-
# @
|
25
|
+
# @abstract Actual load balancing policies don't need to extend this class,
|
26
26
|
# only implement its methods. This class exists for documentation
|
27
|
-
# purposes only
|
27
|
+
# purposes only.
|
28
28
|
class Policy
|
29
|
-
#
|
29
|
+
# Allows policy to initialize with the cluster instance. This method is
|
30
|
+
# called once before connecting to the cluster.
|
31
|
+
# @param cluster [Cassandra::Cluster] current cluster instance
|
32
|
+
# @return [void]
|
33
|
+
def setup(cluster)
|
34
|
+
end
|
35
|
+
|
30
36
|
# @see Cassandra::Listener#host_up
|
31
37
|
def host_up(host)
|
32
38
|
end
|
33
39
|
|
34
|
-
# @abstract implementation should be provided by an actual policy
|
35
40
|
# @see Cassandra::Listener#host_down
|
36
41
|
def host_down(host)
|
37
42
|
end
|
38
43
|
|
39
|
-
# @abstract implementation should be provided by an actual policy
|
40
44
|
# @see Cassandra::Listener#host_found
|
41
45
|
def host_found(host)
|
42
46
|
end
|
43
47
|
|
44
|
-
# @abstract implementation should be provided by an actual policy
|
45
48
|
# @see Cassandra::Listener#host_lost
|
46
49
|
def host_lost(host)
|
47
50
|
end
|
48
51
|
|
49
|
-
# Returns a distance that
|
50
|
-
#
|
52
|
+
# Returns a distance that determines how many connections (if any) the
|
53
|
+
# driver will open to the host.
|
51
54
|
#
|
52
|
-
# @abstract implementation should be provided by an actual policy
|
53
55
|
# @param host [Cassandra::Host] a host instance
|
54
56
|
# @return [Symbol] distance to host. Must be one of
|
55
57
|
# {Cassandra::LoadBalancing::DISTANCES}
|
@@ -62,7 +64,6 @@ module Cassandra
|
|
62
64
|
#
|
63
65
|
# @note Hosts that should be ignored, must not be included in the Plan
|
64
66
|
#
|
65
|
-
# @abstract implementation should be provided by an actual policy
|
66
67
|
# @param keyspace [String] current keyspace of the {Cassandra::Session}
|
67
68
|
# @param statement [Cassandra::Statement] actual statement to be executed
|
68
69
|
# @param options [Cassandra::Execution::Options] execution options to be used
|
@@ -80,7 +81,7 @@ module Cassandra
|
|
80
81
|
|
81
82
|
# A load balancing plan is used to determine the order of hosts for running
|
82
83
|
# queries, preparing statements and establishing connections.
|
83
|
-
# @
|
84
|
+
# @abstract Plans returned by {Cassandra::LoadBalancing::Policy#plan}
|
84
85
|
# implementations don't need to extend this class, only implement its
|
85
86
|
# methods. This class exists for documentation purposes only.
|
86
87
|
class Plan
|
@@ -13,6 +13,7 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
#++
|
15
15
|
|
16
|
-
require 'cassandra/load_balancing/policies/round_robin'
|
17
16
|
require 'cassandra/load_balancing/policies/dc_aware_round_robin'
|
17
|
+
require 'cassandra/load_balancing/policies/round_robin'
|
18
|
+
require 'cassandra/load_balancing/policies/token_aware'
|
18
19
|
require 'cassandra/load_balancing/policies/white_list'
|
@@ -52,12 +52,22 @@ module Cassandra
|
|
52
52
|
mon_initialize
|
53
53
|
end
|
54
54
|
|
55
|
+
# Adds this host to rotation
|
56
|
+
#
|
57
|
+
# @param host [Cassandra::Host] a host instance
|
58
|
+
# @return [Cassandra::LoadBalancing::Policies::RoundRobin] self
|
59
|
+
# @see Cassandra::Listener#host_up
|
55
60
|
def host_up(host)
|
56
61
|
synchronize { @hosts = @hosts.dup.push(host) }
|
57
62
|
|
58
63
|
self
|
59
64
|
end
|
60
65
|
|
66
|
+
# Removes this host from rotation
|
67
|
+
#
|
68
|
+
# @param host [Cassandra::Host] a host instance
|
69
|
+
# @return [Cassandra::LoadBalancing::Policies::RoundRobin] self
|
70
|
+
# @see Cassandra::Listener#host_down
|
61
71
|
def host_down(host)
|
62
72
|
synchronize do
|
63
73
|
@hosts = @hosts.dup
|
@@ -67,18 +77,45 @@ module Cassandra
|
|
67
77
|
self
|
68
78
|
end
|
69
79
|
|
80
|
+
# Noop
|
81
|
+
#
|
82
|
+
# @param host [Cassandra::Host] a host instance
|
83
|
+
# @return [Cassandra::LoadBalancing::Policies::RoundRobin] self
|
84
|
+
# @see Cassandra::Listener#host_found
|
70
85
|
def host_found(host)
|
71
86
|
self
|
72
87
|
end
|
73
88
|
|
89
|
+
# Noop
|
90
|
+
#
|
91
|
+
# @param host [Cassandra::Host] a host instance
|
92
|
+
# @return [Cassandra::LoadBalancing::Policies::RoundRobin] self
|
93
|
+
# @see Cassandra::Listener#host_lost
|
74
94
|
def host_lost(host)
|
75
95
|
self
|
76
96
|
end
|
77
97
|
|
98
|
+
# Returns distance to host. All hosts in rotation are considered
|
99
|
+
# `:local`, all other hosts - `:ignore`.
|
100
|
+
#
|
101
|
+
# @param host [Cassandra::Host] a host instance
|
102
|
+
# @return [Symbol] `:local` for all hosts in rotation and `:ignore` for
|
103
|
+
# all other hosts.
|
104
|
+
# @see Cassandra::LoadBalancing::Policy#distance
|
78
105
|
def distance(host)
|
79
106
|
@hosts.include?(host) ? :local : :ignore
|
80
107
|
end
|
81
108
|
|
109
|
+
# Returns a load balancing plan that rotates hosts by 1 each time a
|
110
|
+
# plan is requested.
|
111
|
+
#
|
112
|
+
# @param keyspace [String] current keyspace of the {Cassandra::Session}
|
113
|
+
# @param statement [Cassandra::Statement] actual statement to be
|
114
|
+
# executed
|
115
|
+
# @param options [Cassandra::Execution::Options] execution options to
|
116
|
+
# be used
|
117
|
+
# @return [Cassandra::LoadBalancing::Plan] a rotated load balancing plan
|
118
|
+
# @see Cassandra::LoadBalancing::Policy#plan
|
82
119
|
def plan(keyspace, statement, options)
|
83
120
|
hosts = @hosts
|
84
121
|
position = @position
|
@@ -0,0 +1,119 @@
|
|
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
|
+
module LoadBalancing
|
21
|
+
module Policies
|
22
|
+
class TokenAware < Policy
|
23
|
+
# @private
|
24
|
+
class Plan
|
25
|
+
def initialize(hosts, policy, keyspace, statement, options)
|
26
|
+
@hosts = hosts
|
27
|
+
@policy = policy
|
28
|
+
@keyspace = keyspace
|
29
|
+
@statement = statement
|
30
|
+
@options = options
|
31
|
+
@seen = ::Hash.new
|
32
|
+
end
|
33
|
+
|
34
|
+
def has_next?
|
35
|
+
until @hosts.empty?
|
36
|
+
host = @hosts.shift
|
37
|
+
|
38
|
+
if @policy.distance(host) == :local
|
39
|
+
@seen[host] = true
|
40
|
+
@next = host
|
41
|
+
break
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
return true if @next
|
46
|
+
|
47
|
+
@plan ||= @policy.plan(@keyspace, @statement, @options)
|
48
|
+
|
49
|
+
while @plan.has_next?
|
50
|
+
host = @plan.next
|
51
|
+
|
52
|
+
unless @seen[host]
|
53
|
+
@next = host
|
54
|
+
return true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
false
|
59
|
+
end
|
60
|
+
|
61
|
+
def next
|
62
|
+
host = @next
|
63
|
+
@next = nil
|
64
|
+
host
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
extend Forwardable
|
69
|
+
|
70
|
+
# @!method distance(host)
|
71
|
+
# Delegates to wrapped policy
|
72
|
+
# @see Cassandra::LoadBalancing::Policy#distance
|
73
|
+
#
|
74
|
+
# @!method host_found(host)
|
75
|
+
# Delegates to wrapped policy
|
76
|
+
# @see Cassandra::LoadBalancing::Policy#host_found
|
77
|
+
#
|
78
|
+
# @!method host_up(host)
|
79
|
+
# Delegates to wrapped policy
|
80
|
+
# @see Cassandra::LoadBalancing::Policy#host_up
|
81
|
+
#
|
82
|
+
# @!method host_down(host)
|
83
|
+
# Delegates to wrapped policy
|
84
|
+
# @see Cassandra::LoadBalancing::Policy#host_down
|
85
|
+
#
|
86
|
+
# @!method host_lost(host)
|
87
|
+
# Delegates to wrapped policy
|
88
|
+
# @see Cassandra::LoadBalancing::Policy#host_lost
|
89
|
+
def_delegators :@policy, :distance, :host_found, :host_up, :host_down, :host_lost
|
90
|
+
|
91
|
+
# @param wrapped_policy [Cassandra::LoadBalancing::Policy] actual policy to filter
|
92
|
+
def initialize(wrapped_policy)
|
93
|
+
methods = [:host_up, :host_down, :host_found, :host_lost, :distance, :plan]
|
94
|
+
|
95
|
+
unless methods.all? {|method| wrapped_policy.respond_to?(method)}
|
96
|
+
raise ::ArgumentError, "supplied policy must be a Cassandra::LoadBalancing::Policy, #{wrapped_policy.inspect} given"
|
97
|
+
end
|
98
|
+
|
99
|
+
@policy = wrapped_policy
|
100
|
+
end
|
101
|
+
|
102
|
+
def setup(cluster)
|
103
|
+
@cluster = cluster
|
104
|
+
@policy.setup(cluster)
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
|
108
|
+
def plan(keyspace, statement, options)
|
109
|
+
return @policy.plan(keyspace, statement, options) unless @cluster
|
110
|
+
|
111
|
+
replicas = @cluster.find_replicas(keyspace, statement)
|
112
|
+
return @policy.plan(keyspace, statement, options) if replicas.empty?
|
113
|
+
|
114
|
+
Plan.new(replicas.dup, @policy, keyspace, statement, options)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|