cassandra-driver 1.0.0.beta.2-java

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.
Files changed (118) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +4 -0
  3. data/README.md +125 -0
  4. data/lib/cassandra/auth/providers/password.rb +73 -0
  5. data/lib/cassandra/auth/providers.rb +16 -0
  6. data/lib/cassandra/auth.rb +97 -0
  7. data/lib/cassandra/client/batch.rb +212 -0
  8. data/lib/cassandra/client/client.rb +591 -0
  9. data/lib/cassandra/client/column_metadata.rb +54 -0
  10. data/lib/cassandra/client/connection_manager.rb +72 -0
  11. data/lib/cassandra/client/connector.rb +277 -0
  12. data/lib/cassandra/client/execute_options_decoder.rb +59 -0
  13. data/lib/cassandra/client/null_logger.rb +37 -0
  14. data/lib/cassandra/client/peer_discovery.rb +50 -0
  15. data/lib/cassandra/client/prepared_statement.rb +314 -0
  16. data/lib/cassandra/client/query_result.rb +230 -0
  17. data/lib/cassandra/client/request_runner.rb +71 -0
  18. data/lib/cassandra/client/result_metadata.rb +48 -0
  19. data/lib/cassandra/client/void_result.rb +78 -0
  20. data/lib/cassandra/client.rb +144 -0
  21. data/lib/cassandra/cluster/client.rb +768 -0
  22. data/lib/cassandra/cluster/connector.rb +244 -0
  23. data/lib/cassandra/cluster/control_connection.rb +425 -0
  24. data/lib/cassandra/cluster/metadata.rb +124 -0
  25. data/lib/cassandra/cluster/options.rb +42 -0
  26. data/lib/cassandra/cluster/registry.rb +198 -0
  27. data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +47 -0
  28. data/lib/cassandra/cluster/schema/partitioners/ordered.rb +37 -0
  29. data/lib/cassandra/cluster/schema/partitioners/random.rb +37 -0
  30. data/lib/cassandra/cluster/schema/partitioners.rb +21 -0
  31. data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +92 -0
  32. data/lib/cassandra/cluster/schema/replication_strategies/none.rb +39 -0
  33. data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +44 -0
  34. data/lib/cassandra/cluster/schema/replication_strategies.rb +21 -0
  35. data/lib/cassandra/cluster/schema/type_parser.rb +138 -0
  36. data/lib/cassandra/cluster/schema.rb +340 -0
  37. data/lib/cassandra/cluster.rb +215 -0
  38. data/lib/cassandra/column.rb +92 -0
  39. data/lib/cassandra/compression/compressors/lz4.rb +72 -0
  40. data/lib/cassandra/compression/compressors/snappy.rb +66 -0
  41. data/lib/cassandra/compression.rb +66 -0
  42. data/lib/cassandra/driver.rb +111 -0
  43. data/lib/cassandra/errors.rb +79 -0
  44. data/lib/cassandra/execution/info.rb +51 -0
  45. data/lib/cassandra/execution/options.rb +80 -0
  46. data/lib/cassandra/execution/trace.rb +152 -0
  47. data/lib/cassandra/future.rb +675 -0
  48. data/lib/cassandra/host.rb +79 -0
  49. data/lib/cassandra/keyspace.rb +133 -0
  50. data/lib/cassandra/listener.rb +87 -0
  51. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +149 -0
  52. data/lib/cassandra/load_balancing/policies/round_robin.rb +132 -0
  53. data/lib/cassandra/load_balancing/policies/token_aware.rb +119 -0
  54. data/lib/cassandra/load_balancing/policies/white_list.rb +90 -0
  55. data/lib/cassandra/load_balancing/policies.rb +19 -0
  56. data/lib/cassandra/load_balancing.rb +113 -0
  57. data/lib/cassandra/protocol/cql_byte_buffer.rb +307 -0
  58. data/lib/cassandra/protocol/cql_protocol_handler.rb +323 -0
  59. data/lib/cassandra/protocol/frame_decoder.rb +128 -0
  60. data/lib/cassandra/protocol/frame_encoder.rb +48 -0
  61. data/lib/cassandra/protocol/request.rb +38 -0
  62. data/lib/cassandra/protocol/requests/auth_response_request.rb +47 -0
  63. data/lib/cassandra/protocol/requests/batch_request.rb +76 -0
  64. data/lib/cassandra/protocol/requests/credentials_request.rb +47 -0
  65. data/lib/cassandra/protocol/requests/execute_request.rb +103 -0
  66. data/lib/cassandra/protocol/requests/options_request.rb +39 -0
  67. data/lib/cassandra/protocol/requests/prepare_request.rb +50 -0
  68. data/lib/cassandra/protocol/requests/query_request.rb +153 -0
  69. data/lib/cassandra/protocol/requests/register_request.rb +38 -0
  70. data/lib/cassandra/protocol/requests/startup_request.rb +49 -0
  71. data/lib/cassandra/protocol/requests/void_query_request.rb +24 -0
  72. data/lib/cassandra/protocol/response.rb +38 -0
  73. data/lib/cassandra/protocol/responses/auth_challenge_response.rb +41 -0
  74. data/lib/cassandra/protocol/responses/auth_success_response.rb +41 -0
  75. data/lib/cassandra/protocol/responses/authenticate_response.rb +41 -0
  76. data/lib/cassandra/protocol/responses/detailed_error_response.rb +60 -0
  77. data/lib/cassandra/protocol/responses/error_response.rb +50 -0
  78. data/lib/cassandra/protocol/responses/event_response.rb +39 -0
  79. data/lib/cassandra/protocol/responses/prepared_result_response.rb +64 -0
  80. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +43 -0
  81. data/lib/cassandra/protocol/responses/ready_response.rb +44 -0
  82. data/lib/cassandra/protocol/responses/result_response.rb +48 -0
  83. data/lib/cassandra/protocol/responses/rows_result_response.rb +139 -0
  84. data/lib/cassandra/protocol/responses/schema_change_event_response.rb +60 -0
  85. data/lib/cassandra/protocol/responses/schema_change_result_response.rb +57 -0
  86. data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +42 -0
  87. data/lib/cassandra/protocol/responses/status_change_event_response.rb +44 -0
  88. data/lib/cassandra/protocol/responses/supported_response.rb +41 -0
  89. data/lib/cassandra/protocol/responses/topology_change_event_response.rb +34 -0
  90. data/lib/cassandra/protocol/responses/void_result_response.rb +39 -0
  91. data/lib/cassandra/protocol/type_converter.rb +384 -0
  92. data/lib/cassandra/protocol.rb +93 -0
  93. data/lib/cassandra/reconnection/policies/constant.rb +48 -0
  94. data/lib/cassandra/reconnection/policies/exponential.rb +79 -0
  95. data/lib/cassandra/reconnection/policies.rb +20 -0
  96. data/lib/cassandra/reconnection.rb +49 -0
  97. data/lib/cassandra/result.rb +215 -0
  98. data/lib/cassandra/retry/policies/default.rb +47 -0
  99. data/lib/cassandra/retry/policies/downgrading_consistency.rb +71 -0
  100. data/lib/cassandra/retry/policies/fallthrough.rb +39 -0
  101. data/lib/cassandra/retry/policies.rb +21 -0
  102. data/lib/cassandra/retry.rb +142 -0
  103. data/lib/cassandra/session.rb +202 -0
  104. data/lib/cassandra/statement.rb +22 -0
  105. data/lib/cassandra/statements/batch.rb +95 -0
  106. data/lib/cassandra/statements/bound.rb +48 -0
  107. data/lib/cassandra/statements/prepared.rb +81 -0
  108. data/lib/cassandra/statements/simple.rb +58 -0
  109. data/lib/cassandra/statements/void.rb +33 -0
  110. data/lib/cassandra/statements.rb +23 -0
  111. data/lib/cassandra/table.rb +299 -0
  112. data/lib/cassandra/time_uuid.rb +142 -0
  113. data/lib/cassandra/util.rb +167 -0
  114. data/lib/cassandra/uuid.rb +104 -0
  115. data/lib/cassandra/version.rb +21 -0
  116. data/lib/cassandra.rb +428 -0
  117. data/lib/cassandra_murmur3.jar +0 -0
  118. metadata +211 -0
@@ -0,0 +1,79 @@
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 Host
21
+ # @return [IPAddr] host ip
22
+ attr_reader :ip
23
+ # @note Host id can be `nil` before cluster has connected.
24
+ # @return [Cassandra::Uuid, nil] host id.
25
+ attr_reader :id
26
+ # @note Host datacenter can be `nil` before cluster has connected.
27
+ # @return [String, nil] host datacenter
28
+ attr_reader :datacenter
29
+ # @note Host rack can be `nil` before cluster has connected.
30
+ # @return [String, nil] host rack
31
+ attr_reader :rack
32
+ # @note Host's cassandra version can be `nil` before cluster has connected.
33
+ # @return [String, nil] version of cassandra that a host is running
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
38
+ # @return [Symbol] host status. Must be `:up` or `:down`
39
+ attr_reader :status
40
+
41
+ # @private
42
+ def initialize(ip, id = nil, rack = nil, datacenter = nil, release_version = nil, tokens = EMPTY_LIST, status = :up)
43
+ @ip = ip
44
+ @id = id
45
+ @rack = rack
46
+ @datacenter = datacenter
47
+ @release_version = release_version
48
+ @tokens = tokens
49
+ @status = status
50
+ end
51
+
52
+ # @return [Boolean] whether this host's status is `:up`
53
+ def up?
54
+ @status == :up
55
+ end
56
+
57
+ # @return [Boolean] whether this host's status is `:down`
58
+ def down?
59
+ @status == :down
60
+ end
61
+
62
+ # @private
63
+ def hash
64
+ @hash ||= @ip.hash
65
+ end
66
+
67
+ # @param other [Cassandra::Host] a host to compare
68
+ # @return [Boolean] whether this host has the same ip as the other
69
+ def eql?(other)
70
+ other.eql?(@ip)
71
+ end
72
+ alias :== :eql?
73
+
74
+ # @return [String] a CLI-friendly host representation
75
+ def inspect
76
+ "#<#{self.class.name}:0x#{self.object_id.to_s(16)} @ip=#{@ip}>"
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,133 @@
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
+ # Represents a cassandra keyspace
21
+ # @see Cassandra::Cluster#each_keyspace
22
+ # @see Cassandra::Cluster#keyspace
23
+ class Keyspace
24
+ # @private
25
+ class Replication
26
+ attr_reader :klass, :options
27
+
28
+ def initialize(klass, options)
29
+ @klass = klass
30
+ @options = options
31
+ end
32
+
33
+ def to_cql
34
+ replication = {'class' => @klass}
35
+ replication.merge!(@options)
36
+
37
+ Util.encode_hash(replication)
38
+ end
39
+
40
+ def eql?(other)
41
+ other.is_a?(Replication) &&
42
+ @klass == other.klass &&
43
+ @options == other.options
44
+ end
45
+ alias :== :eql?
46
+ end
47
+
48
+ # @return [String] this keyspace name
49
+ attr_reader :name
50
+ # @private
51
+ attr_reader :replication
52
+
53
+ # @private
54
+ def initialize(name, durable_writes, replication, tables)
55
+ @name = name
56
+ @durable_writes = durable_writes
57
+ @replication = replication
58
+ @tables = tables
59
+ end
60
+
61
+ # @return [Boolean] whether durables writes are enabled for this keyspace
62
+ def durable_writes?
63
+ @durable_writes
64
+ end
65
+
66
+ # @return [Boolean] whether this keyspace has a table with the given name
67
+ # @param name [String] table name
68
+ def has_table?(name)
69
+ @tables.has_key?(name)
70
+ end
71
+
72
+ # @return [Cassandra::Table, nil] a table or nil
73
+ # @param name [String] table name
74
+ def table(name)
75
+ @tables[name]
76
+ end
77
+
78
+ # Yield or enumerate each table defined in this keyspace
79
+ # @overload each_table
80
+ # @yieldparam table [Cassandra::Table] current table
81
+ # @return [Cassandra::Keyspace] self
82
+ # @overload each_table
83
+ # @return [Array<Cassandra::Table>] a list of tables
84
+ def each_table(&block)
85
+ if block_given?
86
+ @tables.each_value(&block)
87
+ self
88
+ else
89
+ @tables.values
90
+ end
91
+ end
92
+ alias :tables :each_table
93
+
94
+ # @return [String] a cql representation of this table
95
+ def to_cql
96
+ "CREATE KEYSPACE #{Util.escape_name(@name)} WITH REPLICATION = #{@replication.to_cql} AND DURABLE_WRITES = #{@durable_writes};"
97
+ end
98
+
99
+ # @return [Boolean] whether this keyspace is equal to the other
100
+ def eql?(other)
101
+ other.is_a?(Keyspace) &&
102
+ @name == other.name &&
103
+ @durable_writes == other.durable_writes &&
104
+ @replication == other.replication &&
105
+ @tables == other.raw_tables
106
+ end
107
+ alias :== :eql?
108
+
109
+ # @private
110
+ def update_table(table)
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)
120
+ end
121
+
122
+ # @private
123
+ attr_reader :durable_writes
124
+ protected :durable_writes
125
+
126
+ protected
127
+
128
+ # @private
129
+ def raw_tables
130
+ @tables
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,87 @@
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
+ # Cassandra state listener.
21
+ #
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
+ #
26
+ # @see Cassandra::Cluster#register
27
+ class Listener
28
+ # This method is called whenever a host is considered to be up, whether
29
+ # by Cassandra's gossip exchange or when the driver has successfully
30
+ # established a connection to it.
31
+ #
32
+ # @param host [Cassandra::Host] a host instance
33
+ # @return [void]
34
+ def host_up(host)
35
+ end
36
+
37
+ # This method is called whenever a host is considered to be down, whether
38
+ # by Cassandra's gossip exchange or when the driver failed to establish
39
+ # any connections to it.
40
+ #
41
+ # @param host [Cassandra::Host] a host instance
42
+ # @return [void]
43
+ def host_down(host)
44
+ end
45
+
46
+ # This method is called whenever a host is discovered by the driver,
47
+ # whether because it is a completely new node or if its
48
+ # {Cassandra::Host#datacenter} or {Cassandra::Host#rack} have changed.
49
+ #
50
+ # @param host [Cassandra::Host] a host instance
51
+ # @return [void]
52
+ def host_found(host)
53
+ end
54
+
55
+ # This method is called whenever a host leaves the cluster, whether
56
+ # because it is completely gone or if its {Cassandra::Host#datacenter} or
57
+ # {Cassandra::Host#rack} have changed.
58
+ #
59
+ # @param host [Cassandra::Host] a host instance
60
+ # @return [void]
61
+ def host_lost(host)
62
+ end
63
+
64
+ # This method is called whenever a new keyspace is created.
65
+ #
66
+ # @param keyspace [Cassandra::Keyspace] a keyspace instance
67
+ # @return [void]
68
+ def keyspace_created(keyspace)
69
+ end
70
+
71
+ # This method is called whenever an existing keyspace is changed. This
72
+ # happens when a new table is created or an existing table is dropped or
73
+ # altered.
74
+ #
75
+ # @param keyspace [Cassandra::Keyspace] a keyspace instance
76
+ # @return [void]
77
+ def keyspace_changed(keyspace)
78
+ end
79
+
80
+ # This method is called whenever an existing keyspace is dropped.
81
+ #
82
+ # @param keyspace [Cassandra::Keyspace] a keyspace instance
83
+ # @return [void]
84
+ def keyspace_dropped(keyspace)
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,149 @@
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 DCAwareRoundRobin < Policy
23
+ # @private
24
+ class Plan
25
+ def initialize(local, remote, index)
26
+ @local = local
27
+ @remote = remote
28
+ @index = index
29
+
30
+ @local_remaining = @local_total = local.size
31
+ @remote_remaining = @remote_total = remote.size
32
+ end
33
+
34
+ def has_next?
35
+ @local_remaining > 0 || @remote_remaining > 0
36
+ end
37
+
38
+ def next
39
+ if @local_remaining > 0
40
+ @local_remaining -= 1
41
+ i = (@index % @local_total)
42
+ @index += 1
43
+
44
+ return @local[i]
45
+ end
46
+
47
+ if @remote_remaining > 0
48
+ @remote_remaining -= 1
49
+ i = (@index % @remote_total)
50
+ @index += 1
51
+
52
+ return @remote[i]
53
+ end
54
+ end
55
+ end
56
+
57
+ include MonitorMixin
58
+
59
+ def initialize(datacenter, max_remote_hosts_to_use = nil, use_remote_hosts_for_local_consistency = false)
60
+ datacenter = String(datacenter)
61
+ max_remote_hosts_to_use = max_remote_hosts_to_use && Integer(max_remote_hosts_to_use)
62
+
63
+ raise ::ArgumentError, "datacenter cannot be nil" if datacenter.nil?
64
+ raise ::ArgumentError, "max_remote_hosts_to_use must be nil or >= 0" if max_remote_hosts_to_use && max_remote_hosts_to_use < 0
65
+
66
+ @datacenter = datacenter
67
+ @max_remote = max_remote_hosts_to_use
68
+ @local = ::Array.new
69
+ @remote = ::Array.new
70
+ @position = 0
71
+
72
+ @use_remote = !!use_remote_hosts_for_local_consistency
73
+
74
+ mon_initialize
75
+ end
76
+
77
+ def host_up(host)
78
+ if host.datacenter.nil? || host.datacenter == @datacenter
79
+ synchronize { @local = @local.dup.push(host) }
80
+ else
81
+ if @max_remote.nil? || @remote.size < @max_remote
82
+ synchronize { @remote = @remote.dup.push(host) }
83
+ end
84
+ end
85
+
86
+ self
87
+ end
88
+
89
+ def host_down(host)
90
+ if host.datacenter.nil? || host.datacenter == @datacenter
91
+ synchronize do
92
+ @local = @local.dup
93
+ @local.delete(host)
94
+ end
95
+ else
96
+ synchronize do
97
+ @remote = @remote.dup
98
+ @remote.delete(host)
99
+ end
100
+ end
101
+
102
+ self
103
+ end
104
+
105
+ def host_found(host)
106
+ self
107
+ end
108
+
109
+ def host_lost(host)
110
+ self
111
+ end
112
+
113
+ def distance(host)
114
+ if host.datacenter.nil? || host.datacenter == @datacenter
115
+ @local.include?(host) ? :local : :ignore
116
+ else
117
+ @remote.include?(host) ? :remote : :ignore
118
+ end
119
+ end
120
+
121
+ def plan(keyspace, statement, options)
122
+ local = @local
123
+
124
+ if LOCAL_CONSISTENCIES.include?(options.consistency) && !@use_remote
125
+ remote = EMPTY_ARRAY
126
+ else
127
+ remote = @remote
128
+ end
129
+
130
+ position = @position
131
+ total = local.size + remote.size
132
+
133
+ return EMPTY_PLAN if total == 0
134
+
135
+ @position = (@position + 1) % total
136
+
137
+ Plan.new(local, remote, position)
138
+ end
139
+
140
+ private
141
+
142
+ # @private
143
+ LOCAL_CONSISTENCIES = [:local_quorum, :local_one].freeze
144
+ # @private
145
+ EMPTY_ARRAY = [].freeze
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,132 @@
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 RoundRobin < Policy
23
+ # @private
24
+ class Plan
25
+ def initialize(hosts, index)
26
+ @hosts = hosts
27
+ @index = index
28
+
29
+ @total = @remaining = hosts.size
30
+ end
31
+
32
+ def has_next?
33
+ @remaining > 0
34
+ end
35
+
36
+ def next
37
+ return if @remaining == 0
38
+
39
+ @remaining -= 1
40
+ index, @index = @index, (@index + 1) % @total
41
+
42
+ @hosts[index]
43
+ end
44
+ end
45
+
46
+ include MonitorMixin
47
+
48
+ def initialize
49
+ @hosts = ::Array.new
50
+ @position = 0
51
+
52
+ mon_initialize
53
+ end
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
60
+ def host_up(host)
61
+ synchronize { @hosts = @hosts.dup.push(host) }
62
+
63
+ self
64
+ end
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
71
+ def host_down(host)
72
+ synchronize do
73
+ @hosts = @hosts.dup
74
+ @hosts.delete(host)
75
+ end
76
+
77
+ self
78
+ end
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
85
+ def host_found(host)
86
+ self
87
+ end
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
94
+ def host_lost(host)
95
+ self
96
+ end
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
105
+ def distance(host)
106
+ @hosts.include?(host) ? :local : :ignore
107
+ end
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
119
+ def plan(keyspace, statement, options)
120
+ hosts = @hosts
121
+ position = @position
122
+ total = hosts.size
123
+ return EMPTY_PLAN if total == 0
124
+
125
+ @position = (position + 1) % total
126
+
127
+ Plan.new(hosts, position)
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -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