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
@@ -21,16 +21,18 @@ module Cassandra
|
|
21
21
|
# @private
|
22
22
|
class Options
|
23
23
|
attr_reader :credentials, :auth_provider, :compressor, :port,
|
24
|
-
:
|
24
|
+
:connect_timeout, :ssl, :connections_per_local_node,
|
25
|
+
:connections_per_remote_node
|
25
26
|
attr_accessor :protocol_version
|
26
27
|
|
27
|
-
def initialize(protocol_version, credentials, auth_provider, compressor, port,
|
28
|
+
def initialize(protocol_version, credentials, auth_provider, compressor, port, connect_timeout, ssl, connections_per_local_node, connections_per_remote_node)
|
28
29
|
@protocol_version = protocol_version
|
29
30
|
@credentials = credentials
|
30
31
|
@auth_provider = auth_provider
|
31
32
|
@compressor = compressor
|
32
33
|
@port = port
|
33
|
-
@
|
34
|
+
@connect_timeout = connect_timeout
|
35
|
+
@ssl = ssl
|
34
36
|
|
35
37
|
@connections_per_local_node = connections_per_local_node
|
36
38
|
@connections_per_remote_node = connections_per_remote_node
|
@@ -45,7 +45,12 @@ module Cassandra
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def each_host(&block)
|
48
|
-
|
48
|
+
if block_given?
|
49
|
+
@hosts.each_value(&block)
|
50
|
+
self
|
51
|
+
else
|
52
|
+
@hosts.values
|
53
|
+
end
|
49
54
|
end
|
50
55
|
alias :hosts :each_host
|
51
56
|
|
@@ -81,7 +86,11 @@ module Cassandra
|
|
81
86
|
notify_found(host)
|
82
87
|
end
|
83
88
|
|
84
|
-
synchronize
|
89
|
+
synchronize do
|
90
|
+
hosts = @hosts.dup
|
91
|
+
hosts[ip] = host
|
92
|
+
@hosts = hosts
|
93
|
+
end
|
85
94
|
|
86
95
|
self
|
87
96
|
end
|
@@ -94,7 +103,11 @@ module Cassandra
|
|
94
103
|
|
95
104
|
host = toggle_down(host)
|
96
105
|
|
97
|
-
synchronize
|
106
|
+
synchronize do
|
107
|
+
hosts = @hosts.dup
|
108
|
+
hosts[ip] = host
|
109
|
+
@hosts = hosts
|
110
|
+
end
|
98
111
|
|
99
112
|
self
|
100
113
|
end
|
@@ -107,7 +120,11 @@ module Cassandra
|
|
107
120
|
|
108
121
|
host = toggle_up(host)
|
109
122
|
|
110
|
-
synchronize
|
123
|
+
synchronize do
|
124
|
+
hosts = @hosts.dup
|
125
|
+
hosts[ip] = host
|
126
|
+
@hosts = hosts
|
127
|
+
end
|
111
128
|
|
112
129
|
self
|
113
130
|
end
|
@@ -126,17 +143,17 @@ module Cassandra
|
|
126
143
|
|
127
144
|
notify_lost(host)
|
128
145
|
|
129
|
-
|
146
|
+
host
|
130
147
|
end
|
131
148
|
|
132
149
|
private
|
133
150
|
|
134
151
|
def create_host(ip, data)
|
135
|
-
Host.new(ip, data['host_id'], data['rack'], data['data_center'], data['release_version'], :up)
|
152
|
+
Host.new(ip, data['host_id'], data['rack'], data['data_center'], data['release_version'], data['tokens'].freeze, :up)
|
136
153
|
end
|
137
154
|
|
138
155
|
def toggle_up(host)
|
139
|
-
host = Host.new(host.ip, host.id, host.rack, host.datacenter, host.release_version, :up)
|
156
|
+
host = Host.new(host.ip, host.id, host.rack, host.datacenter, host.release_version, host.tokens, :up)
|
140
157
|
@logger.debug("Host #{host.ip} is up")
|
141
158
|
@listeners.each do |listener|
|
142
159
|
listener.host_up(host) rescue nil
|
@@ -145,7 +162,7 @@ module Cassandra
|
|
145
162
|
end
|
146
163
|
|
147
164
|
def toggle_down(host)
|
148
|
-
host = Host.new(host.ip, host.id, host.rack, host.datacenter, host.release_version, :down)
|
165
|
+
host = Host.new(host.ip, host.id, host.rack, host.datacenter, host.release_version, host.tokens, :down)
|
149
166
|
@logger.debug("Host #{host.ip} is down")
|
150
167
|
@listeners.each do |listener|
|
151
168
|
listener.host_down(host) rescue nil
|
@@ -156,7 +173,7 @@ module Cassandra
|
|
156
173
|
def notify_lost(host)
|
157
174
|
if host.up?
|
158
175
|
@logger.debug("Host #{host.ip} is down and lost")
|
159
|
-
host = Host.new(host.ip, host.id, host.rack, host.datacenter, host.release_version, :down)
|
176
|
+
host = Host.new(host.ip, host.id, host.rack, host.datacenter, host.release_version, host.tokens, :down)
|
160
177
|
@listeners.each do |listener|
|
161
178
|
listener.host_down(host) rescue nil
|
162
179
|
listener.host_lost(host) rescue nil
|
@@ -30,6 +30,11 @@ module Cassandra
|
|
30
30
|
mon_initialize
|
31
31
|
end
|
32
32
|
|
33
|
+
def create_partition_key(keyspace, table, values)
|
34
|
+
keyspace = @keyspaces[keyspace]
|
35
|
+
keyspace && keyspace.create_partition_key(table, values)
|
36
|
+
end
|
37
|
+
|
33
38
|
def add_listener(listener)
|
34
39
|
synchronize do
|
35
40
|
@listeners = @listeners.dup.add(listener)
|
@@ -90,7 +95,9 @@ module Cassandra
|
|
90
95
|
created = !@keyspaces.include?(keyspace_name)
|
91
96
|
|
92
97
|
synchronize do
|
93
|
-
|
98
|
+
keyspaces = @keyspaces.dup
|
99
|
+
keyspaces[keyspace_name] = keyspace
|
100
|
+
@keyspaces = keyspaces
|
94
101
|
end
|
95
102
|
|
96
103
|
if created
|
@@ -127,7 +134,9 @@ module Cassandra
|
|
127
134
|
keyspace = keyspace.update_table(table)
|
128
135
|
|
129
136
|
synchronize do
|
130
|
-
|
137
|
+
keyspaces = @keyspaces.dup
|
138
|
+
keyspaces[keyspace_name] = keyspace
|
139
|
+
@keyspaces = keyspaces
|
131
140
|
end
|
132
141
|
|
133
142
|
keyspace_updated(keyspace)
|
@@ -144,7 +153,12 @@ module Cassandra
|
|
144
153
|
end
|
145
154
|
|
146
155
|
def each_keyspace(&block)
|
147
|
-
|
156
|
+
if block_given?
|
157
|
+
@keyspaces.each_value(&block)
|
158
|
+
self
|
159
|
+
else
|
160
|
+
@keyspaces.values
|
161
|
+
end
|
148
162
|
end
|
149
163
|
alias :keyspaces :each_keyspace
|
150
164
|
|
@@ -235,7 +249,8 @@ module Cassandra
|
|
235
249
|
end
|
236
250
|
|
237
251
|
if is_dense
|
238
|
-
value_alias = table['value_alias']
|
252
|
+
value_alias = table['value_alias']
|
253
|
+
value_alias = 'value' if value_alias.nil? || value_alias.empty?
|
239
254
|
type, order = @type_parser.parse(table['default_validator']).results.first
|
240
255
|
other_columns << Column.new(value_alias, type, order)
|
241
256
|
end
|
@@ -245,6 +260,8 @@ module Cassandra
|
|
245
260
|
end
|
246
261
|
else
|
247
262
|
columns.each do |name, row|
|
263
|
+
next if row['column_name'].empty?
|
264
|
+
|
248
265
|
column = create_column(row)
|
249
266
|
type = row['type']
|
250
267
|
index = row['component_index'] || 0
|
@@ -318,4 +335,6 @@ module Cassandra
|
|
318
335
|
end
|
319
336
|
end
|
320
337
|
|
338
|
+
require 'cassandra/cluster/schema/partitioners'
|
339
|
+
require 'cassandra/cluster/schema/replication_strategies'
|
321
340
|
require 'cassandra/cluster/schema/type_parser'
|
@@ -0,0 +1,21 @@
|
|
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
|
+
require 'cassandra/cluster/schema/partitioners/ordered'
|
20
|
+
require 'cassandra/cluster/schema/partitioners/random'
|
21
|
+
require 'cassandra/cluster/schema/partitioners/murmur3'
|
@@ -0,0 +1,47 @@
|
|
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 Partitioners
|
24
|
+
# @private
|
25
|
+
class Murmur3
|
26
|
+
def create_token(partition_key)
|
27
|
+
token = Cassandra::Murmur3.hash(partition_key)
|
28
|
+
token = LONG_MAX if token == LONG_MIN
|
29
|
+
|
30
|
+
token
|
31
|
+
end
|
32
|
+
|
33
|
+
def parse_token(token_string)
|
34
|
+
token_string.to_i
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# @private
|
40
|
+
LONG_MIN = -2 ** 63
|
41
|
+
# @private
|
42
|
+
LONG_MAX = 2 ** 63 - 1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,37 @@
|
|
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 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 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 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 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
|
+
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,92 @@
|
|
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 NetworkTopology
|
26
|
+
def replication_map(token_hosts, token_ring, replication_options)
|
27
|
+
size = token_ring.size
|
28
|
+
racks = ::Hash.new
|
29
|
+
token_hosts.each_value do |host|
|
30
|
+
racks[host.datacenter] ||= ::Set.new
|
31
|
+
racks[host.datacenter].add(host.rack)
|
32
|
+
end
|
33
|
+
|
34
|
+
replication_map = ::Hash.new
|
35
|
+
|
36
|
+
token_ring.each_with_index do |token, i|
|
37
|
+
all_replicas = ::Hash.new
|
38
|
+
visited = ::Hash.new
|
39
|
+
skipped_datacenter_hosts = ::Hash.new
|
40
|
+
replicas = ::Set.new
|
41
|
+
|
42
|
+
size.times do |j|
|
43
|
+
break if all_replicas.size == racks.size && !all_replicas.any? {|(datacenter, r)| r.size < Integer(replication_options[datacenter])}
|
44
|
+
|
45
|
+
host = token_hosts[token_ring[(i + j) % size]]
|
46
|
+
datacenter = host.datacenter
|
47
|
+
next if datacenter.nil?
|
48
|
+
|
49
|
+
factor = replication_options[datacenter]
|
50
|
+
next unless factor
|
51
|
+
|
52
|
+
factor = Integer(factor) rescue next
|
53
|
+
|
54
|
+
replicas_in_datacenter = all_replicas[datacenter] ||= ::Set.new
|
55
|
+
next if replicas_in_datacenter.size >= factor
|
56
|
+
|
57
|
+
rack = host.rack
|
58
|
+
visited_racks = visited[datacenter] ||= ::Set.new
|
59
|
+
|
60
|
+
if rack.nil? || visited_racks.size == racks[datacenter].size
|
61
|
+
replicas << host
|
62
|
+
replicas_in_datacenter << host
|
63
|
+
else
|
64
|
+
if visited_racks.include?(rack)
|
65
|
+
skipped_hosts = skipped_datacenter_hosts[datacenter] ||= ::Set.new
|
66
|
+
skipped_hosts << host
|
67
|
+
else
|
68
|
+
replicas << host
|
69
|
+
replicas_in_datacenter << host
|
70
|
+
visited_racks << rack
|
71
|
+
|
72
|
+
if visited_racks.size == racks[datacenter].size && (skipped_hosts = skipped_datacenter_hosts[datacenter]) && replicas_in_datacenter.size < factor
|
73
|
+
skipped_hosts.each do |skipped_host|
|
74
|
+
replicas << skipped_host
|
75
|
+
replicas_in_datacenter << skipped_host
|
76
|
+
break if replicas_in_datacenter.size >= factor
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
replication_map[token] = replicas.to_a.freeze
|
84
|
+
end
|
85
|
+
|
86
|
+
replication_map
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|