cassandra-driver 3.0.0.beta.1-java → 3.0.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +106 -39
- data/lib/cassandra.rb +396 -148
- data/lib/cassandra/address_resolution.rb +1 -1
- data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +1 -1
- data/lib/cassandra/address_resolution/policies/none.rb +1 -1
- data/lib/cassandra/aggregate.rb +21 -7
- data/lib/cassandra/argument.rb +2 -2
- data/lib/cassandra/attr_boolean.rb +33 -0
- data/lib/cassandra/auth.rb +6 -5
- data/lib/cassandra/auth/providers.rb +1 -1
- data/lib/cassandra/auth/providers/password.rb +5 -13
- data/lib/cassandra/cassandra_logger.rb +80 -0
- data/lib/cassandra/cluster.rb +49 -9
- data/lib/cassandra/cluster/client.rb +835 -209
- data/lib/cassandra/cluster/connection_pool.rb +2 -2
- data/lib/cassandra/cluster/connector.rb +86 -27
- data/lib/cassandra/cluster/control_connection.rb +222 -95
- data/lib/cassandra/cluster/failed_connection.rb +1 -1
- data/lib/cassandra/cluster/metadata.rb +14 -8
- data/lib/cassandra/cluster/options.rb +68 -22
- data/lib/cassandra/cluster/registry.rb +81 -17
- data/lib/cassandra/cluster/schema.rb +70 -8
- data/lib/cassandra/cluster/schema/cql_type_parser.rb +15 -10
- data/lib/cassandra/cluster/schema/fetchers.rb +601 -241
- data/lib/cassandra/cluster/schema/fqcn_type_parser.rb +39 -38
- data/lib/cassandra/cluster/schema/partitioners.rb +1 -1
- data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +6 -8
- data/lib/cassandra/cluster/schema/partitioners/ordered.rb +1 -1
- data/lib/cassandra/cluster/schema/partitioners/random.rb +1 -1
- data/lib/cassandra/cluster/schema/replication_strategies.rb +1 -1
- data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +19 -18
- data/lib/cassandra/cluster/schema/replication_strategies/none.rb +1 -1
- data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +1 -1
- data/lib/cassandra/column.rb +4 -23
- data/lib/cassandra/column_container.rb +322 -0
- data/lib/cassandra/compression.rb +1 -1
- data/lib/cassandra/compression/compressors/lz4.rb +7 -8
- data/lib/cassandra/compression/compressors/snappy.rb +4 -3
- data/lib/cassandra/driver.rb +107 -46
- data/lib/cassandra/errors.rb +303 -52
- data/lib/cassandra/execution/info.rb +16 -5
- data/lib/cassandra/execution/options.rb +102 -55
- data/lib/cassandra/execution/trace.rb +16 -9
- data/lib/cassandra/executors.rb +1 -1
- data/lib/cassandra/function.rb +19 -13
- data/lib/cassandra/function_collection.rb +85 -0
- data/lib/cassandra/future.rb +101 -49
- data/lib/cassandra/host.rb +25 -5
- data/lib/cassandra/index.rb +118 -0
- data/lib/cassandra/keyspace.rb +169 -33
- data/lib/cassandra/listener.rb +1 -1
- data/lib/cassandra/load_balancing.rb +2 -2
- data/lib/cassandra/load_balancing/policies.rb +1 -1
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +39 -25
- data/lib/cassandra/load_balancing/policies/round_robin.rb +8 -1
- data/lib/cassandra/load_balancing/policies/token_aware.rb +22 -13
- data/lib/cassandra/load_balancing/policies/white_list.rb +18 -5
- data/lib/cassandra/materialized_view.rb +90 -0
- data/lib/cassandra/null_logger.rb +27 -6
- data/lib/cassandra/protocol.rb +1 -1
- data/lib/cassandra/protocol/coder.rb +81 -42
- data/lib/cassandra/protocol/cql_byte_buffer.rb +58 -44
- data/lib/cassandra/protocol/cql_protocol_handler.rb +57 -54
- data/lib/cassandra/protocol/request.rb +6 -7
- data/lib/cassandra/protocol/requests/auth_response_request.rb +3 -3
- data/lib/cassandra/protocol/requests/batch_request.rb +17 -8
- data/lib/cassandra/protocol/requests/credentials_request.rb +3 -3
- data/lib/cassandra/protocol/requests/execute_request.rb +39 -20
- data/lib/cassandra/protocol/requests/options_request.rb +1 -1
- data/lib/cassandra/protocol/requests/prepare_request.rb +5 -5
- data/lib/cassandra/protocol/requests/query_request.rb +28 -23
- data/lib/cassandra/protocol/requests/register_request.rb +2 -2
- data/lib/cassandra/protocol/requests/startup_request.rb +8 -8
- data/lib/cassandra/protocol/requests/void_query_request.rb +1 -1
- data/lib/cassandra/protocol/response.rb +3 -4
- data/lib/cassandra/protocol/responses/already_exists_error_response.rb +12 -2
- data/lib/cassandra/protocol/responses/auth_challenge_response.rb +4 -5
- data/lib/cassandra/protocol/responses/auth_success_response.rb +4 -5
- data/lib/cassandra/protocol/responses/authenticate_response.rb +4 -5
- data/lib/cassandra/protocol/responses/error_response.rb +104 -17
- data/lib/cassandra/protocol/responses/event_response.rb +3 -4
- data/lib/cassandra/protocol/responses/function_failure_error_response.rb +13 -2
- data/lib/cassandra/protocol/responses/prepared_result_response.rb +14 -9
- data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +14 -9
- data/lib/cassandra/protocol/responses/read_failure_error_response.rb +26 -4
- data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +22 -3
- data/lib/cassandra/protocol/responses/ready_response.rb +6 -7
- data/lib/cassandra/protocol/responses/result_response.rb +11 -10
- data/lib/cassandra/protocol/responses/rows_result_response.rb +8 -7
- data/lib/cassandra/protocol/responses/schema_change_event_response.rb +8 -8
- data/lib/cassandra/protocol/responses/schema_change_result_response.rb +19 -13
- data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +5 -6
- data/lib/cassandra/protocol/responses/status_change_event_response.rb +5 -6
- data/lib/cassandra/protocol/responses/supported_response.rb +4 -5
- data/lib/cassandra/protocol/responses/topology_change_event_response.rb +4 -5
- data/lib/cassandra/protocol/responses/unavailable_error_response.rb +20 -3
- data/lib/cassandra/protocol/responses/unprepared_error_response.rb +11 -2
- data/lib/cassandra/protocol/responses/void_result_response.rb +4 -5
- data/lib/cassandra/protocol/responses/write_failure_error_response.rb +26 -4
- data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +22 -3
- data/lib/cassandra/protocol/v1.rb +98 -37
- data/lib/cassandra/protocol/v3.rb +121 -50
- data/lib/cassandra/protocol/v4.rb +172 -68
- data/lib/cassandra/reconnection.rb +1 -1
- data/lib/cassandra/reconnection/policies.rb +1 -1
- data/lib/cassandra/reconnection/policies/constant.rb +2 -4
- data/lib/cassandra/reconnection/policies/exponential.rb +6 -6
- data/lib/cassandra/result.rb +55 -20
- data/lib/cassandra/retry.rb +8 -8
- data/lib/cassandra/retry/policies.rb +1 -1
- data/lib/cassandra/retry/policies/default.rb +1 -1
- data/lib/cassandra/retry/policies/downgrading_consistency.rb +4 -2
- data/lib/cassandra/retry/policies/fallthrough.rb +1 -1
- data/lib/cassandra/session.rb +24 -16
- data/lib/cassandra/statement.rb +1 -1
- data/lib/cassandra/statements.rb +1 -1
- data/lib/cassandra/statements/batch.rb +16 -10
- data/lib/cassandra/statements/bound.rb +10 -3
- data/lib/cassandra/statements/prepared.rb +62 -18
- data/lib/cassandra/statements/simple.rb +23 -10
- data/lib/cassandra/statements/void.rb +1 -1
- data/lib/cassandra/table.rb +53 -185
- data/lib/cassandra/time.rb +11 -6
- data/lib/cassandra/time_uuid.rb +12 -14
- 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 +4 -4
- data/lib/cassandra/types.rb +109 -71
- data/lib/cassandra/udt.rb +66 -50
- data/lib/cassandra/util.rb +155 -15
- data/lib/cassandra/uuid.rb +20 -21
- data/lib/cassandra/uuid/generator.rb +7 -5
- data/lib/cassandra/version.rb +2 -2
- data/lib/cassandra_murmur3.jar +0 -0
- data/lib/datastax/cassandra.rb +1 -1
- metadata +27 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e54478ae2983bea8fe87b5cdb7bb4109b64a0321
|
4
|
+
data.tar.gz: 60309ae2ddd6c3adb1b78f932e6985371e1dd1da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6adf8e05498642fa68929c41e0def00dd35bda7ccdddb2caa56e4082a882ef2351fc48c1b33ee824a35f4cd9aa50a9391d40aaa73809311482bd0c352bda3d8c
|
7
|
+
data.tar.gz: 97bbc836f22e5ff90431a32ec9d0143b6c7c11d21b9610fa81018728991b55359395f095f55f826b79cd1248a73a8063173ee3541e263ead85e7460f80aa8812
|
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.github.io/ruby-driver/) or via the release tags, [e.g.
|
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.github.io/ruby-driver/) or via the release tags, [e.g. v3.0.0](https://github.com/datastax/ruby-driver/tree/v3.0.0).*
|
4
4
|
|
5
5
|
[](https://travis-ci.org/datastax/ruby-driver)
|
6
6
|
|
@@ -12,7 +12,7 @@ the Cassandra Query Language version 3 (CQL3) and Cassandra's native protocol.
|
|
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>)
|
15
|
-
- Twitter: Follow the latest news about DataStax Drivers - [@avalanche123](http://twitter.com/avalanche123), [@
|
15
|
+
- Twitter: Follow the latest news about DataStax Drivers - [@avalanche123](http://twitter.com/avalanche123), [@stamhankar999](http://twitter.com/stamhankar999), [@al3xandru](https://twitter.com/al3xandru)
|
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
|
|
@@ -27,17 +27,18 @@ This driver is based on [the cql-rb gem](https://github.com/iconara/cql-rb) by [
|
|
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
|
|
30
|
-
##
|
30
|
+
## Compatibility
|
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
|
35
|
-
* DataStax Enterprise
|
36
|
-
* Ruby (MRI)
|
34
|
+
* Apache Cassandra versions 1.2, 2.0, 2.1, 2.2, and 3.x
|
35
|
+
* DataStax Enterprise 4.0 and above.
|
36
|
+
* Ruby (MRI) 2.2, 2.3
|
37
37
|
* JRuby 1.7
|
38
|
-
* Rubinius 2.2
|
39
38
|
|
40
|
-
__Note__: JRuby 1.6 is not officially supported, although 1.6.8 should work.
|
39
|
+
__Note__: JRuby 1.6 is not officially supported, although 1.6.8 should work. Similarly,
|
40
|
+
MRI 2.0 and 2.1 are not officially supported, but they should work. 1.9.3 is deprecated
|
41
|
+
and is likely to break in the release following 3.0.
|
41
42
|
|
42
43
|
## Quick start
|
43
44
|
|
@@ -53,10 +54,10 @@ end
|
|
53
54
|
keyspace = 'system'
|
54
55
|
session = cluster.connect(keyspace) # create session, optionally scoped to a keyspace, to execute queries
|
55
56
|
|
56
|
-
future = session.execute_async('SELECT keyspace_name,
|
57
|
+
future = session.execute_async('SELECT keyspace_name, table_name FROM system_schema.tables') # fully asynchronous api
|
57
58
|
future.on_success do |rows|
|
58
59
|
rows.each do |row|
|
59
|
-
puts "The keyspace #{row['keyspace_name']} has a table called #{row['
|
60
|
+
puts "The keyspace #{row['keyspace_name']} has a table called #{row['table_name']}"
|
60
61
|
end
|
61
62
|
end
|
62
63
|
future.join
|
@@ -91,31 +92,77 @@ __Note__: if you want to use compression you should also install [snappy](http:/
|
|
91
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/master/examples/cql-rb-wrapper.rb) to assist you with gradual upgrade.
|
93
94
|
|
94
|
-
## What's new in
|
95
|
-
|
96
|
-
Features:
|
95
|
+
## What's new in v3.0.0
|
96
|
+
|
97
|
+
### Features:
|
98
|
+
|
99
|
+
* Add support for Apache Cassandra native protocol v4
|
100
|
+
* Add support for smallint, tinyint, date (`Cassandra::Date`) and time (`Cassandra::Time`) data types.
|
101
|
+
* Include schema metadata for User Defined Functions and User Defined Aggregates.
|
102
|
+
* 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.
|
103
|
+
* Include client ip addresses in request traces, only on Cassandra 3.x.
|
104
|
+
* Add new retry policy decision `Cassandra::Retry::Policy#try_next_host`.
|
105
|
+
* Support specifying statement idempotence with the new `idempotent` option when executing.
|
106
|
+
* Support sending custom payloads when preparing or executing statements using the new `payload` option.
|
107
|
+
* Expose custom payloads received with responses on server exceptions and `Cassandra::Execution::Info` instances.
|
108
|
+
* Expose server warnings on server exceptions and `Cassandra::Execution::Info` instances.
|
109
|
+
* Add `connections_per_local_node`, `connections_per_remote_node`, `requests_per_connection` cluster configuration options to tune parallel query execution and resource usage.
|
110
|
+
* Add `Cassandra::Logger` class to make it easy for users to enable debug logging in the client.
|
111
|
+
* Add `protocol_version` configuration option to allow the user to force the protocol version to use for communication with nodes.
|
112
|
+
* Add support for materialized views and indexes in the schema metadata.
|
113
|
+
* Support the `ReadError`, `WriteError`, and `FunctionCallError` Cassandra error responses introduced in Cassandra 2.2.
|
114
|
+
* Add support for unset variables in bound statements.
|
115
|
+
* Support DSE security (`DseAuthenticator`, configured for LDAP).
|
116
|
+
* Add a timeout option to `Cassandra::Future#get`.
|
117
|
+
|
118
|
+
### Breaking Changes from 2.x:
|
119
|
+
|
120
|
+
* `Cassandra::Future#join` is now an alias to Cassandra::Future#get and will raise an error if the future is resolved with one.
|
121
|
+
* Default consistency level is now LOCAL_ONE.
|
122
|
+
* Enable tcp no-delay by default.
|
123
|
+
* Unavailable errors are retried on the next host in the load balancing plan by default.
|
124
|
+
* 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.
|
125
|
+
* `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:
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
batch.add(query, ['val1', 'val2'])
|
129
|
+
# becomes
|
130
|
+
batch.add(query, arguments: ['val1', 'val2'])
|
97
131
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
*
|
132
|
+
batch.add(query, {p1: 'val1'})
|
133
|
+
# becomes
|
134
|
+
batch.add(query, arguments: {p1: 'val1'})
|
135
|
+
```
|
136
|
+
* The Datacenter-aware load balancing policy (`Cassandra::LoadBalancing::Policies::DCAwareRoundRobin`) defaults to using
|
137
|
+
nodes in the local DC only. In prior releases, the policy would fall back to remote nodes after exhausting local nodes.
|
138
|
+
Specify a positive value (or nil for unlimited) for `max_remote_hosts_to_use` when initializing the policy to allow remote node use.
|
139
|
+
* Unspecified variables in statements previously resulted in an exception. Now they are essentially ignored or treated as null.
|
103
140
|
|
104
|
-
|
141
|
+
### Bug Fixes:
|
105
142
|
|
106
|
-
*
|
143
|
+
* [[RUBY-120](https://datastax-oss.atlassian.net/browse/RUBY-120)] Tuples and UDTs can be used in sets and hash keys.
|
144
|
+
* [[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.
|
145
|
+
* [[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.
|
146
|
+
* [[RUBY-151](https://datastax-oss.atlassian.net/browse/RUBY-151)] Decode incomplete UDTs properly.
|
147
|
+
* [[RUBY-155](https://datastax-oss.atlassian.net/browse/RUBY-155)] Request timeout timer should not include request queuing time.
|
148
|
+
* [[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.
|
149
|
+
* [[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.
|
107
150
|
|
108
|
-
|
151
|
+
## Feedback Requested
|
109
152
|
|
110
|
-
* [
|
153
|
+
*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).
|
111
154
|
|
112
155
|
## Code examples
|
113
156
|
|
114
|
-
The DataStax Ruby Driver uses the awesome [Cucumber Framework](http://cukes.info/) for
|
157
|
+
The DataStax Ruby Driver uses the awesome [Cucumber Framework](http://cukes.info/) for
|
158
|
+
both end-to-end, or acceptance, testing and constructing documentation. All of the
|
159
|
+
features supported by the driver have appropriate acceptance tests with easy-to-copy code
|
160
|
+
examples in the `features/` directory.
|
115
161
|
|
116
162
|
## Running tests
|
117
163
|
|
118
|
-
If you don't feel like reading through the following instructions on how to run
|
164
|
+
If you don't feel like reading through the following instructions on how to run
|
165
|
+
ruby-driver tests, feel free to [check out .travis.yml for the entire build code](https://github.com/datastax/ruby-driver/blob/master/.travis.yml).
|
119
166
|
|
120
167
|
* Check out the driver codebase and install test dependencies:
|
121
168
|
|
@@ -127,26 +174,39 @@ bundle install --without docs
|
|
127
174
|
|
128
175
|
* [Install ccm](http://www.datastax.com/dev/blog/ccm-a-development-tool-for-creating-local-cassandra-clusters)
|
129
176
|
|
130
|
-
* Run tests:
|
177
|
+
* Run tests against different versions of Cassandra:
|
131
178
|
|
132
179
|
```bash
|
133
|
-
bundle exec cucumber # runs end-to-end tests (or bundle exec rake cucumber)
|
134
|
-
bundle exec rspec # runs unit tests (or bundle exec rake rspec)
|
135
|
-
bundle exec rake integration # run integration tests
|
136
|
-
bundle exec rake test # run both as well as integration tests
|
180
|
+
CASSANDRA_VERSION=3.1.1 bundle exec cucumber # runs end-to-end tests (or bundle exec rake cucumber)
|
181
|
+
CASSANDRA_VERSION=3.0.0 bundle exec rspec # runs unit tests (or bundle exec rake rspec)
|
182
|
+
CASSANDRA_VERSION=2.1.12 bundle exec rake integration # run integration tests
|
183
|
+
CASSANDRA_VERSION=2.0.17 bundle exec rake test # run both as well as integration tests
|
137
184
|
```
|
138
185
|
|
139
186
|
## Changelog & versioning
|
140
187
|
|
141
|
-
Check out the [releases on GitHub](https://github.com/datastax/ruby-driver/releases) and
|
188
|
+
Check out the [releases on GitHub](https://github.com/datastax/ruby-driver/releases) and
|
189
|
+
[changelog](https://github.com/datastax/ruby-driver/blob/master/CHANGELOG.md). Version
|
190
|
+
numbering follows the [semantic versioning](http://semver.org/) scheme.
|
142
191
|
|
143
|
-
Private and experimental APIs, defined as whatever is not in the
|
192
|
+
Private and experimental APIs, defined as whatever is not in the
|
193
|
+
[public API documentation][1], i.e. classes and methods marked as `@private`, will change
|
194
|
+
without warning. If you've been recommended to try an experimental API by the maintainers,
|
195
|
+
please let them know if you depend on that API. Experimental APIs will eventually become
|
196
|
+
public, and knowing how they are used helps in determining their maturity.
|
144
197
|
|
145
|
-
Prereleases will be stable, in the sense that they will have finished and properly tested
|
198
|
+
Prereleases will be stable, in the sense that they will have finished and properly tested
|
199
|
+
features only, but may introduce APIs that will change before the final release. Please
|
200
|
+
use the prereleases and report bugs, but don't deploy them to production without
|
201
|
+
consulting the maintainers, or doing extensive testing yourself. If you do deploy to
|
202
|
+
production please let the maintainers know as this helps in determining the maturity of
|
203
|
+
the release.
|
146
204
|
|
147
205
|
## Known bugs & limitations
|
148
206
|
|
149
|
-
*
|
207
|
+
* Specifying a `protocol_version` option of 1 or 2 in cluster options will fail with a
|
208
|
+
`NoHostsAvailable` error rather than a `ProtocolError` against Cassandra node versions 3.0-3.4.
|
209
|
+
* JRuby 1.6 is not officially supported, although 1.6.8 should work.
|
150
210
|
* Because the driver reactor is using `IO.select`, the maximum number of tcp connections allowed is 1024.
|
151
211
|
* Because the driver uses `IO#write_nonblock`, Windows is not supported.
|
152
212
|
|
@@ -158,19 +218,26 @@ For contributing read [CONTRIBUTING.md](https://github.com/datastax/ruby-driver/
|
|
158
218
|
|
159
219
|
## Credits
|
160
220
|
|
161
|
-
This driver is based on the original work of [Theo Hultberg](https://github.com/iconara)
|
162
|
-
|
163
|
-
|
221
|
+
This driver is based on the original work of [Theo Hultberg](https://github.com/iconara)
|
222
|
+
on [cql-rb](https://github.com/iconara/cql-rb/) and adds a series of advanced features
|
223
|
+
that are common across all other DataStax drivers for Apache Cassandra.
|
164
224
|
|
225
|
+
The development effort to provide an up to date, high performance, fully featured Ruby
|
226
|
+
Driver for Apache Cassandra will continue on this project, while
|
227
|
+
[cql-rb](https://github.com/iconara/cql-rb/) will be discontinued.
|
165
228
|
|
166
229
|
## Copyright
|
167
230
|
|
168
|
-
Copyright 2013-
|
231
|
+
Copyright 2013-2016 DataStax, Inc.
|
169
232
|
|
170
|
-
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
233
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
234
|
+
except in compliance with the License. You may obtain a copy of the License at
|
171
235
|
|
172
236
|
[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
173
237
|
|
174
|
-
Unless required by applicable law or agreed to in writing, software distributed under the
|
238
|
+
Unless required by applicable law or agreed to in writing, software distributed under the
|
239
|
+
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
240
|
+
either express or implied. See the License for the specific language governing permissions
|
241
|
+
and limitations under the License.
|
175
242
|
|
176
243
|
[1]: http://datastax.github.io/ruby-driver/api
|
data/lib/cassandra.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright 2013-
|
4
|
+
# Copyright 2013-2016 DataStax, Inc.
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -16,7 +16,6 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#++
|
18
18
|
|
19
|
-
|
20
19
|
require 'ione'
|
21
20
|
require 'json'
|
22
21
|
|
@@ -35,11 +34,13 @@ require 'date'
|
|
35
34
|
|
36
35
|
module Cassandra
|
37
36
|
# A list of all supported request consistencies
|
38
|
-
# @see http://www.datastax.com/documentation/cassandra/2.0/cassandra/dml/dml_config_consistency_c.html Consistency
|
39
|
-
#
|
37
|
+
# @see http://www.datastax.com/documentation/cassandra/2.0/cassandra/dml/dml_config_consistency_c.html Consistency
|
38
|
+
# levels in Apache Cassandra 2.0
|
39
|
+
# @see http://www.datastax.com/documentation/cassandra/1.2/cassandra/dml/dml_config_consistency_c.html Consistency
|
40
|
+
# levels in Apache Cassandra 1.2
|
40
41
|
# @see Cassandra::Session#execute_async
|
41
|
-
CONSISTENCIES = [
|
42
|
-
|
42
|
+
CONSISTENCIES = [:any, :one, :two, :three, :quorum, :all, :local_quorum,
|
43
|
+
:each_quorum, :serial, :local_serial, :local_one].freeze
|
43
44
|
|
44
45
|
# A list of all supported serial consistencies
|
45
46
|
# @see Cassandra::Session#execute_async
|
@@ -48,9 +49,52 @@ module Cassandra
|
|
48
49
|
# A list of all possible write types that a
|
49
50
|
# {Cassandra::Errors::WriteTimeoutError} can have.
|
50
51
|
#
|
51
|
-
# @see https://github.com/apache/cassandra/blob/cassandra-2.0.16/doc/native_protocol_v2.spec#L872-L887 Description of
|
52
|
+
# @see https://github.com/apache/cassandra/blob/cassandra-2.0.16/doc/native_protocol_v2.spec#L872-L887 Description of
|
53
|
+
# possible types of writes in Apache Cassandra native protocol spec v1
|
52
54
|
WRITE_TYPES = [:simple, :batch, :unlogged_batch, :counter, :batch_log].freeze
|
53
55
|
|
56
|
+
CLUSTER_OPTIONS = [
|
57
|
+
:address_resolution,
|
58
|
+
:address_resolution_policy,
|
59
|
+
:auth_provider,
|
60
|
+
:client_cert,
|
61
|
+
:client_timestamps,
|
62
|
+
:compression,
|
63
|
+
:compressor,
|
64
|
+
:connect_timeout,
|
65
|
+
:connections_per_local_node,
|
66
|
+
:connections_per_remote_node,
|
67
|
+
:consistency,
|
68
|
+
:credentials,
|
69
|
+
:datacenter,
|
70
|
+
:futures_factory,
|
71
|
+
:heartbeat_interval,
|
72
|
+
:hosts,
|
73
|
+
:idle_timeout,
|
74
|
+
:listeners,
|
75
|
+
:load_balancing_policy,
|
76
|
+
:logger,
|
77
|
+
:nodelay,
|
78
|
+
:reconnection_policy,
|
79
|
+
:retry_policy,
|
80
|
+
:page_size,
|
81
|
+
:passphrase,
|
82
|
+
:password,
|
83
|
+
:port,
|
84
|
+
:private_key,
|
85
|
+
:protocol_version,
|
86
|
+
:requests_per_connection,
|
87
|
+
:schema_refresh_delay,
|
88
|
+
:schema_refresh_timeout,
|
89
|
+
:server_cert,
|
90
|
+
:shuffle_replicas,
|
91
|
+
:ssl,
|
92
|
+
:synchronize_schema,
|
93
|
+
:timeout,
|
94
|
+
:trace,
|
95
|
+
:username
|
96
|
+
].freeze
|
97
|
+
|
54
98
|
# Creates a {Cassandra::Cluster Cluster instance}.
|
55
99
|
#
|
56
100
|
# @option options [Array<String, IPAddr>] :hosts (['127.0.0.1']) a list of
|
@@ -126,11 +170,34 @@ module Cassandra
|
|
126
170
|
# address resolver to use. Must be one of `:none` or
|
127
171
|
# `:ec2_multi_region`.
|
128
172
|
#
|
129
|
-
# @option options [
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
173
|
+
# @option options [Integer] :connections_per_local_node (nil) Number of connections to
|
174
|
+
# open to each local node; the value of this option directly correlates to the number
|
175
|
+
# of requests the client can make to the local node concurrently. When `nil`, the
|
176
|
+
# setting is `1` for nodes that use the v3 or later protocol, and `2` for nodes that
|
177
|
+
# use the v2 or earlier protocol.
|
178
|
+
#
|
179
|
+
# @option options [Integer] :connections_per_remote_node (1) Number of connections to
|
180
|
+
# open to each remote node; the value of this option directly correlates to the
|
181
|
+
# number of requests the client can make to the remote node concurrently.
|
182
|
+
#
|
183
|
+
# @option options [Integer] :requests_per_connection (nil) Number of outstanding
|
184
|
+
# requests to support on one connection. Depending on the types of requests, some may
|
185
|
+
# get processed in parallel in the Cassandra node. When `nil`, the setting is `1024`
|
186
|
+
# for nodes that use the v3 or later protocol, and `128` for nodes that use the
|
187
|
+
# v2 or earlier protocol.
|
188
|
+
#
|
189
|
+
# @option options [Integer] :protocol_version (nil) Version of protocol to speak to
|
190
|
+
# nodes. By default, this is auto-negotiated to the highest common protocol version
|
191
|
+
# that all nodes in `:hosts` speak.
|
192
|
+
#
|
193
|
+
# @option options [Boolean, Cassandra::TimestampGenerator] :client_timestamps (false) whether the driver
|
194
|
+
# should send timestamps for each executed statement and possibly which timestamp generator to use. Enabling this
|
195
|
+
# setting helps mitigate Cassandra cluster clock skew because the timestamp of the client machine will be used.
|
196
|
+
# This does not help mitigate application cluster clock skew. Also accepts an initialized
|
197
|
+
# {Cassandra::TimestampGenerator}, `:simple` (indicating an instance of {Cassandra::TimestampGenerator::Simple}),
|
198
|
+
# or `:monotonic` (indicating an instance of {Cassandra::TimestampGenerator::TickingOnDuplicate}). If set to true,
|
199
|
+
# it defaults to {Cassandra::TimestampGenerator::Simple} for all Ruby flavors except JRuby. On JRuby, it defaults to
|
200
|
+
# {Cassandra::TimestampGenerator::TickingOnDuplicate}.
|
134
201
|
#
|
135
202
|
# @option options [Boolean] :synchronize_schema (true) whether the driver
|
136
203
|
# should automatically keep schema metadata synchronized. When enabled, the
|
@@ -139,7 +206,8 @@ module Cassandra
|
|
139
206
|
# automatic schema updates. Schema metadata is used by the driver to
|
140
207
|
# determine cluster partitioners as well as to find partition keys and
|
141
208
|
# replicas of prepared statements, this information makes token aware load
|
142
|
-
# balancing possible. One can still
|
209
|
+
# balancing possible. One can still
|
210
|
+
# {Cassandra::Cluster#refresh_schema refresh schema manually}.
|
143
211
|
#
|
144
212
|
# @option options [Numeric] :schema_refresh_delay (1) the driver will wait
|
145
213
|
# for `:schema_refresh_delay` before fetching metadata after receiving a
|
@@ -177,9 +245,15 @@ module Cassandra
|
|
177
245
|
# @option options [Integer] :page_size (10000) default page size for all
|
178
246
|
# select queries. Set this value to `nil` to disable paging.
|
179
247
|
#
|
180
|
-
# @option options [Hash{String => String}] :credentials (none) a hash of credentials -
|
248
|
+
# @option options [Hash{String => String}] :credentials (none) a hash of credentials -
|
249
|
+
# to be used with [credentials authentication in cassandra 1.2](https://github.com/apache/cassandra/blob/cassandra-2.0.16/doc/native_protocol_v1.spec#L238-L250).
|
250
|
+
# Note that if you specified `:username` and `:password` options, those credentials
|
251
|
+
# are configured automatically.
|
181
252
|
#
|
182
|
-
# @option options [Cassandra::Auth::Provider] :auth_provider (none) a custom auth
|
253
|
+
# @option options [Cassandra::Auth::Provider] :auth_provider (none) a custom auth
|
254
|
+
# provider to be used with [SASL authentication in cassandra 2.0](https://github.com/apache/cassandra/blob/cassandra-2.0.16/doc/native_protocol_v2.spec#L257-L273).
|
255
|
+
# Note that if you have specified `:username` and `:password`, then a
|
256
|
+
# {Cassandra::Auth::Providers::Password Password Provider} will be used automatically.
|
183
257
|
#
|
184
258
|
# @option options [Cassandra::Compression::Compressor] :compressor (none) a
|
185
259
|
# custom compressor. Note that if you have specified `:compression`, an
|
@@ -187,8 +261,8 @@ module Cassandra
|
|
187
261
|
#
|
188
262
|
# @option options [Cassandra::AddressResolution::Policy]
|
189
263
|
# :address_resolution_policy default:
|
190
|
-
# {Cassandra::AddressResolution::Policies::None No Resolution Policy} a custom address
|
191
|
-
# policy. Note that if you have specified `:address_resolution`, an
|
264
|
+
# {Cassandra::AddressResolution::Policies::None No Resolution Policy} a custom address
|
265
|
+
# resolution policy. Note that if you have specified `:address_resolution`, an
|
192
266
|
# appropriate address resolution policy will be provided automatically.
|
193
267
|
#
|
194
268
|
# @option options [Object<#all, #error, #value, #promise>] :futures_factory
|
@@ -219,78 +293,140 @@ module Cassandra
|
|
219
293
|
# @return [Cassandra::Future<Cassandra::Cluster>] a future resolving to the
|
220
294
|
# cluster instance.
|
221
295
|
def self.cluster_async(options = {})
|
222
|
-
options = options
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
296
|
+
options = validate_and_massage_options(options)
|
297
|
+
hosts = []
|
298
|
+
|
299
|
+
Array(options.fetch(:hosts, '127.0.0.1')).each do |host|
|
300
|
+
case host
|
301
|
+
when ::IPAddr
|
302
|
+
hosts << host
|
303
|
+
when ::String # ip address or hostname
|
304
|
+
Resolv.each_address(host) do |ip|
|
305
|
+
hosts << ::IPAddr.new(ip)
|
306
|
+
end
|
307
|
+
else
|
308
|
+
raise ::ArgumentError, ":hosts must be String or IPAddr, #{host.inspect} given"
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
if hosts.empty?
|
313
|
+
raise ::ArgumentError,
|
314
|
+
":hosts #{options[:hosts].inspect} could not be resolved to any ip address"
|
315
|
+
end
|
316
|
+
|
317
|
+
hosts.shuffle!
|
318
|
+
rescue => e
|
319
|
+
futures = options.fetch(:futures_factory) { return Future::Error.new(e) }
|
320
|
+
futures.error(e)
|
321
|
+
else
|
322
|
+
driver = Driver.new(options)
|
323
|
+
driver.connect(hosts)
|
324
|
+
end
|
325
|
+
|
326
|
+
# @private
|
327
|
+
SSL_CLASSES = [::TrueClass, ::FalseClass, ::OpenSSL::SSL::SSLContext].freeze
|
328
|
+
|
329
|
+
# rubocop:disable Metrics/AbcSize
|
330
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
331
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
332
|
+
# @private
|
333
|
+
def self.validate_and_massage_options(options)
|
334
|
+
options = options.select do |key, _|
|
335
|
+
CLUSTER_OPTIONS.include?(key)
|
336
|
+
end
|
337
|
+
|
338
|
+
has_username = options.key?(:username)
|
339
|
+
has_password = options.key?(:password)
|
236
340
|
if has_username || has_password
|
237
341
|
if has_username && !has_password
|
238
|
-
raise ::ArgumentError,
|
342
|
+
raise ::ArgumentError,
|
343
|
+
'both :username and :password options must be specified, ' \
|
344
|
+
'but only :username given'
|
239
345
|
end
|
240
346
|
|
241
347
|
if !has_username && has_password
|
242
|
-
raise ::ArgumentError,
|
348
|
+
raise ::ArgumentError,
|
349
|
+
'both :username and :password options must be specified, ' \
|
350
|
+
'but only :password given'
|
243
351
|
end
|
244
352
|
|
245
353
|
username = options.delete(:username)
|
246
354
|
password = options.delete(:password)
|
247
355
|
|
248
|
-
Util.assert_instance_of(::String, username)
|
249
|
-
|
250
|
-
|
251
|
-
Util.
|
356
|
+
Util.assert_instance_of(::String, username) do
|
357
|
+
":username must be a String, #{username.inspect} given"
|
358
|
+
end
|
359
|
+
Util.assert_instance_of(::String, password) do
|
360
|
+
":password must be a String, #{password.inspect} given"
|
361
|
+
end
|
362
|
+
Util.assert_not_empty(username) { ':username cannot be empty' }
|
363
|
+
Util.assert_not_empty(password) { ':password cannot be empty' }
|
252
364
|
|
253
|
-
options[:credentials] = {:
|
365
|
+
options[:credentials] = {username: username, password: password}
|
254
366
|
options[:auth_provider] = Auth::Providers::Password.new(username, password)
|
255
367
|
end
|
256
368
|
|
257
|
-
if options.
|
369
|
+
if options.key?(:credentials)
|
258
370
|
credentials = options[:credentials]
|
259
371
|
|
260
|
-
Util.assert_instance_of(::Hash, credentials)
|
372
|
+
Util.assert_instance_of(::Hash, credentials) do
|
373
|
+
":credentials must be a hash, #{credentials.inspect} given"
|
374
|
+
end
|
261
375
|
end
|
262
376
|
|
263
|
-
if options.
|
377
|
+
if options.key?(:auth_provider)
|
264
378
|
auth_provider = options[:auth_provider]
|
265
379
|
|
266
|
-
Util.assert_responds_to(:create_authenticator, auth_provider)
|
380
|
+
Util.assert_responds_to(:create_authenticator, auth_provider) do
|
381
|
+
":auth_provider #{auth_provider.inspect} must respond to " \
|
382
|
+
":create_authenticator, but doesn't"
|
383
|
+
end
|
267
384
|
end
|
268
385
|
|
269
|
-
has_client_cert = options.
|
270
|
-
has_private_key = options.
|
386
|
+
has_client_cert = options.key?(:client_cert)
|
387
|
+
has_private_key = options.key?(:private_key)
|
271
388
|
|
272
389
|
if has_client_cert || has_private_key
|
273
390
|
if has_client_cert && !has_private_key
|
274
|
-
raise ::ArgumentError,
|
391
|
+
raise ::ArgumentError,
|
392
|
+
'both :client_cert and :private_key options must be specified, ' \
|
393
|
+
'but only :client_cert given'
|
275
394
|
end
|
276
395
|
|
277
396
|
if !has_client_cert && has_private_key
|
278
|
-
raise ::ArgumentError,
|
397
|
+
raise ::ArgumentError,
|
398
|
+
'both :client_cert and :private_key options must be specified, ' \
|
399
|
+
'but only :private_key given'
|
279
400
|
end
|
280
401
|
|
402
|
+
Util.assert_instance_of(::String, options[:client_cert]) do
|
403
|
+
":client_cert must be a string, #{options[:client_cert].inspect} given"
|
404
|
+
end
|
405
|
+
Util.assert_instance_of(::String, options[:private_key]) do
|
406
|
+
":client_cert must be a string, #{options[:private_key].inspect} given"
|
407
|
+
end
|
281
408
|
client_cert = ::File.expand_path(options[:client_cert])
|
282
409
|
private_key = ::File.expand_path(options[:private_key])
|
283
410
|
|
284
|
-
Util.assert_file_exists(client_cert)
|
285
|
-
|
411
|
+
Util.assert_file_exists(client_cert) do
|
412
|
+
":client_cert #{client_cert.inspect} doesn't exist"
|
413
|
+
end
|
414
|
+
Util.assert_file_exists(private_key) do
|
415
|
+
":private_key #{private_key.inspect} doesn't exist"
|
416
|
+
end
|
286
417
|
end
|
287
418
|
|
288
|
-
has_server_cert = options.
|
419
|
+
has_server_cert = options.key?(:server_cert)
|
289
420
|
|
290
421
|
if has_server_cert
|
422
|
+
Util.assert_instance_of(::String, options[:server_cert]) do
|
423
|
+
":server_cert must be a string, #{options[:server_cert].inspect} given"
|
424
|
+
end
|
291
425
|
server_cert = ::File.expand_path(options[:server_cert])
|
292
426
|
|
293
|
-
Util.assert_file_exists(server_cert)
|
427
|
+
Util.assert_file_exists(server_cert) do
|
428
|
+
":server_cert #{server_cert.inspect} doesn't exist"
|
429
|
+
end
|
294
430
|
end
|
295
431
|
|
296
432
|
if has_client_cert || has_server_cert
|
@@ -304,23 +440,26 @@ module Cassandra
|
|
304
440
|
if has_client_cert
|
305
441
|
context.cert = ::OpenSSL::X509::Certificate.new(File.read(client_cert))
|
306
442
|
|
307
|
-
if options.
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
443
|
+
context.key = if options.key?(:passphrase)
|
444
|
+
::OpenSSL::PKey::RSA.new(File.read(private_key),
|
445
|
+
options[:passphrase])
|
446
|
+
else
|
447
|
+
::OpenSSL::PKey::RSA.new(File.read(private_key))
|
448
|
+
end
|
312
449
|
end
|
313
450
|
|
314
451
|
options[:ssl] = context
|
315
452
|
end
|
316
453
|
|
317
|
-
if options.
|
454
|
+
if options.key?(:ssl)
|
318
455
|
ssl = options[:ssl]
|
319
456
|
|
320
|
-
Util.assert_instance_of_one_of(
|
457
|
+
Util.assert_instance_of_one_of(SSL_CLASSES, ssl) do
|
458
|
+
":ssl must be a boolean or an OpenSSL::SSL::SSLContext, #{ssl.inspect} given"
|
459
|
+
end
|
321
460
|
end
|
322
461
|
|
323
|
-
if options.
|
462
|
+
if options.key?(:compression)
|
324
463
|
compression = options.delete(:compression)
|
325
464
|
|
326
465
|
case compression
|
@@ -329,195 +468,296 @@ module Cassandra
|
|
329
468
|
when :lz4
|
330
469
|
options[:compressor] = Compression::Compressors::Lz4.new
|
331
470
|
else
|
332
|
-
raise ::ArgumentError,
|
471
|
+
raise ::ArgumentError,
|
472
|
+
":compression must be either :snappy or :lz4, #{compression.inspect} given"
|
333
473
|
end
|
334
474
|
end
|
335
475
|
|
336
|
-
if options.
|
476
|
+
if options.key?(:compressor)
|
337
477
|
compressor = options[:compressor]
|
338
478
|
methods = [:algorithm, :compress?, :compress, :decompress]
|
339
479
|
|
340
|
-
Util.assert_responds_to_all(methods, compressor)
|
480
|
+
Util.assert_responds_to_all(methods, compressor) do
|
481
|
+
":compressor #{compressor.inspect} must respond to #{methods.inspect}, " \
|
482
|
+
"but doesn't"
|
483
|
+
end
|
341
484
|
end
|
342
485
|
|
343
|
-
if options.
|
344
|
-
|
345
|
-
|
486
|
+
if options.key?(:logger)
|
487
|
+
if options[:logger].nil?
|
488
|
+
# Delete the key because we want to fallback to the default logger in Driver.
|
489
|
+
options.delete(:logger)
|
490
|
+
else
|
491
|
+
# Validate
|
492
|
+
logger = options[:logger]
|
493
|
+
methods = [:debug, :info, :warn, :error, :fatal]
|
346
494
|
|
347
|
-
|
495
|
+
Util.assert_responds_to_all(methods, logger) do
|
496
|
+
":logger #{logger.inspect} must respond to #{methods.inspect}, but doesn't"
|
497
|
+
end
|
498
|
+
end
|
348
499
|
end
|
349
500
|
|
350
|
-
if options.
|
351
|
-
|
352
|
-
|
353
|
-
|
501
|
+
if options.key?(:port)
|
502
|
+
unless options[:port].nil?
|
503
|
+
port = options[:port]
|
504
|
+
Util.assert_instance_of(::Integer, port)
|
505
|
+
Util.assert_one_of(1...2**16, port) do
|
506
|
+
":port must be a valid ip port, #{port} given"
|
507
|
+
end
|
508
|
+
end
|
354
509
|
end
|
355
510
|
|
356
|
-
if options.
|
357
|
-
options[:datacenter] = String(options[:datacenter])
|
358
|
-
end
|
511
|
+
options[:datacenter] = String(options[:datacenter]) if options.key?(:datacenter)
|
359
512
|
|
360
|
-
if options.
|
513
|
+
if options.key?(:connect_timeout)
|
361
514
|
timeout = options[:connect_timeout]
|
362
515
|
|
363
516
|
unless timeout.nil?
|
364
|
-
Util.assert_instance_of(::Numeric, timeout)
|
365
|
-
|
517
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
518
|
+
":connect_timeout must be a number of seconds, #{timeout.inspect} given"
|
519
|
+
end
|
520
|
+
Util.assert(timeout > 0) do
|
521
|
+
":connect_timeout must be greater than 0, #{timeout} given"
|
522
|
+
end
|
366
523
|
end
|
367
524
|
end
|
368
525
|
|
369
|
-
if options.
|
526
|
+
if options.key?(:timeout)
|
370
527
|
timeout = options[:timeout]
|
371
528
|
|
372
529
|
unless timeout.nil?
|
373
|
-
Util.assert_instance_of(::Numeric, timeout)
|
530
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
531
|
+
":timeout must be a number of seconds, #{timeout.inspect} given"
|
532
|
+
end
|
374
533
|
Util.assert(timeout > 0) { ":timeout must be greater than 0, #{timeout} given" }
|
375
534
|
end
|
376
535
|
end
|
377
536
|
|
378
|
-
if options.
|
537
|
+
if options.key?(:heartbeat_interval)
|
379
538
|
timeout = options[:heartbeat_interval]
|
380
539
|
|
381
540
|
unless timeout.nil?
|
382
|
-
Util.assert_instance_of(::Numeric, timeout)
|
383
|
-
|
541
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
542
|
+
":heartbeat_interval must be a number of seconds, #{timeout.inspect} given"
|
543
|
+
end
|
544
|
+
Util.assert(timeout > 0) do
|
545
|
+
":heartbeat_interval must be greater than 0, #{timeout} given"
|
546
|
+
end
|
384
547
|
end
|
385
548
|
end
|
386
549
|
|
387
|
-
if options.
|
550
|
+
if options.key?(:idle_timeout)
|
388
551
|
timeout = options[:idle_timeout]
|
389
552
|
|
390
553
|
unless timeout.nil?
|
391
|
-
Util.assert_instance_of(::Numeric, timeout)
|
392
|
-
|
554
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
555
|
+
":idle_timeout must be a number of seconds, #{timeout.inspect} given"
|
556
|
+
end
|
557
|
+
Util.assert(timeout > 0) do
|
558
|
+
":idle_timeout must be greater than 0, #{timeout} given"
|
559
|
+
end
|
393
560
|
end
|
394
561
|
end
|
395
562
|
|
396
|
-
if options.
|
563
|
+
if options.key?(:schema_refresh_delay)
|
397
564
|
timeout = options[:schema_refresh_delay]
|
398
565
|
|
399
|
-
Util.assert_instance_of(::Numeric, timeout)
|
400
|
-
|
566
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
567
|
+
":schema_refresh_delay must be a number of seconds, #{timeout.inspect} given"
|
568
|
+
end
|
569
|
+
Util.assert(timeout > 0) do
|
570
|
+
":schema_refresh_delay must be greater than 0, #{timeout} given"
|
571
|
+
end
|
401
572
|
end
|
402
573
|
|
403
|
-
if options.
|
574
|
+
if options.key?(:schema_refresh_timeout)
|
404
575
|
timeout = options[:schema_refresh_timeout]
|
405
576
|
|
406
|
-
Util.assert_instance_of(::Numeric, timeout)
|
407
|
-
|
577
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
578
|
+
":schema_refresh_timeout must be a number of seconds, #{timeout.inspect} given"
|
579
|
+
end
|
580
|
+
Util.assert(timeout > 0) do
|
581
|
+
":schema_refresh_timeout must be greater than 0, #{timeout} given"
|
582
|
+
end
|
408
583
|
end
|
409
584
|
|
410
|
-
if options.
|
585
|
+
if options.key?(:load_balancing_policy)
|
411
586
|
load_balancing_policy = options[:load_balancing_policy]
|
412
|
-
methods = [:host_up, :host_down, :host_found, :host_lost, :setup, :teardown,
|
587
|
+
methods = [:host_up, :host_down, :host_found, :host_lost, :setup, :teardown,
|
588
|
+
:distance, :plan]
|
413
589
|
|
414
|
-
Util.assert_responds_to_all(methods, load_balancing_policy)
|
590
|
+
Util.assert_responds_to_all(methods, load_balancing_policy) do
|
591
|
+
":load_balancing_policy #{load_balancing_policy.inspect} must respond " \
|
592
|
+
"to #{methods.inspect}, but doesn't"
|
593
|
+
end
|
415
594
|
end
|
416
595
|
|
417
|
-
if options.
|
596
|
+
if options.key?(:reconnection_policy)
|
418
597
|
reconnection_policy = options[:reconnection_policy]
|
419
598
|
|
420
|
-
Util.assert_responds_to(:schedule, reconnection_policy)
|
599
|
+
Util.assert_responds_to(:schedule, reconnection_policy) do
|
600
|
+
":reconnection_policy #{reconnection_policy.inspect} must respond to " \
|
601
|
+
":schedule, but doesn't"
|
602
|
+
end
|
421
603
|
end
|
422
604
|
|
423
|
-
if options.
|
605
|
+
if options.key?(:retry_policy)
|
424
606
|
retry_policy = options[:retry_policy]
|
425
607
|
methods = [:read_timeout, :write_timeout, :unavailable]
|
426
608
|
|
427
|
-
Util.assert_responds_to_all(methods, retry_policy)
|
609
|
+
Util.assert_responds_to_all(methods, retry_policy) do
|
610
|
+
":retry_policy #{retry_policy.inspect} must respond to #{methods.inspect}, " \
|
611
|
+
"but doesn't"
|
612
|
+
end
|
428
613
|
end
|
429
614
|
|
430
|
-
if options.
|
431
|
-
options[:listeners] = Array(options[:listeners])
|
432
|
-
end
|
615
|
+
options[:listeners] = Array(options[:listeners]) if options.key?(:listeners)
|
433
616
|
|
434
|
-
if options.
|
617
|
+
if options.key?(:consistency)
|
435
618
|
consistency = options[:consistency]
|
436
619
|
|
437
|
-
Util.assert_one_of(CONSISTENCIES, consistency)
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
options[:nodelay] = !!options[:nodelay]
|
620
|
+
Util.assert_one_of(CONSISTENCIES, consistency) do
|
621
|
+
":consistency must be one of #{CONSISTENCIES.inspect}, " \
|
622
|
+
"#{consistency.inspect} given"
|
623
|
+
end
|
442
624
|
end
|
443
625
|
|
444
|
-
if options.
|
445
|
-
|
446
|
-
|
626
|
+
options[:nodelay] = !!options[:nodelay] if options.key?(:nodelay)
|
627
|
+
options[:trace] = !!options[:trace] if options.key?(:trace)
|
628
|
+
options[:shuffle_replicas] = !!options[:shuffle_replicas] if options.key?(:shuffle_replicas)
|
447
629
|
|
448
|
-
if options.
|
449
|
-
options[:shuffle_replicas] = !!options[:shuffle_replicas]
|
450
|
-
end
|
451
|
-
|
452
|
-
if options.has_key?(:page_size)
|
630
|
+
if options.key?(:page_size)
|
453
631
|
page_size = options[:page_size]
|
454
632
|
|
455
633
|
unless page_size.nil?
|
456
|
-
page_size = options[:page_size]
|
457
|
-
Util.
|
634
|
+
page_size = options[:page_size]
|
635
|
+
Util.assert_instance_of(::Integer, page_size)
|
636
|
+
Util.assert_one_of(1...2**32, page_size) do
|
637
|
+
":page_size must be a positive integer, #{page_size.inspect} given"
|
638
|
+
end
|
639
|
+
end
|
640
|
+
end
|
641
|
+
|
642
|
+
if options.key?(:protocol_version)
|
643
|
+
protocol_version = options[:protocol_version]
|
644
|
+
unless protocol_version.nil?
|
645
|
+
Util.assert_instance_of(::Integer, protocol_version)
|
646
|
+
Util.assert_one_of(1..4, protocol_version) do
|
647
|
+
":protocol_version must be a positive integer, #{protocol_version.inspect} given"
|
648
|
+
end
|
458
649
|
end
|
459
650
|
end
|
460
651
|
|
461
|
-
if options.
|
652
|
+
if options.key?(:futures_factory)
|
462
653
|
futures_factory = options[:futures_factory]
|
463
654
|
methods = [:error, :value, :promise, :all]
|
464
655
|
|
465
|
-
Util.assert_responds_to_all(methods, futures_factory)
|
656
|
+
Util.assert_responds_to_all(methods, futures_factory) do
|
657
|
+
":futures_factory #{futures_factory.inspect} must respond to " \
|
658
|
+
"#{methods.inspect}, but doesn't"
|
659
|
+
end
|
466
660
|
end
|
467
661
|
|
468
|
-
if options.
|
662
|
+
if options.key?(:address_resolution)
|
469
663
|
address_resolution = options.delete(:address_resolution)
|
470
664
|
|
471
665
|
case address_resolution
|
472
666
|
when :none
|
473
667
|
# do nothing
|
474
668
|
when :ec2_multi_region
|
475
|
-
options[:address_resolution_policy] =
|
669
|
+
options[:address_resolution_policy] =
|
670
|
+
AddressResolution::Policies::EC2MultiRegion.new
|
476
671
|
else
|
477
|
-
raise ::ArgumentError,
|
672
|
+
raise ::ArgumentError,
|
673
|
+
':address_resolution must be either :none or :ec2_multi_region, ' \
|
674
|
+
"#{address_resolution.inspect} given"
|
478
675
|
end
|
479
676
|
end
|
480
677
|
|
481
|
-
if options.
|
678
|
+
if options.key?(:address_resolution_policy)
|
482
679
|
address_resolver = options[:address_resolution_policy]
|
483
680
|
|
484
|
-
Util.assert_responds_to(:resolve, address_resolver)
|
681
|
+
Util.assert_responds_to(:resolve, address_resolver) do
|
682
|
+
':address_resolution_policy must respond to :resolve, ' \
|
683
|
+
"#{address_resolver.inspect} but doesn't"
|
684
|
+
end
|
485
685
|
end
|
486
686
|
|
487
|
-
if options.
|
488
|
-
|
687
|
+
options[:synchronize_schema] = !!options[:synchronize_schema] if options.key?(:synchronize_schema)
|
688
|
+
|
689
|
+
if options.key?(:client_timestamps)
|
690
|
+
timestamp_generator = case options[:client_timestamps]
|
691
|
+
when true
|
692
|
+
if RUBY_ENGINE == 'jruby'
|
693
|
+
Cassandra::TimestampGenerator::TickingOnDuplicate.new
|
694
|
+
else
|
695
|
+
Cassandra::TimestampGenerator::Simple.new
|
696
|
+
end
|
697
|
+
when false
|
698
|
+
nil
|
699
|
+
when :simple
|
700
|
+
Cassandra::TimestampGenerator::Simple.new
|
701
|
+
when :monotonic
|
702
|
+
Cassandra::TimestampGenerator::TickingOnDuplicate.new
|
703
|
+
else
|
704
|
+
# The value must be a generator instance.
|
705
|
+
options[:client_timestamps]
|
706
|
+
end
|
707
|
+
|
708
|
+
if timestamp_generator
|
709
|
+
Util.assert_responds_to(:next, timestamp_generator) do
|
710
|
+
":client_timestamps #{options[:client_timestamps].inspect} must be a boolean, :simple, :monotonic, or " \
|
711
|
+
'an object that responds to :next'
|
712
|
+
end
|
713
|
+
end
|
714
|
+
options.delete(:client_timestamps)
|
715
|
+
options[:timestamp_generator] = timestamp_generator
|
489
716
|
end
|
490
717
|
|
491
|
-
if options.
|
492
|
-
|
718
|
+
if options.key?(:connections_per_local_node)
|
719
|
+
connections_per_node = options[:connections_per_local_node]
|
720
|
+
|
721
|
+
unless connections_per_node.nil?
|
722
|
+
connections_per_node = options[:connections_per_local_node]
|
723
|
+
Util.assert_instance_of(::Integer, connections_per_node)
|
724
|
+
Util.assert_one_of(1...2**16, connections_per_node) do
|
725
|
+
':connections_per_local_node must be a positive integer between ' \
|
726
|
+
"1 and 65535, #{connections_per_node.inspect} given"
|
727
|
+
end
|
728
|
+
end
|
493
729
|
end
|
494
730
|
|
495
|
-
|
731
|
+
if options.key?(:connections_per_remote_node)
|
732
|
+
connections_per_node = options[:connections_per_remote_node]
|
496
733
|
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
hosts << ::IPAddr.new(ip)
|
734
|
+
unless connections_per_node.nil?
|
735
|
+
connections_per_node = options[:connections_per_remote_node]
|
736
|
+
Util.assert_instance_of(::Integer, connections_per_node)
|
737
|
+
Util.assert_one_of(1...2**16, connections_per_node) do
|
738
|
+
':connections_per_remote_node must be a positive integer between ' \
|
739
|
+
"1 and 65535, #{connections_per_node.inspect} given"
|
504
740
|
end
|
505
|
-
else
|
506
|
-
raise ::ArgumentError, ":hosts must be String or IPAddr, #{host.inspect} given"
|
507
741
|
end
|
508
742
|
end
|
509
743
|
|
510
|
-
if
|
511
|
-
|
512
|
-
end
|
744
|
+
if options.key?(:requests_per_connection)
|
745
|
+
requests_per_connection = options[:requests_per_connection]
|
513
746
|
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
747
|
+
unless requests_per_connection.nil?
|
748
|
+
requests_per_connection = options[:requests_per_connection]
|
749
|
+
Util.assert_instance_of(::Integer, requests_per_connection)
|
750
|
+
|
751
|
+
# v3 protocol says that max stream-id is 32767 (2^15-1). This setting might be
|
752
|
+
# used to talk to a v2 (or less) node, but then we'll adjust it down.
|
753
|
+
|
754
|
+
Util.assert_one_of(1...2**15, requests_per_connection) do
|
755
|
+
':requests_per_connection must be a positive integer, ' \
|
756
|
+
"#{requests_per_connection.inspect} given"
|
757
|
+
end
|
758
|
+
end
|
759
|
+
end
|
760
|
+
options
|
521
761
|
end
|
522
762
|
|
523
763
|
# @private
|
@@ -535,9 +775,11 @@ module Cassandra
|
|
535
775
|
# => 1970-1-1
|
536
776
|
# ::Date.jd(DATE_OFFSET + 2 ** 32, ::Date::GREGORIAN)
|
537
777
|
# => 5881580-07-12
|
538
|
-
DATE_OFFSET = (::Time.utc(1970, 1, 1).to_date.jd - 2
|
778
|
+
DATE_OFFSET = (::Time.utc(1970, 1, 1).to_date.jd - 2**31)
|
539
779
|
end
|
540
780
|
|
781
|
+
require 'cassandra/attr_boolean'
|
782
|
+
require 'cassandra/version'
|
541
783
|
require 'cassandra/uuid'
|
542
784
|
require 'cassandra/time_uuid'
|
543
785
|
require 'cassandra/tuple'
|
@@ -550,6 +792,7 @@ require 'cassandra/errors'
|
|
550
792
|
require 'cassandra/compression'
|
551
793
|
require 'cassandra/protocol'
|
552
794
|
require 'cassandra/auth'
|
795
|
+
require 'cassandra/cassandra_logger'
|
553
796
|
require 'cassandra/null_logger'
|
554
797
|
|
555
798
|
require 'cassandra/executors'
|
@@ -565,9 +808,13 @@ require 'cassandra/statements'
|
|
565
808
|
require 'cassandra/aggregate'
|
566
809
|
require 'cassandra/argument'
|
567
810
|
require 'cassandra/function'
|
811
|
+
require 'cassandra/function_collection'
|
568
812
|
require 'cassandra/column'
|
813
|
+
require 'cassandra/column_container'
|
569
814
|
require 'cassandra/table'
|
815
|
+
require 'cassandra/materialized_view'
|
570
816
|
require 'cassandra/keyspace'
|
817
|
+
require 'cassandra/index'
|
571
818
|
|
572
819
|
require 'cassandra/execution/info'
|
573
820
|
require 'cassandra/execution/options'
|
@@ -577,6 +824,7 @@ require 'cassandra/load_balancing'
|
|
577
824
|
require 'cassandra/reconnection'
|
578
825
|
require 'cassandra/retry'
|
579
826
|
require 'cassandra/address_resolution'
|
827
|
+
require 'cassandra/timestamp_generator'
|
580
828
|
|
581
829
|
require 'cassandra/util'
|
582
830
|
|
@@ -587,7 +835,7 @@ module Cassandra
|
|
587
835
|
# @private
|
588
836
|
VOID_STATEMENT = Statements::Void.new
|
589
837
|
# @private
|
590
|
-
VOID_OPTIONS = Execution::Options.new(
|
838
|
+
VOID_OPTIONS = Execution::Options.new(consistency: :one)
|
591
839
|
# @private
|
592
840
|
NO_HOSTS = Errors::NoHostsAvailable.new
|
593
841
|
end
|