yugabyte-ycql-driver 3.2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +13 -0
- data/README.md +242 -0
- data/ext/cassandra_murmur3/cassandra_murmur3.c +178 -0
- data/ext/cassandra_murmur3/extconf.rb +2 -0
- data/lib/cassandra/address_resolution.rb +36 -0
- data/lib/cassandra/address_resolution/policies.rb +2 -0
- data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +56 -0
- data/lib/cassandra/address_resolution/policies/none.rb +35 -0
- data/lib/cassandra/aggregate.rb +123 -0
- data/lib/cassandra/argument.rb +51 -0
- data/lib/cassandra/attr_boolean.rb +33 -0
- data/lib/cassandra/auth.rb +100 -0
- data/lib/cassandra/auth/providers.rb +17 -0
- data/lib/cassandra/auth/providers/password.rb +65 -0
- data/lib/cassandra/cassandra_logger.rb +80 -0
- data/lib/cassandra/cluster.rb +331 -0
- data/lib/cassandra/cluster/client.rb +1612 -0
- data/lib/cassandra/cluster/connection_pool.rb +78 -0
- data/lib/cassandra/cluster/connector.rb +372 -0
- data/lib/cassandra/cluster/control_connection.rb +962 -0
- data/lib/cassandra/cluster/failed_connection.rb +35 -0
- data/lib/cassandra/cluster/metadata.rb +142 -0
- data/lib/cassandra/cluster/options.rb +145 -0
- data/lib/cassandra/cluster/registry.rb +284 -0
- data/lib/cassandra/cluster/schema.rb +405 -0
- data/lib/cassandra/cluster/schema/cql_type_parser.rb +112 -0
- data/lib/cassandra/cluster/schema/fetchers.rb +1627 -0
- data/lib/cassandra/cluster/schema/fqcn_type_parser.rb +175 -0
- data/lib/cassandra/cluster/schema/partitioners.rb +21 -0
- data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +45 -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 +102 -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/column.rb +66 -0
- data/lib/cassandra/column_container.rb +326 -0
- data/lib/cassandra/compression.rb +69 -0
- data/lib/cassandra/compression/compressors/lz4.rb +73 -0
- data/lib/cassandra/compression/compressors/snappy.rb +69 -0
- data/lib/cassandra/custom_data.rb +53 -0
- data/lib/cassandra/driver.rb +260 -0
- data/lib/cassandra/errors.rb +784 -0
- data/lib/cassandra/execution/info.rb +69 -0
- data/lib/cassandra/execution/options.rb +267 -0
- data/lib/cassandra/execution/profile.rb +153 -0
- data/lib/cassandra/execution/profile_manager.rb +71 -0
- data/lib/cassandra/execution/trace.rb +192 -0
- data/lib/cassandra/executors.rb +113 -0
- data/lib/cassandra/function.rb +156 -0
- data/lib/cassandra/function_collection.rb +85 -0
- data/lib/cassandra/future.rb +794 -0
- data/lib/cassandra/host.rb +102 -0
- data/lib/cassandra/index.rb +118 -0
- data/lib/cassandra/keyspace.rb +473 -0
- data/lib/cassandra/listener.rb +87 -0
- data/lib/cassandra/load_balancing.rb +121 -0
- data/lib/cassandra/load_balancing/policies.rb +20 -0
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +172 -0
- data/lib/cassandra/load_balancing/policies/round_robin.rb +141 -0
- data/lib/cassandra/load_balancing/policies/token_aware.rb +149 -0
- data/lib/cassandra/load_balancing/policies/white_list.rb +100 -0
- data/lib/cassandra/materialized_view.rb +92 -0
- data/lib/cassandra/null_logger.rb +56 -0
- data/lib/cassandra/protocol.rb +102 -0
- data/lib/cassandra/protocol/coder.rb +1085 -0
- data/lib/cassandra/protocol/cql_byte_buffer.rb +418 -0
- data/lib/cassandra/protocol/cql_protocol_handler.rb +448 -0
- data/lib/cassandra/protocol/request.rb +41 -0
- data/lib/cassandra/protocol/requests/auth_response_request.rb +51 -0
- data/lib/cassandra/protocol/requests/batch_request.rb +117 -0
- data/lib/cassandra/protocol/requests/credentials_request.rb +51 -0
- data/lib/cassandra/protocol/requests/execute_request.rb +122 -0
- data/lib/cassandra/protocol/requests/options_request.rb +39 -0
- data/lib/cassandra/protocol/requests/prepare_request.rb +59 -0
- data/lib/cassandra/protocol/requests/query_request.rb +112 -0
- data/lib/cassandra/protocol/requests/register_request.rb +38 -0
- data/lib/cassandra/protocol/requests/startup_request.rb +49 -0
- data/lib/cassandra/protocol/requests/void_query_request.rb +24 -0
- data/lib/cassandra/protocol/response.rb +28 -0
- data/lib/cassandra/protocol/responses/already_exists_error_response.rb +50 -0
- data/lib/cassandra/protocol/responses/auth_challenge_response.rb +36 -0
- data/lib/cassandra/protocol/responses/auth_success_response.rb +36 -0
- data/lib/cassandra/protocol/responses/authenticate_response.rb +36 -0
- data/lib/cassandra/protocol/responses/error_response.rb +142 -0
- data/lib/cassandra/protocol/responses/event_response.rb +30 -0
- data/lib/cassandra/protocol/responses/function_failure_error_response.rb +52 -0
- data/lib/cassandra/protocol/responses/prepared_result_response.rb +62 -0
- data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +59 -0
- data/lib/cassandra/protocol/responses/read_failure_error_response.rb +71 -0
- data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +61 -0
- data/lib/cassandra/protocol/responses/ready_response.rb +43 -0
- data/lib/cassandra/protocol/responses/result_response.rb +42 -0
- data/lib/cassandra/protocol/responses/rows_result_response.rb +39 -0
- data/lib/cassandra/protocol/responses/schema_change_event_response.rb +73 -0
- data/lib/cassandra/protocol/responses/schema_change_result_response.rb +70 -0
- data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +37 -0
- data/lib/cassandra/protocol/responses/status_change_event_response.rb +39 -0
- data/lib/cassandra/protocol/responses/supported_response.rb +36 -0
- data/lib/cassandra/protocol/responses/topology_change_event_response.rb +33 -0
- data/lib/cassandra/protocol/responses/unavailable_error_response.rb +58 -0
- data/lib/cassandra/protocol/responses/unprepared_error_response.rb +48 -0
- data/lib/cassandra/protocol/responses/void_result_response.rb +34 -0
- data/lib/cassandra/protocol/responses/write_failure_error_response.rb +73 -0
- data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +63 -0
- data/lib/cassandra/protocol/v1.rb +326 -0
- data/lib/cassandra/protocol/v3.rb +358 -0
- data/lib/cassandra/protocol/v4.rb +478 -0
- data/lib/cassandra/reconnection.rb +49 -0
- data/lib/cassandra/reconnection/policies.rb +20 -0
- data/lib/cassandra/reconnection/policies/constant.rb +46 -0
- data/lib/cassandra/reconnection/policies/exponential.rb +79 -0
- data/lib/cassandra/result.rb +276 -0
- data/lib/cassandra/retry.rb +154 -0
- data/lib/cassandra/retry/policies.rb +21 -0
- data/lib/cassandra/retry/policies/default.rb +53 -0
- data/lib/cassandra/retry/policies/downgrading_consistency.rb +73 -0
- data/lib/cassandra/retry/policies/fallthrough.rb +39 -0
- data/lib/cassandra/session.rb +270 -0
- data/lib/cassandra/statement.rb +32 -0
- data/lib/cassandra/statements.rb +23 -0
- data/lib/cassandra/statements/batch.rb +146 -0
- data/lib/cassandra/statements/bound.rb +65 -0
- data/lib/cassandra/statements/prepared.rb +235 -0
- data/lib/cassandra/statements/simple.rb +118 -0
- data/lib/cassandra/statements/void.rb +38 -0
- data/lib/cassandra/table.rb +240 -0
- data/lib/cassandra/time.rb +103 -0
- data/lib/cassandra/time_uuid.rb +78 -0
- data/lib/cassandra/timestamp_generator.rb +37 -0
- data/lib/cassandra/timestamp_generator/simple.rb +38 -0
- data/lib/cassandra/timestamp_generator/ticking_on_duplicate.rb +58 -0
- data/lib/cassandra/trigger.rb +67 -0
- data/lib/cassandra/tuple.rb +131 -0
- data/lib/cassandra/types.rb +1704 -0
- data/lib/cassandra/udt.rb +443 -0
- data/lib/cassandra/util.rb +464 -0
- data/lib/cassandra/uuid.rb +110 -0
- data/lib/cassandra/uuid/generator.rb +212 -0
- data/lib/cassandra/version.rb +21 -0
- data/lib/datastax/cassandra.rb +47 -0
- data/lib/ycql.rb +842 -0
- metadata +243 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Copyright DataStax, Inc.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#++
|
|
18
|
+
|
|
19
|
+
module Cassandra
|
|
20
|
+
# Represents a UUID value.
|
|
21
|
+
#
|
|
22
|
+
# This is a very basic implementation of UUIDs and exists more or less just
|
|
23
|
+
# to encode and decode UUIDs from and to Cassandra.
|
|
24
|
+
#
|
|
25
|
+
# If you want to generate UUIDs see {Cassandra::Uuid::Generator}.
|
|
26
|
+
#
|
|
27
|
+
class Uuid
|
|
28
|
+
# @private
|
|
29
|
+
RAW_FORMAT = '%032x'.force_encoding(Encoding::ASCII).freeze
|
|
30
|
+
# @private
|
|
31
|
+
HYPHEN = '-'.force_encoding(Encoding::ASCII).freeze
|
|
32
|
+
# @private
|
|
33
|
+
EMPTY_STRING = ''.freeze
|
|
34
|
+
|
|
35
|
+
# Creates a new UUID either from a string (expected to be on the standard 8-4-4-4-12
|
|
36
|
+
# form, or just 32 characters without hyphens), or from a 128 bit number.
|
|
37
|
+
#
|
|
38
|
+
# @param uuid [String] a 32 char uuid
|
|
39
|
+
#
|
|
40
|
+
# @raise [ArgumentError] if the string does not conform to the expected format
|
|
41
|
+
#
|
|
42
|
+
def initialize(uuid)
|
|
43
|
+
@n = case uuid
|
|
44
|
+
when String
|
|
45
|
+
from_s(uuid)
|
|
46
|
+
else
|
|
47
|
+
uuid
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Returns a string representation of this UUID in the standard 8-4-4-4-12 form.
|
|
52
|
+
#
|
|
53
|
+
def to_s
|
|
54
|
+
@s ||= begin
|
|
55
|
+
s = RAW_FORMAT % @n
|
|
56
|
+
s.insert(20, HYPHEN)
|
|
57
|
+
s.insert(16, HYPHEN)
|
|
58
|
+
s.insert(12, HYPHEN)
|
|
59
|
+
s.insert(8, HYPHEN)
|
|
60
|
+
s
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @private
|
|
65
|
+
def hash
|
|
66
|
+
@h ||= begin
|
|
67
|
+
h = 17
|
|
68
|
+
h = 31 * h + @n.hash
|
|
69
|
+
h
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Returns the numerical representation of this UUID
|
|
74
|
+
#
|
|
75
|
+
# @return [Bignum] the 128 bit numerical representation
|
|
76
|
+
#
|
|
77
|
+
def value
|
|
78
|
+
@n
|
|
79
|
+
end
|
|
80
|
+
alias to_i value
|
|
81
|
+
|
|
82
|
+
# @private
|
|
83
|
+
def eql?(other)
|
|
84
|
+
other.respond_to?(:value) && value == other.value
|
|
85
|
+
end
|
|
86
|
+
alias == eql?
|
|
87
|
+
|
|
88
|
+
if RUBY_ENGINE == 'jruby'
|
|
89
|
+
# @private
|
|
90
|
+
HEX_RE = /^[A-Fa-f0-9]+$/
|
|
91
|
+
# See https://github.com/jruby/jruby/issues/1608
|
|
92
|
+
# @private
|
|
93
|
+
def from_s(str)
|
|
94
|
+
str = str.gsub(HYPHEN, EMPTY_STRING)
|
|
95
|
+
raise ::ArgumentError, "Expected 32 hexadecimal digits but got #{str.length}" unless str.length == 32
|
|
96
|
+
raise ::ArgumentError, "invalid value for Integer(): \"#{str}\"" unless str =~ HEX_RE
|
|
97
|
+
Integer(str, 16)
|
|
98
|
+
end
|
|
99
|
+
else
|
|
100
|
+
# @private
|
|
101
|
+
def from_s(str)
|
|
102
|
+
str = str.gsub(HYPHEN, EMPTY_STRING)
|
|
103
|
+
raise ::ArgumentError, "Expected 32 hexadecimal digits but got #{str.length}" unless str.length == 32
|
|
104
|
+
Integer(str, 16)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
require 'cassandra/uuid/generator'
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Copyright DataStax, Inc.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#++
|
|
18
|
+
|
|
19
|
+
module Cassandra
|
|
20
|
+
class Uuid
|
|
21
|
+
# A UUID generator.
|
|
22
|
+
#
|
|
23
|
+
# This class can be used to genereate Apache Cassandra timeuuid and uuid
|
|
24
|
+
# values.
|
|
25
|
+
#
|
|
26
|
+
# @see Cassandra::Uuid::Generator#now Generating a sequence time UUIDs
|
|
27
|
+
# with reasonable uniqueness guarantees.
|
|
28
|
+
# @see Cassandra::Uuid::Generator#at Generating a time UUID for a given
|
|
29
|
+
# time object or unix timestamp.
|
|
30
|
+
# @see Cassandra::Uuid::Generator#uuid Generating completely random v4
|
|
31
|
+
# UUIDs.
|
|
32
|
+
#
|
|
33
|
+
# @note Instances of this class are absolutely not threadsafe. You should
|
|
34
|
+
# never share instances between threads.
|
|
35
|
+
#
|
|
36
|
+
class Generator
|
|
37
|
+
# Create a new UUID generator.
|
|
38
|
+
#
|
|
39
|
+
# The clock ID and node ID components are set to random numbers when the
|
|
40
|
+
# generator is created. These are used for generation of time UUIDs only.
|
|
41
|
+
#
|
|
42
|
+
# @param [Integer] node_id an alternate node ID
|
|
43
|
+
# @param [Integer] clock_id an alternate clock ID
|
|
44
|
+
# @param [Object<#now>] clock used to generate timeuuid from current time
|
|
45
|
+
#
|
|
46
|
+
# @raise [ArgumentError] if clock doesn't respond to `now`
|
|
47
|
+
def initialize(node_id = (::SecureRandom.random_number(2**47) | 0x010000000000),
|
|
48
|
+
clock_id = ::SecureRandom.random_number(65536),
|
|
49
|
+
clock = ::Time)
|
|
50
|
+
raise ::ArgumentError, 'invalid clock' unless clock.respond_to?(:now)
|
|
51
|
+
|
|
52
|
+
@node_id = Integer(node_id)
|
|
53
|
+
@clock_id = Integer(clock_id)
|
|
54
|
+
@clock = clock
|
|
55
|
+
@last_usecs = nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Returns a new UUID with a time component that is the current time.
|
|
59
|
+
#
|
|
60
|
+
# If two calls to {#now} happen within the time afforded by the system
|
|
61
|
+
# clock resolution a counter is incremented and added to the time
|
|
62
|
+
# component.
|
|
63
|
+
#
|
|
64
|
+
# If the clock moves backwards the clock ID is reset to a new random
|
|
65
|
+
# number.
|
|
66
|
+
#
|
|
67
|
+
# @example Creating a sequential TimeUuids for the current time
|
|
68
|
+
# generator = Cassandra::Uuid::Generator.new
|
|
69
|
+
# timeuuids = 5.times.map { generator.now }
|
|
70
|
+
#
|
|
71
|
+
# puts timeuuids.zip(timeuuids.map(&:to_time)).map(&:inspect)
|
|
72
|
+
#
|
|
73
|
+
# # Outputs:
|
|
74
|
+
# # [8614b7d0-5646-11e4-8e54-6761d3995ef3, 2014-10-17 21:42:42 UTC]
|
|
75
|
+
# # [8614b91a-5646-11e4-8e54-6761d3995ef3, 2014-10-17 21:42:42 UTC]
|
|
76
|
+
# # [8614b960-5646-11e4-8e54-6761d3995ef3, 2014-10-17 21:42:42 UTC]
|
|
77
|
+
# # [8614b99c-5646-11e4-8e54-6761d3995ef3, 2014-10-17 21:42:42 UTC]
|
|
78
|
+
# # [8614b9ce-5646-11e4-8e54-6761d3995ef3, 2014-10-17 21:42:42 UTC]
|
|
79
|
+
#
|
|
80
|
+
# @see Time.now
|
|
81
|
+
#
|
|
82
|
+
# @return [Cassandra::TimeUuid] a new UUID
|
|
83
|
+
def now
|
|
84
|
+
now = @clock.now
|
|
85
|
+
usecs = now.to_i * 1_000_000 + now.usec
|
|
86
|
+
|
|
87
|
+
if @last_usecs && @last_usecs - @sequence <= usecs && usecs <= @last_usecs
|
|
88
|
+
@sequence += 1
|
|
89
|
+
elsif @last_usecs && @last_usecs > usecs
|
|
90
|
+
@sequence = 0
|
|
91
|
+
@clock_id = ::SecureRandom.random_number(65536)
|
|
92
|
+
else
|
|
93
|
+
@sequence = 0
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
@last_usecs = usecs + @sequence
|
|
97
|
+
from_usecs(@last_usecs)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Returns a new UUID with a time component based on the specified Time.
|
|
101
|
+
# A piece of jitter is added to ensure that multiple calls with the same
|
|
102
|
+
# time do not generate the same UUID (if you want determinism you can set
|
|
103
|
+
# the second parameter to zero).
|
|
104
|
+
#
|
|
105
|
+
# @overload at(time, jitter = SecureRandom.random_number(65536))
|
|
106
|
+
# @param [Time] time a Time instance
|
|
107
|
+
# @param [Integer] jitter a number of microseconds to add to the time
|
|
108
|
+
# @return [Cassandra::TimeUuid] a new UUID
|
|
109
|
+
# @overload at(seconds_with_frac, jitter = SecureRandom.random_number(65536))
|
|
110
|
+
# @param [Numeric] seconds_with_frac can be {Integer}, {Float},
|
|
111
|
+
# {Rational}, or other {Numeric}
|
|
112
|
+
# @param [Integer] jitter a number of microseconds to add to the time
|
|
113
|
+
# @return [Cassandra::TimeUuid] a new UUID
|
|
114
|
+
# @overload at(seconds, microseconds_with_frac, jitter = SecureRandom.random_number(65536))
|
|
115
|
+
# @param [Integer] seconds
|
|
116
|
+
# @param [Numeric] microseconds_with_frac can be {Integer}, {Float},
|
|
117
|
+
# {Rational}, or other {Numeric}
|
|
118
|
+
# @param [Integer] jitter a number of microseconds to add to the time
|
|
119
|
+
# @return [Cassandra::TimeUuid] a new UUID
|
|
120
|
+
#
|
|
121
|
+
# @note the `jitter` argument accepted by all variants of this method is
|
|
122
|
+
# required to add randomness to generated {Cassandra::TimeUuid} and
|
|
123
|
+
# might affect the order of generated timestamps. You should set
|
|
124
|
+
# `jitter` to 0 when the source time(stamp)s are unique.
|
|
125
|
+
#
|
|
126
|
+
# @example Creating a TimeUuid from a Time instance
|
|
127
|
+
# generator = Cassandra::Uuid::Generator.new
|
|
128
|
+
# timeuuid = generator.at(Time.at(1413582460))
|
|
129
|
+
#
|
|
130
|
+
# puts timeuuid.to_time
|
|
131
|
+
#
|
|
132
|
+
# # Outputs:
|
|
133
|
+
# # 2014-10-17 21:47:40 UTC
|
|
134
|
+
#
|
|
135
|
+
# @example Creating a TimeUuid from a timestamp
|
|
136
|
+
# generator = Cassandra::Uuid::Generator.new
|
|
137
|
+
# timeuuid = generator.at(1413582423)
|
|
138
|
+
#
|
|
139
|
+
# puts timeuuid.to_time
|
|
140
|
+
#
|
|
141
|
+
# # Outputs:
|
|
142
|
+
# # 2014-10-17 21:47:03 UTC
|
|
143
|
+
#
|
|
144
|
+
# @example Avoid jitter in generated TimeUuid
|
|
145
|
+
# timestamp = 1413582418
|
|
146
|
+
# generator = Cassandra::Uuid::Generator.new
|
|
147
|
+
# timeuuid = generator.at(timestamp, 0)
|
|
148
|
+
#
|
|
149
|
+
# puts timeuuid.to_time.to_i
|
|
150
|
+
#
|
|
151
|
+
# # Outputs:
|
|
152
|
+
# # 1413582418
|
|
153
|
+
#
|
|
154
|
+
# @raise [ArgumentError] when given no arguments or more than 3 arguments
|
|
155
|
+
#
|
|
156
|
+
# @see Time.at
|
|
157
|
+
def at(*args)
|
|
158
|
+
raise ::ArgumentError, 'not enough arguments' if args.empty?
|
|
159
|
+
raise ::ArgumentError, 'too many arguments' if args.size > 3
|
|
160
|
+
|
|
161
|
+
if args.first.is_a?(::Time)
|
|
162
|
+
time = args.shift
|
|
163
|
+
jitter = args.empty? ? ::SecureRandom.random_number(65536) : Integer(args.shift)
|
|
164
|
+
else
|
|
165
|
+
jitter = args.size > 2 ? Integer(args.pop) : ::SecureRandom.random_number(65536)
|
|
166
|
+
time = ::Time.at(*args)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
from_usecs(time.to_i * 1_000_000 + time.usec + jitter)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Returns a completely random version 4 UUID.
|
|
173
|
+
#
|
|
174
|
+
# @example Generating a random Uuid
|
|
175
|
+
# generator = Cassandra::Uuid::Generator.new
|
|
176
|
+
# uuid = generator.uuid
|
|
177
|
+
#
|
|
178
|
+
# puts uuid
|
|
179
|
+
#
|
|
180
|
+
# # Outputs:
|
|
181
|
+
# # 664dedae-e162-4bc0-9066-b9f1968252aa
|
|
182
|
+
#
|
|
183
|
+
# @see SecureRandom.uuid
|
|
184
|
+
#
|
|
185
|
+
# @return [Cassandra::Uuid] a new UUID
|
|
186
|
+
def uuid
|
|
187
|
+
Uuid.new(::SecureRandom.uuid)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
private
|
|
191
|
+
|
|
192
|
+
# @private
|
|
193
|
+
def from_usecs(usecs)
|
|
194
|
+
t = TimeUuid::GREGORIAN_OFFSET + usecs * 10
|
|
195
|
+
time_hi = t & 0x0fff000000000000
|
|
196
|
+
time_mid = t & 0x0000ffff00000000
|
|
197
|
+
time_low = t & 0x00000000ffffffff
|
|
198
|
+
version = 1
|
|
199
|
+
clock_id = @clock_id & 0x3fff
|
|
200
|
+
node_id = @node_id & 0xffffffffffff
|
|
201
|
+
variant = 0x8000
|
|
202
|
+
|
|
203
|
+
n = (time_low << 96) | (time_mid << 48) | (time_hi << 16)
|
|
204
|
+
n |= version << 76
|
|
205
|
+
n |= (clock_id | variant) << 48
|
|
206
|
+
n |= node_id
|
|
207
|
+
|
|
208
|
+
TimeUuid.new(n)
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Copyright DataStax, Inc.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#++
|
|
18
|
+
|
|
19
|
+
module Cassandra
|
|
20
|
+
VERSION = '3.2.3.1'.freeze
|
|
21
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Copyright DataStax, Inc.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#++
|
|
18
|
+
|
|
19
|
+
module DataStax
|
|
20
|
+
@base = __FILE__ + '/../..'
|
|
21
|
+
|
|
22
|
+
def self.require(path)
|
|
23
|
+
if path.start_with?('cassandra/')
|
|
24
|
+
include(path)
|
|
25
|
+
else
|
|
26
|
+
::Kernel.require(path)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.include(path)
|
|
31
|
+
path = File.expand_path(path + '.rb', @base)
|
|
32
|
+
class_eval(File.read(path), path, 1)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
previous = nil
|
|
36
|
+
murmur3 = nil
|
|
37
|
+
if defined?(::Cassandra)
|
|
38
|
+
previous = ::Cassandra
|
|
39
|
+
murmur3 = ::Cassandra::Murmur3
|
|
40
|
+
Object.send(:remove_const, :Cassandra)
|
|
41
|
+
end
|
|
42
|
+
include 'cassandra'
|
|
43
|
+
murmur3 ||= ::Cassandra::Murmur3
|
|
44
|
+
DataStax::Cassandra::Murmur3 = murmur3
|
|
45
|
+
Object.send(:remove_const, :Cassandra) if defined?(::Cassandra)
|
|
46
|
+
::Cassandra = previous if previous
|
|
47
|
+
end
|
data/lib/ycql.rb
ADDED
|
@@ -0,0 +1,842 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Copyright DataStax, Inc.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#++
|
|
18
|
+
|
|
19
|
+
require 'ione'
|
|
20
|
+
require 'json'
|
|
21
|
+
|
|
22
|
+
require 'monitor'
|
|
23
|
+
require 'ipaddr'
|
|
24
|
+
require 'set'
|
|
25
|
+
require 'bigdecimal'
|
|
26
|
+
require 'forwardable'
|
|
27
|
+
require 'digest'
|
|
28
|
+
require 'stringio'
|
|
29
|
+
require 'resolv'
|
|
30
|
+
require 'openssl'
|
|
31
|
+
require 'securerandom'
|
|
32
|
+
require 'time'
|
|
33
|
+
require 'date'
|
|
34
|
+
|
|
35
|
+
module Cassandra
|
|
36
|
+
# A list of all supported request consistencies
|
|
37
|
+
# @see http://www.datastax.com/documentation/cassandra/2.0/cassandra/dml/dml_config_consistency_c.html Consistency
|
|
38
|
+
# levels in Apache Cassandra 2.0
|
|
39
|
+
# @see http://www.datastax.com/documentation/cassandra/1.2/cassandra/dml/dml_config_consistency_c.html Consistency
|
|
40
|
+
# levels in Apache Cassandra 1.2
|
|
41
|
+
# @see Cassandra::Session#execute_async
|
|
42
|
+
CONSISTENCIES = [:any, :one, :two, :three, :quorum, :all, :local_quorum,
|
|
43
|
+
:each_quorum, :serial, :local_serial, :local_one].freeze
|
|
44
|
+
|
|
45
|
+
# A list of all supported serial consistencies
|
|
46
|
+
# @see Cassandra::Session#execute_async
|
|
47
|
+
SERIAL_CONSISTENCIES = [:serial, :local_serial].freeze
|
|
48
|
+
|
|
49
|
+
# A list of all possible write types that a
|
|
50
|
+
# {Cassandra::Errors::WriteTimeoutError} can have.
|
|
51
|
+
#
|
|
52
|
+
# @see https://github.com/apache/cassandra/blob/cassandra-2.0.16/doc/native_protocol_v2.spec#L872-L887 Description of
|
|
53
|
+
# possible types of writes in Apache Cassandra native protocol spec v1
|
|
54
|
+
WRITE_TYPES = [:simple, :batch, :unlogged_batch, :counter, :batch_log].freeze
|
|
55
|
+
|
|
56
|
+
CLUSTER_OPTIONS = [
|
|
57
|
+
:address_resolution,
|
|
58
|
+
:address_resolution_policy,
|
|
59
|
+
:allow_beta_protocol,
|
|
60
|
+
:auth_provider,
|
|
61
|
+
:client_cert,
|
|
62
|
+
:client_timestamps,
|
|
63
|
+
:compression,
|
|
64
|
+
:compressor,
|
|
65
|
+
:connect_timeout,
|
|
66
|
+
:connections_per_local_node,
|
|
67
|
+
:connections_per_remote_node,
|
|
68
|
+
:consistency,
|
|
69
|
+
:credentials,
|
|
70
|
+
:custom_types,
|
|
71
|
+
:datacenter,
|
|
72
|
+
:execution_profiles,
|
|
73
|
+
:futures_factory,
|
|
74
|
+
:heartbeat_interval,
|
|
75
|
+
:hosts,
|
|
76
|
+
:idle_timeout,
|
|
77
|
+
:listeners,
|
|
78
|
+
:load_balancing_policy,
|
|
79
|
+
:logger,
|
|
80
|
+
:nodelay,
|
|
81
|
+
:reconnection_policy,
|
|
82
|
+
:retry_policy,
|
|
83
|
+
:page_size,
|
|
84
|
+
:passphrase,
|
|
85
|
+
:password,
|
|
86
|
+
:port,
|
|
87
|
+
:private_key,
|
|
88
|
+
:protocol_version,
|
|
89
|
+
:requests_per_connection,
|
|
90
|
+
:schema_refresh_delay,
|
|
91
|
+
:schema_refresh_timeout,
|
|
92
|
+
:server_cert,
|
|
93
|
+
:shuffle_replicas,
|
|
94
|
+
:ssl,
|
|
95
|
+
:synchronize_schema,
|
|
96
|
+
:timeout,
|
|
97
|
+
:trace,
|
|
98
|
+
:username
|
|
99
|
+
].freeze
|
|
100
|
+
|
|
101
|
+
# Creates a {Cassandra::Cluster Cluster instance}.
|
|
102
|
+
#
|
|
103
|
+
# @option options [Array<String, IPAddr>] :hosts (['127.0.0.1']) a list of
|
|
104
|
+
# initial addresses. Note that the entire list of cluster members will be
|
|
105
|
+
# discovered automatically once a connection to any hosts from the original
|
|
106
|
+
# list is successful.
|
|
107
|
+
#
|
|
108
|
+
# @option options [Integer] :port (9042) cassandra native protocol port.
|
|
109
|
+
#
|
|
110
|
+
# @option options [Boolean] :nodelay (true) when set to `true`, disables
|
|
111
|
+
# nagle algorithm.
|
|
112
|
+
#
|
|
113
|
+
# @option options [String] :datacenter (nil) name of current datacenter.
|
|
114
|
+
# First datacenter found will be assumed current by default. Note that you
|
|
115
|
+
# can skip this option if you specify only hosts from the local datacenter
|
|
116
|
+
# in `:hosts` option.
|
|
117
|
+
#
|
|
118
|
+
# @option options [Boolean] :shuffle_replicas (true) whether replicas list
|
|
119
|
+
# found by the default Token-Aware Load Balancing Policy should be
|
|
120
|
+
# shuffled. See {Cassandra::LoadBalancing::Policies::TokenAware#initialize Token-Aware Load Balancing Policy}.
|
|
121
|
+
#
|
|
122
|
+
# @option options [Hash<String|Symbol, ExecutionProfile>] :execution_profiles (nil)
|
|
123
|
+
# Hash of {Cassandra::Execution::Profile}s that are available for client use (e.g.
|
|
124
|
+
# {Session#execute}, {Session#execute_async}, {Session#prepare}, and {Session#prepare_async}).
|
|
125
|
+
#
|
|
126
|
+
# @option options [Numeric] :connect_timeout (10) connection timeout in
|
|
127
|
+
# seconds. Setting value to `nil` will reset it to 5 seconds.
|
|
128
|
+
#
|
|
129
|
+
# @option options [Numeric] :timeout (12) request execution timeout in
|
|
130
|
+
# seconds. Setting value to `nil` will remove request timeout.
|
|
131
|
+
#
|
|
132
|
+
# @option options [Numeric] :heartbeat_interval (30) how often should a
|
|
133
|
+
# heartbeat be sent to determine if a connection is alive. Several things to
|
|
134
|
+
# note about this option. Only one heartbeat request will ever be
|
|
135
|
+
# outstanding on a given connection. Each heatbeat will be sent in at least
|
|
136
|
+
# `:heartbeat_interval` seconds after the last request has been sent on a
|
|
137
|
+
# given connection. Setting value to `nil` will remove connection timeout.
|
|
138
|
+
#
|
|
139
|
+
# @option options [Numeric] :idle_timeout (60) period of inactivity after
|
|
140
|
+
# which a connection is considered dead. Note that this value should be at
|
|
141
|
+
# least a few times larger than `:heartbeat_interval`. Setting value to
|
|
142
|
+
# `nil` will remove automatic connection termination.
|
|
143
|
+
#
|
|
144
|
+
# @option options [String] :username (none) username to use for
|
|
145
|
+
# authentication to cassandra. Note that you must also specify `:password`.
|
|
146
|
+
#
|
|
147
|
+
# @option options [String] :password (none) password to use for
|
|
148
|
+
# authentication to cassandra. Note that you must also specify `:username`.
|
|
149
|
+
#
|
|
150
|
+
# @option options [Boolean, OpenSSL::SSL::SSLContext] :ssl (false) enable
|
|
151
|
+
# default ssl authentication if `true` (not recommended). Also accepts an
|
|
152
|
+
# initialized {OpenSSL::SSL::SSLContext}. Note that this option should be
|
|
153
|
+
# ignored if `:server_cert`, `:client_cert`, `:private_key` or
|
|
154
|
+
# `:passphrase` are given.
|
|
155
|
+
#
|
|
156
|
+
# @option options [String] :server_cert (none) path to server certificate or
|
|
157
|
+
# certificate authority file.
|
|
158
|
+
#
|
|
159
|
+
# @option options [String] :client_cert (none) path to client certificate
|
|
160
|
+
# file. Note that this option is only required when encryption is
|
|
161
|
+
# configured to require client authentication.
|
|
162
|
+
#
|
|
163
|
+
# @option options [String] :private_key (none) path to client private key.
|
|
164
|
+
# Note that this option is only required when encryption is configured to
|
|
165
|
+
# require client authentication.
|
|
166
|
+
#
|
|
167
|
+
# @option options [String] :passphrase (none) passphrase for private key.
|
|
168
|
+
#
|
|
169
|
+
# @option options [Symbol] :compression (none) compression to use. Must be
|
|
170
|
+
# either `:snappy` or `:lz4`. Also note, that in order for compression to
|
|
171
|
+
# work, you must install 'snappy' or 'lz4-ruby' gems.
|
|
172
|
+
#
|
|
173
|
+
# @option options [Cassandra::LoadBalancing::Policy] :load_balancing_policy
|
|
174
|
+
# default: token aware data center aware round robin.
|
|
175
|
+
#
|
|
176
|
+
# @option options [Symbol] :address_resolution (:none) a pre-configured
|
|
177
|
+
# address resolver to use. Must be one of `:none` or
|
|
178
|
+
# `:ec2_multi_region`.
|
|
179
|
+
#
|
|
180
|
+
# @option options [Integer] :connections_per_local_node (nil) Number of connections to
|
|
181
|
+
# open to each local node; the value of this option directly correlates to the number
|
|
182
|
+
# of requests the client can make to the local node concurrently. When `nil`, the
|
|
183
|
+
# setting is `1` for nodes that use the v3 or later protocol, and `2` for nodes that
|
|
184
|
+
# use the v2 or earlier protocol.
|
|
185
|
+
#
|
|
186
|
+
# @option options [Integer] :connections_per_remote_node (1) Number of connections to
|
|
187
|
+
# open to each remote node; the value of this option directly correlates to the
|
|
188
|
+
# number of requests the client can make to the remote node concurrently.
|
|
189
|
+
#
|
|
190
|
+
# @option options [Integer] :requests_per_connection (nil) Number of outstanding
|
|
191
|
+
# requests to support on one connection. Depending on the types of requests, some may
|
|
192
|
+
# get processed in parallel in the Cassandra node. When `nil`, the setting is `1024`
|
|
193
|
+
# for nodes that use the v3 or later protocol, and `128` for nodes that use the
|
|
194
|
+
# v2 or earlier protocol.
|
|
195
|
+
#
|
|
196
|
+
# @option options [Integer] :protocol_version (nil) Version of protocol to speak to
|
|
197
|
+
# nodes. By default, this is auto-negotiated to the highest common protocol version
|
|
198
|
+
# that all nodes in `:hosts` speak.
|
|
199
|
+
#
|
|
200
|
+
# @option options [Boolean] :allow_beta_protocol (false) whether the driver should attempt to speak to nodes
|
|
201
|
+
# with a beta version of the newest protocol (which is still under development). USE WITH CAUTION!
|
|
202
|
+
#
|
|
203
|
+
# @option options [Boolean, Cassandra::TimestampGenerator] :client_timestamps (false) whether the driver
|
|
204
|
+
# should send timestamps for each executed statement and possibly which timestamp generator to use. Enabling this
|
|
205
|
+
# setting helps mitigate Cassandra cluster clock skew because the timestamp of the client machine will be used.
|
|
206
|
+
# This does not help mitigate application cluster clock skew. Also accepts an initialized
|
|
207
|
+
# {Cassandra::TimestampGenerator}, `:simple` (indicating an instance of {Cassandra::TimestampGenerator::Simple}),
|
|
208
|
+
# or `:monotonic` (indicating an instance of {Cassandra::TimestampGenerator::TickingOnDuplicate}). If set to true,
|
|
209
|
+
# it defaults to {Cassandra::TimestampGenerator::Simple} for all Ruby flavors except JRuby. On JRuby, it defaults to
|
|
210
|
+
# {Cassandra::TimestampGenerator::TickingOnDuplicate}.
|
|
211
|
+
#
|
|
212
|
+
# @option options [Boolean] :synchronize_schema (true) whether the driver
|
|
213
|
+
# should automatically keep schema metadata synchronized. When enabled, the
|
|
214
|
+
# driver updates schema metadata after receiving schema change
|
|
215
|
+
# notifications from Cassandra. Setting this setting to `false` disables
|
|
216
|
+
# automatic schema updates. Schema metadata is used by the driver to
|
|
217
|
+
# determine cluster partitioners as well as to find partition keys and
|
|
218
|
+
# replicas of prepared statements, this information makes token aware load
|
|
219
|
+
# balancing possible. One can still
|
|
220
|
+
# {Cassandra::Cluster#refresh_schema refresh schema manually}.
|
|
221
|
+
#
|
|
222
|
+
# @option options [Numeric] :schema_refresh_delay (1) the driver will wait
|
|
223
|
+
# for `:schema_refresh_delay` before fetching metadata after receiving a
|
|
224
|
+
# schema change event. This timer is restarted every time a new schema
|
|
225
|
+
# change event is received. Finally, when the timer expires or a maximum
|
|
226
|
+
# wait time of `:schema_refresh_timeout` has been reached, a schema refresh
|
|
227
|
+
# attempt will be made and the timeout is reset.
|
|
228
|
+
#
|
|
229
|
+
# @option options [Numeric] :schema_refresh_timeout (10) the maximum delay
|
|
230
|
+
# before automatically refreshing schema. Such delay can occur whenever
|
|
231
|
+
# multiple schema change events are continuously arriving within
|
|
232
|
+
# `:schema_refresh_delay` interval.
|
|
233
|
+
#
|
|
234
|
+
# @option options [Cassandra::Reconnection::Policy] :reconnection_policy
|
|
235
|
+
# default: {Cassandra::Reconnection::Policies::Exponential Exponential}.
|
|
236
|
+
# Note that the default policy is configured with `(0.5, 30, 2)`.
|
|
237
|
+
#
|
|
238
|
+
# @option options [Cassandra::Retry::Policy] :retry_policy default:
|
|
239
|
+
# {Cassandra::Retry::Policies::Default Default Retry Policy}.
|
|
240
|
+
#
|
|
241
|
+
# @option options [Logger] :logger (none) logger. a {Logger} instance from the
|
|
242
|
+
# standard library or any object responding to standard log methods
|
|
243
|
+
# (`#debug`, `#info`, `#warn`, `#error` and `#fatal`).
|
|
244
|
+
#
|
|
245
|
+
# @option options [Enumerable<Cassandra::Listener>] :listeners (none)
|
|
246
|
+
# initial listeners. A list of initial cluster state listeners. Note that a
|
|
247
|
+
# `:load_balancing` policy is automatically registered with the cluster.
|
|
248
|
+
#
|
|
249
|
+
# @option options [Symbol] :consistency (:local_quorum) default consistency
|
|
250
|
+
# to use for all requests. Must be one of {Cassandra::CONSISTENCIES}.
|
|
251
|
+
#
|
|
252
|
+
# @option options [Boolean] :trace (false) whether or not to trace all
|
|
253
|
+
# requests by default.
|
|
254
|
+
#
|
|
255
|
+
# @option options [Integer] :page_size (10000) default page size for all
|
|
256
|
+
# select queries. Set this value to `nil` to disable paging.
|
|
257
|
+
#
|
|
258
|
+
# @option options [Hash{String => String}] :credentials (none) a hash of credentials -
|
|
259
|
+
# 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).
|
|
260
|
+
# Note that if you specified `:username` and `:password` options, those credentials
|
|
261
|
+
# are configured automatically.
|
|
262
|
+
#
|
|
263
|
+
# @option options [Cassandra::Auth::Provider] :auth_provider (none) a custom auth
|
|
264
|
+
# 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).
|
|
265
|
+
# Note that if you have specified `:username` and `:password`, then a
|
|
266
|
+
# {Cassandra::Auth::Providers::Password Password Provider} will be used automatically.
|
|
267
|
+
#
|
|
268
|
+
# @option options [Cassandra::Compression::Compressor] :compressor (none) a
|
|
269
|
+
# custom compressor. Note that if you have specified `:compression`, an
|
|
270
|
+
# appropriate compressor will be provided automatically.
|
|
271
|
+
#
|
|
272
|
+
# @option options [Cassandra::AddressResolution::Policy]
|
|
273
|
+
# :address_resolution_policy default:
|
|
274
|
+
# {Cassandra::AddressResolution::Policies::None No Resolution Policy} a custom address
|
|
275
|
+
# resolution policy. Note that if you have specified `:address_resolution`, an
|
|
276
|
+
# appropriate address resolution policy will be provided automatically.
|
|
277
|
+
#
|
|
278
|
+
# @option options [Object<#all, #error, #value, #promise>] :futures_factory
|
|
279
|
+
# default: {Cassandra::Future} a futures factory to assist with integration
|
|
280
|
+
# into existing futures library. Note that promises returned by this object
|
|
281
|
+
# must conform to {Cassandra::Promise} api, which is not yet public. Things
|
|
282
|
+
# may change, use at your own risk.
|
|
283
|
+
#
|
|
284
|
+
# @example Connecting to localhost
|
|
285
|
+
# cluster = Cassandra.cluster
|
|
286
|
+
#
|
|
287
|
+
# @example Configuring {Cassandra::Cluster}
|
|
288
|
+
# cluster = Cassandra.cluster(
|
|
289
|
+
# username: username,
|
|
290
|
+
# password: password,
|
|
291
|
+
# hosts: ['10.0.1.1', '10.0.1.2', '10.0.1.3']
|
|
292
|
+
# )
|
|
293
|
+
#
|
|
294
|
+
# @return [Cassandra::Cluster] a cluster instance
|
|
295
|
+
def self.cluster(options = {})
|
|
296
|
+
cluster_async(options).get
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
# Creates a {Cassandra::Cluster Cluster instance}.
|
|
300
|
+
#
|
|
301
|
+
# @see Cassandra.cluster
|
|
302
|
+
#
|
|
303
|
+
# @return [Cassandra::Future<Cassandra::Cluster>] a future resolving to the
|
|
304
|
+
# cluster instance.
|
|
305
|
+
def self.cluster_async(options = {})
|
|
306
|
+
options, hosts = validate_and_massage_options(options)
|
|
307
|
+
rescue => e
|
|
308
|
+
futures = options.fetch(:futures_factory) { return Future::Error.new(e) }
|
|
309
|
+
futures.error(e)
|
|
310
|
+
else
|
|
311
|
+
driver = Driver.new(options)
|
|
312
|
+
driver.connect(hosts)
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# @private
|
|
316
|
+
SSL_CLASSES = [::TrueClass, ::FalseClass, ::OpenSSL::SSL::SSLContext].freeze
|
|
317
|
+
|
|
318
|
+
# rubocop:disable Metrics/AbcSize
|
|
319
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
320
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
|
321
|
+
# @private
|
|
322
|
+
def self.validate_and_massage_options(options)
|
|
323
|
+
options = options.select do |key, _|
|
|
324
|
+
CLUSTER_OPTIONS.include?(key)
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
if options.key?(:execution_profiles)
|
|
328
|
+
[:load_balancing_policy, :retry_policy, :timeout, :consistency].each do |opt|
|
|
329
|
+
raise ::ArgumentError, "#{opt} is not allowed when execution profiles are used" if options.key?(opt)
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
has_username = options.key?(:username)
|
|
334
|
+
has_password = options.key?(:password)
|
|
335
|
+
if has_username || has_password
|
|
336
|
+
if has_username && !has_password
|
|
337
|
+
raise ::ArgumentError,
|
|
338
|
+
'both :username and :password options must be specified, ' \
|
|
339
|
+
'but only :username given'
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
if !has_username && has_password
|
|
343
|
+
raise ::ArgumentError,
|
|
344
|
+
'both :username and :password options must be specified, ' \
|
|
345
|
+
'but only :password given'
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
username = options.delete(:username)
|
|
349
|
+
password = options.delete(:password)
|
|
350
|
+
|
|
351
|
+
Util.assert_instance_of(::String, username) do
|
|
352
|
+
":username must be a String, #{username.inspect} given"
|
|
353
|
+
end
|
|
354
|
+
Util.assert_instance_of(::String, password) do
|
|
355
|
+
":password must be a String, #{password.inspect} given"
|
|
356
|
+
end
|
|
357
|
+
Util.assert_not_empty(username) { ':username cannot be empty' }
|
|
358
|
+
Util.assert_not_empty(password) { ':password cannot be empty' }
|
|
359
|
+
|
|
360
|
+
options[:credentials] = {username: username, password: password}
|
|
361
|
+
options[:auth_provider] = Auth::Providers::Password.new(username, password)
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
if options.key?(:credentials)
|
|
365
|
+
credentials = options[:credentials]
|
|
366
|
+
|
|
367
|
+
Util.assert_instance_of(::Hash, credentials) do
|
|
368
|
+
":credentials must be a hash, #{credentials.inspect} given"
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
if options.key?(:auth_provider)
|
|
373
|
+
auth_provider = options[:auth_provider]
|
|
374
|
+
|
|
375
|
+
Util.assert_responds_to(:create_authenticator, auth_provider) do
|
|
376
|
+
":auth_provider #{auth_provider.inspect} must respond to " \
|
|
377
|
+
":create_authenticator, but doesn't"
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
has_client_cert = options.key?(:client_cert)
|
|
382
|
+
has_private_key = options.key?(:private_key)
|
|
383
|
+
|
|
384
|
+
if has_client_cert || has_private_key
|
|
385
|
+
if has_client_cert && !has_private_key
|
|
386
|
+
raise ::ArgumentError,
|
|
387
|
+
'both :client_cert and :private_key options must be specified, ' \
|
|
388
|
+
'but only :client_cert given'
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
if !has_client_cert && has_private_key
|
|
392
|
+
raise ::ArgumentError,
|
|
393
|
+
'both :client_cert and :private_key options must be specified, ' \
|
|
394
|
+
'but only :private_key given'
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
Util.assert_instance_of(::String, options[:client_cert]) do
|
|
398
|
+
":client_cert must be a string, #{options[:client_cert].inspect} given"
|
|
399
|
+
end
|
|
400
|
+
Util.assert_instance_of(::String, options[:private_key]) do
|
|
401
|
+
":client_cert must be a string, #{options[:private_key].inspect} given"
|
|
402
|
+
end
|
|
403
|
+
client_cert = ::File.expand_path(options[:client_cert])
|
|
404
|
+
private_key = ::File.expand_path(options[:private_key])
|
|
405
|
+
|
|
406
|
+
Util.assert_file_exists(client_cert) do
|
|
407
|
+
":client_cert #{client_cert.inspect} doesn't exist"
|
|
408
|
+
end
|
|
409
|
+
Util.assert_file_exists(private_key) do
|
|
410
|
+
":private_key #{private_key.inspect} doesn't exist"
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
has_server_cert = options.key?(:server_cert)
|
|
415
|
+
|
|
416
|
+
if has_server_cert
|
|
417
|
+
Util.assert_instance_of(::String, options[:server_cert]) do
|
|
418
|
+
":server_cert must be a string, #{options[:server_cert].inspect} given"
|
|
419
|
+
end
|
|
420
|
+
server_cert = ::File.expand_path(options[:server_cert])
|
|
421
|
+
|
|
422
|
+
Util.assert_file_exists(server_cert) do
|
|
423
|
+
":server_cert #{server_cert.inspect} doesn't exist"
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
if has_client_cert || has_server_cert
|
|
428
|
+
context = ::OpenSSL::SSL::SSLContext.new
|
|
429
|
+
|
|
430
|
+
if has_server_cert
|
|
431
|
+
context.ca_file = server_cert
|
|
432
|
+
context.verify_mode = ::OpenSSL::SSL::VERIFY_PEER
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
if has_client_cert
|
|
436
|
+
context.cert = ::OpenSSL::X509::Certificate.new(File.read(client_cert))
|
|
437
|
+
|
|
438
|
+
context.key = if options.key?(:passphrase)
|
|
439
|
+
::OpenSSL::PKey::RSA.new(File.read(private_key),
|
|
440
|
+
options[:passphrase])
|
|
441
|
+
else
|
|
442
|
+
::OpenSSL::PKey::RSA.new(File.read(private_key))
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
options[:ssl] = context
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
if options.key?(:ssl)
|
|
450
|
+
ssl = options[:ssl]
|
|
451
|
+
|
|
452
|
+
Util.assert_instance_of_one_of(SSL_CLASSES, ssl) do
|
|
453
|
+
":ssl must be a boolean or an OpenSSL::SSL::SSLContext, #{ssl.inspect} given"
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
if options.key?(:compression)
|
|
458
|
+
compression = options.delete(:compression)
|
|
459
|
+
|
|
460
|
+
case compression
|
|
461
|
+
when :snappy
|
|
462
|
+
options[:compressor] = Compression::Compressors::Snappy.new
|
|
463
|
+
when :lz4
|
|
464
|
+
options[:compressor] = Compression::Compressors::Lz4.new
|
|
465
|
+
else
|
|
466
|
+
raise ::ArgumentError,
|
|
467
|
+
":compression must be either :snappy or :lz4, #{compression.inspect} given"
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
if options.key?(:compressor)
|
|
472
|
+
compressor = options[:compressor]
|
|
473
|
+
methods = [:algorithm, :compress?, :compress, :decompress]
|
|
474
|
+
|
|
475
|
+
Util.assert_responds_to_all(methods, compressor) do
|
|
476
|
+
":compressor #{compressor.inspect} must respond to #{methods.inspect}, " \
|
|
477
|
+
"but doesn't"
|
|
478
|
+
end
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
if options.key?(:logger)
|
|
482
|
+
if options[:logger].nil?
|
|
483
|
+
# Delete the key because we want to fallback to the default logger in Driver.
|
|
484
|
+
options.delete(:logger)
|
|
485
|
+
else
|
|
486
|
+
# Validate
|
|
487
|
+
logger = options[:logger]
|
|
488
|
+
methods = [:debug, :info, :warn, :error, :fatal]
|
|
489
|
+
|
|
490
|
+
Util.assert_responds_to_all(methods, logger) do
|
|
491
|
+
":logger #{logger.inspect} must respond to #{methods.inspect}, but doesn't"
|
|
492
|
+
end
|
|
493
|
+
end
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
if options.key?(:port)
|
|
497
|
+
unless options[:port].nil?
|
|
498
|
+
port = options[:port]
|
|
499
|
+
Util.assert_instance_of(::Integer, port)
|
|
500
|
+
Util.assert_one_of(1...2**16, port) do
|
|
501
|
+
":port must be a valid ip port, #{port} given"
|
|
502
|
+
end
|
|
503
|
+
end
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
options[:datacenter] = String(options[:datacenter]) if options.key?(:datacenter)
|
|
507
|
+
|
|
508
|
+
if options.key?(:connect_timeout)
|
|
509
|
+
timeout = options[:connect_timeout]
|
|
510
|
+
|
|
511
|
+
unless timeout.nil?
|
|
512
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
|
513
|
+
":connect_timeout must be a number of seconds, #{timeout.inspect} given"
|
|
514
|
+
end
|
|
515
|
+
Util.assert(timeout > 0) do
|
|
516
|
+
":connect_timeout must be greater than 0, #{timeout} given"
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
if options.key?(:execution_profiles)
|
|
522
|
+
Util.assert_instance_of(::Hash, options[:execution_profiles],
|
|
523
|
+
':execution_profiles must be a hash of <name,ExecutionProfile> entries.')
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
if options.key?(:heartbeat_interval)
|
|
527
|
+
timeout = options[:heartbeat_interval]
|
|
528
|
+
|
|
529
|
+
unless timeout.nil?
|
|
530
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
|
531
|
+
":heartbeat_interval must be a number of seconds, #{timeout.inspect} given"
|
|
532
|
+
end
|
|
533
|
+
Util.assert(timeout > 0) do
|
|
534
|
+
":heartbeat_interval must be greater than 0, #{timeout} given"
|
|
535
|
+
end
|
|
536
|
+
end
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
if options.key?(:idle_timeout)
|
|
540
|
+
timeout = options[:idle_timeout]
|
|
541
|
+
|
|
542
|
+
unless timeout.nil?
|
|
543
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
|
544
|
+
":idle_timeout must be a number of seconds, #{timeout.inspect} given"
|
|
545
|
+
end
|
|
546
|
+
Util.assert(timeout > 0) do
|
|
547
|
+
":idle_timeout must be greater than 0, #{timeout} given"
|
|
548
|
+
end
|
|
549
|
+
end
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
if options.key?(:schema_refresh_delay)
|
|
553
|
+
timeout = options[:schema_refresh_delay]
|
|
554
|
+
|
|
555
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
|
556
|
+
":schema_refresh_delay must be a number of seconds, #{timeout.inspect} given"
|
|
557
|
+
end
|
|
558
|
+
Util.assert(timeout > 0) do
|
|
559
|
+
":schema_refresh_delay must be greater than 0, #{timeout} given"
|
|
560
|
+
end
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
if options.key?(:schema_refresh_timeout)
|
|
564
|
+
timeout = options[:schema_refresh_timeout]
|
|
565
|
+
|
|
566
|
+
Util.assert_instance_of(::Numeric, timeout) do
|
|
567
|
+
":schema_refresh_timeout must be a number of seconds, #{timeout.inspect} given"
|
|
568
|
+
end
|
|
569
|
+
Util.assert(timeout > 0) do
|
|
570
|
+
":schema_refresh_timeout must be greater than 0, #{timeout} given"
|
|
571
|
+
end
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
if options.key?(:reconnection_policy)
|
|
575
|
+
reconnection_policy = options[:reconnection_policy]
|
|
576
|
+
|
|
577
|
+
Util.assert_responds_to(:schedule, reconnection_policy) do
|
|
578
|
+
":reconnection_policy #{reconnection_policy.inspect} must respond to " \
|
|
579
|
+
":schedule, but doesn't"
|
|
580
|
+
end
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
# Validate options that go in an execution profile. Instantiating one
|
|
584
|
+
# causes validation automatically.
|
|
585
|
+
Cassandra::Execution::Profile.new(options)
|
|
586
|
+
|
|
587
|
+
options[:listeners] = Array(options[:listeners]) if options.key?(:listeners)
|
|
588
|
+
options[:nodelay] = !!options[:nodelay] if options.key?(:nodelay)
|
|
589
|
+
options[:trace] = !!options[:trace] if options.key?(:trace)
|
|
590
|
+
options[:shuffle_replicas] = !!options[:shuffle_replicas] if options.key?(:shuffle_replicas)
|
|
591
|
+
options[:allow_beta_protocol] = !!options[:allow_beta_protocol] if options.key?(:allow_beta_protocol)
|
|
592
|
+
|
|
593
|
+
if options.key?(:page_size)
|
|
594
|
+
page_size = options[:page_size]
|
|
595
|
+
|
|
596
|
+
unless page_size.nil?
|
|
597
|
+
page_size = options[:page_size]
|
|
598
|
+
Util.assert_instance_of(::Integer, page_size)
|
|
599
|
+
Util.assert_one_of(1...2**32, page_size) do
|
|
600
|
+
":page_size must be a positive integer, #{page_size.inspect} given"
|
|
601
|
+
end
|
|
602
|
+
end
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
if options.key?(:protocol_version)
|
|
606
|
+
protocol_version = options[:protocol_version]
|
|
607
|
+
unless protocol_version.nil?
|
|
608
|
+
Util.assert_instance_of(::Integer, protocol_version)
|
|
609
|
+
Util.assert_one_of(1..Cassandra::Protocol::Versions::MAX_SUPPORTED_VERSION, protocol_version,
|
|
610
|
+
':protocol_version must be a positive integer between 1 and ' \
|
|
611
|
+
"#{Cassandra::Protocol::Versions::MAX_SUPPORTED_VERSION}, #{protocol_version.inspect} given")
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
Util.assert(!(options[:allow_beta_protocol] && options[:protocol_version]),
|
|
616
|
+
'only one of :allow_beta_protocol and :protocol_version may be specified, both given')
|
|
617
|
+
|
|
618
|
+
if options.key?(:futures_factory)
|
|
619
|
+
futures_factory = options[:futures_factory]
|
|
620
|
+
methods = [:error, :value, :promise, :all]
|
|
621
|
+
|
|
622
|
+
Util.assert_responds_to_all(methods, futures_factory) do
|
|
623
|
+
":futures_factory #{futures_factory.inspect} must respond to " \
|
|
624
|
+
"#{methods.inspect}, but doesn't"
|
|
625
|
+
end
|
|
626
|
+
end
|
|
627
|
+
|
|
628
|
+
if options.key?(:address_resolution)
|
|
629
|
+
address_resolution = options.delete(:address_resolution)
|
|
630
|
+
|
|
631
|
+
case address_resolution
|
|
632
|
+
when :none
|
|
633
|
+
# do nothing
|
|
634
|
+
when :ec2_multi_region
|
|
635
|
+
options[:address_resolution_policy] =
|
|
636
|
+
AddressResolution::Policies::EC2MultiRegion.new
|
|
637
|
+
else
|
|
638
|
+
raise ::ArgumentError,
|
|
639
|
+
':address_resolution must be either :none or :ec2_multi_region, ' \
|
|
640
|
+
"#{address_resolution.inspect} given"
|
|
641
|
+
end
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
if options.key?(:address_resolution_policy)
|
|
645
|
+
address_resolver = options[:address_resolution_policy]
|
|
646
|
+
|
|
647
|
+
Util.assert_responds_to(:resolve, address_resolver) do
|
|
648
|
+
':address_resolution_policy must respond to :resolve, ' \
|
|
649
|
+
"#{address_resolver.inspect} but doesn't"
|
|
650
|
+
end
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
options[:synchronize_schema] = !!options[:synchronize_schema] if options.key?(:synchronize_schema)
|
|
654
|
+
|
|
655
|
+
if options.key?(:client_timestamps)
|
|
656
|
+
timestamp_generator = case options[:client_timestamps]
|
|
657
|
+
when true
|
|
658
|
+
if RUBY_ENGINE == 'jruby'
|
|
659
|
+
Cassandra::TimestampGenerator::TickingOnDuplicate.new
|
|
660
|
+
else
|
|
661
|
+
Cassandra::TimestampGenerator::Simple.new
|
|
662
|
+
end
|
|
663
|
+
when false
|
|
664
|
+
nil
|
|
665
|
+
when :simple
|
|
666
|
+
Cassandra::TimestampGenerator::Simple.new
|
|
667
|
+
when :monotonic
|
|
668
|
+
Cassandra::TimestampGenerator::TickingOnDuplicate.new
|
|
669
|
+
else
|
|
670
|
+
# The value must be a generator instance.
|
|
671
|
+
options[:client_timestamps]
|
|
672
|
+
end
|
|
673
|
+
|
|
674
|
+
if timestamp_generator
|
|
675
|
+
Util.assert_responds_to(:next, timestamp_generator) do
|
|
676
|
+
":client_timestamps #{options[:client_timestamps].inspect} must be a boolean, :simple, :monotonic, or " \
|
|
677
|
+
'an object that responds to :next'
|
|
678
|
+
end
|
|
679
|
+
end
|
|
680
|
+
options.delete(:client_timestamps)
|
|
681
|
+
options[:timestamp_generator] = timestamp_generator
|
|
682
|
+
end
|
|
683
|
+
|
|
684
|
+
if options.key?(:connections_per_local_node)
|
|
685
|
+
connections_per_node = options[:connections_per_local_node]
|
|
686
|
+
|
|
687
|
+
unless connections_per_node.nil?
|
|
688
|
+
connections_per_node = options[:connections_per_local_node]
|
|
689
|
+
Util.assert_instance_of(::Integer, connections_per_node)
|
|
690
|
+
Util.assert_one_of(1...2**16, connections_per_node) do
|
|
691
|
+
':connections_per_local_node must be a positive integer between ' \
|
|
692
|
+
"1 and 65535, #{connections_per_node.inspect} given"
|
|
693
|
+
end
|
|
694
|
+
end
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
if options.key?(:connections_per_remote_node)
|
|
698
|
+
connections_per_node = options[:connections_per_remote_node]
|
|
699
|
+
|
|
700
|
+
unless connections_per_node.nil?
|
|
701
|
+
connections_per_node = options[:connections_per_remote_node]
|
|
702
|
+
Util.assert_instance_of(::Integer, connections_per_node)
|
|
703
|
+
Util.assert_one_of(1...2**16, connections_per_node) do
|
|
704
|
+
':connections_per_remote_node must be a positive integer between ' \
|
|
705
|
+
"1 and 65535, #{connections_per_node.inspect} given"
|
|
706
|
+
end
|
|
707
|
+
end
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
if options.key?(:requests_per_connection)
|
|
711
|
+
requests_per_connection = options[:requests_per_connection]
|
|
712
|
+
|
|
713
|
+
unless requests_per_connection.nil?
|
|
714
|
+
requests_per_connection = options[:requests_per_connection]
|
|
715
|
+
Util.assert_instance_of(::Integer, requests_per_connection)
|
|
716
|
+
|
|
717
|
+
# v3 protocol says that max stream-id is 32767 (2^15-1). This setting might be
|
|
718
|
+
# used to talk to a v2 (or less) node, but then we'll adjust it down.
|
|
719
|
+
|
|
720
|
+
Util.assert_one_of(1...2**15, requests_per_connection) do
|
|
721
|
+
':requests_per_connection must be a positive integer, ' \
|
|
722
|
+
"#{requests_per_connection.inspect} given"
|
|
723
|
+
end
|
|
724
|
+
end
|
|
725
|
+
end
|
|
726
|
+
|
|
727
|
+
# Get host addresses.
|
|
728
|
+
hosts = []
|
|
729
|
+
|
|
730
|
+
Array(options.fetch(:hosts, '127.0.0.1')).each do |host|
|
|
731
|
+
case host
|
|
732
|
+
when ::IPAddr
|
|
733
|
+
hosts << host
|
|
734
|
+
when ::String # ip address or hostname
|
|
735
|
+
Resolv.each_address(host) do |ip|
|
|
736
|
+
hosts << ::IPAddr.new(ip)
|
|
737
|
+
end
|
|
738
|
+
else
|
|
739
|
+
raise ::ArgumentError, ":hosts must be String or IPAddr, #{host.inspect} given"
|
|
740
|
+
end
|
|
741
|
+
end
|
|
742
|
+
|
|
743
|
+
if hosts.empty?
|
|
744
|
+
raise ::ArgumentError,
|
|
745
|
+
":hosts #{options[:hosts].inspect} could not be resolved to any ip address"
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
hosts.shuffle!
|
|
749
|
+
|
|
750
|
+
[options, hosts]
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
# @private
|
|
754
|
+
EMPTY_LIST = [].freeze
|
|
755
|
+
# @private
|
|
756
|
+
NOT_SET = ::Object.new
|
|
757
|
+
# @private
|
|
758
|
+
NULL_BYTE = "\x00".freeze
|
|
759
|
+
|
|
760
|
+
# @private
|
|
761
|
+
# ensures that:
|
|
762
|
+
# ::Date.jd(DATE_OFFSET, ::Date::GREGORIAN)
|
|
763
|
+
# => -5877641-06-23
|
|
764
|
+
# ::Date.jd(DATE_OFFSET + 2 ** 31, ::Date::GREGORIAN)
|
|
765
|
+
# => 1970-1-1
|
|
766
|
+
# ::Date.jd(DATE_OFFSET + 2 ** 32, ::Date::GREGORIAN)
|
|
767
|
+
# => 5881580-07-12
|
|
768
|
+
DATE_OFFSET = (::Time.utc(1970, 1, 1).to_date.jd - 2**31)
|
|
769
|
+
end
|
|
770
|
+
|
|
771
|
+
require 'cassandra/attr_boolean'
|
|
772
|
+
require 'cassandra/version'
|
|
773
|
+
require 'cassandra/uuid'
|
|
774
|
+
require 'cassandra/time_uuid'
|
|
775
|
+
require 'cassandra/tuple'
|
|
776
|
+
require 'cassandra/udt'
|
|
777
|
+
require 'cassandra/time'
|
|
778
|
+
|
|
779
|
+
require 'cassandra/types'
|
|
780
|
+
|
|
781
|
+
require 'cassandra/errors'
|
|
782
|
+
require 'cassandra/compression'
|
|
783
|
+
require 'cassandra/protocol'
|
|
784
|
+
require 'cassandra/auth'
|
|
785
|
+
require 'cassandra/cassandra_logger'
|
|
786
|
+
require 'cassandra/null_logger'
|
|
787
|
+
|
|
788
|
+
require 'cassandra/executors'
|
|
789
|
+
require 'cassandra/future'
|
|
790
|
+
require 'cassandra/cluster'
|
|
791
|
+
require 'cassandra/custom_data'
|
|
792
|
+
require 'cassandra/driver'
|
|
793
|
+
require 'cassandra/host'
|
|
794
|
+
require 'cassandra/session'
|
|
795
|
+
require 'cassandra/result'
|
|
796
|
+
require 'cassandra/statement'
|
|
797
|
+
require 'cassandra/statements'
|
|
798
|
+
|
|
799
|
+
require 'cassandra/aggregate'
|
|
800
|
+
require 'cassandra/argument'
|
|
801
|
+
require 'cassandra/function'
|
|
802
|
+
require 'cassandra/function_collection'
|
|
803
|
+
require 'cassandra/column'
|
|
804
|
+
require 'cassandra/column_container'
|
|
805
|
+
require 'cassandra/table'
|
|
806
|
+
require 'cassandra/materialized_view'
|
|
807
|
+
require 'cassandra/keyspace'
|
|
808
|
+
require 'cassandra/index'
|
|
809
|
+
require 'cassandra/trigger'
|
|
810
|
+
|
|
811
|
+
require 'cassandra/execution/info'
|
|
812
|
+
require 'cassandra/execution/options'
|
|
813
|
+
require 'cassandra/execution/profile_manager'
|
|
814
|
+
require 'cassandra/execution/profile'
|
|
815
|
+
require 'cassandra/execution/trace'
|
|
816
|
+
|
|
817
|
+
require 'cassandra/load_balancing'
|
|
818
|
+
require 'cassandra/reconnection'
|
|
819
|
+
require 'cassandra/retry'
|
|
820
|
+
require 'cassandra/address_resolution'
|
|
821
|
+
require 'cassandra/timestamp_generator'
|
|
822
|
+
|
|
823
|
+
require 'cassandra/util'
|
|
824
|
+
|
|
825
|
+
# murmur3 hash extension
|
|
826
|
+
require 'cassandra_murmur3'
|
|
827
|
+
|
|
828
|
+
# SortedSet has a race condition where it does some class/global initialization when the first instance is created.
|
|
829
|
+
# If this is done in a multi-threaded environment, bad things can happen. So force the initialization here,
|
|
830
|
+
# when loading the C* module.
|
|
831
|
+
::SortedSet.new
|
|
832
|
+
|
|
833
|
+
module Cassandra
|
|
834
|
+
# @private
|
|
835
|
+
VOID_STATEMENT = Statements::Void.new
|
|
836
|
+
# @private
|
|
837
|
+
VOID_OPTIONS = Execution::Options.new(consistency: :quorum,
|
|
838
|
+
load_balancing_policy: LoadBalancing::Policies::RoundRobin.new,
|
|
839
|
+
retry_policy: Retry::Policies::Default.new)
|
|
840
|
+
# @private
|
|
841
|
+
NO_HOSTS = Errors::NoHostsAvailable.new
|
|
842
|
+
end
|