cassandra-driver 2.1.3 → 2.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/cassandra.rb +19 -4
- data/lib/cassandra/cluster/client.rb +27 -20
- data/lib/cassandra/cluster/connector.rb +7 -0
- data/lib/cassandra/cluster/control_connection.rb +4 -1
- data/lib/cassandra/cluster/metadata.rb +16 -6
- data/lib/cassandra/cluster/options.rb +11 -1
- data/lib/cassandra/cluster/schema.rb +1 -1
- data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +44 -35
- data/lib/cassandra/cluster/schema/type_parser.rb +7 -1
- data/lib/cassandra/compression.rb +3 -0
- data/lib/cassandra/compression/compressors/lz4.rb +8 -6
- data/lib/cassandra/compression/compressors/snappy.rb +8 -6
- data/lib/cassandra/driver.rb +10 -2
- data/lib/cassandra/protocol/cql_byte_buffer.rb +4 -0
- data/lib/cassandra/protocol/requests/batch_request.rb +14 -3
- data/lib/cassandra/protocol/requests/execute_request.rb +9 -2
- data/lib/cassandra/protocol/requests/query_request.rb +12 -3
- data/lib/cassandra/types.rb +6 -1
- data/lib/cassandra/version.rb +1 -1
- data/lib/datastax/cassandra.rb +44 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2cdc6e7f7e4ea8335880a2f7ae135973c5503c63
|
4
|
+
data.tar.gz: ace95202610793f5f590da1dddca5baa784a4c5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65160480a00709ed5d0941645b898426913fe63dfc72d6a82a8e73ea00d04671639f6196249aeb9321f95a7ecca9865c8b62ba41786cce86a90ac0b6fc4221ca
|
7
|
+
data.tar.gz: a44eea7203ce53245ead5dfc992f430d48159a21094ce74197a0634982aaef21b7dd59072785941ac3135a6bddfa2dd262528983d780c10ee5fda1b3ed8519d7
|
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/
|
157
|
+
For contributing read [CONTRIBUTING.md](https://github.com/datastax/ruby-driver/blob/master/CONTRIBUTING.md)
|
158
158
|
|
159
159
|
## Credits
|
160
160
|
|
data/lib/cassandra.rb
CHANGED
@@ -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) {
|
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
|
-
|
211
|
-
|
212
|
-
|
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
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
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
|
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
|
-
|
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] =
|
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
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
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
|
-
|
55
|
-
|
59
|
+
size.times do |j|
|
60
|
+
break if added_replicas.size >= factor
|
56
61
|
|
57
|
-
|
58
|
-
|
62
|
+
tk = ring[(i + j) % size]
|
63
|
+
next unless tk
|
64
|
+
host = token_hosts[tk]
|
65
|
+
rack = host.rack
|
59
66
|
|
60
|
-
|
61
|
-
|
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
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
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
|
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
|
@@ -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
|
data/lib/cassandra/driver.rb
CHANGED
@@ -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
|
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
|
|
@@ -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
|
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
|
-
|
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
|
data/lib/cassandra/types.rb
CHANGED
@@ -1199,8 +1199,13 @@ module Cassandra
|
|
1199
1199
|
|
1200
1200
|
# @return [String] a cassandra representation of this type
|
1201
1201
|
def to_s
|
1202
|
-
"
|
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
|
data/lib/cassandra/version.rb
CHANGED
@@ -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.
|
4
|
+
version: 2.1.4
|
5
5
|
platform: ruby
|
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-
|
12
|
+
date: 2015-07-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ione
|
@@ -178,6 +178,7 @@ files:
|
|
178
178
|
- lib/cassandra/uuid.rb
|
179
179
|
- lib/cassandra/version.rb
|
180
180
|
- lib/cassandra.rb
|
181
|
+
- lib/datastax/cassandra.rb
|
181
182
|
- README.md
|
182
183
|
- .yardopts
|
183
184
|
- ext/cassandra_murmur3/extconf.rb
|