cassandra-driver 1.0.0.beta.1 → 1.0.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +20 -12
- data/ext/cassandra_murmur3/cassandra_murmur3.c +178 -0
- data/ext/cassandra_murmur3/extconf.rb +2 -0
- data/lib/cassandra.rb +132 -24
- data/lib/cassandra/auth.rb +5 -5
- data/lib/cassandra/client/connector.rb +11 -6
- data/lib/cassandra/cluster.rb +47 -23
- data/lib/cassandra/cluster/client.rb +5 -4
- data/lib/cassandra/cluster/connector.rb +17 -4
- data/lib/cassandra/cluster/control_connection.rb +21 -16
- data/lib/cassandra/cluster/metadata.rb +124 -0
- data/lib/cassandra/cluster/options.rb +5 -3
- data/lib/cassandra/cluster/registry.rb +26 -9
- data/lib/cassandra/cluster/schema.rb +23 -4
- data/lib/cassandra/cluster/schema/partitioners.rb +21 -0
- data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +47 -0
- data/lib/cassandra/cluster/schema/partitioners/ordered.rb +37 -0
- data/lib/cassandra/cluster/schema/partitioners/random.rb +37 -0
- data/lib/cassandra/cluster/schema/replication_strategies.rb +21 -0
- data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +92 -0
- data/lib/cassandra/cluster/schema/replication_strategies/none.rb +39 -0
- data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +44 -0
- data/lib/cassandra/cluster/schema/type_parser.rb +1 -1
- data/lib/cassandra/compression.rb +1 -1
- data/lib/cassandra/driver.rb +29 -4
- data/lib/cassandra/execution/options.rb +3 -0
- data/lib/cassandra/host.rb +9 -5
- data/lib/cassandra/keyspace.rb +17 -4
- data/lib/cassandra/listener.rb +3 -3
- data/lib/cassandra/load_balancing.rb +12 -11
- data/lib/cassandra/load_balancing/policies.rb +2 -1
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +1 -1
- data/lib/cassandra/load_balancing/policies/round_robin.rb +37 -0
- data/lib/cassandra/load_balancing/policies/token_aware.rb +119 -0
- data/lib/cassandra/protocol/cql_protocol_handler.rb +2 -2
- data/lib/cassandra/reconnection.rb +5 -5
- data/lib/cassandra/retry.rb +3 -3
- data/lib/cassandra/session.rb +7 -0
- data/lib/cassandra/statements/bound.rb +4 -2
- data/lib/cassandra/statements/prepared.rb +28 -6
- data/lib/cassandra/table.rb +49 -4
- data/lib/cassandra/time_uuid.rb +1 -0
- data/lib/cassandra/util.rb +0 -2
- data/lib/cassandra/version.rb +1 -1
- metadata +50 -45
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 64e457a1343d136c65ff074454ac9e0cb42d29e4
|
4
|
+
data.tar.gz: 2ad5d0fc62e3e7655600de5e6096c98ec5458148
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 016bd646cd22533d0b59966ff936829bfc60e785355c7badff6ac8d2d71d6be094402b4539db74460579033209d27fc521945c16b89798e4647e4a791a02d792
|
7
|
+
data.tar.gz: c02fdbbd1faa6e2cacdd627d375116a5ad409ab1c430a1aa1f1ce3b2d1a71bcb7273e5676364507150e6581d409af006685d84cfae7d20904727d77382844240
|
data/README.md
CHANGED
@@ -12,12 +12,12 @@ the Cassandra Query Language version 3 (CQL3) and Cassandra's native protocol.
|
|
12
12
|
- IRC: #datastax-drivers on [irc.freenode.net](http://freenode.net>)
|
13
13
|
- TWITTER: Follow the latest news about DataStax Drivers - [@avalanche123](http://twitter.com/avalanche123), [@mfiguiere](http://twitter.com/mfiguiere), [@al3xandru](https://twitter.com/al3xandru)
|
14
14
|
|
15
|
-
This driver is based on [the cql-rb gem](https://github.com/iconara/cql-rb) by [Theo Hultberg](https://github.com/iconara) and we
|
15
|
+
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:
|
16
16
|
|
17
|
-
* [asynchronous execution](/features/asynchronous_io/)
|
18
|
-
* one-off, [prepared](/features/prepared_statements/) and [batch statements](/features/batch_statements/)
|
17
|
+
* [asynchronous execution](http://datastax.github.io/ruby-driver/features/asynchronous_io/)
|
18
|
+
* one-off, [prepared](http://datastax.github.io/ruby-driver/features/basics/prepared_statements/) and [batch statements](http://datastax.github.io/ruby-driver/features/basics/batch_statements/)
|
19
19
|
* automatic peer discovery and cluster metadata
|
20
|
-
* various [load-balancing](/features/load_balancing/), [retry](/features/retry_policies/) and reconnection policies, [with ability to write your own](/features/load_balancing/implementing_a_policy/)
|
20
|
+
* various [load-balancing](http://datastax.github.io/ruby-driver/features/load_balancing/), [retry](http://datastax.github.io/ruby-driver/features/retry_policies/) and reconnection policies, [with ability to write your own](http://datastax.github.io/ruby-driver/features/load_balancing/implementing_a_policy/)
|
21
21
|
|
22
22
|
## Compability
|
23
23
|
|
@@ -37,7 +37,7 @@ require 'cassandra'
|
|
37
37
|
|
38
38
|
cluster = Cassandra.connect # connects to localhost by default
|
39
39
|
|
40
|
-
cluster.
|
40
|
+
cluster.each_host do |host| # automatically discovers all peers
|
41
41
|
puts "Host #{host.ip}: id=#{host.id} datacenter=#{host.datacenter} rack=#{host.rack}"
|
42
42
|
end
|
43
43
|
|
@@ -57,34 +57,42 @@ The host you specify is just a seed node, the driver will automatically discover
|
|
57
57
|
|
58
58
|
Read more:
|
59
59
|
|
60
|
-
* [`
|
61
|
-
* [`Session#execute_async` options](/api/session/#execute_async-instance_method)
|
62
|
-
* [Usage documentation](/features)
|
60
|
+
* [`Cassandra.connect` options](http://datastax.github.io/ruby-driver/api/#connect-class_method)
|
61
|
+
* [`Session#execute_async` options](http://datastax.github.io/ruby-driver/api/session/#execute_async-instance_method)
|
62
|
+
* [Usage documentation](http://datastax.github.io/ruby-driver/features)
|
63
63
|
|
64
64
|
## Installation
|
65
65
|
|
66
66
|
Install via rubygems
|
67
67
|
|
68
68
|
```bash
|
69
|
-
gem install cassandra-driver
|
69
|
+
gem install cassandra-driver --pre
|
70
70
|
```
|
71
71
|
|
72
72
|
Install via Gemfile
|
73
73
|
|
74
74
|
```ruby
|
75
|
-
gem 'cassandra-driver'
|
75
|
+
gem 'cassandra-driver', '~> 1.0.0.beta'
|
76
76
|
```
|
77
77
|
|
78
|
-
Note: if you want to use compression you should also install [snappy](http://rubygems.org/gems/snappy) or [lz4-ruby](http://rubygems.org/gems/lz4-ruby). [Read more about compression.](/features/#compression)
|
78
|
+
Note: if you want to use compression you should also install [snappy](http://rubygems.org/gems/snappy) or [lz4-ruby](http://rubygems.org/gems/lz4-ruby). [Read more about compression.](http://datastax.github.io/ruby-driver/features/#compression)
|
79
79
|
|
80
80
|
|
81
81
|
## Upgrading from cql-rb
|
82
82
|
|
83
83
|
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.
|
84
84
|
|
85
|
+
## What's new in v1.0.0.beta.2
|
86
|
+
|
87
|
+
Current release introduces the following new features:
|
88
|
+
|
89
|
+
* TokenAware load balancing policy
|
90
|
+
* Domain names
|
91
|
+
* SSL encryption
|
92
|
+
|
85
93
|
## Changelog & versioning
|
86
94
|
|
87
|
-
Check out the [releases on GitHub](https://github.com/datastax/ruby-driver/releases). Version numbering follows the [semantic versioning](http://semver.org/) scheme.
|
95
|
+
Check out the [releases on GitHub](https://github.com/datastax/ruby-driver/releases) and [changelog](https://github.com/datastax/ruby-driver/blob/master/CHANGELOG.md). Version numbering follows the [semantic versioning](http://semver.org/) scheme.
|
88
96
|
|
89
97
|
Private and experimental APIs, defined as whatever is not in the [public API documentation][1], i.e. classes and methods marked as `@private`, will change without warning. If you've been recommended to try an experimental API by the maintainers, please let them know if you depend on that API. Experimental APIs will eventually become public, and knowing how they are used helps in determining their maturity.
|
90
98
|
|
@@ -0,0 +1,178 @@
|
|
1
|
+
// Copyright 2013-2014 DataStax, Inc.
|
2
|
+
//
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
// you may not use this file except in compliance with the License.
|
5
|
+
// You may obtain a copy of the License at
|
6
|
+
//
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
//
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
// See the License for the specific language governing permissions and
|
13
|
+
// limitations under the License.
|
14
|
+
|
15
|
+
#include <ruby.h>
|
16
|
+
|
17
|
+
/*-----------------------------------------------------------------------------
|
18
|
+
* MurmurHash3 was written by Austin Appleby, and is placed in the public
|
19
|
+
* domain. The author hereby disclaims copyright to this source code.
|
20
|
+
*/
|
21
|
+
|
22
|
+
//-----------------------------------------------------------------------------
|
23
|
+
// Platform-specific functions and macros
|
24
|
+
|
25
|
+
#ifdef _MSC_VER
|
26
|
+
typedef unsigned __int64 uint64_t;
|
27
|
+
typedef __int64 int64_t;
|
28
|
+
|
29
|
+
#define FORCE_INLINE __forceinline
|
30
|
+
#else
|
31
|
+
#include <stdint.h>
|
32
|
+
#ifdef __GNUC__
|
33
|
+
#define FORCE_INLINE __attribute__((always_inline)) inline
|
34
|
+
#else
|
35
|
+
#define FORCE_INLINE inline
|
36
|
+
#endif
|
37
|
+
#endif
|
38
|
+
|
39
|
+
#define BIG_CONSTANT(x) (x##LLU)
|
40
|
+
|
41
|
+
static FORCE_INLINE int64_t
|
42
|
+
rotl(int64_t x, int8_t r)
|
43
|
+
{
|
44
|
+
// cast to unsigned for logical right bitshift (to match C* MM3 implementation)
|
45
|
+
return (x << r) | ((int64_t) (((uint64_t) x) >> (64 - r)));
|
46
|
+
}
|
47
|
+
|
48
|
+
static FORCE_INLINE int64_t
|
49
|
+
getblock(const int64_t* p, int i)
|
50
|
+
{
|
51
|
+
return p[i];
|
52
|
+
}
|
53
|
+
|
54
|
+
static FORCE_INLINE int64_t
|
55
|
+
fmix(int64_t k)
|
56
|
+
{
|
57
|
+
// cast to unsigned for logical right bitshift (to match C* MM3 implementation)
|
58
|
+
k ^= ((uint64_t) k) >> 33;
|
59
|
+
k *= BIG_CONSTANT(0xff51afd7ed558ccd);
|
60
|
+
k ^= ((uint64_t) k) >> 33;
|
61
|
+
k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
|
62
|
+
k ^= ((uint64_t) k) >> 33;
|
63
|
+
|
64
|
+
return k;
|
65
|
+
}
|
66
|
+
|
67
|
+
static VALUE
|
68
|
+
rb_murmur3_hash(VALUE self, VALUE rb_string)
|
69
|
+
{
|
70
|
+
char* bytes;
|
71
|
+
int64_t length;
|
72
|
+
|
73
|
+
Check_Type(rb_string, T_STRING);
|
74
|
+
|
75
|
+
bytes = RSTRING_PTR(rb_string);
|
76
|
+
length = RSTRING_LEN(rb_string);
|
77
|
+
|
78
|
+
const int nblocks = length / 16;
|
79
|
+
int i;
|
80
|
+
|
81
|
+
int64_t h1 = 0;
|
82
|
+
int64_t h2 = 0;
|
83
|
+
|
84
|
+
int64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
|
85
|
+
int64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
|
86
|
+
|
87
|
+
//----------
|
88
|
+
// body
|
89
|
+
|
90
|
+
const int64_t* blocks = (const int64_t*)(bytes);
|
91
|
+
|
92
|
+
for(i = 0; i < nblocks; i++)
|
93
|
+
{
|
94
|
+
int64_t k1 = getblock(blocks, i * 2 + 0);
|
95
|
+
int64_t k2 = getblock(blocks, i * 2 + 1);
|
96
|
+
|
97
|
+
k1 *= c1;
|
98
|
+
k1 = rotl(k1, 31);
|
99
|
+
k1 *= c2;
|
100
|
+
h1 ^= k1;
|
101
|
+
|
102
|
+
h1 = rotl(h1, 27);
|
103
|
+
h1 += h2;
|
104
|
+
h1 = h1 * 5 + 0x52dce729;
|
105
|
+
|
106
|
+
k2 *= c2;
|
107
|
+
k2 = rotl(k2, 33);
|
108
|
+
k2 *= c1;
|
109
|
+
h2 ^= k2;
|
110
|
+
|
111
|
+
h2 = rotl(h2, 31);
|
112
|
+
h2 += h1;
|
113
|
+
h2 = h2 * 5 + 0x38495ab5;
|
114
|
+
}
|
115
|
+
|
116
|
+
//----------
|
117
|
+
// tail
|
118
|
+
|
119
|
+
const int8_t* tail = (const int8_t*) (bytes + nblocks * 16);
|
120
|
+
|
121
|
+
int64_t k1 = 0;
|
122
|
+
int64_t k2 = 0;
|
123
|
+
|
124
|
+
switch(length & 15)
|
125
|
+
{
|
126
|
+
case 15: k2 ^= ((int64_t) tail[14]) << 48;
|
127
|
+
case 14: k2 ^= ((int64_t) tail[13]) << 40;
|
128
|
+
case 13: k2 ^= ((int64_t) tail[12]) << 32;
|
129
|
+
case 12: k2 ^= ((int64_t) tail[11]) << 24;
|
130
|
+
case 11: k2 ^= ((int64_t) tail[10]) << 16;
|
131
|
+
case 10: k2 ^= ((int64_t) tail[ 9]) << 8;
|
132
|
+
case 9: k2 ^= ((int64_t) tail[ 8]) << 0;
|
133
|
+
k2 *= c2;
|
134
|
+
k2 = rotl(k2, 33);
|
135
|
+
k2 *= c1;
|
136
|
+
h2 ^= k2;
|
137
|
+
case 8: k1 ^= ((int64_t) tail[7]) << 56;
|
138
|
+
case 7: k1 ^= ((int64_t) tail[6]) << 48;
|
139
|
+
case 6: k1 ^= ((int64_t) tail[5]) << 40;
|
140
|
+
case 5: k1 ^= ((int64_t) tail[4]) << 32;
|
141
|
+
case 4: k1 ^= ((int64_t) tail[3]) << 24;
|
142
|
+
case 3: k1 ^= ((int64_t) tail[2]) << 16;
|
143
|
+
case 2: k1 ^= ((int64_t) tail[1]) << 8;
|
144
|
+
case 1: k1 ^= ((int64_t) tail[0]) << 0;
|
145
|
+
k1 *= c1;
|
146
|
+
k1 = rotl(k1, 31);
|
147
|
+
k1 *= c2;
|
148
|
+
h1 ^= k1;
|
149
|
+
};
|
150
|
+
|
151
|
+
//----------
|
152
|
+
// finalization
|
153
|
+
|
154
|
+
h1 ^= length;
|
155
|
+
h2 ^= length;
|
156
|
+
|
157
|
+
h1 += h2;
|
158
|
+
h2 += h1;
|
159
|
+
|
160
|
+
h1 = fmix(h1);
|
161
|
+
h2 = fmix(h2);
|
162
|
+
|
163
|
+
h1 += h2;
|
164
|
+
h2 += h1;
|
165
|
+
|
166
|
+
return LL2NUM(h1);
|
167
|
+
}
|
168
|
+
|
169
|
+
void
|
170
|
+
Init_cassandra_murmur3()
|
171
|
+
{
|
172
|
+
VALUE mCassandra, mMurmur3;
|
173
|
+
|
174
|
+
mCassandra = rb_define_module_under(rb_cObject, "Cassandra");
|
175
|
+
mMurmur3 = rb_define_module_under(mCassandra, "Murmur3");
|
176
|
+
|
177
|
+
rb_define_module_function(mMurmur3, "hash", rb_murmur3_hash, 1);
|
178
|
+
}
|
data/lib/cassandra.rb
CHANGED
@@ -26,6 +26,10 @@ require 'set'
|
|
26
26
|
require 'bigdecimal'
|
27
27
|
require 'forwardable'
|
28
28
|
require 'timeout'
|
29
|
+
require 'digest'
|
30
|
+
require 'stringio'
|
31
|
+
require 'resolv'
|
32
|
+
require 'openssl'
|
29
33
|
|
30
34
|
module Cassandra
|
31
35
|
# A list of all supported request consistencies
|
@@ -42,55 +46,77 @@ module Cassandra
|
|
42
46
|
# @option options [Array<String, IPAddr>] :hosts (['127.0.0.1']) a list of
|
43
47
|
# initial addresses. Note that the entire list of cluster members will be
|
44
48
|
# discovered automatically once a connection to any hosts from the original
|
45
|
-
# list is successful
|
49
|
+
# list is successful.
|
46
50
|
#
|
47
|
-
# @option options [Integer] :port (9042) cassandra native protocol port
|
51
|
+
# @option options [Integer] :port (9042) cassandra native protocol port.
|
52
|
+
#
|
53
|
+
# @option options [Numeric] :connect_timeout (10) connection timeout in
|
54
|
+
# seconds.
|
48
55
|
#
|
49
56
|
# @option options [String] :username (none) username to use for
|
50
|
-
# authentication to cassandra. Note that you must also specify `:password
|
57
|
+
# authentication to cassandra. Note that you must also specify `:password`.
|
51
58
|
#
|
52
59
|
# @option options [String] :password (none) password to use for
|
53
|
-
# authentication to cassandra. Note that you must also specify `:username
|
60
|
+
# authentication to cassandra. Note that you must also specify `:username`.
|
61
|
+
#
|
62
|
+
# @option options [Boolean, OpenSSL::SSL::SSLContext] :ssl (false) enable
|
63
|
+
# default ssl authentication if `true` (not recommended). Also accepts an
|
64
|
+
# initialized {OpenSSL::SSL::SSLContext}. Note that this option should be
|
65
|
+
# ignored if `:server_cert`, `:client_cert`, `:private_key` or
|
66
|
+
# `:passphrase` are given.
|
67
|
+
#
|
68
|
+
# @option options [String] :server_cert (none) path to server certificate or
|
69
|
+
# certificate authority file.
|
70
|
+
#
|
71
|
+
# @option options [String] :client_cert (none) path to client certificate
|
72
|
+
# file. Note that this option is only required when encryption is
|
73
|
+
# configured to require client authentication.
|
74
|
+
#
|
75
|
+
# @option options [String] :private_key (none) path to client private key.
|
76
|
+
# Note that this option is only required when encryption is configured to
|
77
|
+
# require client authentication.
|
78
|
+
#
|
79
|
+
# @option options [String] :passphrase (none) passphrase for private key.
|
54
80
|
#
|
55
81
|
# @option options [Symbol] :compression (none) compression to use. Must be
|
56
82
|
# either `:snappy` or `:lz4`. Also note, that in order for compression to
|
57
|
-
# work, you must install 'snappy' or 'lz4-ruby' gems
|
83
|
+
# work, you must install 'snappy' or 'lz4-ruby' gems.
|
58
84
|
#
|
59
85
|
# @option options [Cassandra::LoadBalancing::Policy] :load_balancing_policy
|
60
|
-
# default: {Cassandra::LoadBalancing::Policies::RoundRobin}
|
86
|
+
# default: {Cassandra::LoadBalancing::Policies::RoundRobin}.
|
61
87
|
#
|
62
88
|
# @option options [Cassandra::Reconnection::Policy] :reconnection_policy
|
63
89
|
# default: {Cassandra::Reconnection::Policies::Exponential}. Note that the
|
64
90
|
# default policy is configured with
|
65
|
-
# `Reconnection::Policies::Exponential.new(0.5, 30, 2)
|
91
|
+
# `Reconnection::Policies::Exponential.new(0.5, 30, 2)`.
|
66
92
|
#
|
67
93
|
# @option options [Cassandra::Retry::Policy] :retry_policy default:
|
68
|
-
# {Cassandra::Retry::Policies::Default}
|
94
|
+
# {Cassandra::Retry::Policies::Default}.
|
69
95
|
#
|
70
96
|
# @option options [Logger] :logger (none) logger. a {Logger} instance from the
|
71
97
|
# standard library or any object responding to standard log methods
|
72
|
-
# (`#debug`, `#info`, `#warn`, `#error` and `#fatal`)
|
98
|
+
# (`#debug`, `#info`, `#warn`, `#error` and `#fatal`).
|
73
99
|
#
|
74
100
|
# @option options [Enumerable<Cassandra::Listener>] :listeners (none)
|
75
101
|
# initial listeners. A list of initial cluster state listeners. Note that a
|
76
|
-
# load_balancing policy is automatically registered with the cluster.
|
102
|
+
# `:load_balancing` policy is automatically registered with the cluster.
|
77
103
|
#
|
78
104
|
# @option options [Symbol] :consistency (:quorum) default consistency to use
|
79
|
-
# for all requests. Must be one of {Cassandra::CONSISTENCIES}
|
105
|
+
# for all requests. Must be one of {Cassandra::CONSISTENCIES}.
|
80
106
|
#
|
81
107
|
# @option options [Boolean] :trace (false) whether or not to trace all
|
82
|
-
# requests by default
|
108
|
+
# requests by default.
|
83
109
|
#
|
84
110
|
# @option options [Integer] :page_size (nil) default page size for all select
|
85
|
-
# queries
|
111
|
+
# queries.
|
86
112
|
#
|
87
|
-
# @option options [Hash{String => String}] :credentials (none) a hash of credentials - to be used with [credentials authentication in cassandra 1.2](https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L238-L250). Note that if you specified `:username` and `:password` options, those credentials are configured automatically
|
113
|
+
# @option options [Hash{String => String}] :credentials (none) a hash of credentials - to be used with [credentials authentication in cassandra 1.2](https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v1.spec#L238-L250). Note that if you specified `:username` and `:password` options, those credentials are configured automatically.
|
88
114
|
#
|
89
|
-
# @option options [Cassandra::Auth::Provider] :auth_provider (none) a custom auth provider to be used with [SASL authentication in cassandra 2.0](https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v2.spec#L257-L273). Note that if you have specified `:username` and `:password`, then a {Cassandra::Auth::Providers::Password} will be used automatically
|
115
|
+
# @option options [Cassandra::Auth::Provider] :auth_provider (none) a custom auth provider to be used with [SASL authentication in cassandra 2.0](https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v2.spec#L257-L273). Note that if you have specified `:username` and `:password`, then a {Cassandra::Auth::Providers::Password} will be used automatically.
|
90
116
|
#
|
91
117
|
# @option options [Cassandra::Compressor] :compressor (none) a custom
|
92
118
|
# compressor. Note that if you have specified `:compression`, an
|
93
|
-
# appropriate compressor will be provided automatically
|
119
|
+
# appropriate compressor will be provided automatically.
|
94
120
|
#
|
95
121
|
# @option options [Object<#all, #error, #value, #promise>] :futures_factory
|
96
122
|
# (none) a custom futures factory to assist with integration into existing
|
@@ -114,7 +140,8 @@ module Cassandra
|
|
114
140
|
[ :credentials, :auth_provider, :compression, :hosts, :logger, :port,
|
115
141
|
:load_balancing_policy, :reconnection_policy, :retry_policy, :listeners,
|
116
142
|
:consistency, :trace, :page_size, :compressor, :username, :password,
|
117
|
-
:
|
143
|
+
:ssl, :server_cert, :client_cert, :private_key, :passphrase,
|
144
|
+
:connect_timeout, :futures_factory
|
118
145
|
].include?(key)
|
119
146
|
end
|
120
147
|
|
@@ -155,6 +182,69 @@ module Cassandra
|
|
155
182
|
end
|
156
183
|
end
|
157
184
|
|
185
|
+
has_client_cert = options.has_key?(:client_cert)
|
186
|
+
has_private_key = options.has_key?(:private_key)
|
187
|
+
|
188
|
+
if has_client_cert || has_private_key
|
189
|
+
if has_client_cert && !has_private_key
|
190
|
+
raise ::ArgumentError, "both :client_cert and :private_key options must be specified, but only :client_cert given"
|
191
|
+
end
|
192
|
+
|
193
|
+
if !has_client_cert && has_private_key
|
194
|
+
raise ::ArgumentError, "both :client_cert and :private_key options must be specified, but only :private_key given"
|
195
|
+
end
|
196
|
+
|
197
|
+
client_cert = ::File.expand_path(options[:client_cert])
|
198
|
+
private_key = ::File.expand_path(options[:private_key])
|
199
|
+
|
200
|
+
unless ::File.exists?(client_cert)
|
201
|
+
raise ::ArgumentError, ":client_cert #{client_cert.inspect} doesn't exist"
|
202
|
+
end
|
203
|
+
|
204
|
+
unless ::File.exists?(private_key)
|
205
|
+
raise ::ArgumentError, ":private_key #{private_key.inspect} doesn't exist"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
has_server_cert = options.has_key?(:server_cert)
|
210
|
+
|
211
|
+
if has_server_cert
|
212
|
+
server_cert = ::File.expand_path(options[:server_cert])
|
213
|
+
|
214
|
+
unless ::File.exists?(server_cert)
|
215
|
+
raise ::ArgumentError, ":server_cert #{server_cert.inspect} doesn't exist"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
if has_client_cert || has_server_cert
|
220
|
+
context = ::OpenSSL::SSL::SSLContext.new
|
221
|
+
|
222
|
+
if has_server_cert
|
223
|
+
context.ca_file = server_cert
|
224
|
+
context.verify_mode = ::OpenSSL::SSL::VERIFY_PEER
|
225
|
+
end
|
226
|
+
|
227
|
+
if has_client_cert
|
228
|
+
context.cert = ::OpenSSL::X509::Certificate.new(File.read(client_cert))
|
229
|
+
|
230
|
+
if options.has_key?(:passphrase)
|
231
|
+
context.key = ::OpenSSL::PKey::RSA.new(File.read(private_key), options[:passphrase])
|
232
|
+
else
|
233
|
+
context.key = ::OpenSSL::PKey::RSA.new(File.read(private_key))
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
options[:ssl] = context
|
238
|
+
end
|
239
|
+
|
240
|
+
if options.has_key?(:ssl)
|
241
|
+
ssl = options[:ssl]
|
242
|
+
|
243
|
+
unless ssl.is_a?(::TrueClass) || ssl.is_a?(::FalseClass) || ssl.is_a?(::OpenSSL::SSL::SSLContext)
|
244
|
+
raise ":ssl must be a boolean or an OpenSSL::SSL::SSLContext, #{ssl.inspect} given"
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
158
248
|
if options.has_key?(:compression)
|
159
249
|
compression = options.delete(:compression)
|
160
250
|
|
@@ -196,9 +286,17 @@ module Cassandra
|
|
196
286
|
end
|
197
287
|
end
|
198
288
|
|
289
|
+
if options.has_key?(:connect_timeout)
|
290
|
+
timeout = options[:connect_timeout] = Integer(options[:connect_timeout])
|
291
|
+
|
292
|
+
if timeout < 0
|
293
|
+
raise ::ArgumentError, ":connect_timeout must be a positive value, #{timeout.given}"
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
199
297
|
if options.has_key?(:load_balancing_policy)
|
200
298
|
load_balancing_policy = options[:load_balancing_policy]
|
201
|
-
methods = [:host_up, :host_down, :host_found, :host_lost, :distance, :plan]
|
299
|
+
methods = [:host_up, :host_down, :host_found, :host_lost, :setup, :distance, :plan]
|
202
300
|
|
203
301
|
unless methods.all? {|method| load_balancing_policy.respond_to?(method)}
|
204
302
|
raise ::ArgumentError, ":load_balancing_policy #{load_balancing_policy.inspect} must respond to #{methods.inspect}, but doesn't"
|
@@ -259,20 +357,25 @@ module Cassandra
|
|
259
357
|
end
|
260
358
|
end
|
261
359
|
|
262
|
-
hosts =
|
263
|
-
hosts << ::IPAddr.new('127.0.0.1') if hosts.empty?
|
360
|
+
hosts = []
|
264
361
|
|
265
|
-
hosts.
|
362
|
+
Array(options.fetch(:hosts, '127.0.0.1')).each do |host|
|
266
363
|
case host
|
267
364
|
when ::IPAddr
|
268
|
-
host
|
269
|
-
when ::String
|
270
|
-
|
365
|
+
hosts << host
|
366
|
+
when ::String # ip address or hostname
|
367
|
+
Resolv.each_address(host) do |ip|
|
368
|
+
hosts << ::IPAddr.new(ip)
|
369
|
+
end
|
271
370
|
else
|
272
371
|
raise ::ArgumentError, ":hosts must be String or IPAddr, #{host.inspect} given"
|
273
372
|
end
|
274
373
|
end
|
275
374
|
|
375
|
+
if hosts.empty?
|
376
|
+
raise ::ArgumentError, ":hosts #{options[:hosts].inspect} could not be resolved to any ip address"
|
377
|
+
end
|
378
|
+
|
276
379
|
Driver.new(options).connect(hosts).value
|
277
380
|
end
|
278
381
|
end
|
@@ -308,6 +411,9 @@ require 'cassandra/retry'
|
|
308
411
|
|
309
412
|
require 'cassandra/util'
|
310
413
|
|
414
|
+
# murmur3 hash extension
|
415
|
+
require 'cassandra_murmur3'
|
416
|
+
|
311
417
|
module Cassandra
|
312
418
|
# @private
|
313
419
|
Io = Ione::Io
|
@@ -317,4 +423,6 @@ module Cassandra
|
|
317
423
|
VOID_OPTIONS = Execution::Options.new({:consistency => :one})
|
318
424
|
# @private
|
319
425
|
NO_HOSTS = Errors::NoHostsAvailable.new
|
426
|
+
# @private
|
427
|
+
EMPTY_LIST = [].freeze
|
320
428
|
end
|