cassandra-driver 2.1.3-java → 2.1.4-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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 345d45fb0e82aa5c218cbc343971f1f9067825e5
4
- data.tar.gz: 64d3a7ca35bda6993cf5d220a53b6aa4cfbc8afc
3
+ metadata.gz: 32c86970c749f6a1afe3c4af85e2d16eb62c11f9
4
+ data.tar.gz: 97c1cacbbffa03e9d1162dce3bbf0a1929b02af2
5
5
  SHA512:
6
- metadata.gz: 9dc189fe0f294bfddbdde8e6c38815a64292c365b92b367ab85861b22745aea870dfb360385489380ec3aec9ac187f1db3227f129adfd17c7a14912530c925ca
7
- data.tar.gz: f10710d0fc9d98169b42ab50b6175b7ede11a317a17c5994526fd6db6130123b04405840cba3852b55fece86f876e2b27b555aab35ce55c5f5d7fc592e48f2de
6
+ metadata.gz: 52a010f2c3254b953ff1d9af072ecba957def21236fafa3467029ef1fa4a50428c8179a5ee9cc5b9a421082347ad45da07966512bc8cf012fa687578eabcada9
7
+ data.tar.gz: 85094e7b051ae8c91c1b6caf8669383e4671ccb18095f6265c6aff8270f47fe0debde9465042e2bb1ec8070f29e8fd66d5bd6f6d6dd132ea5d54a1e99e5cf121
data/README.md CHANGED
@@ -154,7 +154,7 @@ Please [refer to the usage documentation for more information on common pitfalls
154
154
 
155
155
  ## Contributing
156
156
 
157
- For contributing read [CONTRIBUTING.md](https://github.com/datastax/ruby-driver/blob/master/README.md)
157
+ For contributing read [CONTRIBUTING.md](https://github.com/datastax/ruby-driver/blob/master/CONTRIBUTING.md)
158
158
 
159
159
  ## Credits
160
160
 
@@ -59,6 +59,9 @@ module Cassandra
59
59
  #
60
60
  # @option options [Integer] :port (9042) cassandra native protocol port.
61
61
  #
62
+ # @option options [Boolean] :nodelay (false) when set to `true`, disables
63
+ # nagle algorithm.
64
+ #
62
65
  # @option options [String] :datacenter (nil) name of current datacenter.
63
66
  # First datacenter found will be assumed current by default. Note that you
64
67
  # can skip this option if you specify only hosts from the local datacenter
@@ -122,6 +125,12 @@ module Cassandra
122
125
  # address resolver to use. Must be one of `:none` or
123
126
  # `:ec2_multi_region`.
124
127
  #
128
+ # @option options [Boolean] :client_timestamps (false) whether the driver
129
+ # should send timestamps for each executed statement. Enabling this setting
130
+ # allows mitigating Cassandra cluster clock skew because the timestamp of
131
+ # the client machine will be used. This does not help mitigate application
132
+ # cluster clock skew.
133
+ #
125
134
  # @option options [Boolean] :synchronize_schema (true) whether the driver
126
135
  # should automatically keep schema metadata synchronized. When enabled, the
127
136
  # driver updates schema metadata after receiving schema change
@@ -217,7 +226,7 @@ module Cassandra
217
226
  :connect_timeout, :futures_factory, :datacenter, :address_resolution,
218
227
  :address_resolution_policy, :idle_timeout, :heartbeat_interval, :timeout,
219
228
  :synchronize_schema, :schema_refresh_delay, :schema_refresh_timeout,
220
- :shuffle_replicas
229
+ :shuffle_replicas, :client_timestamps
221
230
  ].include?(key)
222
231
  end
223
232
 
@@ -315,10 +324,8 @@ module Cassandra
315
324
 
316
325
  case compression
317
326
  when :snappy
318
- require 'cassandra/compression/compressors/snappy'
319
327
  options[:compressor] = Compression::Compressors::Snappy.new
320
328
  when :lz4
321
- require 'cassandra/compression/compressors/lz4'
322
329
  options[:compressor] = Compression::Compressors::Lz4.new
323
330
  else
324
331
  raise ::ArgumentError, ":compression must be either :snappy or :lz4, #{compression.inspect} given"
@@ -429,6 +436,10 @@ module Cassandra
429
436
  Util.assert_one_of(CONSISTENCIES, consistency) { ":consistency must be one of #{CONSISTENCIES.inspect}, #{consistency.inspect} given" }
430
437
  end
431
438
 
439
+ if options.has_key?(:nodelay)
440
+ options[:nodelay] = !!options[:nodelay]
441
+ end
442
+
432
443
  if options.has_key?(:trace)
433
444
  options[:trace] = !!options[:trace]
434
445
  end
@@ -476,6 +487,10 @@ module Cassandra
476
487
  options[:synchronize_schema] = !!options[:synchronize_schema]
477
488
  end
478
489
 
490
+ if options.has_key?(:client_timestamps)
491
+ options[:client_timestamps] = !!options[:client_timestamps]
492
+ end
493
+
479
494
  hosts = []
480
495
 
481
496
  Array(options.fetch(:hosts, '127.0.0.1')).each do |host|
@@ -497,7 +512,7 @@ module Cassandra
497
512
 
498
513
  hosts.shuffle!
499
514
  rescue => e
500
- futures = options.fetch(:futures_factory) { Driver.new.futures_factory }
515
+ futures = options.fetch(:futures_factory) { return Future::Error.new(e) }
501
516
  futures.error(e)
502
517
  else
503
518
  driver = Driver.new(options)
@@ -207,9 +207,11 @@ module Cassandra
207
207
  def query(statement, options)
208
208
  return @futures.error(Errors::ClientError.new("Positional arguments are not supported by the current version of Apache Cassandra")) if !statement.params.empty? && @connection_options.protocol_version == 1
209
209
 
210
- request = Protocol::QueryRequest.new(statement.cql, statement.params, statement.params_types, options.consistency, options.serial_consistency, options.page_size, options.paging_state, options.trace?, statement.params_names)
211
- timeout = options.timeout
212
- promise = @futures.promise
210
+ timestamp = nil
211
+ timestamp = Time.now if @connection_options.client_timestamps? && @connection_options.protocol_version > 2
212
+ request = Protocol::QueryRequest.new(statement.cql, statement.params, statement.params_types, options.consistency, options.serial_consistency, options.page_size, options.paging_state, options.trace?, statement.params_names, timestamp)
213
+ timeout = options.timeout
214
+ promise = @futures.promise
213
215
 
214
216
  keyspace = @keyspace
215
217
  plan = @load_balancing_policy.plan(keyspace, statement, options)
@@ -234,9 +236,11 @@ module Cassandra
234
236
  end
235
237
 
236
238
  def execute(statement, options)
239
+ timestamp = nil
240
+ timestamp = Time.now if @connection_options.client_timestamps? && @connection_options.protocol_version > 2
237
241
  timeout = options.timeout
238
242
  result_metadata = statement.result_metadata
239
- request = Protocol::ExecuteRequest.new(nil, statement.params_types, statement.params, result_metadata.nil?, options.consistency, options.serial_consistency, options.page_size, options.paging_state, options.trace?)
243
+ request = Protocol::ExecuteRequest.new(nil, statement.params_types, statement.params, result_metadata.nil?, options.consistency, options.serial_consistency, options.page_size, options.paging_state, options.trace?, timestamp)
240
244
  promise = @futures.promise
241
245
 
242
246
  keyspace = @keyspace
@@ -250,12 +254,15 @@ module Cassandra
250
254
  def batch(statement, options)
251
255
  return @futures.error(Errors::ClientError.new("Batch statements are not supported by the current version of Apache Cassandra")) if @connection_options.protocol_version < 2
252
256
 
253
- timeout = options.timeout
254
- keyspace = @keyspace
255
- plan = @load_balancing_policy.plan(keyspace, statement, options)
256
- promise = @futures.promise
257
+ timestamp = nil
258
+ timestamp = Time.now if @connection_options.client_timestamps? && @connection_options.protocol_version > 2
259
+ timeout = options.timeout
260
+ request = Protocol::BatchRequest.new(BATCH_TYPES[statement.type], options.consistency, options.trace?, options.serial_consistency, timestamp)
261
+ keyspace = @keyspace
262
+ plan = @load_balancing_policy.plan(keyspace, statement, options)
263
+ promise = @futures.promise
257
264
 
258
- batch_by_plan(promise, keyspace, statement, options, plan, timeout)
265
+ batch_by_plan(promise, keyspace, statement, options, request, plan, timeout)
259
266
 
260
267
  promise.future
261
268
  end
@@ -509,7 +516,7 @@ module Cassandra
509
516
  end
510
517
  end
511
518
 
512
- def batch_by_plan(promise, keyspace, statement, options, plan, timeout, errors = nil, hosts = [])
519
+ def batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors = nil, hosts = [])
513
520
  unless plan.has_next?
514
521
  promise.break(Errors::NoHostsAvailable.new(errors))
515
522
  return
@@ -522,7 +529,7 @@ module Cassandra
522
529
  unless pool
523
530
  errors ||= {}
524
531
  errors[host] = NOT_CONNECTED
525
- return batch_by_plan(promise, keyspace, statement, options, plan, timeout, errors, hosts)
532
+ return batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
526
533
  end
527
534
 
528
535
  connection = pool.random_connection
@@ -531,14 +538,14 @@ module Cassandra
531
538
  switch = switch_keyspace(connection, keyspace, timeout)
532
539
  switch.on_complete do |s|
533
540
  if s.resolved?
534
- batch_and_send_request_by_plan(host, connection, promise, keyspace, statement, options, plan, timeout, errors, hosts)
541
+ batch_and_send_request_by_plan(host, connection, promise, keyspace, statement, request, options, plan, timeout, errors, hosts)
535
542
  else
536
543
  s.on_failure do |e|
537
544
  case e
538
545
  when Errors::HostError
539
546
  errors ||= {}
540
547
  errors[host] = e
541
- batch_by_plan(promise, keyspace, statement, options, plan, timeout, errors, hosts)
548
+ batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
542
549
  else
543
550
  promise.break(e)
544
551
  end
@@ -546,16 +553,16 @@ module Cassandra
546
553
  end
547
554
  end
548
555
  else
549
- batch_and_send_request_by_plan(host, connection, promise, keyspace, statement, options, plan, timeout, errors, hosts)
556
+ batch_and_send_request_by_plan(host, connection, promise, keyspace, statement, request, options, plan, timeout, errors, hosts)
550
557
  end
551
558
  rescue => e
552
559
  errors ||= {}
553
560
  errors[host] = e
554
- batch_by_plan(promise, keyspace, statement, options, plan, timeout, errors, hosts)
561
+ batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
555
562
  end
556
563
 
557
- def batch_and_send_request_by_plan(host, connection, promise, keyspace, statement, options, plan, timeout, errors, hosts)
558
- request = Protocol::BatchRequest.new(BATCH_TYPES[statement.type], options.consistency, options.trace?)
564
+ def batch_and_send_request_by_plan(host, connection, promise, keyspace, statement, request, options, plan, timeout, errors, hosts)
565
+ request.clear
559
566
  unprepared = Hash.new {|hash, cql| hash[cql] = []}
560
567
 
561
568
  statement.statements.each do |statement|
@@ -598,7 +605,7 @@ module Cassandra
598
605
  when Errors::HostError
599
606
  errors ||= {}
600
607
  errors[host] = e
601
- batch_by_plan(promise, keyspace, statement, options, plan, timeout, errors, hosts)
608
+ batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
602
609
  else
603
610
  promise.break(e)
604
611
  end
@@ -711,7 +718,7 @@ module Cassandra
711
718
  when Protocol::ExecuteRequest
712
719
  execute_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
713
720
  when Protocol::BatchRequest
714
- batch_by_plan(promise, keyspace, statement, options, plan, timeout, errors, hosts)
721
+ batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
715
722
  end
716
723
  else
717
724
  promise.break(error)
@@ -774,7 +781,7 @@ module Cassandra
774
781
  when Protocol::ExecuteRequest
775
782
  execute_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
776
783
  when Protocol::BatchRequest
777
- batch_by_plan(promise, keyspace, statement, options, plan, timeout, errors, hosts)
784
+ batch_by_plan(promise, keyspace, statement, options, request, plan, timeout, errors, hosts)
778
785
  else
779
786
  promise.break(e)
780
787
  end
@@ -114,6 +114,13 @@ module Cassandra
114
114
  def do_connect(host)
115
115
  @reactor.connect(host.ip.to_s, @connection_options.port, {:timeout => @connection_options.connect_timeout, :ssl => @connection_options.ssl}) do |connection|
116
116
  raise Errors::ClientError, 'Not connected, reactor stopped' unless connection
117
+
118
+ if @connection_options.nodelay?
119
+ connection.to_io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
120
+ else
121
+ connection.to_io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 0)
122
+ end
123
+
117
124
  Protocol::CqlProtocolHandler.new(connection, @reactor, @connection_options.protocol_version, @connection_options.compressor, @connection_options.heartbeat_interval, @connection_options.idle_timeout)
118
125
  end.flat_map do |connection|
119
126
  f = request_options(connection)
@@ -242,6 +242,8 @@ module Cassandra
242
242
  def refresh_schema_async
243
243
  connection = @connection
244
244
 
245
+ @logger.info("Refreshing schema")
246
+
245
247
  return Ione::Future.failed(Errors::ClientError.new('Not connected')) if connection.nil?
246
248
 
247
249
  keyspaces = send_select_request(connection, SELECT_KEYSPACES)
@@ -259,6 +261,7 @@ module Cassandra
259
261
 
260
262
  @schema.update_keyspaces(host, keyspaces, tables, columns, types)
261
263
  @metadata.rebuild_token_map
264
+ @logger.info("Schema refreshed")
262
265
  end
263
266
  end
264
267
 
@@ -674,7 +677,7 @@ Control connection failed and is unlikely to recover.
674
677
  register_async
675
678
  end
676
679
  f = f.flat_map { refresh_hosts_async_maybe_retry }
677
- f = f.flat_map { refresh_schema_async_maybe_retry }
680
+ f = f.flat_map { refresh_schema_async_maybe_retry } if @connection_options.synchronize_schema?
678
681
  f = f.fallback do |error|
679
682
  @logger.debug("Connection to #{host.ip} failed (#{error.class.name}: #{error.message})")
680
683
 
@@ -80,16 +80,22 @@ module Cassandra
80
80
 
81
81
  token_ring = tokens.to_a
82
82
  token_replicas = ::Hash.new
83
+ token_maps = ::Hash.new
83
84
 
84
85
  @schema.each_keyspace do |keyspace|
85
86
  replication = keyspace.replication
86
- strategy = @strategies[replication.klass] || @default_strategy
87
+ key = replication_key(replication.klass, replication.options)
88
+
89
+ unless token_maps.include?(key)
90
+ strategy = @strategies[replication.klass] || @default_strategy
91
+ token_maps[key] = strategy.replication_map(
92
+ token_to_host,
93
+ token_ring,
94
+ replication.options
95
+ )
96
+ end
87
97
 
88
- token_replicas[keyspace.name] = strategy.replication_map(
89
- token_to_host,
90
- token_ring,
91
- replication.options
92
- )
98
+ token_replicas[keyspace.name] = token_maps[key]
93
99
  end
94
100
 
95
101
  @token_replicas = token_replicas
@@ -100,6 +106,10 @@ module Cassandra
100
106
 
101
107
  private
102
108
 
109
+ def replication_key(klass, options)
110
+ (klass + ':' + options.keys.sort.map {|k| "#{k}=#{options[k]}"}.join(',')).hash
111
+ end
112
+
103
113
  def insertion_point(list, item)
104
114
  min = 0
105
115
  max = list.size - 1
@@ -25,7 +25,7 @@ module Cassandra
25
25
  :schema_refresh_delay, :schema_refresh_timeout
26
26
  attr_accessor :protocol_version
27
27
 
28
- def initialize(protocol_version, credentials, auth_provider, compressor, port, connect_timeout, ssl, connections_per_local_node, connections_per_remote_node, heartbeat_interval, idle_timeout, synchronize_schema, schema_refresh_delay, schema_refresh_timeout)
28
+ def initialize(protocol_version, credentials, auth_provider, compressor, port, connect_timeout, ssl, connections_per_local_node, connections_per_remote_node, heartbeat_interval, idle_timeout, synchronize_schema, schema_refresh_delay, schema_refresh_timeout, client_timestamps, nodelay)
29
29
  @protocol_version = protocol_version
30
30
  @credentials = credentials
31
31
  @auth_provider = auth_provider
@@ -38,6 +38,8 @@ module Cassandra
38
38
  @synchronize_schema = synchronize_schema
39
39
  @schema_refresh_delay = schema_refresh_delay
40
40
  @schema_refresh_timeout = schema_refresh_timeout
41
+ @client_timestamps = client_timestamps
42
+ @nodelay = nodelay
41
43
 
42
44
  @connections_per_local_node = connections_per_local_node
43
45
  @connections_per_remote_node = connections_per_remote_node
@@ -47,6 +49,14 @@ module Cassandra
47
49
  @synchronize_schema
48
50
  end
49
51
 
52
+ def client_timestamps?
53
+ @client_timestamps
54
+ end
55
+
56
+ def nodelay?
57
+ @nodelay
58
+ end
59
+
50
60
  def compression
51
61
  @compressor && @compressor.algorithm
52
62
  end
@@ -385,7 +385,7 @@ module Cassandra
385
385
  index = Column::Index.new(column['index_name'])
386
386
  else
387
387
  options = ::JSON.load(column['index_options'])
388
- index = Column::Index.new(column['index_name'], options['class_name'])
388
+ index = Column::Index.new(column['index_name'], options && options['class_name'])
389
389
  end
390
390
 
391
391
  Column.new(name, type, order, index, is_static, is_frozen)
@@ -24,56 +24,65 @@ module Cassandra
24
24
  # @private
25
25
  class NetworkTopology
26
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|
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
+
30
34
  racks[host.datacenter] ||= ::Set.new
31
35
  racks[host.datacenter].add(host.rack)
36
+
37
+ datacenter_token_rings[host.datacenter] ||= Hash.new
38
+ datacenter_token_rings[host.datacenter][i] = token
32
39
  end
33
40
 
34
41
  replication_map = ::Hash.new
35
42
 
36
43
  token_ring.each_with_index do |token, i|
37
- all_replicas = ::Hash.new
38
- visited = ::Hash.new
39
- skipped_datacenter_hosts = ::Hash.new
40
44
  replicas = ::Set.new
45
+ visited = ::Hash.new
46
+ skipped = ::Hash.new
41
47
 
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
+ replication_options.each do |datacenter, factor|
49
+ ring = datacenter_token_rings[datacenter]
50
+ next unless ring
51
+ factor = [Integer(factor), ring.size].min rescue next
48
52
 
49
- factor = replication_options[datacenter]
50
- next unless factor
51
53
 
52
- factor = Integer(factor) rescue next
54
+ total_racks = racks[datacenter].size
55
+ visited_racks = visited[datacenter] ||= ::Set.new
56
+ skipped_hosts = skipped[datacenter] ||= ::Set.new
57
+ added_replicas = ::Set.new
53
58
 
54
- replicas_in_datacenter = all_replicas[datacenter] ||= ::Set.new
55
- next if replicas_in_datacenter.size >= factor
59
+ size.times do |j|
60
+ break if added_replicas.size >= factor
56
61
 
57
- rack = host.rack
58
- visited_racks = visited[datacenter] ||= ::Set.new
62
+ tk = ring[(i + j) % size]
63
+ next unless tk
64
+ host = token_hosts[tk]
65
+ rack = host.rack
59
66
 
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
67
+ # unknown rack or seen all racks
68
+ if rack.nil? || visited_racks.size == total_racks
68
69
  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
70
+ added_replicas << host
71
+ else
72
+ if visited_racks.include?(rack)
73
+ skipped_hosts << host
74
+ else
75
+ replicas << host
76
+ visited_racks << rack
77
+ added_replicas << host
78
+
79
+ if visited_racks.size == total_racks
80
+ skipped_hosts.each do |skipped_host|
81
+ break if added_replicas.size >= factor
82
+
83
+ replicas << skipped_host
84
+ added_replicas << host
85
+ end
77
86
  end
78
87
  end
79
88
  end
@@ -108,7 +108,7 @@ module Cassandra
108
108
  return lookup_type(node.children.first)
109
109
  end
110
110
 
111
- type = @@types[node.name]
111
+ type = @@types.fetch(node.name) { return Cassandra::Types.custom(dump_node(node)) }
112
112
 
113
113
  case type
114
114
  when :set, :list
@@ -159,6 +159,12 @@ module Cassandra
159
159
 
160
160
  root
161
161
  end
162
+
163
+ def dump_node(node)
164
+ str = node.name
165
+ str << '(' + node.children.map {|n| dump_node(n)}.join(',') + ')' unless node.children.empty?
166
+ str
167
+ end
162
168
  end
163
169
  end
164
170
  end
@@ -64,3 +64,6 @@ module Cassandra
64
64
  end
65
65
  end
66
66
  end
67
+
68
+ require 'cassandra/compression/compressors/snappy'
69
+ require 'cassandra/compression/compressors/lz4'
@@ -16,12 +16,6 @@
16
16
  # limitations under the License.
17
17
  #++
18
18
 
19
- begin
20
- require 'lz4-ruby'
21
- rescue LoadError => e
22
- raise LoadError, %[LZ4 support requires the "lz4-ruby" gem: #{e.message}], e.backtrace
23
- end
24
-
25
19
  module Cassandra
26
20
  module Compression
27
21
  module Compressors
@@ -40,6 +34,14 @@ module Cassandra
40
34
  # @param [Integer] min_size (64) Don't compress frames smaller than
41
35
  # this size (see {#compress?}).
42
36
  def initialize(min_size=64)
37
+ unless defined?(::LZ4::Raw)
38
+ begin
39
+ require 'lz4-ruby'
40
+ rescue LoadError => e
41
+ raise LoadError, %[LZ4 support requires the "lz4-ruby" gem: #{e.message}], e.backtrace
42
+ end
43
+ end
44
+
43
45
  @algorithm = 'lz4'.freeze
44
46
  @min_size = min_size
45
47
  end
@@ -16,12 +16,6 @@
16
16
  # limitations under the License.
17
17
  #++
18
18
 
19
- begin
20
- require 'snappy'
21
- rescue LoadError => e
22
- raise LoadError, %[Snappy support requires the "snappy" gem: #{e.message}], e.backtrace
23
- end
24
-
25
19
  module Cassandra
26
20
  module Compression
27
21
  module Compressors
@@ -40,6 +34,14 @@ module Cassandra
40
34
  # @param [Integer] min_size (64) Don't compress frames smaller than
41
35
  # this size (see {#compress?}).
42
36
  def initialize(min_size=64)
37
+ unless defined?(::Snappy)
38
+ begin
39
+ require 'snappy'
40
+ rescue LoadError => e
41
+ raise LoadError, %[Snappy support requires the "snappy" gem: #{e.message}], e.backtrace
42
+ end
43
+ end
44
+
43
45
  @algorithm = 'snappy'.freeze
44
46
  @min_size = min_size
45
47
  end
@@ -86,7 +86,9 @@ module Cassandra
86
86
  idle_timeout,
87
87
  synchronize_schema,
88
88
  schema_refresh_delay,
89
- schema_refresh_timeout
89
+ schema_refresh_timeout,
90
+ client_timestamps,
91
+ nodelay
90
92
  )
91
93
  end
92
94
 
@@ -114,6 +116,8 @@ module Cassandra
114
116
  let(:schema_refresh_timeout) { 10 }
115
117
  let(:thread_pool_size) { 4 }
116
118
  let(:shuffle_replicas) { true }
119
+ let(:client_timestamps) { false }
120
+ let(:nodelay) { false }
117
121
 
118
122
  let(:connections_per_local_node) { 2 }
119
123
  let(:connections_per_remote_node) { 1 }
@@ -143,7 +147,11 @@ module Cassandra
143
147
  if f.resolved?
144
148
  promise.fulfill(cluster)
145
149
  else
146
- f.on_failure {|e| promise.break(e)}
150
+ f.on_failure do |e|
151
+ cluster.close_async.on_complete do |_, _|
152
+ promise.break(e)
153
+ end
154
+ end
147
155
  end
148
156
  end
149
157
 
@@ -258,6 +258,10 @@ module Cassandra
258
258
  self
259
259
  end
260
260
 
261
+ def append_timestamp(timestamp)
262
+ append_long(timestamp.tv_sec * 1000000 + timestamp.tv_usec)
263
+ end
264
+
261
265
  def append_long(n)
262
266
  top = n >> 32
263
267
  bottom = n & 0xffffffff
@@ -23,14 +23,21 @@ module Cassandra
23
23
  UNLOGGED_TYPE = 1
24
24
  COUNTER_TYPE = 2
25
25
 
26
- attr_reader :type
26
+ attr_reader :type, :timestamp
27
27
  attr_accessor :consistency, :retries
28
28
 
29
- def initialize(type, consistency, trace=false)
29
+ def initialize(type, consistency, trace=false, serial_consistency = nil, timestamp = nil)
30
30
  super(0x0D, trace)
31
31
  @type = type
32
32
  @parts = []
33
33
  @consistency = consistency
34
+ @serial_consistency = serial_consistency
35
+ @timestamp = timestamp
36
+ end
37
+
38
+ def clear
39
+ @parts.clear
40
+ nil
34
41
  end
35
42
 
36
43
  def add_query(cql, values, types)
@@ -54,9 +61,13 @@ module Cassandra
54
61
  buffer.append_consistency(@consistency)
55
62
 
56
63
  if protocol_version > 2
57
- flags = 0
64
+ flags = 0
65
+ flags |= 0x10 if @serial_consistency
66
+ flags |= 0x20 if @timestamp
58
67
 
59
68
  buffer.append(flags.chr)
69
+ buffer.append_consistency(@serial_consistency) if @serial_consistency
70
+ buffer.append_timestamp(@timestamp) if @timestamp
60
71
  end
61
72
 
62
73
  buffer
@@ -19,10 +19,10 @@
19
19
  module Cassandra
20
20
  module Protocol
21
21
  class ExecuteRequest < Request
22
- attr_reader :metadata, :values, :request_metadata, :serial_consistency, :page_size, :paging_state
22
+ attr_reader :metadata, :values, :request_metadata, :serial_consistency, :page_size, :paging_state, :timestamp
23
23
  attr_accessor :consistency, :retries, :id
24
24
 
25
- def initialize(id, metadata, values, request_metadata, consistency, serial_consistency=nil, page_size=nil, paging_state=nil, trace=false)
25
+ def initialize(id, metadata, values, request_metadata, consistency, serial_consistency=nil, page_size=nil, paging_state=nil, trace=false, timestamp = nil)
26
26
  raise ArgumentError, "Metadata for #{metadata.size} columns, but #{values.size} values given" if metadata.size != values.size
27
27
  raise ArgumentError, %(No such consistency: #{consistency.inspect}) if consistency.nil? || !CONSISTENCIES.include?(consistency)
28
28
  raise ArgumentError, %(No such consistency: #{serial_consistency.inspect}) unless serial_consistency.nil? || CONSISTENCIES.include?(serial_consistency)
@@ -36,6 +36,7 @@ module Cassandra
36
36
  @serial_consistency = serial_consistency
37
37
  @page_size = page_size
38
38
  @paging_state = paging_state
39
+ @timestamp = timestamp
39
40
  end
40
41
 
41
42
  def write(buffer, protocol_version, encoder)
@@ -48,6 +49,9 @@ module Cassandra
48
49
  flags |= 0x04 if @page_size
49
50
  flags |= 0x08 if @paging_state
50
51
  flags |= 0x10 if @serial_consistency
52
+ if protocol_version > 2
53
+ flags |= 0x20 if @timestamp
54
+ end
51
55
  buffer.append(flags.chr)
52
56
  if @values.size > 0
53
57
  encoder.write_parameters(buffer, @values, @metadata)
@@ -55,6 +59,9 @@ module Cassandra
55
59
  buffer.append_int(@page_size) if @page_size
56
60
  buffer.append_bytes(@paging_state) if @paging_state
57
61
  buffer.append_consistency(@serial_consistency) if @serial_consistency
62
+ if protocol_version > 2
63
+ buffer.append_timestamp(@timestamp) if @timestamp
64
+ end
58
65
  else
59
66
  encoder.write_parameters(buffer, @values, @metadata)
60
67
  buffer.append_consistency(@consistency)
@@ -19,10 +19,10 @@
19
19
  module Cassandra
20
20
  module Protocol
21
21
  class QueryRequest < Request
22
- attr_reader :cql, :values, :type_hints, :serial_consistency, :page_size, :paging_state
22
+ attr_reader :cql, :values, :type_hints, :serial_consistency, :page_size, :paging_state, :timestamp
23
23
  attr_accessor :consistency, :retries
24
24
 
25
- def initialize(cql, values, type_hints, consistency, serial_consistency = nil, page_size = nil, paging_state = nil, trace = false, names = EMPTY_LIST)
25
+ def initialize(cql, values, type_hints, consistency, serial_consistency = nil, page_size = nil, paging_state = nil, trace = false, names = EMPTY_LIST, timestamp = nil)
26
26
  super(7, trace)
27
27
  @cql = cql
28
28
  @values = values
@@ -32,6 +32,7 @@ module Cassandra
32
32
  @page_size = page_size
33
33
  @paging_state = paging_state
34
34
  @names = names
35
+ @timestamp = timestamp
35
36
  end
36
37
 
37
38
  def write(buffer, protocol_version, encoder)
@@ -42,9 +43,14 @@ module Cassandra
42
43
  flags |= 0x04 if @page_size
43
44
  flags |= 0x08 if @paging_state
44
45
  flags |= 0x10 if @serial_consistency
46
+ if protocol_version > 2
47
+ flags |= 0x20 if @timestamp
48
+ end
45
49
  if @values && @values.size > 0
46
50
  flags |= 0x01
47
- flags |= 0x40 unless @names.empty?
51
+ if protocol_version > 2
52
+ flags |= 0x40 unless @names.empty?
53
+ end
48
54
  buffer.append(flags.chr)
49
55
  encoder.write_parameters(buffer, @values, @type_hints, @names)
50
56
  else
@@ -53,6 +59,9 @@ module Cassandra
53
59
  buffer.append_int(@page_size) if @page_size
54
60
  buffer.append_bytes(@paging_state) if @paging_state
55
61
  buffer.append_consistency(@serial_consistency) if @serial_consistency
62
+ if protocol_version > 2
63
+ buffer.append_timestamp(@timestamp) if @timestamp
64
+ end
56
65
  end
57
66
  buffer
58
67
  end
@@ -1199,8 +1199,13 @@ module Cassandra
1199
1199
 
1200
1200
  # @return [String] a cassandra representation of this type
1201
1201
  def to_s
1202
- "custom: #{@name}"
1202
+ "'#{@name}'"
1203
1203
  end
1204
+
1205
+ def eql?(other)
1206
+ other.is_a?(Custom) && @name == other.name
1207
+ end
1208
+ alias :== :eql?
1204
1209
  end
1205
1210
 
1206
1211
  # @return [Cassandra::Types::Varchar] varchar type
@@ -17,5 +17,5 @@
17
17
  #++
18
18
 
19
19
  module Cassandra
20
- VERSION = '2.1.3'.freeze
20
+ VERSION = '2.1.4'.freeze
21
21
  end
Binary file
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 2013-2015 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 DataStax
20
+ @base = __FILE__ + '/../..'
21
+
22
+ def self.require(path)
23
+ if path.start_with?('cassandra/')
24
+ include(path)
25
+ else
26
+ ::Kernel.require(path)
27
+ end
28
+ end
29
+
30
+ def self.include(path)
31
+ path = File.expand_path(path + '.rb', @base)
32
+ class_eval(File.read(path), path, 1)
33
+ end
34
+
35
+ previous = nil
36
+ if defined?(::Cassandra)
37
+ previous = ::Cassandra
38
+ Object.send(:remove_const, :Cassandra)
39
+ end
40
+ include 'cassandra'
41
+ DataStax::Cassandra::Murmur3 = ::Cassandra::Murmur3
42
+ Object.send(:remove_const, :Cassandra)
43
+ ::Cassandra = previous if previous
44
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cassandra-driver
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.3
4
+ version: 2.1.4
5
5
  platform: java
6
6
  authors:
7
7
  - Theo Hultberg
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-03-13 00:00:00.000000000 Z
12
+ date: 2015-07-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ione
@@ -180,6 +180,7 @@ files:
180
180
  - lib/cassandra/uuid/generator.rb
181
181
  - lib/cassandra/version.rb
182
182
  - lib/cassandra_murmur3.jar
183
+ - lib/datastax/cassandra.rb
183
184
  homepage: http://datastax.github.io/ruby-driver
184
185
  licenses:
185
186
  - Apache License 2.0