yugabyte-ycql-driver 3.2.3.1

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 (145) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +13 -0
  3. data/README.md +242 -0
  4. data/ext/cassandra_murmur3/cassandra_murmur3.c +178 -0
  5. data/ext/cassandra_murmur3/extconf.rb +2 -0
  6. data/lib/cassandra/address_resolution.rb +36 -0
  7. data/lib/cassandra/address_resolution/policies.rb +2 -0
  8. data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +56 -0
  9. data/lib/cassandra/address_resolution/policies/none.rb +35 -0
  10. data/lib/cassandra/aggregate.rb +123 -0
  11. data/lib/cassandra/argument.rb +51 -0
  12. data/lib/cassandra/attr_boolean.rb +33 -0
  13. data/lib/cassandra/auth.rb +100 -0
  14. data/lib/cassandra/auth/providers.rb +17 -0
  15. data/lib/cassandra/auth/providers/password.rb +65 -0
  16. data/lib/cassandra/cassandra_logger.rb +80 -0
  17. data/lib/cassandra/cluster.rb +331 -0
  18. data/lib/cassandra/cluster/client.rb +1612 -0
  19. data/lib/cassandra/cluster/connection_pool.rb +78 -0
  20. data/lib/cassandra/cluster/connector.rb +372 -0
  21. data/lib/cassandra/cluster/control_connection.rb +962 -0
  22. data/lib/cassandra/cluster/failed_connection.rb +35 -0
  23. data/lib/cassandra/cluster/metadata.rb +142 -0
  24. data/lib/cassandra/cluster/options.rb +145 -0
  25. data/lib/cassandra/cluster/registry.rb +284 -0
  26. data/lib/cassandra/cluster/schema.rb +405 -0
  27. data/lib/cassandra/cluster/schema/cql_type_parser.rb +112 -0
  28. data/lib/cassandra/cluster/schema/fetchers.rb +1627 -0
  29. data/lib/cassandra/cluster/schema/fqcn_type_parser.rb +175 -0
  30. data/lib/cassandra/cluster/schema/partitioners.rb +21 -0
  31. data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +45 -0
  32. data/lib/cassandra/cluster/schema/partitioners/ordered.rb +37 -0
  33. data/lib/cassandra/cluster/schema/partitioners/random.rb +37 -0
  34. data/lib/cassandra/cluster/schema/replication_strategies.rb +21 -0
  35. data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +102 -0
  36. data/lib/cassandra/cluster/schema/replication_strategies/none.rb +39 -0
  37. data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +44 -0
  38. data/lib/cassandra/column.rb +66 -0
  39. data/lib/cassandra/column_container.rb +326 -0
  40. data/lib/cassandra/compression.rb +69 -0
  41. data/lib/cassandra/compression/compressors/lz4.rb +73 -0
  42. data/lib/cassandra/compression/compressors/snappy.rb +69 -0
  43. data/lib/cassandra/custom_data.rb +53 -0
  44. data/lib/cassandra/driver.rb +260 -0
  45. data/lib/cassandra/errors.rb +784 -0
  46. data/lib/cassandra/execution/info.rb +69 -0
  47. data/lib/cassandra/execution/options.rb +267 -0
  48. data/lib/cassandra/execution/profile.rb +153 -0
  49. data/lib/cassandra/execution/profile_manager.rb +71 -0
  50. data/lib/cassandra/execution/trace.rb +192 -0
  51. data/lib/cassandra/executors.rb +113 -0
  52. data/lib/cassandra/function.rb +156 -0
  53. data/lib/cassandra/function_collection.rb +85 -0
  54. data/lib/cassandra/future.rb +794 -0
  55. data/lib/cassandra/host.rb +102 -0
  56. data/lib/cassandra/index.rb +118 -0
  57. data/lib/cassandra/keyspace.rb +473 -0
  58. data/lib/cassandra/listener.rb +87 -0
  59. data/lib/cassandra/load_balancing.rb +121 -0
  60. data/lib/cassandra/load_balancing/policies.rb +20 -0
  61. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +172 -0
  62. data/lib/cassandra/load_balancing/policies/round_robin.rb +141 -0
  63. data/lib/cassandra/load_balancing/policies/token_aware.rb +149 -0
  64. data/lib/cassandra/load_balancing/policies/white_list.rb +100 -0
  65. data/lib/cassandra/materialized_view.rb +92 -0
  66. data/lib/cassandra/null_logger.rb +56 -0
  67. data/lib/cassandra/protocol.rb +102 -0
  68. data/lib/cassandra/protocol/coder.rb +1085 -0
  69. data/lib/cassandra/protocol/cql_byte_buffer.rb +418 -0
  70. data/lib/cassandra/protocol/cql_protocol_handler.rb +448 -0
  71. data/lib/cassandra/protocol/request.rb +41 -0
  72. data/lib/cassandra/protocol/requests/auth_response_request.rb +51 -0
  73. data/lib/cassandra/protocol/requests/batch_request.rb +117 -0
  74. data/lib/cassandra/protocol/requests/credentials_request.rb +51 -0
  75. data/lib/cassandra/protocol/requests/execute_request.rb +122 -0
  76. data/lib/cassandra/protocol/requests/options_request.rb +39 -0
  77. data/lib/cassandra/protocol/requests/prepare_request.rb +59 -0
  78. data/lib/cassandra/protocol/requests/query_request.rb +112 -0
  79. data/lib/cassandra/protocol/requests/register_request.rb +38 -0
  80. data/lib/cassandra/protocol/requests/startup_request.rb +49 -0
  81. data/lib/cassandra/protocol/requests/void_query_request.rb +24 -0
  82. data/lib/cassandra/protocol/response.rb +28 -0
  83. data/lib/cassandra/protocol/responses/already_exists_error_response.rb +50 -0
  84. data/lib/cassandra/protocol/responses/auth_challenge_response.rb +36 -0
  85. data/lib/cassandra/protocol/responses/auth_success_response.rb +36 -0
  86. data/lib/cassandra/protocol/responses/authenticate_response.rb +36 -0
  87. data/lib/cassandra/protocol/responses/error_response.rb +142 -0
  88. data/lib/cassandra/protocol/responses/event_response.rb +30 -0
  89. data/lib/cassandra/protocol/responses/function_failure_error_response.rb +52 -0
  90. data/lib/cassandra/protocol/responses/prepared_result_response.rb +62 -0
  91. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +59 -0
  92. data/lib/cassandra/protocol/responses/read_failure_error_response.rb +71 -0
  93. data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +61 -0
  94. data/lib/cassandra/protocol/responses/ready_response.rb +43 -0
  95. data/lib/cassandra/protocol/responses/result_response.rb +42 -0
  96. data/lib/cassandra/protocol/responses/rows_result_response.rb +39 -0
  97. data/lib/cassandra/protocol/responses/schema_change_event_response.rb +73 -0
  98. data/lib/cassandra/protocol/responses/schema_change_result_response.rb +70 -0
  99. data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +37 -0
  100. data/lib/cassandra/protocol/responses/status_change_event_response.rb +39 -0
  101. data/lib/cassandra/protocol/responses/supported_response.rb +36 -0
  102. data/lib/cassandra/protocol/responses/topology_change_event_response.rb +33 -0
  103. data/lib/cassandra/protocol/responses/unavailable_error_response.rb +58 -0
  104. data/lib/cassandra/protocol/responses/unprepared_error_response.rb +48 -0
  105. data/lib/cassandra/protocol/responses/void_result_response.rb +34 -0
  106. data/lib/cassandra/protocol/responses/write_failure_error_response.rb +73 -0
  107. data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +63 -0
  108. data/lib/cassandra/protocol/v1.rb +326 -0
  109. data/lib/cassandra/protocol/v3.rb +358 -0
  110. data/lib/cassandra/protocol/v4.rb +478 -0
  111. data/lib/cassandra/reconnection.rb +49 -0
  112. data/lib/cassandra/reconnection/policies.rb +20 -0
  113. data/lib/cassandra/reconnection/policies/constant.rb +46 -0
  114. data/lib/cassandra/reconnection/policies/exponential.rb +79 -0
  115. data/lib/cassandra/result.rb +276 -0
  116. data/lib/cassandra/retry.rb +154 -0
  117. data/lib/cassandra/retry/policies.rb +21 -0
  118. data/lib/cassandra/retry/policies/default.rb +53 -0
  119. data/lib/cassandra/retry/policies/downgrading_consistency.rb +73 -0
  120. data/lib/cassandra/retry/policies/fallthrough.rb +39 -0
  121. data/lib/cassandra/session.rb +270 -0
  122. data/lib/cassandra/statement.rb +32 -0
  123. data/lib/cassandra/statements.rb +23 -0
  124. data/lib/cassandra/statements/batch.rb +146 -0
  125. data/lib/cassandra/statements/bound.rb +65 -0
  126. data/lib/cassandra/statements/prepared.rb +235 -0
  127. data/lib/cassandra/statements/simple.rb +118 -0
  128. data/lib/cassandra/statements/void.rb +38 -0
  129. data/lib/cassandra/table.rb +240 -0
  130. data/lib/cassandra/time.rb +103 -0
  131. data/lib/cassandra/time_uuid.rb +78 -0
  132. data/lib/cassandra/timestamp_generator.rb +37 -0
  133. data/lib/cassandra/timestamp_generator/simple.rb +38 -0
  134. data/lib/cassandra/timestamp_generator/ticking_on_duplicate.rb +58 -0
  135. data/lib/cassandra/trigger.rb +67 -0
  136. data/lib/cassandra/tuple.rb +131 -0
  137. data/lib/cassandra/types.rb +1704 -0
  138. data/lib/cassandra/udt.rb +443 -0
  139. data/lib/cassandra/util.rb +464 -0
  140. data/lib/cassandra/uuid.rb +110 -0
  141. data/lib/cassandra/uuid/generator.rb +212 -0
  142. data/lib/cassandra/version.rb +21 -0
  143. data/lib/datastax/cassandra.rb +47 -0
  144. data/lib/ycql.rb +842 -0
  145. metadata +243 -0
@@ -0,0 +1,175 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 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
+ class FQCNTypeParser
23
+ # @private
24
+ Node = Struct.new(:parent, :name, :children)
25
+ # @private
26
+ Result = Struct.new(:results, :collections)
27
+
28
+ @@types = {
29
+ 'org.apache.cassandra.db.marshal.AsciiType' => :ascii,
30
+ 'org.apache.cassandra.db.marshal.LongType' => :bigint,
31
+ 'org.apache.cassandra.db.marshal.BytesType' => :blob,
32
+ 'org.apache.cassandra.db.marshal.BooleanType' => :boolean,
33
+ 'org.apache.cassandra.db.marshal.CounterColumnType' => :counter,
34
+ 'org.apache.cassandra.db.marshal.DecimalType' => :decimal,
35
+ 'org.apache.cassandra.db.marshal.DoubleType' => :double,
36
+ 'org.apache.cassandra.db.marshal.FloatType' => :float,
37
+ 'org.apache.cassandra.db.marshal.InetAddressType' => :inet,
38
+ 'org.apache.cassandra.db.marshal.Int32Type' => :int,
39
+ 'org.apache.cassandra.db.marshal.UTF8Type' => :text,
40
+ 'org.apache.cassandra.db.marshal.TimestampType' => :timestamp,
41
+ 'org.apache.cassandra.db.marshal.DateType' => :timestamp,
42
+ 'org.apache.cassandra.db.marshal.UUIDType' => :uuid,
43
+ 'org.apache.cassandra.db.marshal.IntegerType' => :varint,
44
+ 'org.apache.cassandra.db.marshal.TimeUUIDType' => :timeuuid,
45
+ 'org.apache.cassandra.db.marshal.MapType' => :map,
46
+ 'org.apache.cassandra.db.marshal.SetType' => :set,
47
+ 'org.apache.cassandra.db.marshal.ListType' => :list,
48
+ 'org.apache.cassandra.db.marshal.UserType' => :udt,
49
+ 'org.apache.cassandra.db.marshal.TupleType' => :tuple,
50
+ 'org.apache.cassandra.db.marshal.ShortType' => :smallint,
51
+ 'org.apache.cassandra.db.marshal.ByteType' => :tinyint,
52
+ 'org.apache.cassandra.db.marshal.TimeType' => :time,
53
+ 'org.apache.cassandra.db.marshal.SimpleDateType' => :date,
54
+ 'org.apache.cassandra.db.marshal.FrozenType' => :frozen
55
+ }.freeze
56
+
57
+ def parse(string)
58
+ create_result(parse_node(string))
59
+ end
60
+
61
+ private
62
+
63
+ def create_result(node)
64
+ collections = nil
65
+ results = []
66
+
67
+ if node.name == 'org.apache.cassandra.db.marshal.CompositeType'
68
+ collections = {}
69
+
70
+ if node.children.last.name ==
71
+ 'org.apache.cassandra.db.marshal.ColumnToCollectionType'
72
+ node.children.pop.children.each do |child|
73
+ key, name = child.name.split(':')
74
+ key = [key].pack('H*').force_encoding(::Encoding::UTF_8)
75
+
76
+ if name == 'org.apache.cassandra.db.marshal.ReversedType'
77
+ collections[key] = lookup_type(child.children.first)
78
+ else
79
+ child.name = name
80
+ collections[key] = lookup_type(child)
81
+ end
82
+ end
83
+ end
84
+
85
+ node.children.each do |child|
86
+ results << create_type(child)
87
+ end
88
+ else
89
+ results << create_type(node)
90
+ end
91
+
92
+ Result.new(results, collections)
93
+ end
94
+
95
+ def create_type(node)
96
+ order = :asc
97
+ frozen = false
98
+
99
+ if node.name == 'org.apache.cassandra.db.marshal.ReversedType'
100
+ order = :desc
101
+ node = node.children.first
102
+ end
103
+
104
+ if node.name == 'org.apache.cassandra.db.marshal.FrozenType'
105
+ frozen = true
106
+ node = node.children.first
107
+ end
108
+
109
+ [lookup_type(node), order, frozen]
110
+ end
111
+
112
+ def lookup_type(node)
113
+ type = @@types.fetch(node.name) do
114
+ return Cassandra::Types.custom(dump_node(node))
115
+ end
116
+
117
+ case type
118
+ when :set, :list, :frozen
119
+ Cassandra::Types.send(type, lookup_type(node.children.first))
120
+ when :map
121
+ Cassandra::Types.map(*node.children.map(&method(:lookup_type)))
122
+ when :udt
123
+ keyspace = node.children.shift.name
124
+ name = [node.children.shift.name].pack('H*')
125
+ fields = node.children.map do |child|
126
+ field_name, child_name = child.name.split(':')
127
+
128
+ child.name = child_name
129
+ field_name = [field_name].pack('H*').force_encoding(::Encoding::UTF_8)
130
+
131
+ [field_name, lookup_type(child)]
132
+ end
133
+
134
+ Cassandra::Types.udt(keyspace, name, fields)
135
+ when :tuple
136
+ Cassandra::Types.tuple(*node.children.map(&method(:lookup_type)))
137
+ else
138
+ Cassandra::Types.send(type)
139
+ end
140
+ end
141
+
142
+ def parse_node(string)
143
+ root = node = Node.new(nil, '', [])
144
+
145
+ string.each_char do |char|
146
+ case char
147
+ when '(' # starting type params
148
+ child = Node.new(node, '', [])
149
+ node.children << child
150
+ node = child
151
+ when ','
152
+ child = Node.new(node.parent, '', [])
153
+ node.parent.children << child
154
+ node = child
155
+ when ')'
156
+ node = node.parent
157
+ when ' '
158
+ next
159
+ else
160
+ node.name << char
161
+ end
162
+ end
163
+
164
+ root
165
+ end
166
+
167
+ def dump_node(node)
168
+ str = node.name
169
+ str << '(' + node.children.map { |n| dump_node(n) }.join(',') + ')' unless node.children.empty?
170
+ str
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 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
+ require 'cassandra/cluster/schema/partitioners/ordered'
20
+ require 'cassandra/cluster/schema/partitioners/random'
21
+ require 'cassandra/cluster/schema/partitioners/murmur3'
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 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 Partitioners
24
+ # @private
25
+ class Murmur3
26
+ # @private
27
+ LONG_MIN = -2**63
28
+ # @private
29
+ LONG_MAX = 2**63 - 1
30
+
31
+ def create_token(partition_key)
32
+ token = Cassandra::Murmur3.hash(partition_key)
33
+ token = LONG_MAX if token == LONG_MIN
34
+
35
+ token
36
+ end
37
+
38
+ def parse_token(token_string)
39
+ token_string.to_i
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 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 Partitioners
24
+ # @private
25
+ class Ordered
26
+ def create_token(partition_key)
27
+ partition_key
28
+ end
29
+
30
+ def parse_token(token_string)
31
+ token_string
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 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 Partitioners
24
+ # @private
25
+ class Random
26
+ def create_token(partition_key)
27
+ Digest::MD5.hexdigest(partition_key).to_i(16)
28
+ end
29
+
30
+ def parse_token(token_string)
31
+ token_string.to_i
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 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
+ require 'cassandra/cluster/schema/replication_strategies/simple'
20
+ require 'cassandra/cluster/schema/replication_strategies/network_topology'
21
+ require 'cassandra/cluster/schema/replication_strategies/none'
@@ -0,0 +1,102 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 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 NetworkTopology
26
+ def replication_map(token_hosts, token_ring, replication_options)
27
+ racks = ::Hash.new
28
+ datacenter_token_rings = ::Hash.new
29
+ size = token_ring.size
30
+
31
+ token_ring.each_with_index do |token, i|
32
+ host = token_hosts[token]
33
+
34
+ racks[host.datacenter] ||= ::Set.new
35
+ racks[host.datacenter].add(host.rack)
36
+
37
+ datacenter_token_rings[host.datacenter] ||= {}
38
+ datacenter_token_rings[host.datacenter][i] = token
39
+ end
40
+
41
+ replication_map = ::Hash.new
42
+
43
+ token_ring.each_with_index do |token, i|
44
+ replicas = ::Set.new
45
+ visited = ::Hash.new
46
+ skipped = ::Hash.new
47
+
48
+ replication_options.each do |datacenter, factor|
49
+ ring = datacenter_token_rings[datacenter]
50
+ next unless ring
51
+ factor = begin
52
+ [Integer(factor), ring.size].min
53
+ rescue
54
+ next
55
+ end
56
+
57
+ total_racks = racks[datacenter].size
58
+ visited_racks = visited[datacenter] ||= ::Set.new
59
+ skipped_hosts = skipped[datacenter] ||= ::Set.new
60
+ added_replicas = ::Set.new
61
+
62
+ size.times do |j|
63
+ break if added_replicas.size >= factor
64
+
65
+ tk = ring[(i + j) % size]
66
+ next unless tk
67
+ host = token_hosts[tk]
68
+ rack = host.rack
69
+
70
+ # unknown rack or seen all racks
71
+ if rack.nil? || visited_racks.size == total_racks
72
+ replicas << host
73
+ added_replicas << host
74
+ elsif visited_racks.include?(rack)
75
+ skipped_hosts << host
76
+ else
77
+ replicas << host
78
+ visited_racks << rack
79
+ added_replicas << host
80
+
81
+ if visited_racks.size == total_racks
82
+ skipped_hosts.each do |skipped_host|
83
+ break if added_replicas.size >= factor
84
+
85
+ replicas << skipped_host
86
+ added_replicas << host
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ replication_map[token] = replicas.to_a.freeze
94
+ end
95
+
96
+ replication_map
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end