cassandra-driver 3.0.0.rc.2-java → 3.0.2-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +51 -39
- data/lib/cassandra.rb +74 -32
- data/lib/cassandra/auth.rb +3 -1
- data/lib/cassandra/cluster.rb +14 -3
- data/lib/cassandra/cluster/client.rb +98 -62
- data/lib/cassandra/cluster/connector.rb +7 -9
- data/lib/cassandra/cluster/metadata.rb +1 -1
- data/lib/cassandra/cluster/options.rb +19 -7
- data/lib/cassandra/cluster/schema/cql_type_parser.rb +3 -0
- data/lib/cassandra/cluster/schema/fetchers.rb +1 -1
- data/lib/cassandra/custom_data.rb +51 -0
- data/lib/cassandra/driver.rb +23 -20
- data/lib/cassandra/execution/options.rb +1 -1
- data/lib/cassandra/index.rb +22 -8
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +19 -1
- data/lib/cassandra/load_balancing/policies/round_robin.rb +7 -0
- data/lib/cassandra/load_balancing/policies/token_aware.rb +7 -0
- data/lib/cassandra/load_balancing/policies/white_list.rb +7 -0
- data/lib/cassandra/protocol.rb +7 -0
- data/lib/cassandra/protocol/coder.rb +28 -8
- data/lib/cassandra/protocol/cql_byte_buffer.rb +21 -4
- data/lib/cassandra/protocol/cql_protocol_handler.rb +3 -2
- data/lib/cassandra/protocol/requests/batch_request.rb +1 -1
- data/lib/cassandra/protocol/requests/execute_request.rb +1 -1
- data/lib/cassandra/protocol/requests/query_request.rb +1 -1
- data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +4 -2
- data/lib/cassandra/protocol/v1.rb +2 -1
- data/lib/cassandra/protocol/v3.rb +2 -1
- data/lib/cassandra/protocol/v4.rb +5 -3
- data/lib/cassandra/result.rb +2 -2
- data/lib/cassandra/session.rb +10 -15
- data/lib/cassandra/statement.rb +5 -0
- data/lib/cassandra/statements/batch.rb +6 -0
- data/lib/cassandra/statements/bound.rb +5 -0
- data/lib/cassandra/statements/prepared.rb +11 -2
- data/lib/cassandra/statements/simple.rb +5 -0
- data/lib/cassandra/statements/void.rb +5 -0
- data/lib/cassandra/table.rb +5 -5
- data/lib/cassandra/timestamp_generator.rb +37 -0
- data/lib/cassandra/timestamp_generator/simple.rb +38 -0
- data/lib/cassandra/timestamp_generator/ticking_on_duplicate.rb +58 -0
- data/lib/cassandra/tuple.rb +2 -2
- data/lib/cassandra/types.rb +2 -2
- data/lib/cassandra/util.rb +136 -2
- data/lib/cassandra/version.rb +1 -1
- data/lib/cassandra_murmur3.jar +0 -0
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 78dc265751584f3c23a824f4f8f8cfebd5f98d32
|
4
|
+
data.tar.gz: 303da68ffd2ec37685f54a22e7c26f0f3568b51d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ecd09602150990d62b56ba5b0c75e1131f54b7c598171f0ca17927dfaf2fc3a2b1bc66c2ffb7b1b61f0164daa6fcbd359c3c6d6528230b05d4e5ba34482665b
|
7
|
+
data.tar.gz: 64d64fadf8a713b97079096af4aafd966689f9b8e9e0a6e1acae8442229de407599e3d4318eed80614fb30af5fb53db4a98e340c9a8c3490b03ae07e3a363023
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Datastax Ruby Driver for Apache Cassandra
|
2
2
|
|
3
|
-
*If you're reading this on GitHub, please note that this is the readme for the development version and that some features described here might not yet have been released. You can [find the documentation for latest version through ruby driver docs](http://datastax.
|
3
|
+
*If you're reading this on GitHub, please note that this is the readme for the development version and that some features described here might not yet have been released. You can [find the documentation for the latest version through ruby driver docs](http://docs.datastax.com/en/latest-ruby-driver/ruby-driver/whatsNew.html) or via the release tags, [e.g. v3.0.2](https://github.com/datastax/ruby-driver/tree/v3.0.2).*
|
4
4
|
|
5
5
|
[![Build Status](https://travis-ci.org/datastax/ruby-driver.svg?branch=master)](https://travis-ci.org/datastax/ruby-driver)
|
6
6
|
|
@@ -8,7 +8,7 @@ A Ruby client driver for Apache Cassandra. This driver works exclusively with
|
|
8
8
|
the Cassandra Query Language version 3 (CQL3) and Cassandra's native protocol.
|
9
9
|
|
10
10
|
- Code: https://github.com/datastax/ruby-driver
|
11
|
-
- Docs: http://datastax.
|
11
|
+
- Docs: http://docs.datastax.com/en/latest-ruby-driver/ruby-driver/whatsNew.html
|
12
12
|
- Jira: https://datastax-oss.atlassian.net/browse/RUBY
|
13
13
|
- Mailing List: https://groups.google.com/a/lists.datastax.com/forum/#!forum/ruby-driver-user
|
14
14
|
- IRC: #datastax-drivers on [irc.freenode.net](http://freenode.net>)
|
@@ -16,14 +16,14 @@ the Cassandra Query Language version 3 (CQL3) and Cassandra's native protocol.
|
|
16
16
|
|
17
17
|
This driver is based on [the cql-rb gem](https://github.com/iconara/cql-rb) by [Theo Hultberg](https://github.com/iconara) and we added support for:
|
18
18
|
|
19
|
-
* [Asynchronous execution](http://datastax.
|
20
|
-
* One-off, [prepared](http://datastax.
|
21
|
-
* Automatic peer discovery and cluster metadata with [support for change notifications](http://datastax.
|
22
|
-
* Various [load-balancing](http://datastax.
|
23
|
-
* [SSL encryption](http://datastax.
|
24
|
-
* [Flexible and robust error handling](http://datastax.
|
25
|
-
* [Per-request execution information and tracing](http://datastax.
|
26
|
-
* [Configurable address resolution](http://datastax.
|
19
|
+
* [Asynchronous execution](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/asynchronous_io/)
|
20
|
+
* One-off, [prepared](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/basics/prepared_statements/) and [batch statements](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/basics/batch_statements/)
|
21
|
+
* Automatic peer discovery and cluster metadata with [support for change notifications](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/state_listeners/)
|
22
|
+
* Various [load-balancing](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/load_balancing/), [retry](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/retry_policies/) and [reconnection](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/reconnection/) policies with [ability to write your own](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/load_balancing/implementing_a_policy/)
|
23
|
+
* [SSL encryption](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/security/ssl_encryption/)
|
24
|
+
* [Flexible and robust error handling](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/error_handling/)
|
25
|
+
* [Per-request execution information and tracing](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/debugging/)
|
26
|
+
* [Configurable address resolution](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/address_resolution/)
|
27
27
|
|
28
28
|
[Check out the slides from Ruby Driver Explained](https://speakerdeck.com/avalanche123/ruby-driver-explained) for a detailed overview of the Ruby Driver architecture.
|
29
29
|
|
@@ -31,8 +31,8 @@ This driver is based on [the cql-rb gem](https://github.com/iconara/cql-rb) by [
|
|
31
31
|
|
32
32
|
This driver works exclusively with the Cassandra Query Language v3 (CQL3) and Cassandra's native protocol. The current version works with:
|
33
33
|
|
34
|
-
* Apache Cassandra versions 1.2, 2.0, 2.1, and 3.x
|
35
|
-
* DataStax Enterprise 4.0
|
34
|
+
* Apache Cassandra versions 1.2, 2.0, 2.1, 2.2, and 3.x
|
35
|
+
* DataStax Enterprise 4.0 and above.
|
36
36
|
* Ruby (MRI) 2.2, 2.3
|
37
37
|
* JRuby 1.7
|
38
38
|
|
@@ -67,9 +67,9 @@ __Note__: The host you specify is just a seed node, the driver will automaticall
|
|
67
67
|
|
68
68
|
Read more:
|
69
69
|
|
70
|
-
* [`Cassandra.cluster` options](http://datastax.
|
71
|
-
* [`Session#execute_async` options](http://datastax.
|
72
|
-
* [Usage documentation](http://datastax.
|
70
|
+
* [`Cassandra.cluster` options](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/api/cassandra/#cluster-class_method)
|
71
|
+
* [`Session#execute_async` options](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/api/cassandra/session/#execute_async-instance_method)
|
72
|
+
* [Usage documentation](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features)
|
73
73
|
|
74
74
|
## Installation
|
75
75
|
|
@@ -85,39 +85,46 @@ Install via Gemfile
|
|
85
85
|
gem 'cassandra-driver'
|
86
86
|
```
|
87
87
|
|
88
|
-
__Note__: if you want to use compression you should also install [snappy](http://rubygems.org/gems/snappy) or [lz4-ruby](http://rubygems.org/gems/lz4-ruby). [Read more about compression.](http://datastax.
|
88
|
+
__Note__: if you want to use compression you should also install [snappy](http://rubygems.org/gems/snappy) or [lz4-ruby](http://rubygems.org/gems/lz4-ruby). [Read more about compression.](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/#compression)
|
89
89
|
|
90
90
|
|
91
91
|
## Upgrading from cql-rb
|
92
92
|
|
93
|
-
Some of the new features added to the driver have unfortunately led to changes in the original cql-rb API. In the examples directory, you can find [an example of how to wrap the ruby driver to achieve almost complete interface parity with cql-rb](https://github.com/datastax/ruby-driver/blob/
|
93
|
+
Some of the new features added to the driver have unfortunately led to changes in the original cql-rb API. In the examples directory, you can find [an example of how to wrap the ruby driver to achieve almost complete interface parity with cql-rb](https://github.com/datastax/ruby-driver/blob/v3.0.2/examples/cql-rb-wrapper.rb) to assist you with gradual upgrade.
|
94
94
|
|
95
|
-
## What's new in v3.0
|
95
|
+
## What's new in v3.0
|
96
|
+
|
97
|
+
See the [changelog](https://github.com/datastax/ruby-driver/blob/v3.0.2/CHANGELOG.md) for details on patch versions.
|
96
98
|
|
97
99
|
### Features:
|
98
100
|
|
99
|
-
* Apache Cassandra native protocol v4
|
100
|
-
* Add support for smallint, tinyint, date (Cassandra::Date) and time (Cassandra::Time) data types.
|
101
|
+
* Add support for Apache Cassandra native protocol v4
|
102
|
+
* Add support for smallint, tinyint, date (`Cassandra::Date`) and time (`Cassandra::Time`) data types.
|
101
103
|
* Include schema metadata for User Defined Functions and User Defined Aggregates.
|
104
|
+
* Augment the `Cassandra::Table` object to expose many more attributes: `id`, `options`, `keyspace`, `partition_key`, `clustering_columns`, and `clustering_order`. This makes it significantly easier to write administration scripts that report various attributes of your schema, which may help to highlight areas for improvement.
|
102
105
|
* Include client ip addresses in request traces, only on Cassandra 3.x.
|
103
|
-
* Add new retry policy decision Cassandra::Retry::Policy#try_next_host
|
104
|
-
* Support specifying statement idempotence with the new
|
105
|
-
* Support sending custom payloads when preparing or executing statements using the new
|
106
|
-
* Expose custom payloads received with responses on server exceptions and Cassandra::Execution::Info instances.
|
107
|
-
* Expose server warnings on server exceptions and Cassandra::Execution::Info instances.
|
108
|
-
* Add connections_per_local_node
|
109
|
-
* Add Cassandra::Logger class to make it easy for users to enable debug logging in the client.
|
110
|
-
* Add protocol_version configuration option to allow the user to force the protocol version to use for communication with nodes.
|
106
|
+
* Add new retry policy decision `Cassandra::Retry::Policy#try_next_host`.
|
107
|
+
* Support specifying statement idempotence with the new `idempotent` option when executing.
|
108
|
+
* Support sending custom payloads when preparing or executing statements using the new `payload` option.
|
109
|
+
* Expose custom payloads received with responses on server exceptions and `Cassandra::Execution::Info` instances.
|
110
|
+
* Expose server warnings on server exceptions and `Cassandra::Execution::Info` instances.
|
111
|
+
* Add `connections_per_local_node`, `connections_per_remote_node`, `requests_per_connection` cluster configuration options to tune parallel query execution and resource usage.
|
112
|
+
* Add `Cassandra::Logger` class to make it easy for users to enable debug logging in the client.
|
113
|
+
* Add `protocol_version` configuration option to allow the user to force the protocol version to use for communication with nodes.
|
111
114
|
* Add support for materialized views and indexes in the schema metadata.
|
115
|
+
* Support the `ReadError`, `WriteError`, and `FunctionCallError` Cassandra error responses introduced in Cassandra 2.2.
|
116
|
+
* Add support for unset variables in bound statements.
|
117
|
+
* Support DSE security (`DseAuthenticator`, configured for LDAP).
|
118
|
+
* Add a timeout option to `Cassandra::Future#get`.
|
112
119
|
|
113
|
-
### Breaking Changes:
|
120
|
+
### Breaking Changes from 2.x:
|
114
121
|
|
115
|
-
* Cassandra::Future#join is now an alias to Cassandra::Future#get and will raise an error if the future is resolved with one.
|
122
|
+
* `Cassandra::Future#join` is now an alias to Cassandra::Future#get and will raise an error if the future is resolved with one.
|
116
123
|
* Default consistency level is now LOCAL_ONE.
|
117
124
|
* Enable tcp no-delay by default.
|
118
125
|
* Unavailable errors are retried on the next host in the load balancing plan by default.
|
119
|
-
* Statement execution no longer retried on timeouts, unless
|
120
|
-
* Cassandra::Statements::Batch#add
|
126
|
+
* Statement execution no longer retried on timeouts, unless the statement is marked as idempotent in the call to `Cassandra::Session#execute*` or when creating a `Cassandra::Statement` object.
|
127
|
+
* `Cassandra::Statements::Batch#add` and `Cassandra::Session#execute*` signatures have changed in how one specifies query parameters. Specify the query parameters array as the value of the arguments key:
|
121
128
|
|
122
129
|
```ruby
|
123
130
|
batch.add(query, ['val1', 'val2'])
|
@@ -128,6 +135,10 @@ batch.add(query, {p1: 'val1'})
|
|
128
135
|
# becomes
|
129
136
|
batch.add(query, arguments: {p1: 'val1'})
|
130
137
|
```
|
138
|
+
* The Datacenter-aware load balancing policy (`Cassandra::LoadBalancing::Policies::DCAwareRoundRobin`) defaults to using
|
139
|
+
nodes in the local DC only. In prior releases, the policy would fall back to remote nodes after exhausting local nodes.
|
140
|
+
Specify a positive value (or nil for unlimited) for `max_remote_hosts_to_use` when initializing the policy to allow remote node use.
|
141
|
+
* Unspecified variables in statements previously resulted in an exception. Now they are essentially ignored or treated as null.
|
131
142
|
|
132
143
|
### Bug Fixes:
|
133
144
|
|
@@ -135,12 +146,13 @@ batch.add(query, arguments: {p1: 'val1'})
|
|
135
146
|
* [[RUBY-143](https://datastax-oss.atlassian.net/browse/RUBY-143)] Retry querying system table for metadata of new hosts when prior attempts fail, ultimately enabling use of new hosts.
|
136
147
|
* [[RUBY-150](https://datastax-oss.atlassian.net/browse/RUBY-150)] Fixed a protocol decoding error that occurred when multiple messages are available in a stream.
|
137
148
|
* [[RUBY-151](https://datastax-oss.atlassian.net/browse/RUBY-151)] Decode incomplete UDTs properly.
|
138
|
-
* [[RUBY-
|
149
|
+
* [[RUBY-155](https://datastax-oss.atlassian.net/browse/RUBY-155)] Request timeout timer should not include request queuing time.
|
150
|
+
* [[RUBY-161](https://datastax-oss.atlassian.net/browse/RUBY-161)] Protocol version negotiation in mixed version clusters should not fall back to v1 unless it is truly warranted.
|
151
|
+
* [[RUBY-214](https://datastax-oss.atlassian.net/browse/RUBY-214)] Ensure client timestamps have microsecond precision in JRuby. Previously, some row updates would get lost in high transaction environments.
|
139
152
|
|
140
153
|
## Feedback Requested
|
141
154
|
|
142
|
-
*Help us focus our efforts!* [Provide your input](http://goo.gl/forms/pCs8PTpHLf)
|
143
|
-
on the Ruby Driver Platform and Runtime Survey (we kept it short).
|
155
|
+
*Help us focus our efforts!* [Provide your input](http://goo.gl/forms/pCs8PTpHLf) on the Ruby Driver Platform and Runtime Survey (we kept it short).
|
144
156
|
|
145
157
|
## Code examples
|
146
158
|
|
@@ -152,7 +164,7 @@ examples in the `features/` directory.
|
|
152
164
|
## Running tests
|
153
165
|
|
154
166
|
If you don't feel like reading through the following instructions on how to run
|
155
|
-
ruby-driver tests, feel free to [check out .travis.yml for the entire build code](https://github.com/datastax/ruby-driver/blob/
|
167
|
+
ruby-driver tests, feel free to [check out .travis.yml for the entire build code](https://github.com/datastax/ruby-driver/blob/v3.0.2/.travis.yml).
|
156
168
|
|
157
169
|
* Check out the driver codebase and install test dependencies:
|
158
170
|
|
@@ -176,7 +188,7 @@ CASSANDRA_VERSION=2.0.17 bundle exec rake test # run both as well as integration
|
|
176
188
|
## Changelog & versioning
|
177
189
|
|
178
190
|
Check out the [releases on GitHub](https://github.com/datastax/ruby-driver/releases) and
|
179
|
-
[changelog](https://github.com/datastax/ruby-driver/blob/
|
191
|
+
[changelog](https://github.com/datastax/ruby-driver/blob/v3.0.2/CHANGELOG.md). Version
|
180
192
|
numbering follows the [semantic versioning](http://semver.org/) scheme.
|
181
193
|
|
182
194
|
Private and experimental APIs, defined as whatever is not in the
|
@@ -200,7 +212,7 @@ the release.
|
|
200
212
|
* Because the driver reactor is using `IO.select`, the maximum number of tcp connections allowed is 1024.
|
201
213
|
* Because the driver uses `IO#write_nonblock`, Windows is not supported.
|
202
214
|
|
203
|
-
Please [refer to the usage documentation for more information on common pitfalls](http://datastax.
|
215
|
+
Please [refer to the usage documentation for more information on common pitfalls](http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/features/)
|
204
216
|
|
205
217
|
## Contributing
|
206
218
|
|
@@ -230,4 +242,4 @@ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
|
230
242
|
either express or implied. See the License for the specific language governing permissions
|
231
243
|
and limitations under the License.
|
232
244
|
|
233
|
-
[1]: http://datastax.
|
245
|
+
[1]: http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/api
|
data/lib/cassandra.rb
CHANGED
@@ -66,6 +66,7 @@ module Cassandra
|
|
66
66
|
:connections_per_remote_node,
|
67
67
|
:consistency,
|
68
68
|
:credentials,
|
69
|
+
:custom_types,
|
69
70
|
:datacenter,
|
70
71
|
:futures_factory,
|
71
72
|
:heartbeat_interval,
|
@@ -187,14 +188,17 @@ module Cassandra
|
|
187
188
|
# v2 or earlier protocol.
|
188
189
|
#
|
189
190
|
# @option options [Integer] :protocol_version (nil) Version of protocol to speak to
|
190
|
-
# nodes. By default, this is auto-negotiated to the
|
191
|
+
# nodes. By default, this is auto-negotiated to the highest common protocol version
|
191
192
|
# that all nodes in `:hosts` speak.
|
192
193
|
#
|
193
|
-
# @option options [Boolean] :client_timestamps (false) whether the driver
|
194
|
-
# should send timestamps for each executed statement. Enabling this
|
195
|
-
#
|
196
|
-
#
|
197
|
-
#
|
194
|
+
# @option options [Boolean, Cassandra::TimestampGenerator] :client_timestamps (false) whether the driver
|
195
|
+
# should send timestamps for each executed statement and possibly which timestamp generator to use. Enabling this
|
196
|
+
# setting helps mitigate Cassandra cluster clock skew because the timestamp of the client machine will be used.
|
197
|
+
# This does not help mitigate application cluster clock skew. Also accepts an initialized
|
198
|
+
# {Cassandra::TimestampGenerator}, `:simple` (indicating an instance of {Cassandra::TimestampGenerator::Simple}),
|
199
|
+
# or `:monotonic` (indicating an instance of {Cassandra::TimestampGenerator::TickingOnDuplicate}). If set to true,
|
200
|
+
# it defaults to {Cassandra::TimestampGenerator::Simple} for all Ruby flavors except JRuby. On JRuby, it defaults to
|
201
|
+
# {Cassandra::TimestampGenerator::TickingOnDuplicate}.
|
198
202
|
#
|
199
203
|
# @option options [Boolean] :synchronize_schema (true) whether the driver
|
200
204
|
# should automatically keep schema metadata synchronized. When enabled, the
|
@@ -290,28 +294,7 @@ module Cassandra
|
|
290
294
|
# @return [Cassandra::Future<Cassandra::Cluster>] a future resolving to the
|
291
295
|
# cluster instance.
|
292
296
|
def self.cluster_async(options = {})
|
293
|
-
options = validate_and_massage_options(options)
|
294
|
-
hosts = []
|
295
|
-
|
296
|
-
Array(options.fetch(:hosts, '127.0.0.1')).each do |host|
|
297
|
-
case host
|
298
|
-
when ::IPAddr
|
299
|
-
hosts << host
|
300
|
-
when ::String # ip address or hostname
|
301
|
-
Resolv.each_address(host) do |ip|
|
302
|
-
hosts << ::IPAddr.new(ip)
|
303
|
-
end
|
304
|
-
else
|
305
|
-
raise ::ArgumentError, ":hosts must be String or IPAddr, #{host.inspect} given"
|
306
|
-
end
|
307
|
-
end
|
308
|
-
|
309
|
-
if hosts.empty?
|
310
|
-
raise ::ArgumentError,
|
311
|
-
":hosts #{options[:hosts].inspect} could not be resolved to any ip address"
|
312
|
-
end
|
313
|
-
|
314
|
-
hosts.shuffle!
|
297
|
+
options, hosts = validate_and_massage_options(options)
|
315
298
|
rescue => e
|
316
299
|
futures = options.fetch(:futures_factory) { return Future::Error.new(e) }
|
317
300
|
futures.error(e)
|
@@ -661,14 +644,14 @@ module Cassandra
|
|
661
644
|
|
662
645
|
case address_resolution
|
663
646
|
when :none
|
664
|
-
|
647
|
+
# do nothing
|
665
648
|
when :ec2_multi_region
|
666
649
|
options[:address_resolution_policy] =
|
667
650
|
AddressResolution::Policies::EC2MultiRegion.new
|
668
651
|
else
|
669
652
|
raise ::ArgumentError,
|
670
653
|
':address_resolution must be either :none or :ec2_multi_region, ' \
|
671
|
-
|
654
|
+
"#{address_resolution.inspect} given"
|
672
655
|
end
|
673
656
|
end
|
674
657
|
|
@@ -682,7 +665,35 @@ module Cassandra
|
|
682
665
|
end
|
683
666
|
|
684
667
|
options[:synchronize_schema] = !!options[:synchronize_schema] if options.key?(:synchronize_schema)
|
685
|
-
|
668
|
+
|
669
|
+
if options.key?(:client_timestamps)
|
670
|
+
timestamp_generator = case options[:client_timestamps]
|
671
|
+
when true
|
672
|
+
if RUBY_ENGINE == 'jruby'
|
673
|
+
Cassandra::TimestampGenerator::TickingOnDuplicate.new
|
674
|
+
else
|
675
|
+
Cassandra::TimestampGenerator::Simple.new
|
676
|
+
end
|
677
|
+
when false
|
678
|
+
nil
|
679
|
+
when :simple
|
680
|
+
Cassandra::TimestampGenerator::Simple.new
|
681
|
+
when :monotonic
|
682
|
+
Cassandra::TimestampGenerator::TickingOnDuplicate.new
|
683
|
+
else
|
684
|
+
# The value must be a generator instance.
|
685
|
+
options[:client_timestamps]
|
686
|
+
end
|
687
|
+
|
688
|
+
if timestamp_generator
|
689
|
+
Util.assert_responds_to(:next, timestamp_generator) do
|
690
|
+
":client_timestamps #{options[:client_timestamps].inspect} must be a boolean, :simple, :monotonic, or " \
|
691
|
+
'an object that responds to :next'
|
692
|
+
end
|
693
|
+
end
|
694
|
+
options.delete(:client_timestamps)
|
695
|
+
options[:timestamp_generator] = timestamp_generator
|
696
|
+
end
|
686
697
|
|
687
698
|
if options.key?(:connections_per_local_node)
|
688
699
|
connections_per_node = options[:connections_per_local_node]
|
@@ -726,7 +737,31 @@ module Cassandra
|
|
726
737
|
end
|
727
738
|
end
|
728
739
|
end
|
729
|
-
|
740
|
+
|
741
|
+
# Get host addresses.
|
742
|
+
hosts = []
|
743
|
+
|
744
|
+
Array(options.fetch(:hosts, '127.0.0.1')).each do |host|
|
745
|
+
case host
|
746
|
+
when ::IPAddr
|
747
|
+
hosts << host
|
748
|
+
when ::String # ip address or hostname
|
749
|
+
Resolv.each_address(host) do |ip|
|
750
|
+
hosts << ::IPAddr.new(ip)
|
751
|
+
end
|
752
|
+
else
|
753
|
+
raise ::ArgumentError, ":hosts must be String or IPAddr, #{host.inspect} given"
|
754
|
+
end
|
755
|
+
end
|
756
|
+
|
757
|
+
if hosts.empty?
|
758
|
+
raise ::ArgumentError,
|
759
|
+
":hosts #{options[:hosts].inspect} could not be resolved to any ip address"
|
760
|
+
end
|
761
|
+
|
762
|
+
hosts.shuffle!
|
763
|
+
|
764
|
+
[options, hosts]
|
730
765
|
end
|
731
766
|
|
732
767
|
# @private
|
@@ -767,6 +802,7 @@ require 'cassandra/null_logger'
|
|
767
802
|
require 'cassandra/executors'
|
768
803
|
require 'cassandra/future'
|
769
804
|
require 'cassandra/cluster'
|
805
|
+
require 'cassandra/custom_data'
|
770
806
|
require 'cassandra/driver'
|
771
807
|
require 'cassandra/host'
|
772
808
|
require 'cassandra/session'
|
@@ -793,12 +829,18 @@ require 'cassandra/load_balancing'
|
|
793
829
|
require 'cassandra/reconnection'
|
794
830
|
require 'cassandra/retry'
|
795
831
|
require 'cassandra/address_resolution'
|
832
|
+
require 'cassandra/timestamp_generator'
|
796
833
|
|
797
834
|
require 'cassandra/util'
|
798
835
|
|
799
836
|
# murmur3 hash extension
|
800
837
|
require 'cassandra_murmur3'
|
801
838
|
|
839
|
+
# SortedSet has a race condition where it does some class/global initialization when the first instance is created.
|
840
|
+
# If this is done in a multi-threaded environment, bad things can happen. So force the initialization here,
|
841
|
+
# when loading the C* module.
|
842
|
+
::SortedSet.new
|
843
|
+
|
802
844
|
module Cassandra
|
803
845
|
# @private
|
804
846
|
VOID_STATEMENT = Statements::Void.new
|
data/lib/cassandra/auth.rb
CHANGED
@@ -34,7 +34,7 @@ module Cassandra
|
|
34
34
|
#
|
35
35
|
# @see Cassandra::Auth::Providers
|
36
36
|
class Provider
|
37
|
-
# @!method create_authenticator(authentication_class,
|
37
|
+
# @!method create_authenticator(authentication_class, host)
|
38
38
|
#
|
39
39
|
# Create a new authenticator object. This method will be called once per
|
40
40
|
# connection that requires authentication. The auth provider can create
|
@@ -45,6 +45,8 @@ module Cassandra
|
|
45
45
|
#
|
46
46
|
# @param authentication_class [String] the authentication class used by
|
47
47
|
# the server.
|
48
|
+
# @param host [Cassandra::Host] the node to whom we're authenticating.
|
49
|
+
#
|
48
50
|
# @return [Cassandra::Auth::Authenticator, nil] an object with an
|
49
51
|
# interface matching {Cassandra::Auth::Authenticator} or `nil` if the
|
50
52
|
# authentication class is not supported.
|
data/lib/cassandra/cluster.rb
CHANGED
@@ -41,7 +41,8 @@ module Cassandra
|
|
41
41
|
retry_policy,
|
42
42
|
address_resolution_policy,
|
43
43
|
connector,
|
44
|
-
futures_factory
|
44
|
+
futures_factory,
|
45
|
+
timestamp_generator)
|
45
46
|
@logger = logger
|
46
47
|
@io_reactor = io_reactor
|
47
48
|
@executor = executor
|
@@ -57,6 +58,7 @@ module Cassandra
|
|
57
58
|
@address_resolver = address_resolution_policy
|
58
59
|
@connector = connector
|
59
60
|
@futures = futures_factory
|
61
|
+
@timestamp_generator = timestamp_generator
|
60
62
|
|
61
63
|
@control_connection.on_close do |_cause|
|
62
64
|
begin
|
@@ -204,7 +206,8 @@ module Cassandra
|
|
204
206
|
@retry_policy,
|
205
207
|
@address_resolver,
|
206
208
|
@connection_options,
|
207
|
-
@futures
|
209
|
+
@futures,
|
210
|
+
@timestamp_generator)
|
208
211
|
session = Session.new(client, @execution_options, @futures)
|
209
212
|
promise = @futures.promise
|
210
213
|
|
@@ -275,7 +278,15 @@ module Cassandra
|
|
275
278
|
|
276
279
|
# @private
|
277
280
|
def inspect
|
278
|
-
"#<#{self.class.name}:0x#{object_id.to_s(16)}
|
281
|
+
"#<#{self.class.name}:0x#{object_id.to_s(16)} " \
|
282
|
+
"name=#{name.inspect}, " \
|
283
|
+
"port=#{@connection_options.port}, " \
|
284
|
+
"protocol_version=#{@connection_options.protocol_version}, " \
|
285
|
+
"load_balancing_policy=#{@load_balancing_policy.inspect}, " \
|
286
|
+
"consistency=#{@execution_options.consistency.inspect}, " \
|
287
|
+
"timeout=#{@execution_options.timeout.inspect}, " \
|
288
|
+
"hosts=#{hosts.inspect}, " \
|
289
|
+
"keyspaces=#{keyspaces.inspect}>"
|
279
290
|
end
|
280
291
|
end
|
281
292
|
end
|
@@ -34,7 +34,8 @@ module Cassandra
|
|
34
34
|
retry_policy,
|
35
35
|
address_resolution_policy,
|
36
36
|
connection_options,
|
37
|
-
futures_factory
|
37
|
+
futures_factory,
|
38
|
+
timestamp_generator)
|
38
39
|
@logger = logger
|
39
40
|
@registry = cluster_registry
|
40
41
|
@schema = cluster_schema
|
@@ -52,6 +53,7 @@ module Cassandra
|
|
52
53
|
@pending_connections = ::Hash.new
|
53
54
|
@keyspace = nil
|
54
55
|
@state = :idle
|
56
|
+
@timestamp_generator = timestamp_generator
|
55
57
|
|
56
58
|
mon_initialize
|
57
59
|
end
|
@@ -228,11 +230,7 @@ module Cassandra
|
|
228
230
|
'Apache Cassandra'))
|
229
231
|
end
|
230
232
|
|
231
|
-
timestamp =
|
232
|
-
if @connection_options.client_timestamps? &&
|
233
|
-
@connection_options.protocol_version > 2
|
234
|
-
timestamp = ::Time.now
|
235
|
-
end
|
233
|
+
timestamp = @timestamp_generator.next if @timestamp_generator && @connection_options.protocol_version > 2
|
236
234
|
payload = nil
|
237
235
|
payload = options.payload if @connection_options.protocol_version >= 4
|
238
236
|
request = Protocol::QueryRequest.new(statement.cql,
|
@@ -286,11 +284,7 @@ module Cassandra
|
|
286
284
|
end
|
287
285
|
|
288
286
|
def execute(statement, options)
|
289
|
-
timestamp =
|
290
|
-
if @connection_options.client_timestamps? &&
|
291
|
-
@connection_options.protocol_version > 2
|
292
|
-
timestamp = ::Time.now
|
293
|
-
end
|
287
|
+
timestamp = @timestamp_generator.next if @timestamp_generator && @connection_options.protocol_version > 2
|
294
288
|
payload = nil
|
295
289
|
payload = options.payload if @connection_options.protocol_version >= 4
|
296
290
|
timeout = options.timeout
|
@@ -324,11 +318,7 @@ module Cassandra
|
|
324
318
|
'Apache Cassandra'))
|
325
319
|
end
|
326
320
|
|
327
|
-
timestamp =
|
328
|
-
if @connection_options.client_timestamps? &&
|
329
|
-
@connection_options.protocol_version > 2
|
330
|
-
timestamp = ::Time.now
|
331
|
-
end
|
321
|
+
timestamp = @timestamp_generator.next if @timestamp_generator && @connection_options.protocol_version > 2
|
332
322
|
payload = nil
|
333
323
|
payload = options.payload if @connection_options.protocol_version >= 4
|
334
324
|
timeout = options.timeout
|
@@ -644,7 +634,15 @@ module Cassandra
|
|
644
634
|
errors,
|
645
635
|
hosts)
|
646
636
|
cql = statement.cql
|
647
|
-
id
|
637
|
+
id = nil
|
638
|
+
host_is_up = true
|
639
|
+
synchronize do
|
640
|
+
if @prepared_statements[host].nil?
|
641
|
+
host_is_up = false
|
642
|
+
else
|
643
|
+
id = @prepared_statements[host][cql]
|
644
|
+
end
|
645
|
+
end
|
648
646
|
|
649
647
|
if id
|
650
648
|
request.id = id
|
@@ -659,6 +657,19 @@ module Cassandra
|
|
659
657
|
timeout,
|
660
658
|
errors,
|
661
659
|
hosts)
|
660
|
+
elsif !host_is_up
|
661
|
+
# We've hit a race condition where the plan says we can query this host, but the host has gone
|
662
|
+
# down in the mean time. Just execute the plan again on the next host.
|
663
|
+
@logger.debug("#{host} is down; executing plan on next host")
|
664
|
+
execute_by_plan(promise,
|
665
|
+
keyspace,
|
666
|
+
statement,
|
667
|
+
options,
|
668
|
+
request,
|
669
|
+
plan,
|
670
|
+
timeout,
|
671
|
+
errors,
|
672
|
+
hosts)
|
662
673
|
else
|
663
674
|
prepare = prepare_statement(host, connection, cql, timeout)
|
664
675
|
prepare.on_complete do |_|
|
@@ -816,10 +827,29 @@ module Cassandra
|
|
816
827
|
cql = statement.cql
|
817
828
|
|
818
829
|
if statement.is_a?(Statements::Bound)
|
819
|
-
|
830
|
+
host_is_up = true
|
831
|
+
id = nil
|
832
|
+
synchronize do
|
833
|
+
if @prepared_statements[host].nil?
|
834
|
+
host_is_up = false
|
835
|
+
else
|
836
|
+
id = @prepared_statements[host][cql]
|
837
|
+
end
|
838
|
+
end
|
820
839
|
|
821
840
|
if id
|
822
841
|
request.add_prepared(id, statement.params, statement.params_types)
|
842
|
+
elsif !host_is_up
|
843
|
+
@logger.debug("#{host} is down; executing on next host in plan")
|
844
|
+
return batch_by_plan(promise,
|
845
|
+
keyspace,
|
846
|
+
batch_statement,
|
847
|
+
options,
|
848
|
+
request,
|
849
|
+
plan,
|
850
|
+
timeout,
|
851
|
+
errors,
|
852
|
+
hosts)
|
823
853
|
else
|
824
854
|
unprepared[cql] << statement
|
825
855
|
end
|
@@ -1156,17 +1186,17 @@ module Cassandra
|
|
1156
1186
|
end
|
1157
1187
|
when Protocol::SetKeyspaceResultResponse
|
1158
1188
|
@keyspace = r.keyspace
|
1159
|
-
promise.fulfill(Results::Void.new(r.custom_payload,
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1189
|
+
promise.fulfill(Cassandra::Results::Void.new(r.custom_payload,
|
1190
|
+
r.warnings,
|
1191
|
+
r.trace_id,
|
1192
|
+
keyspace,
|
1193
|
+
statement,
|
1194
|
+
options,
|
1195
|
+
hosts,
|
1196
|
+
request.consistency,
|
1197
|
+
retries,
|
1198
|
+
self,
|
1199
|
+
@futures))
|
1170
1200
|
when Protocol::PreparedResultResponse
|
1171
1201
|
cql = request.cql
|
1172
1202
|
synchronize do
|
@@ -1328,7 +1358,7 @@ module Cassandra
|
|
1328
1358
|
promise.fulfill(
|
1329
1359
|
Results::Void.new(r.custom_payload,
|
1330
1360
|
r.warnings,
|
1331
|
-
|
1361
|
+
nil,
|
1332
1362
|
keyspace,
|
1333
1363
|
statement,
|
1334
1364
|
options,
|
@@ -1360,38 +1390,44 @@ module Cassandra
|
|
1360
1390
|
end
|
1361
1391
|
else
|
1362
1392
|
response_future.on_failure do |ex|
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1393
|
+
if ex.is_a?(Errors::HostError) ||
|
1394
|
+
(ex.is_a?(Errors::TimeoutError) && statement.idempotent?)
|
1395
|
+
|
1396
|
+
errors[host] = ex
|
1397
|
+
case request
|
1398
|
+
when Protocol::QueryRequest, Protocol::PrepareRequest
|
1399
|
+
send_request_by_plan(promise,
|
1400
|
+
keyspace,
|
1401
|
+
statement,
|
1402
|
+
options,
|
1403
|
+
request,
|
1404
|
+
plan,
|
1405
|
+
timeout,
|
1406
|
+
errors,
|
1407
|
+
hosts)
|
1408
|
+
when Protocol::ExecuteRequest
|
1409
|
+
execute_by_plan(promise,
|
1410
|
+
keyspace,
|
1411
|
+
statement,
|
1412
|
+
options,
|
1413
|
+
request,
|
1414
|
+
plan,
|
1415
|
+
timeout,
|
1416
|
+
errors,
|
1417
|
+
hosts)
|
1418
|
+
when Protocol::BatchRequest
|
1419
|
+
batch_by_plan(promise,
|
1420
|
+
keyspace,
|
1421
|
+
statement,
|
1422
|
+
options,
|
1423
|
+
request,
|
1424
|
+
plan,
|
1425
|
+
timeout,
|
1426
|
+
errors,
|
1427
|
+
hosts)
|
1428
|
+
else
|
1429
|
+
promise.break(ex)
|
1430
|
+
end
|
1395
1431
|
else
|
1396
1432
|
promise.break(ex)
|
1397
1433
|
end
|