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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +20 -12
  3. data/ext/cassandra_murmur3/cassandra_murmur3.c +178 -0
  4. data/ext/cassandra_murmur3/extconf.rb +2 -0
  5. data/lib/cassandra.rb +132 -24
  6. data/lib/cassandra/auth.rb +5 -5
  7. data/lib/cassandra/client/connector.rb +11 -6
  8. data/lib/cassandra/cluster.rb +47 -23
  9. data/lib/cassandra/cluster/client.rb +5 -4
  10. data/lib/cassandra/cluster/connector.rb +17 -4
  11. data/lib/cassandra/cluster/control_connection.rb +21 -16
  12. data/lib/cassandra/cluster/metadata.rb +124 -0
  13. data/lib/cassandra/cluster/options.rb +5 -3
  14. data/lib/cassandra/cluster/registry.rb +26 -9
  15. data/lib/cassandra/cluster/schema.rb +23 -4
  16. data/lib/cassandra/cluster/schema/partitioners.rb +21 -0
  17. data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +47 -0
  18. data/lib/cassandra/cluster/schema/partitioners/ordered.rb +37 -0
  19. data/lib/cassandra/cluster/schema/partitioners/random.rb +37 -0
  20. data/lib/cassandra/cluster/schema/replication_strategies.rb +21 -0
  21. data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +92 -0
  22. data/lib/cassandra/cluster/schema/replication_strategies/none.rb +39 -0
  23. data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +44 -0
  24. data/lib/cassandra/cluster/schema/type_parser.rb +1 -1
  25. data/lib/cassandra/compression.rb +1 -1
  26. data/lib/cassandra/driver.rb +29 -4
  27. data/lib/cassandra/execution/options.rb +3 -0
  28. data/lib/cassandra/host.rb +9 -5
  29. data/lib/cassandra/keyspace.rb +17 -4
  30. data/lib/cassandra/listener.rb +3 -3
  31. data/lib/cassandra/load_balancing.rb +12 -11
  32. data/lib/cassandra/load_balancing/policies.rb +2 -1
  33. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +1 -1
  34. data/lib/cassandra/load_balancing/policies/round_robin.rb +37 -0
  35. data/lib/cassandra/load_balancing/policies/token_aware.rb +119 -0
  36. data/lib/cassandra/protocol/cql_protocol_handler.rb +2 -2
  37. data/lib/cassandra/reconnection.rb +5 -5
  38. data/lib/cassandra/retry.rb +3 -3
  39. data/lib/cassandra/session.rb +7 -0
  40. data/lib/cassandra/statements/bound.rb +4 -2
  41. data/lib/cassandra/statements/prepared.rb +28 -6
  42. data/lib/cassandra/table.rb +49 -4
  43. data/lib/cassandra/time_uuid.rb +1 -0
  44. data/lib/cassandra/util.rb +0 -2
  45. data/lib/cassandra/version.rb +1 -1
  46. 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
- :connection_timeout, :connections_per_local_node, :connections_per_remote_node
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, connection_timeout, connections_per_local_node, connections_per_remote_node)
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
- @connection_timeout = connection_timeout
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
- @hosts.values.each(&block)
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 { @hosts = @hosts.merge(ip => host) }
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 { @hosts = @hosts.merge(ip => host) }
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 { @hosts = @hosts.merge(ip => host) }
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
- self
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
- @keyspaces = @keyspaces.merge(keyspace_name => keyspace)
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
- @keyspaces = @keyspaces.merge(keyspace_name => keyspace)
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
- @keyspaces.values.each(&block)
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'] || 'value'
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