cassandra-driver 3.0.3-java → 3.1.0-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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +46 -31
  3. data/lib/cassandra.rb +35 -44
  4. data/lib/cassandra/cluster.rb +40 -11
  5. data/lib/cassandra/cluster/client.rb +193 -159
  6. data/lib/cassandra/cluster/connector.rb +12 -10
  7. data/lib/cassandra/cluster/control_connection.rb +38 -10
  8. data/lib/cassandra/cluster/options.rb +8 -4
  9. data/lib/cassandra/cluster/registry.rb +1 -2
  10. data/lib/cassandra/cluster/schema/fetchers.rb +122 -26
  11. data/lib/cassandra/column_container.rb +9 -4
  12. data/lib/cassandra/custom_data.rb +24 -22
  13. data/lib/cassandra/driver.rb +30 -13
  14. data/lib/cassandra/errors.rb +12 -2
  15. data/lib/cassandra/execution/options.rb +52 -16
  16. data/lib/cassandra/execution/profile.rb +150 -0
  17. data/lib/cassandra/execution/profile_manager.rb +71 -0
  18. data/lib/cassandra/execution/trace.rb +5 -4
  19. data/lib/cassandra/executors.rb +1 -1
  20. data/lib/cassandra/index.rb +1 -1
  21. data/lib/cassandra/keyspace.rb +36 -1
  22. data/lib/cassandra/protocol.rb +5 -0
  23. data/lib/cassandra/protocol/coder.rb +2 -1
  24. data/lib/cassandra/protocol/cql_byte_buffer.rb +21 -0
  25. data/lib/cassandra/protocol/responses/read_failure_error_response.rb +10 -4
  26. data/lib/cassandra/protocol/responses/write_failure_error_response.rb +14 -8
  27. data/lib/cassandra/protocol/v3.rb +2 -1
  28. data/lib/cassandra/protocol/v4.rb +58 -20
  29. data/lib/cassandra/result.rb +1 -1
  30. data/lib/cassandra/session.rb +43 -16
  31. data/lib/cassandra/statements/bound.rb +5 -1
  32. data/lib/cassandra/statements/prepared.rb +8 -3
  33. data/lib/cassandra/table.rb +72 -0
  34. data/lib/cassandra/trigger.rb +67 -0
  35. data/lib/cassandra/types.rb +12 -24
  36. data/lib/cassandra/udt.rb +3 -6
  37. data/lib/cassandra/uuid/generator.rb +6 -3
  38. data/lib/cassandra/version.rb +1 -1
  39. data/lib/cassandra_murmur3.jar +0 -0
  40. metadata +5 -2
@@ -0,0 +1,71 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 2013-2016 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 Execution
21
+ # @private
22
+ class ProfileManager
23
+ attr_reader :profiles
24
+ attr_reader :load_balancing_policies
25
+
26
+ def initialize(default_profile, profiles)
27
+ # default_profile is the default profile that we constructed internally. However, the user can override it
28
+ # with their own :default profile. If that happens, ignore the internally generated default profile.
29
+
30
+ profiles[:default] = default_profile unless profiles.key?(:default)
31
+
32
+ # Save off all of the load-balancing policies for easy access.
33
+ @load_balancing_policies = Set.new
34
+ profiles.each do |name, profile|
35
+ @load_balancing_policies << profile.load_balancing_policy
36
+ end
37
+ @profiles = profiles
38
+ end
39
+
40
+ def default_profile
41
+ @profiles[:default]
42
+ end
43
+
44
+ def distance(host)
45
+ # Return the min distance to the host, as per each lbp.
46
+ distances = Set.new
47
+ @load_balancing_policies.each do |lbp|
48
+ distances.add(lbp.distance(host))
49
+ end
50
+ return :local if distances.include?(:local)
51
+ return :remote if distances.include?(:remote)
52
+
53
+ # Fall back to ignore the host.
54
+ :ignore
55
+ end
56
+
57
+ # NOTE: It's only safe to call add_profile when setting up the cluster object. In particular,
58
+ # this is only ok before calling Driver#connect.
59
+ def add_profile(name, profile)
60
+ @profiles[name] = profile
61
+ @load_balancing_policies << profile.load_balancing_policy
62
+ end
63
+
64
+ # @private
65
+ def inspect
66
+ "#<#{self.class.name}:0x#{object_id.to_s(16)} " \
67
+ "profiles=#{@profiles.inspect}>"
68
+ end
69
+ end
70
+ end
71
+ end
@@ -53,7 +53,7 @@ module Cassandra
53
53
  attr_reader :id
54
54
 
55
55
  # @private
56
- def initialize(id, client)
56
+ def initialize(id, client, load_balancing_policy)
57
57
  @id = id
58
58
  @client = client
59
59
  @coordinator = nil
@@ -65,6 +65,7 @@ module Cassandra
65
65
  @client_ip = nil
66
66
  @loaded = false
67
67
  @loaded_events = false
68
+ @load_balancing_policy = load_balancing_policy
68
69
 
69
70
  mon_initialize
70
71
  end
@@ -141,12 +142,12 @@ module Cassandra
141
142
 
142
143
  attempt = 1
143
144
  data = @client.query(Statements::Simple.new(SELECT_SESSION % @id),
144
- VOID_OPTIONS).get.first
145
+ VOID_OPTIONS.override(load_balancing_policy: @load_balancing_policy)).get.first
145
146
 
146
147
  while data.nil? && attempt <= 5
147
148
  sleep(attempt * 0.4)
148
149
  data = @client.query(Statements::Simple.new(SELECT_SESSION % @id),
149
- VOID_OPTIONS).get.first
150
+ VOID_OPTIONS.override(load_balancing_policy: @load_balancing_policy)).get.first
150
151
  break if data
151
152
  attempt += 1
152
153
  end
@@ -173,7 +174,7 @@ module Cassandra
173
174
  @events = []
174
175
 
175
176
  @client.query(Statements::Simple.new(SELECT_EVENTS % @id),
176
- VOID_OPTIONS).get.each do |row|
177
+ VOID_OPTIONS.override(load_balancing_policy: @load_balancing_policy)).get.each do |row|
177
178
  @events << Event.new(row['event_id'],
178
179
  row['activity'],
179
180
  row['source'],
@@ -43,8 +43,8 @@ module Cassandra
43
43
  @cond = new_cond
44
44
  @tasks = ::Array.new
45
45
  @waiting = 0
46
- @pool = ::Array.new(size, &method(:spawn_thread))
47
46
  @term = false
47
+ @pool = ::Array.new(size, &method(:spawn_thread))
48
48
  end
49
49
 
50
50
  def execute(*args, &block)
@@ -62,7 +62,7 @@ module Cassandra
62
62
  @options['class_name']
63
63
  end
64
64
 
65
- # @return [String] a cql representation of this table
65
+ # @return [String] a cql representation of this index
66
66
  def to_cql
67
67
  keyspace_name = Util.escape_name(@table.keyspace.name)
68
68
  table_name = Util.escape_name(@table.name)
@@ -69,11 +69,18 @@ module Cassandra
69
69
  @views = views
70
70
 
71
71
  # Set the keyspace attribute on the tables and views.
72
+ # Also set up the index collection on the keyspace and the view-collection on each table.
73
+ @indexes_hash = {}
72
74
  @tables.each_value do |t|
73
75
  t.set_keyspace(self)
76
+ t.each_index do |index|
77
+ @indexes_hash[index.name] = index
78
+ end
74
79
  end
75
80
  @views.each_value do |v|
76
81
  v.set_keyspace(self)
82
+ table = v.base_table
83
+ table.add_view(v) if table
77
84
  end
78
85
  end
79
86
 
@@ -110,6 +117,34 @@ module Cassandra
110
117
  end
111
118
  alias tables each_table
112
119
 
120
+ # @return [Boolean] whether this keyspace has an index with the given name
121
+ # @param name [String] index name
122
+ def has_index?(name)
123
+ @indexes_hash.key?(name)
124
+ end
125
+
126
+ # @return [Cassandra::Index, nil] an index or nil
127
+ # @param name [String] index name
128
+ def index(name)
129
+ @indexes_hash[name]
130
+ end
131
+
132
+ # Yield or enumerate each index defined in this keyspace
133
+ # @overload each_index
134
+ # @yieldparam index [Cassandra::Index] current index
135
+ # @return [Cassandra::Keyspace] self
136
+ # @overload each_index
137
+ # @return [Array<Cassandra::Index>] a list of indexes
138
+ def each_index(&block)
139
+ if block_given?
140
+ @indexes_hash.each_value(&block)
141
+ self
142
+ else
143
+ @indexes_hash.values
144
+ end
145
+ end
146
+ alias indexes each_index
147
+
113
148
  # @return [Boolean] whether this keyspace has a materialized view with the given name
114
149
  # @param name [String] materialized view name
115
150
  def has_materialized_view?(name)
@@ -133,7 +168,7 @@ module Cassandra
133
168
  def each_materialized_view(&block)
134
169
  if block_given?
135
170
  @views.each_value do |v|
136
- block.call(v) if v.base_table
171
+ yield(v) if v.base_table
137
172
  end
138
173
  self
139
174
  else
@@ -49,6 +49,11 @@ module Cassandra
49
49
  SCHEMA_CHANGE_TARGET_FUNCTION = 'FUNCTION'.freeze
50
50
  SCHEMA_CHANGE_TARGET_AGGREGATE = 'AGGREGATE'.freeze
51
51
  end
52
+
53
+ module Versions
54
+ BETA_VERSION = 5
55
+ MAX_SUPPORTED_VERSION = 4
56
+ end
52
57
  end
53
58
  end
54
59
 
@@ -268,7 +268,8 @@ module Cassandra
268
268
  value = ::Hash.new
269
269
 
270
270
  buffer.read_signed_int.times do
271
- value[read_value_v4(buffer, key_type, custom_type_handlers)] = read_value_v4(buffer, value_type, custom_type_handlers)
271
+ value[read_value_v4(buffer, key_type, custom_type_handlers)] =
272
+ read_value_v4(buffer, value_type, custom_type_handlers)
272
273
  end
273
274
 
274
275
  value
@@ -204,6 +204,15 @@ module Cassandra
204
204
  e.backtrace
205
205
  end
206
206
 
207
+ def read_inet_addr
208
+ size = read_byte
209
+ IPAddr.new_ntoh(read(size))
210
+ rescue RangeError => e
211
+ raise Errors::DecodingError,
212
+ "Not enough bytes available to decode an INET addr: #{e.message}",
213
+ e.backtrace
214
+ end
215
+
207
216
  def read_consistency
208
217
  index = read_unsigned_short
209
218
  if index >= CONSISTENCIES.size || CONSISTENCIES[index].nil?
@@ -232,6 +241,18 @@ module Cassandra
232
241
  map
233
242
  end
234
243
 
244
+ def read_reason_map
245
+ # reason_map is new in v5. Starts with an int indicating the number of key-value pairs, followed by
246
+ # the key-value pairs. Keys are inet's, values are short int's.
247
+ map = {}
248
+ map_size = read_int
249
+ map_size.times do
250
+ key = read_inet_addr
251
+ map[key] = read_short
252
+ end
253
+ map
254
+ end
255
+
235
256
  def read_string_multimap
236
257
  map = {}
237
258
  map_size = read_unsigned_short
@@ -19,7 +19,7 @@
19
19
  module Cassandra
20
20
  module Protocol
21
21
  class ReadFailureErrorResponse < ErrorResponse
22
- attr_reader :consistency, :received, :blockfor, :numfailures, :data_present
22
+ attr_reader :consistency, :received, :blockfor, :numfailures, :data_present, :failures_by_node
23
23
 
24
24
  def initialize(custom_payload,
25
25
  warnings,
@@ -29,14 +29,19 @@ module Cassandra
29
29
  received,
30
30
  blockfor,
31
31
  numfailures,
32
- data_present)
32
+ data_present,
33
+ failures_by_node)
33
34
  super(custom_payload, warnings, code, message)
34
35
 
35
36
  @consistency = consistency
36
37
  @received = received
37
38
  @blockfor = blockfor
38
- @numfailures = numfailures
39
39
  @data_present = data_present
40
+ @failures_by_node = failures_by_node
41
+
42
+ # If failures_by_node is set, numfailures isn't, and v.v. Set @numfailures to the size of the failure-map
43
+ # if numfailures is nil.
44
+ @numfailures = numfailures || @failures_by_node.size
40
45
  end
41
46
 
42
47
  def to_error(keyspace, statement, options, hosts, consistency, retries)
@@ -53,7 +58,8 @@ module Cassandra
53
58
  @consistency,
54
59
  @blockfor,
55
60
  @numfailures,
56
- @received)
61
+ @received,
62
+ @failures_by_node)
57
63
  end
58
64
 
59
65
  def to_s
@@ -19,7 +19,7 @@
19
19
  module Cassandra
20
20
  module Protocol
21
21
  class WriteFailureErrorResponse < ErrorResponse
22
- attr_reader :consistency, :received, :blockfor, :numfailures, :write_type
22
+ attr_reader :consistency, :received, :blockfor, :numfailures, :write_type, :failures_by_node
23
23
 
24
24
  def initialize(custom_payload,
25
25
  warnings,
@@ -29,16 +29,21 @@ module Cassandra
29
29
  received,
30
30
  blockfor,
31
31
  numfailures,
32
- write_type)
32
+ write_type,
33
+ failures_by_node)
33
34
  super(custom_payload, warnings, code, message)
34
35
 
35
36
  write_type.downcase!
36
37
 
37
- @consistency = consistency
38
- @received = received
39
- @blockfor = blockfor
40
- @numfailures = numfailures
41
- @write_type = write_type.to_sym
38
+ @consistency = consistency
39
+ @received = received
40
+ @blockfor = blockfor
41
+ @write_type = write_type.to_sym
42
+ @failures_by_node = failures_by_node
43
+
44
+ # If failures_by_node is set, numfailures isn't, and v.v. Set @numfailures to the size of the failure-map
45
+ # if numfailures is nil.
46
+ @numfailures = numfailures || @failures_by_node.size
42
47
  end
43
48
 
44
49
  def to_error(keyspace, statement, options, hosts, consistency, retries)
@@ -55,7 +60,8 @@ module Cassandra
55
60
  @consistency,
56
61
  @blockfor,
57
62
  @numfailures,
58
- @received)
63
+ @received,
64
+ @failures_by_node)
59
65
  end
60
66
 
61
67
  def to_s
@@ -166,7 +166,8 @@ module Cassandra
166
166
  if compression == 1
167
167
  if @compressor
168
168
  buffer = CqlByteBuffer.new(
169
- @compressor.decompress(buffer.read(frame_length)))
169
+ @compressor.decompress(buffer.read(frame_length))
170
+ )
170
171
  frame_length = buffer.size
171
172
  else
172
173
  raise Errors::DecodingError,
@@ -23,7 +23,7 @@ module Cassandra
23
23
  class Encoder
24
24
  HEADER_FORMAT = 'c2ncN'.freeze
25
25
 
26
- def initialize(compressor = nil, protocol_version = 4)
26
+ def initialize(compressor, protocol_version)
27
27
  @compressor = compressor
28
28
  @protocol_version = protocol_version
29
29
  end
@@ -31,6 +31,7 @@ module Cassandra
31
31
  def encode(buffer, request, stream_id)
32
32
  flags = 0
33
33
  flags |= 0x02 if request.trace?
34
+ flags |= 0x10 if @protocol_version == Cassandra::Protocol::Versions::BETA_VERSION
34
35
 
35
36
  body = CqlByteBuffer.new
36
37
 
@@ -178,7 +179,8 @@ module Cassandra
178
179
  if compression
179
180
  if @compressor
180
181
  buffer = CqlByteBuffer.new(
181
- @compressor.decompress(buffer.read(frame_length)))
182
+ @compressor.decompress(buffer.read(frame_length))
183
+ )
182
184
  frame_length = buffer.size
183
185
  else
184
186
  raise Errors::DecodingError,
@@ -259,15 +261,33 @@ module Cassandra
259
261
  buffer.read_int,
260
262
  (buffer.read_byte != 0))
261
263
  when 0x1300
262
- ReadFailureErrorResponse.new(custom_payload,
263
- warnings,
264
- code,
265
- message,
266
- buffer.read_consistency,
267
- buffer.read_int,
268
- buffer.read_int,
269
- buffer.read_int,
270
- (buffer.read_byte != 0))
264
+ cl = buffer.read_consistency
265
+ received = buffer.read_int
266
+ block_for = buffer.read_int
267
+ if protocol_version < 5
268
+ ReadFailureErrorResponse.new(custom_payload,
269
+ warnings,
270
+ code,
271
+ message,
272
+ cl,
273
+ received,
274
+ block_for,
275
+ buffer.read_int,
276
+ (buffer.read_byte != 0),
277
+ nil)
278
+ else
279
+ failures_by_node = buffer.read_reason_map
280
+ ReadFailureErrorResponse.new(custom_payload,
281
+ warnings,
282
+ code,
283
+ message,
284
+ cl,
285
+ received,
286
+ block_for,
287
+ nil,
288
+ (buffer.read_byte != 0),
289
+ failures_by_node)
290
+ end
271
291
  when 0x1400
272
292
  FunctionFailureErrorResponse.new(custom_payload,
273
293
  warnings,
@@ -277,15 +297,33 @@ module Cassandra
277
297
  buffer.read_string,
278
298
  buffer.read_string_list)
279
299
  when 0x1500
280
- WriteFailureErrorResponse.new(custom_payload,
281
- warnings,
282
- code,
283
- message,
284
- buffer.read_consistency,
285
- buffer.read_int,
286
- buffer.read_int,
287
- buffer.read_int,
288
- buffer.read_string)
300
+ cl = buffer.read_consistency
301
+ received = buffer.read_int
302
+ block_for = buffer.read_int
303
+ if protocol_version < 5
304
+ WriteFailureErrorResponse.new(custom_payload,
305
+ warnings,
306
+ code,
307
+ message,
308
+ cl,
309
+ received,
310
+ block_for,
311
+ buffer.read_int,
312
+ buffer.read_string,
313
+ nil)
314
+ else
315
+ failures_by_node = buffer.read_reason_map
316
+ WriteFailureErrorResponse.new(custom_payload,
317
+ warnings,
318
+ code,
319
+ message,
320
+ cl,
321
+ received,
322
+ block_for,
323
+ nil,
324
+ buffer.read_string,
325
+ failures_by_node)
326
+ end
289
327
  when 0x2400
290
328
  AlreadyExistsErrorResponse.new(custom_payload,
291
329
  warnings,