cassandra-driver 3.0.0.beta.1 → 3.0.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +90 -38
- data/ext/cassandra_murmur3/cassandra_murmur3.c +1 -1
- data/lib/cassandra.rb +327 -130
- 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/auth.rb +4 -4
- data/lib/cassandra/auth/providers.rb +1 -1
- data/lib/cassandra/auth/providers/password.rb +9 -5
- data/lib/cassandra/cassandra_logger.rb +80 -0
- data/lib/cassandra/cluster.rb +38 -9
- data/lib/cassandra/cluster/client.rb +801 -205
- data/lib/cassandra/cluster/connection_pool.rb +2 -2
- data/lib/cassandra/cluster/connector.rb +74 -25
- data/lib/cassandra/cluster/control_connection.rb +217 -82
- data/lib/cassandra/cluster/failed_connection.rb +1 -1
- data/lib/cassandra/cluster/metadata.rb +12 -4
- data/lib/cassandra/cluster/options.rb +60 -11
- data/lib/cassandra/cluster/registry.rb +69 -16
- data/lib/cassandra/cluster/schema.rb +25 -7
- data/lib/cassandra/cluster/schema/cql_type_parser.rb +15 -10
- data/lib/cassandra/cluster/schema/fetchers.rb +263 -106
- data/lib/cassandra/cluster/schema/fqcn_type_parser.rb +41 -36
- data/lib/cassandra/cluster/schema/partitioners.rb +1 -1
- data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +3 -3
- 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 +3 -3
- data/lib/cassandra/compression.rb +1 -1
- data/lib/cassandra/compression/compressors/lz4.rb +4 -3
- data/lib/cassandra/compression/compressors/snappy.rb +4 -3
- data/lib/cassandra/driver.rb +103 -41
- data/lib/cassandra/errors.rb +265 -30
- data/lib/cassandra/execution/info.rb +16 -5
- data/lib/cassandra/execution/options.rb +99 -54
- 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 +106 -48
- data/lib/cassandra/host.rb +10 -4
- data/lib/cassandra/keyspace.rb +90 -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 +18 -18
- data/lib/cassandra/load_balancing/policies/round_robin.rb +1 -1
- data/lib/cassandra/load_balancing/policies/token_aware.rb +15 -13
- data/lib/cassandra/load_balancing/policies/white_list.rb +11 -5
- data/lib/cassandra/null_logger.rb +27 -6
- data/lib/cassandra/protocol.rb +1 -1
- data/lib/cassandra/protocol/coder.rb +78 -39
- data/lib/cassandra/protocol/cql_byte_buffer.rb +50 -33
- data/lib/cassandra/protocol/cql_protocol_handler.rb +44 -45
- data/lib/cassandra/protocol/request.rb +2 -2
- data/lib/cassandra/protocol/requests/auth_response_request.rb +3 -3
- data/lib/cassandra/protocol/requests/batch_request.rb +16 -7
- data/lib/cassandra/protocol/requests/credentials_request.rb +3 -3
- data/lib/cassandra/protocol/requests/execute_request.rb +41 -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 +27 -22
- data/lib/cassandra/protocol/requests/register_request.rb +2 -2
- data/lib/cassandra/protocol/requests/startup_request.rb +6 -4
- data/lib/cassandra/protocol/requests/void_query_request.rb +1 -1
- data/lib/cassandra/protocol/response.rb +2 -2
- data/lib/cassandra/protocol/responses/already_exists_error_response.rb +12 -2
- data/lib/cassandra/protocol/responses/auth_challenge_response.rb +1 -1
- data/lib/cassandra/protocol/responses/auth_success_response.rb +1 -1
- data/lib/cassandra/protocol/responses/authenticate_response.rb +1 -1
- data/lib/cassandra/protocol/responses/error_response.rb +101 -13
- data/lib/cassandra/protocol/responses/event_response.rb +1 -1
- data/lib/cassandra/protocol/responses/function_failure_error_response.rb +13 -2
- data/lib/cassandra/protocol/responses/prepared_result_response.rb +11 -5
- 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 +3 -3
- data/lib/cassandra/protocol/responses/result_response.rb +4 -2
- data/lib/cassandra/protocol/responses/rows_result_response.rb +5 -3
- data/lib/cassandra/protocol/responses/schema_change_event_response.rb +5 -4
- data/lib/cassandra/protocol/responses/schema_change_result_response.rb +16 -9
- data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +2 -2
- data/lib/cassandra/protocol/responses/status_change_event_response.rb +2 -2
- data/lib/cassandra/protocol/responses/supported_response.rb +1 -1
- data/lib/cassandra/protocol/responses/topology_change_event_response.rb +1 -1
- 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 +1 -1
- 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 +101 -36
- data/lib/cassandra/protocol/v3.rb +124 -51
- 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 +53 -19
- 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 +7 -3
- data/lib/cassandra/retry/policies/fallthrough.rb +1 -1
- data/lib/cassandra/session.rb +22 -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 +59 -15
- data/lib/cassandra/statements/simple.rb +23 -10
- data/lib/cassandra/statements/void.rb +1 -1
- data/lib/cassandra/table.rb +79 -30
- data/lib/cassandra/time.rb +11 -6
- data/lib/cassandra/time_uuid.rb +7 -7
- data/lib/cassandra/tuple.rb +16 -8
- data/lib/cassandra/types.rb +20 -9
- data/lib/cassandra/udt.rb +32 -36
- data/lib/cassandra/util.rb +20 -13
- data/lib/cassandra/uuid.rb +22 -15
- data/lib/cassandra/uuid/generator.rb +7 -5
- data/lib/cassandra/version.rb +2 -2
- data/lib/datastax/cassandra.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YTFhMzk5ZGFjZWJhYTQzZDFhYjA5ZGM3Mzk0YjY1MWMwODdjMDUyNA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NGE5OTQ1YjYyNjA1ZTVhNDI4OGQzNmJiMmFlMzJlNzRlMzNiMTkyMw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MWZiZmZiOWNkMzFkMDM3NzE3ZTQxMzUzZWM5NjU1MjA1ODI2ODFkNDkxNzI4
|
10
|
+
YjlmNmJhZGE2OTEyNWY1ZmIyOWQwNjhlNTQyNjdiN2U2Njk3ZDYyMzNhYTg4
|
11
|
+
NmZjYjY5YmZiMDRlNTA2Njg4ZTQ2YTJlZWQ3YjVhY2MwNGE0NjA=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NDJiNzQ1ZTgzN2VkOTBmYWZjOGFmN2QwMDc4OWU3YmQxMjdlYmFjZGQ0OTM5
|
14
|
+
NDlmYmQxMDE1YjczZmNmZjg4MGRjNDY1ODRhZjNlYzBkODE2YTQ5YmM0Njlm
|
15
|
+
N2IyYjhkM2JhZmUwMjUyM2I4ODhlM2VmY2Q5YmNkZTUzZmM1ZGE=
|
data/README.md
CHANGED
@@ -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 and
|
35
|
-
* DataStax Enterprise
|
36
|
-
* Ruby (MRI)
|
34
|
+
* Apache Cassandra versions 1.2, 2.0, 2.1, and 3.x
|
35
|
+
* DataStax Enterprise 4.0, 4.5, 4.6, 4.7, and 4.8
|
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,64 @@ __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
|
+
* 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
|
+
* 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 :idempotent option when executing.
|
105
|
+
* Support sending custom payloads when preparing or executing statements using the new :payload option.
|
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, connections_per_remote_node, requests_per_connection cluster configuration options to tune parallel query execution and resource usage.
|
109
|
+
* Add Cassandra::Logger class to make it easy for users to enable debug logging in the client.
|
110
|
+
|
111
|
+
### Breaking Changes:
|
112
|
+
|
113
|
+
* Cassandra::Future#join is now an alias to Cassandra::Future#get and will raise an error if the future is resolved with one.
|
114
|
+
* Default consistency level is now LOCAL_ONE.
|
115
|
+
* Enable tcp no-delay by default.
|
116
|
+
* Unavailable errors are retried on the next host in the load balancing plan by default.
|
117
|
+
* Statement execution no longer retried on timeouts, unless :idempotent => true has been specified when executing.
|
118
|
+
* Cassandra::Statements::Batch#add signature has changed in how one specifies query parameters. Specify the query parameters array as the value of the arguments key:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
batch.add(query, ['val1', 'val2'])
|
122
|
+
# becomes
|
123
|
+
batch.add(query, arguments: ['val1', 'val2'])
|
97
124
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
* [Public types api for type definition and introspection](http://datastax.github.io/ruby-driver/api/types/)
|
125
|
+
batch.add(query, {p1: 'val1'})
|
126
|
+
# becomes
|
127
|
+
batch.add(query, arguments: {p1: 'val1'})
|
128
|
+
```
|
103
129
|
|
104
|
-
|
130
|
+
### Bug Fixes:
|
105
131
|
|
106
|
-
*
|
132
|
+
* [[RUBY-120](https://datastax-oss.atlassian.net/browse/RUBY-120)] Tuples and UDTs can be used in sets and hash keys.
|
133
|
+
* [[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.
|
134
|
+
* [[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.
|
135
|
+
* [[RUBY-151](https://datastax-oss.atlassian.net/browse/RUBY-151)] Decode incomplete UDTs properly.
|
107
136
|
|
108
|
-
|
137
|
+
## Feedback Requested
|
109
138
|
|
110
|
-
* [
|
139
|
+
*Help us focus our efforts!* [Provide your input](http://goo.gl/forms/pCs8PTpHLf)
|
140
|
+
on the Ruby Driver Platform and Runtime Survey (we kept it short).
|
111
141
|
|
112
142
|
## Code examples
|
113
143
|
|
114
|
-
The DataStax Ruby Driver uses the awesome [Cucumber Framework](http://cukes.info/) for
|
144
|
+
The DataStax Ruby Driver uses the awesome [Cucumber Framework](http://cukes.info/) for
|
145
|
+
both end-to-end, or acceptance, testing and constructing documentation. All of the
|
146
|
+
features supported by the driver have appropriate acceptance tests with easy-to-copy code
|
147
|
+
examples in the `features/` directory.
|
115
148
|
|
116
149
|
## Running tests
|
117
150
|
|
118
|
-
If you don't feel like reading through the following instructions on how to run
|
151
|
+
If you don't feel like reading through the following instructions on how to run
|
152
|
+
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
153
|
|
120
154
|
* Check out the driver codebase and install test dependencies:
|
121
155
|
|
@@ -127,26 +161,37 @@ bundle install --without docs
|
|
127
161
|
|
128
162
|
* [Install ccm](http://www.datastax.com/dev/blog/ccm-a-development-tool-for-creating-local-cassandra-clusters)
|
129
163
|
|
130
|
-
* Run tests:
|
164
|
+
* Run tests against different versions of Cassandra:
|
131
165
|
|
132
166
|
```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
|
167
|
+
CASSANDRA_VERSION=3.1.1 bundle exec cucumber # runs end-to-end tests (or bundle exec rake cucumber)
|
168
|
+
CASSANDRA_VERSION=3.0.0 bundle exec rspec # runs unit tests (or bundle exec rake rspec)
|
169
|
+
CASSANDRA_VERSION=2.1.12 bundle exec rake integration # run integration tests
|
170
|
+
CASSANDRA_VERSION=2.0.17 bundle exec rake test # run both as well as integration tests
|
137
171
|
```
|
138
172
|
|
139
173
|
## Changelog & versioning
|
140
174
|
|
141
|
-
Check out the [releases on GitHub](https://github.com/datastax/ruby-driver/releases) and
|
175
|
+
Check out the [releases on GitHub](https://github.com/datastax/ruby-driver/releases) and
|
176
|
+
[changelog](https://github.com/datastax/ruby-driver/blob/master/CHANGELOG.md). Version
|
177
|
+
numbering follows the [semantic versioning](http://semver.org/) scheme.
|
142
178
|
|
143
|
-
Private and experimental APIs, defined as whatever is not in the
|
179
|
+
Private and experimental APIs, defined as whatever is not in the
|
180
|
+
[public API documentation][1], i.e. classes and methods marked as `@private`, will change
|
181
|
+
without warning. If you've been recommended to try an experimental API by the maintainers,
|
182
|
+
please let them know if you depend on that API. Experimental APIs will eventually become
|
183
|
+
public, and knowing how they are used helps in determining their maturity.
|
144
184
|
|
145
|
-
Prereleases will be stable, in the sense that they will have finished and properly tested
|
185
|
+
Prereleases will be stable, in the sense that they will have finished and properly tested
|
186
|
+
features only, but may introduce APIs that will change before the final release. Please
|
187
|
+
use the prereleases and report bugs, but don't deploy them to production without
|
188
|
+
consulting the maintainers, or doing extensive testing yourself. If you do deploy to
|
189
|
+
production please let the maintainers know as this helps in determining the maturity of
|
190
|
+
the release.
|
146
191
|
|
147
192
|
## Known bugs & limitations
|
148
193
|
|
149
|
-
* JRuby 1.6 is not officially supported, although 1.6.8 should work
|
194
|
+
* JRuby 1.6 is not officially supported, although 1.6.8 should work.
|
150
195
|
* Because the driver reactor is using `IO.select`, the maximum number of tcp connections allowed is 1024.
|
151
196
|
* Because the driver uses `IO#write_nonblock`, Windows is not supported.
|
152
197
|
|
@@ -158,19 +203,26 @@ For contributing read [CONTRIBUTING.md](https://github.com/datastax/ruby-driver/
|
|
158
203
|
|
159
204
|
## Credits
|
160
205
|
|
161
|
-
This driver is based on the original work of [Theo Hultberg](https://github.com/iconara)
|
162
|
-
|
163
|
-
|
206
|
+
This driver is based on the original work of [Theo Hultberg](https://github.com/iconara)
|
207
|
+
on [cql-rb](https://github.com/iconara/cql-rb/) and adds a series of advanced features
|
208
|
+
that are common across all other DataStax drivers for Apache Cassandra.
|
164
209
|
|
210
|
+
The development effort to provide an up to date, high performance, fully featured Ruby
|
211
|
+
Driver for Apache Cassandra will continue on this project, while
|
212
|
+
[cql-rb](https://github.com/iconara/cql-rb/) will be discontinued.
|
165
213
|
|
166
214
|
## Copyright
|
167
215
|
|
168
|
-
Copyright 2013-
|
216
|
+
Copyright 2013-2016 DataStax, Inc.
|
169
217
|
|
170
|
-
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
218
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
219
|
+
except in compliance with the License. You may obtain a copy of the License at
|
171
220
|
|
172
221
|
[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
173
222
|
|
174
|
-
Unless required by applicable law or agreed to in writing, software distributed under the
|
223
|
+
Unless required by applicable law or agreed to in writing, software distributed under the
|
224
|
+
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
225
|
+
either express or implied. See the License for the specific language governing permissions
|
226
|
+
and limitations under the License.
|
175
227
|
|
176
228
|
[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
|
|
@@ -38,8 +37,8 @@ module Cassandra
|
|
38
37
|
# @see http://www.datastax.com/documentation/cassandra/2.0/cassandra/dml/dml_config_consistency_c.html Consistency levels in Apache Cassandra 2.0
|
39
38
|
# @see http://www.datastax.com/documentation/cassandra/1.2/cassandra/dml/dml_config_consistency_c.html Consistency levels in Apache Cassandra 1.2
|
40
39
|
# @see Cassandra::Session#execute_async
|
41
|
-
CONSISTENCIES = [
|
42
|
-
|
40
|
+
CONSISTENCIES = [:any, :one, :two, :three, :quorum, :all, :local_quorum,
|
41
|
+
:each_quorum, :serial, :local_serial, :local_one].freeze
|
43
42
|
|
44
43
|
# A list of all supported serial consistencies
|
45
44
|
# @see Cassandra::Session#execute_async
|
@@ -126,6 +125,22 @@ module Cassandra
|
|
126
125
|
# address resolver to use. Must be one of `:none` or
|
127
126
|
# `:ec2_multi_region`.
|
128
127
|
#
|
128
|
+
# @option options [Integer] :connections_per_local_node (nil) Number of connections to
|
129
|
+
# open to each local node; the value of this option directly correlates to the number
|
130
|
+
# of requests the client can make to the local node concurrently. When `nil`, the
|
131
|
+
# setting is `1` for nodes that use the v3 or later protocol, and `2` for nodes that
|
132
|
+
# use the v2 or earlier protocol.
|
133
|
+
#
|
134
|
+
# @option options [Integer] :connections_per_remote_node (1) Number of connections to
|
135
|
+
# open to each remote node; the value of this option directly correlates to the
|
136
|
+
# number of requests the client can make to the remote node concurrently.
|
137
|
+
#
|
138
|
+
# @option options [Integer] :requests_per_connection (nil) Number of outstanding
|
139
|
+
# requests to support on one connection. Depending on the types of requests, some may
|
140
|
+
# get processed in parallel in the Cassandra node. When `nil`, the setting is `1024`
|
141
|
+
# for nodes that use the v3 or later protocol, and `128` for nodes that use the
|
142
|
+
# v2 or earlier protocol.
|
143
|
+
#
|
129
144
|
# @option options [Boolean] :client_timestamps (false) whether the driver
|
130
145
|
# should send timestamps for each executed statement. Enabling this setting
|
131
146
|
# allows mitigating Cassandra cluster clock skew because the timestamp of
|
@@ -139,7 +154,8 @@ module Cassandra
|
|
139
154
|
# automatic schema updates. Schema metadata is used by the driver to
|
140
155
|
# determine cluster partitioners as well as to find partition keys and
|
141
156
|
# replicas of prepared statements, this information makes token aware load
|
142
|
-
# balancing possible. One can still
|
157
|
+
# balancing possible. One can still
|
158
|
+
# {Cassandra::Cluster#refresh_schema refresh schema manually}.
|
143
159
|
#
|
144
160
|
# @option options [Numeric] :schema_refresh_delay (1) the driver will wait
|
145
161
|
# for `:schema_refresh_delay` before fetching metadata after receiving a
|
@@ -177,9 +193,15 @@ module Cassandra
|
|
177
193
|
# @option options [Integer] :page_size (10000) default page size for all
|
178
194
|
# select queries. Set this value to `nil` to disable paging.
|
179
195
|
#
|
180
|
-
# @option options [Hash{String => String}] :credentials (none) a hash of credentials -
|
196
|
+
# @option options [Hash{String => String}] :credentials (none) a hash of credentials -
|
197
|
+
# 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).
|
198
|
+
# Note that if you specified `:username` and `:password` options, those credentials
|
199
|
+
# are configured automatically.
|
181
200
|
#
|
182
|
-
# @option options [Cassandra::Auth::Provider] :auth_provider (none) a custom auth
|
201
|
+
# @option options [Cassandra::Auth::Provider] :auth_provider (none) a custom auth
|
202
|
+
# 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).
|
203
|
+
# Note that if you have specified `:username` and `:password`, then a
|
204
|
+
# {Cassandra::Auth::Providers::Password Password Provider} will be used automatically.
|
183
205
|
#
|
184
206
|
# @option options [Cassandra::Compression::Compressor] :compressor (none) a
|
185
207
|
# custom compressor. Note that if you have specified `:compression`, an
|
@@ -187,8 +209,8 @@ module Cassandra
|
|
187
209
|
#
|
188
210
|
# @option options [Cassandra::AddressResolution::Policy]
|
189
211
|
# :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
|
212
|
+
# {Cassandra::AddressResolution::Policies::None No Resolution Policy} a custom address
|
213
|
+
# resolution policy. Note that if you have specified `:address_resolution`, an
|
192
214
|
# appropriate address resolution policy will be provided automatically.
|
193
215
|
#
|
194
216
|
# @option options [Object<#all, #error, #value, #promise>] :futures_factory
|
@@ -219,78 +241,176 @@ module Cassandra
|
|
219
241
|
# @return [Cassandra::Future<Cassandra::Cluster>] a future resolving to the
|
220
242
|
# cluster instance.
|
221
243
|
def self.cluster_async(options = {})
|
222
|
-
options = options
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
244
|
+
options = validate_and_massage_options(options)
|
245
|
+
hosts = []
|
246
|
+
|
247
|
+
Array(options.fetch(:hosts, '127.0.0.1')).each do |host|
|
248
|
+
case host
|
249
|
+
when ::IPAddr
|
250
|
+
hosts << host
|
251
|
+
when ::String # ip address or hostname
|
252
|
+
Resolv.each_address(host) do |ip|
|
253
|
+
hosts << ::IPAddr.new(ip)
|
254
|
+
end
|
255
|
+
else
|
256
|
+
raise ::ArgumentError, ":hosts must be String or IPAddr, #{host.inspect} given"
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
if hosts.empty?
|
261
|
+
raise ::ArgumentError,
|
262
|
+
":hosts #{options[:hosts].inspect} could not be resolved to any ip address"
|
263
|
+
end
|
264
|
+
|
265
|
+
hosts.shuffle!
|
266
|
+
rescue => e
|
267
|
+
futures = options.fetch(:futures_factory) { return Future::Error.new(e) }
|
268
|
+
futures.error(e)
|
269
|
+
else
|
270
|
+
driver = Driver.new(options)
|
271
|
+
driver.connect(hosts)
|
272
|
+
end
|
273
|
+
|
274
|
+
# @private
|
275
|
+
SSL_CLASSES = [::TrueClass, ::FalseClass, ::OpenSSL::SSL::SSLContext].freeze
|
276
|
+
|
277
|
+
# @private
|
278
|
+
def self.validate_and_massage_options(options)
|
279
|
+
options = options.select do |key, _|
|
280
|
+
[
|
281
|
+
:address_resolution,
|
282
|
+
:address_resolution_policy,
|
283
|
+
:auth_provider,
|
284
|
+
:client_cert,
|
285
|
+
:client_timestamps,
|
286
|
+
:compression,
|
287
|
+
:compressor,
|
288
|
+
:connect_timeout,
|
289
|
+
:connections_per_local_node,
|
290
|
+
:connections_per_remote_node,
|
291
|
+
:consistency,
|
292
|
+
:credentials,
|
293
|
+
:datacenter,
|
294
|
+
:futures_factory,
|
295
|
+
:heartbeat_interval,
|
296
|
+
:hosts,
|
297
|
+
:idle_timeout,
|
298
|
+
:listeners,
|
299
|
+
:load_balancing_policy,
|
300
|
+
:logger,
|
301
|
+
:nodelay,
|
302
|
+
:reconnection_policy,
|
303
|
+
:retry_policy,
|
304
|
+
:page_size,
|
305
|
+
:passphrase,
|
306
|
+
:password,
|
307
|
+
:port,
|
308
|
+
:private_key,
|
309
|
+
:requests_per_connection,
|
310
|
+
:schema_refresh_delay,
|
311
|
+
:schema_refresh_timeout,
|
312
|
+
:server_cert,
|
313
|
+
:shuffle_replicas,
|
314
|
+
:ssl,
|
315
|
+
:synchronize_schema,
|
316
|
+
:timeout,
|
317
|
+
:trace,
|
318
|
+
:username
|
231
319
|
].include?(key)
|
232
320
|
end
|
233
321
|
|
234
|
-
has_username = options.
|
235
|
-
has_password = options.
|
322
|
+
has_username = options.key?(:username)
|
323
|
+
has_password = options.key?(:password)
|
236
324
|
if has_username || has_password
|
237
325
|
if has_username && !has_password
|
238
|
-
raise ::ArgumentError,
|
326
|
+
raise ::ArgumentError,
|
327
|
+
'both :username and :password options must be specified, ' \
|
328
|
+
'but only :username given'
|
239
329
|
end
|
240
330
|
|
241
331
|
if !has_username && has_password
|
242
|
-
raise ::ArgumentError,
|
332
|
+
raise ::ArgumentError,
|
333
|
+
'both :username and :password options must be specified, ' \
|
334
|
+
'but only :password given'
|
243
335
|
end
|
244
336
|
|
245
337
|
username = options.delete(:username)
|
246
338
|
password = options.delete(:password)
|
247
339
|
|
248
|
-
Util.assert_instance_of(::String, username)
|
249
|
-
|
250
|
-
|
251
|
-
Util.
|
340
|
+
Util.assert_instance_of(::String, username) do
|
341
|
+
":username must be a String, #{username.inspect} given"
|
342
|
+
end
|
343
|
+
Util.assert_instance_of(::String, password) do
|
344
|
+
":password must be a String, #{password.inspect} given"
|
345
|
+
end
|
346
|
+
Util.assert_not_empty(username) { ':username cannot be empty' }
|
347
|
+
Util.assert_not_empty(password) { ':password cannot be empty' }
|
252
348
|
|
253
|
-
options[:credentials] = {:
|
349
|
+
options[:credentials] = {username: username, password: password}
|
254
350
|
options[:auth_provider] = Auth::Providers::Password.new(username, password)
|
255
351
|
end
|
256
352
|
|
257
|
-
if options.
|
353
|
+
if options.key?(:credentials)
|
258
354
|
credentials = options[:credentials]
|
259
355
|
|
260
|
-
Util.assert_instance_of(::Hash, credentials)
|
356
|
+
Util.assert_instance_of(::Hash, credentials) do
|
357
|
+
":credentials must be a hash, #{credentials.inspect} given"
|
358
|
+
end
|
261
359
|
end
|
262
360
|
|
263
|
-
if options.
|
361
|
+
if options.key?(:auth_provider)
|
264
362
|
auth_provider = options[:auth_provider]
|
265
363
|
|
266
|
-
Util.assert_responds_to(:create_authenticator, auth_provider)
|
364
|
+
Util.assert_responds_to(:create_authenticator, auth_provider) do
|
365
|
+
":auth_provider #{auth_provider.inspect} must respond to " \
|
366
|
+
":create_authenticator, but doesn't"
|
367
|
+
end
|
267
368
|
end
|
268
369
|
|
269
|
-
has_client_cert = options.
|
270
|
-
has_private_key = options.
|
370
|
+
has_client_cert = options.key?(:client_cert)
|
371
|
+
has_private_key = options.key?(:private_key)
|
271
372
|
|
272
373
|
if has_client_cert || has_private_key
|
273
374
|
if has_client_cert && !has_private_key
|
274
|
-
raise ::ArgumentError,
|
375
|
+
raise ::ArgumentError,
|
376
|
+
'both :client_cert and :private_key options must be specified, ' \
|
377
|
+
'but only :client_cert given'
|
275
378
|
end
|
276
379
|
|
277
380
|
if !has_client_cert && has_private_key
|
278
|
-
raise ::ArgumentError,
|
381
|
+
raise ::ArgumentError,
|
382
|
+
'both :client_cert and :private_key options must be specified, ' \
|
383
|
+
'but only :private_key given'
|
279
384
|
end
|
280
385
|
|
386
|
+
Util.assert_instance_of(::String, options[:client_cert]) do
|
387
|
+
":client_cert must be a string, #{options[:client_cert].inspect} given"
|
388
|
+
end
|
389
|
+
Util.assert_instance_of(::String, options[:private_key]) do
|
390
|
+
":client_cert must be a string, #{options[:private_key].inspect} given"
|
391
|
+
end
|
281
392
|
client_cert = ::File.expand_path(options[:client_cert])
|
282
393
|
private_key = ::File.expand_path(options[:private_key])
|
283
394
|
|
284
|
-
Util.assert_file_exists(client_cert)
|
285
|
-
|
395
|
+
Util.assert_file_exists(client_cert) do
|
396
|
+
":client_cert #{client_cert.inspect} doesn't exist"
|
397
|
+
end
|
398
|
+
Util.assert_file_exists(private_key) do
|
399
|
+
":private_key #{private_key.inspect} doesn't exist"
|
400
|
+
end
|
286
401
|
end
|
287
402
|
|
288
|
-
has_server_cert = options.
|
403
|
+
has_server_cert = options.key?(:server_cert)
|
289
404
|
|
290
405
|
if has_server_cert
|
406
|
+
Util.assert_instance_of(::String, options[:server_cert]) do
|
407
|
+
":server_cert must be a string, #{options[:server_cert].inspect} given"
|
408
|
+
end
|
291
409
|
server_cert = ::File.expand_path(options[:server_cert])
|
292
410
|
|
293
|
-
Util.assert_file_exists(server_cert)
|
411
|
+
Util.assert_file_exists(server_cert) do
|
412
|
+
":server_cert #{server_cert.inspect} doesn't exist"
|
413
|
+
end
|
294
414
|
end
|
295
415
|
|
296
416
|
if has_client_cert || has_server_cert
|
@@ -304,23 +424,26 @@ module Cassandra
|
|
304
424
|
if has_client_cert
|
305
425
|
context.cert = ::OpenSSL::X509::Certificate.new(File.read(client_cert))
|
306
426
|
|
307
|
-
if options.
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
427
|
+
context.key = if options.key?(:passphrase)
|
428
|
+
::OpenSSL::PKey::RSA.new(File.read(private_key),
|
429
|
+
options[:passphrase])
|
430
|
+
else
|
431
|
+
::OpenSSL::PKey::RSA.new(File.read(private_key))
|
432
|
+
end
|
312
433
|
end
|
313
434
|
|
314
435
|
options[:ssl] = context
|
315
436
|
end
|
316
437
|
|
317
|
-
if options.
|
438
|
+
if options.key?(:ssl)
|
318
439
|
ssl = options[:ssl]
|
319
440
|
|
320
|
-
Util.assert_instance_of_one_of(
|
441
|
+
Util.assert_instance_of_one_of(SSL_CLASSES, ssl) do
|
442
|
+
":ssl must be a boolean or an OpenSSL::SSL::SSLContext, #{ssl.inspect} given"
|
443
|
+
end
|
321
444
|
end
|
322
445
|
|
323
|
-
if options.
|
446
|
+
if options.key?(:compression)
|
324
447
|
compression = options.delete(:compression)
|
325
448
|
|
326
449
|
case compression
|
@@ -329,195 +452,267 @@ module Cassandra
|
|
329
452
|
when :lz4
|
330
453
|
options[:compressor] = Compression::Compressors::Lz4.new
|
331
454
|
else
|
332
|
-
raise ::ArgumentError,
|
455
|
+
raise ::ArgumentError,
|
456
|
+
":compression must be either :snappy or :lz4, #{compression.inspect} given"
|
333
457
|
end
|
334
458
|
end
|
335
459
|
|
336
|
-
if options.
|
460
|
+
if options.key?(:compressor)
|
337
461
|
compressor = options[:compressor]
|
338
462
|
methods = [:algorithm, :compress?, :compress, :decompress]
|
339
463
|
|
340
|
-
Util.assert_responds_to_all(methods, compressor)
|
464
|
+
Util.assert_responds_to_all(methods, compressor) do
|
465
|
+
":compressor #{compressor.inspect} must respond to #{methods.inspect}, " \
|
466
|
+
"but doesn't"
|
467
|
+
end
|
341
468
|
end
|
342
469
|
|
343
|
-
if options.
|
344
|
-
|
345
|
-
|
470
|
+
if options.key?(:logger)
|
471
|
+
if options[:logger].nil?
|
472
|
+
# Delete the key because we want to fallback to the default logger in Driver.
|
473
|
+
options.delete(:logger)
|
474
|
+
else
|
475
|
+
# Validate
|
476
|
+
logger = options[:logger]
|
477
|
+
methods = [:debug, :info, :warn, :error, :fatal]
|
346
478
|
|
347
|
-
|
479
|
+
Util.assert_responds_to_all(methods, logger) do
|
480
|
+
":logger #{logger.inspect} must respond to #{methods.inspect}, but doesn't"
|
481
|
+
end
|
482
|
+
end
|
348
483
|
end
|
349
484
|
|
350
|
-
if options.
|
351
|
-
|
352
|
-
|
353
|
-
|
485
|
+
if options.key?(:port)
|
486
|
+
unless options[:port].nil?
|
487
|
+
port = options[:port]
|
488
|
+
Util.assert_instance_of(::Integer, port)
|
489
|
+
Util.assert_one_of(1...2**16, port) do
|
490
|
+
":port must be a valid ip port, #{port} given"
|
491
|
+
end
|
492
|
+
end
|
354
493
|
end
|
355
494
|
|
356
|
-
if options.
|
357
|
-
options[:datacenter] = String(options[:datacenter])
|
358
|
-
end
|
495
|
+
options[:datacenter] = String(options[:datacenter]) if options.key?(:datacenter)
|
359
496
|
|
360
|
-
if options.
|
497
|
+
if options.key?(:connect_timeout)
|
361
498
|
timeout = options[:connect_timeout]
|
362
499
|
|
363
500
|
unless timeout.nil?
|
364
|
-
Util.assert_instance_of(::Numeric, timeout)
|
365
|
-
|
501
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
502
|
+
":connect_timeout must be a number of seconds, #{timeout.inspect} given"
|
503
|
+
end
|
504
|
+
Util.assert(timeout > 0) do
|
505
|
+
":connect_timeout must be greater than 0, #{timeout} given"
|
506
|
+
end
|
366
507
|
end
|
367
508
|
end
|
368
509
|
|
369
|
-
if options.
|
510
|
+
if options.key?(:timeout)
|
370
511
|
timeout = options[:timeout]
|
371
512
|
|
372
513
|
unless timeout.nil?
|
373
|
-
Util.assert_instance_of(::Numeric, timeout)
|
514
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
515
|
+
":timeout must be a number of seconds, #{timeout.inspect} given"
|
516
|
+
end
|
374
517
|
Util.assert(timeout > 0) { ":timeout must be greater than 0, #{timeout} given" }
|
375
518
|
end
|
376
519
|
end
|
377
520
|
|
378
|
-
if options.
|
521
|
+
if options.key?(:heartbeat_interval)
|
379
522
|
timeout = options[:heartbeat_interval]
|
380
523
|
|
381
524
|
unless timeout.nil?
|
382
|
-
Util.assert_instance_of(::Numeric, timeout)
|
383
|
-
|
525
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
526
|
+
":heartbeat_interval must be a number of seconds, #{timeout.inspect} given"
|
527
|
+
end
|
528
|
+
Util.assert(timeout > 0) do
|
529
|
+
":heartbeat_interval must be greater than 0, #{timeout} given"
|
530
|
+
end
|
384
531
|
end
|
385
532
|
end
|
386
533
|
|
387
|
-
if options.
|
534
|
+
if options.key?(:idle_timeout)
|
388
535
|
timeout = options[:idle_timeout]
|
389
536
|
|
390
537
|
unless timeout.nil?
|
391
|
-
Util.assert_instance_of(::Numeric, timeout)
|
392
|
-
|
538
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
539
|
+
":idle_timeout must be a number of seconds, #{timeout.inspect} given"
|
540
|
+
end
|
541
|
+
Util.assert(timeout > 0) do
|
542
|
+
":idle_timeout must be greater than 0, #{timeout} given"
|
543
|
+
end
|
393
544
|
end
|
394
545
|
end
|
395
546
|
|
396
|
-
if options.
|
547
|
+
if options.key?(:schema_refresh_delay)
|
397
548
|
timeout = options[:schema_refresh_delay]
|
398
549
|
|
399
|
-
Util.assert_instance_of(::Numeric, timeout)
|
400
|
-
|
550
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
551
|
+
":schema_refresh_delay must be a number of seconds, #{timeout.inspect} given"
|
552
|
+
end
|
553
|
+
Util.assert(timeout > 0) do
|
554
|
+
":schema_refresh_delay must be greater than 0, #{timeout} given"
|
555
|
+
end
|
401
556
|
end
|
402
557
|
|
403
|
-
if options.
|
558
|
+
if options.key?(:schema_refresh_timeout)
|
404
559
|
timeout = options[:schema_refresh_timeout]
|
405
560
|
|
406
|
-
Util.assert_instance_of(::Numeric, timeout)
|
407
|
-
|
561
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
562
|
+
":schema_refresh_timeout must be a number of seconds, #{timeout.inspect} given"
|
563
|
+
end
|
564
|
+
Util.assert(timeout > 0) do
|
565
|
+
":schema_refresh_timeout must be greater than 0, #{timeout} given"
|
566
|
+
end
|
408
567
|
end
|
409
568
|
|
410
|
-
if options.
|
569
|
+
if options.key?(:load_balancing_policy)
|
411
570
|
load_balancing_policy = options[:load_balancing_policy]
|
412
|
-
methods = [:host_up, :host_down, :host_found, :host_lost, :setup, :teardown,
|
571
|
+
methods = [:host_up, :host_down, :host_found, :host_lost, :setup, :teardown,
|
572
|
+
:distance, :plan]
|
413
573
|
|
414
|
-
Util.assert_responds_to_all(methods, load_balancing_policy)
|
574
|
+
Util.assert_responds_to_all(methods, load_balancing_policy) do
|
575
|
+
":load_balancing_policy #{load_balancing_policy.inspect} must respond " \
|
576
|
+
"to #{methods.inspect}, but doesn't"
|
577
|
+
end
|
415
578
|
end
|
416
579
|
|
417
|
-
if options.
|
580
|
+
if options.key?(:reconnection_policy)
|
418
581
|
reconnection_policy = options[:reconnection_policy]
|
419
582
|
|
420
|
-
Util.assert_responds_to(:schedule, reconnection_policy)
|
583
|
+
Util.assert_responds_to(:schedule, reconnection_policy) do
|
584
|
+
":reconnection_policy #{reconnection_policy.inspect} must respond to " \
|
585
|
+
":schedule, but doesn't"
|
586
|
+
end
|
421
587
|
end
|
422
588
|
|
423
|
-
if options.
|
589
|
+
if options.key?(:retry_policy)
|
424
590
|
retry_policy = options[:retry_policy]
|
425
591
|
methods = [:read_timeout, :write_timeout, :unavailable]
|
426
592
|
|
427
|
-
Util.assert_responds_to_all(methods, retry_policy)
|
593
|
+
Util.assert_responds_to_all(methods, retry_policy) do
|
594
|
+
":retry_policy #{retry_policy.inspect} must respond to #{methods.inspect}, " \
|
595
|
+
"but doesn't"
|
596
|
+
end
|
428
597
|
end
|
429
598
|
|
430
|
-
if options.
|
431
|
-
options[:listeners] = Array(options[:listeners])
|
432
|
-
end
|
599
|
+
options[:listeners] = Array(options[:listeners]) if options.key?(:listeners)
|
433
600
|
|
434
|
-
if options.
|
601
|
+
if options.key?(:consistency)
|
435
602
|
consistency = options[:consistency]
|
436
603
|
|
437
|
-
Util.assert_one_of(CONSISTENCIES, consistency)
|
604
|
+
Util.assert_one_of(CONSISTENCIES, consistency) do
|
605
|
+
":consistency must be one of #{CONSISTENCIES.inspect}, " \
|
606
|
+
"#{consistency.inspect} given"
|
607
|
+
end
|
438
608
|
end
|
439
609
|
|
440
|
-
if options.
|
441
|
-
options[:nodelay] = !!options[:nodelay]
|
442
|
-
end
|
610
|
+
options[:nodelay] = !!options[:nodelay] if options.key?(:nodelay)
|
443
611
|
|
444
|
-
if options.
|
445
|
-
options[:trace] = !!options[:trace]
|
446
|
-
end
|
612
|
+
options[:trace] = !!options[:trace] if options.key?(:trace)
|
447
613
|
|
448
|
-
if options.
|
614
|
+
if options.key?(:shuffle_replicas)
|
449
615
|
options[:shuffle_replicas] = !!options[:shuffle_replicas]
|
450
616
|
end
|
451
617
|
|
452
|
-
if options.
|
618
|
+
if options.key?(:page_size)
|
453
619
|
page_size = options[:page_size]
|
454
620
|
|
455
621
|
unless page_size.nil?
|
456
|
-
page_size = options[:page_size]
|
457
|
-
Util.
|
622
|
+
page_size = options[:page_size]
|
623
|
+
Util.assert_instance_of(::Integer, page_size)
|
624
|
+
Util.assert_one_of(1...2**32, page_size) do
|
625
|
+
":page_size must be a positive integer, #{page_size.inspect} given"
|
626
|
+
end
|
458
627
|
end
|
459
628
|
end
|
460
629
|
|
461
|
-
if options.
|
630
|
+
if options.key?(:futures_factory)
|
462
631
|
futures_factory = options[:futures_factory]
|
463
632
|
methods = [:error, :value, :promise, :all]
|
464
633
|
|
465
|
-
Util.assert_responds_to_all(methods, futures_factory)
|
634
|
+
Util.assert_responds_to_all(methods, futures_factory) do
|
635
|
+
":futures_factory #{futures_factory.inspect} must respond to " \
|
636
|
+
"#{methods.inspect}, but doesn't"
|
637
|
+
end
|
466
638
|
end
|
467
639
|
|
468
|
-
if options.
|
640
|
+
if options.key?(:address_resolution)
|
469
641
|
address_resolution = options.delete(:address_resolution)
|
470
642
|
|
471
643
|
case address_resolution
|
472
644
|
when :none
|
473
645
|
# do nothing
|
474
646
|
when :ec2_multi_region
|
475
|
-
options[:address_resolution_policy] =
|
647
|
+
options[:address_resolution_policy] =
|
648
|
+
AddressResolution::Policies::EC2MultiRegion.new
|
476
649
|
else
|
477
|
-
raise ::ArgumentError,
|
650
|
+
raise ::ArgumentError,
|
651
|
+
':address_resolution must be either :none or :ec2_multi_region, ' \
|
652
|
+
"#{address_resolution.inspect} given"
|
478
653
|
end
|
479
654
|
end
|
480
655
|
|
481
|
-
if options.
|
656
|
+
if options.key?(:address_resolution_policy)
|
482
657
|
address_resolver = options[:address_resolution_policy]
|
483
658
|
|
484
|
-
Util.assert_responds_to(:resolve, address_resolver)
|
659
|
+
Util.assert_responds_to(:resolve, address_resolver) do
|
660
|
+
':address_resolution_policy must respond to :resolve, ' \
|
661
|
+
"#{address_resolver.inspect} but doesn't"
|
662
|
+
end
|
485
663
|
end
|
486
664
|
|
487
|
-
if options.
|
665
|
+
if options.key?(:synchronize_schema)
|
488
666
|
options[:synchronize_schema] = !!options[:synchronize_schema]
|
489
667
|
end
|
490
668
|
|
491
|
-
if options.
|
669
|
+
if options.key?(:client_timestamps)
|
492
670
|
options[:client_timestamps] = !!options[:client_timestamps]
|
493
671
|
end
|
494
672
|
|
495
|
-
|
673
|
+
if options.key?(:connections_per_local_node)
|
674
|
+
connections_per_node = options[:connections_per_local_node]
|
496
675
|
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
hosts << ::IPAddr.new(ip)
|
676
|
+
unless connections_per_node.nil?
|
677
|
+
connections_per_node = options[:connections_per_local_node]
|
678
|
+
Util.assert_instance_of(::Integer, connections_per_node)
|
679
|
+
Util.assert_one_of(1...2**16, connections_per_node) do
|
680
|
+
':connections_per_local_node must be a positive integer between ' \
|
681
|
+
"1 and 65535, #{connections_per_node.inspect} given"
|
504
682
|
end
|
505
|
-
else
|
506
|
-
raise ::ArgumentError, ":hosts must be String or IPAddr, #{host.inspect} given"
|
507
683
|
end
|
508
684
|
end
|
509
685
|
|
510
|
-
if
|
511
|
-
|
686
|
+
if options.key?(:connections_per_remote_node)
|
687
|
+
connections_per_node = options[:connections_per_remote_node]
|
688
|
+
|
689
|
+
unless connections_per_node.nil?
|
690
|
+
connections_per_node = options[:connections_per_remote_node]
|
691
|
+
Util.assert_instance_of(::Integer, connections_per_node)
|
692
|
+
Util.assert_one_of(1...2**16, connections_per_node) do
|
693
|
+
':connections_per_remote_node must be a positive integer between ' \
|
694
|
+
"1 and 65535, #{connections_per_node.inspect} given"
|
695
|
+
end
|
696
|
+
end
|
512
697
|
end
|
513
698
|
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
699
|
+
if options.key?(:requests_per_connection)
|
700
|
+
requests_per_connection = options[:requests_per_connection]
|
701
|
+
|
702
|
+
unless requests_per_connection.nil?
|
703
|
+
requests_per_connection = options[:requests_per_connection]
|
704
|
+
Util.assert_instance_of(::Integer, requests_per_connection)
|
705
|
+
|
706
|
+
# v3 protocol says that max stream-id is 32767 (2^15-1). This setting might be
|
707
|
+
# used to talk to a v2 (or less) node, but then we'll adjust it down.
|
708
|
+
|
709
|
+
Util.assert_one_of(1...2**15, requests_per_connection) do
|
710
|
+
':requests_per_connection must be a positive integer, ' \
|
711
|
+
"#{requests_per_connection.inspect} given"
|
712
|
+
end
|
713
|
+
end
|
714
|
+
end
|
715
|
+
options
|
521
716
|
end
|
522
717
|
|
523
718
|
# @private
|
@@ -535,7 +730,7 @@ module Cassandra
|
|
535
730
|
# => 1970-1-1
|
536
731
|
# ::Date.jd(DATE_OFFSET + 2 ** 32, ::Date::GREGORIAN)
|
537
732
|
# => 5881580-07-12
|
538
|
-
DATE_OFFSET = (::Time.utc(1970, 1, 1).to_date.jd - 2
|
733
|
+
DATE_OFFSET = (::Time.utc(1970, 1, 1).to_date.jd - 2**31)
|
539
734
|
end
|
540
735
|
|
541
736
|
require 'cassandra/uuid'
|
@@ -550,6 +745,7 @@ require 'cassandra/errors'
|
|
550
745
|
require 'cassandra/compression'
|
551
746
|
require 'cassandra/protocol'
|
552
747
|
require 'cassandra/auth'
|
748
|
+
require 'cassandra/cassandra_logger'
|
553
749
|
require 'cassandra/null_logger'
|
554
750
|
|
555
751
|
require 'cassandra/executors'
|
@@ -565,6 +761,7 @@ require 'cassandra/statements'
|
|
565
761
|
require 'cassandra/aggregate'
|
566
762
|
require 'cassandra/argument'
|
567
763
|
require 'cassandra/function'
|
764
|
+
require 'cassandra/function_collection'
|
568
765
|
require 'cassandra/column'
|
569
766
|
require 'cassandra/table'
|
570
767
|
require 'cassandra/keyspace'
|
@@ -587,7 +784,7 @@ module Cassandra
|
|
587
784
|
# @private
|
588
785
|
VOID_STATEMENT = Statements::Void.new
|
589
786
|
# @private
|
590
|
-
VOID_OPTIONS = Execution::Options.new(
|
787
|
+
VOID_OPTIONS = Execution::Options.new(consistency: :one)
|
591
788
|
# @private
|
592
789
|
NO_HOSTS = Errors::NoHostsAvailable.new
|
593
790
|
end
|