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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +20 -12
  3. data/ext/cassandra_murmur3/cassandra_murmur3.c +178 -0
  4. data/ext/cassandra_murmur3/extconf.rb +2 -0
  5. data/lib/cassandra.rb +132 -24
  6. data/lib/cassandra/auth.rb +5 -5
  7. data/lib/cassandra/client/connector.rb +11 -6
  8. data/lib/cassandra/cluster.rb +47 -23
  9. data/lib/cassandra/cluster/client.rb +5 -4
  10. data/lib/cassandra/cluster/connector.rb +17 -4
  11. data/lib/cassandra/cluster/control_connection.rb +21 -16
  12. data/lib/cassandra/cluster/metadata.rb +124 -0
  13. data/lib/cassandra/cluster/options.rb +5 -3
  14. data/lib/cassandra/cluster/registry.rb +26 -9
  15. data/lib/cassandra/cluster/schema.rb +23 -4
  16. data/lib/cassandra/cluster/schema/partitioners.rb +21 -0
  17. data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +47 -0
  18. data/lib/cassandra/cluster/schema/partitioners/ordered.rb +37 -0
  19. data/lib/cassandra/cluster/schema/partitioners/random.rb +37 -0
  20. data/lib/cassandra/cluster/schema/replication_strategies.rb +21 -0
  21. data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +92 -0
  22. data/lib/cassandra/cluster/schema/replication_strategies/none.rb +39 -0
  23. data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +44 -0
  24. data/lib/cassandra/cluster/schema/type_parser.rb +1 -1
  25. data/lib/cassandra/compression.rb +1 -1
  26. data/lib/cassandra/driver.rb +29 -4
  27. data/lib/cassandra/execution/options.rb +3 -0
  28. data/lib/cassandra/host.rb +9 -5
  29. data/lib/cassandra/keyspace.rb +17 -4
  30. data/lib/cassandra/listener.rb +3 -3
  31. data/lib/cassandra/load_balancing.rb +12 -11
  32. data/lib/cassandra/load_balancing/policies.rb +2 -1
  33. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +1 -1
  34. data/lib/cassandra/load_balancing/policies/round_robin.rb +37 -0
  35. data/lib/cassandra/load_balancing/policies/token_aware.rb +119 -0
  36. data/lib/cassandra/protocol/cql_protocol_handler.rb +2 -2
  37. data/lib/cassandra/reconnection.rb +5 -5
  38. data/lib/cassandra/retry.rb +3 -3
  39. data/lib/cassandra/session.rb +7 -0
  40. data/lib/cassandra/statements/bound.rb +4 -2
  41. data/lib/cassandra/statements/prepared.rb +28 -6
  42. data/lib/cassandra/table.rb +49 -4
  43. data/lib/cassandra/time_uuid.rb +1 -0
  44. data/lib/cassandra/util.rb +0 -2
  45. data/lib/cassandra/version.rb +1 -1
  46. 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 addded support for:
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.each_hosts do |host| # automatically discovers all peers
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
- * [`Cql.connect` options](/api/#connect-class_method)
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
+ }
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile('cassandra_murmur3')
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
- :futures_factory
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 = options.fetch(:hosts, [])
263
- hosts << ::IPAddr.new('127.0.0.1') if hosts.empty?
360
+ hosts = []
264
361
 
265
- hosts.map! do |host|
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
- ::IPAddr.new(host)
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