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
@@ -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
|