cassandra-driver 3.0.0.rc.2-java → 3.0.2-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 +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
|
[](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
|