cassandra-driver 1.0.0.beta.2-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +4 -0
- data/README.md +125 -0
- data/lib/cassandra/auth/providers/password.rb +73 -0
- data/lib/cassandra/auth/providers.rb +16 -0
- data/lib/cassandra/auth.rb +97 -0
- data/lib/cassandra/client/batch.rb +212 -0
- data/lib/cassandra/client/client.rb +591 -0
- data/lib/cassandra/client/column_metadata.rb +54 -0
- data/lib/cassandra/client/connection_manager.rb +72 -0
- data/lib/cassandra/client/connector.rb +277 -0
- data/lib/cassandra/client/execute_options_decoder.rb +59 -0
- data/lib/cassandra/client/null_logger.rb +37 -0
- data/lib/cassandra/client/peer_discovery.rb +50 -0
- data/lib/cassandra/client/prepared_statement.rb +314 -0
- data/lib/cassandra/client/query_result.rb +230 -0
- data/lib/cassandra/client/request_runner.rb +71 -0
- data/lib/cassandra/client/result_metadata.rb +48 -0
- data/lib/cassandra/client/void_result.rb +78 -0
- data/lib/cassandra/client.rb +144 -0
- data/lib/cassandra/cluster/client.rb +768 -0
- data/lib/cassandra/cluster/connector.rb +244 -0
- data/lib/cassandra/cluster/control_connection.rb +425 -0
- data/lib/cassandra/cluster/metadata.rb +124 -0
- data/lib/cassandra/cluster/options.rb +42 -0
- data/lib/cassandra/cluster/registry.rb +198 -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/partitioners.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/replication_strategies.rb +21 -0
- data/lib/cassandra/cluster/schema/type_parser.rb +138 -0
- data/lib/cassandra/cluster/schema.rb +340 -0
- data/lib/cassandra/cluster.rb +215 -0
- data/lib/cassandra/column.rb +92 -0
- data/lib/cassandra/compression/compressors/lz4.rb +72 -0
- data/lib/cassandra/compression/compressors/snappy.rb +66 -0
- data/lib/cassandra/compression.rb +66 -0
- data/lib/cassandra/driver.rb +111 -0
- data/lib/cassandra/errors.rb +79 -0
- data/lib/cassandra/execution/info.rb +51 -0
- data/lib/cassandra/execution/options.rb +80 -0
- data/lib/cassandra/execution/trace.rb +152 -0
- data/lib/cassandra/future.rb +675 -0
- data/lib/cassandra/host.rb +79 -0
- data/lib/cassandra/keyspace.rb +133 -0
- data/lib/cassandra/listener.rb +87 -0
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +149 -0
- data/lib/cassandra/load_balancing/policies/round_robin.rb +132 -0
- data/lib/cassandra/load_balancing/policies/token_aware.rb +119 -0
- data/lib/cassandra/load_balancing/policies/white_list.rb +90 -0
- data/lib/cassandra/load_balancing/policies.rb +19 -0
- data/lib/cassandra/load_balancing.rb +113 -0
- data/lib/cassandra/protocol/cql_byte_buffer.rb +307 -0
- data/lib/cassandra/protocol/cql_protocol_handler.rb +323 -0
- data/lib/cassandra/protocol/frame_decoder.rb +128 -0
- data/lib/cassandra/protocol/frame_encoder.rb +48 -0
- data/lib/cassandra/protocol/request.rb +38 -0
- data/lib/cassandra/protocol/requests/auth_response_request.rb +47 -0
- data/lib/cassandra/protocol/requests/batch_request.rb +76 -0
- data/lib/cassandra/protocol/requests/credentials_request.rb +47 -0
- data/lib/cassandra/protocol/requests/execute_request.rb +103 -0
- data/lib/cassandra/protocol/requests/options_request.rb +39 -0
- data/lib/cassandra/protocol/requests/prepare_request.rb +50 -0
- data/lib/cassandra/protocol/requests/query_request.rb +153 -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 +38 -0
- data/lib/cassandra/protocol/responses/auth_challenge_response.rb +41 -0
- data/lib/cassandra/protocol/responses/auth_success_response.rb +41 -0
- data/lib/cassandra/protocol/responses/authenticate_response.rb +41 -0
- data/lib/cassandra/protocol/responses/detailed_error_response.rb +60 -0
- data/lib/cassandra/protocol/responses/error_response.rb +50 -0
- data/lib/cassandra/protocol/responses/event_response.rb +39 -0
- data/lib/cassandra/protocol/responses/prepared_result_response.rb +64 -0
- data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +43 -0
- data/lib/cassandra/protocol/responses/ready_response.rb +44 -0
- data/lib/cassandra/protocol/responses/result_response.rb +48 -0
- data/lib/cassandra/protocol/responses/rows_result_response.rb +139 -0
- data/lib/cassandra/protocol/responses/schema_change_event_response.rb +60 -0
- data/lib/cassandra/protocol/responses/schema_change_result_response.rb +57 -0
- data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +42 -0
- data/lib/cassandra/protocol/responses/status_change_event_response.rb +44 -0
- data/lib/cassandra/protocol/responses/supported_response.rb +41 -0
- data/lib/cassandra/protocol/responses/topology_change_event_response.rb +34 -0
- data/lib/cassandra/protocol/responses/void_result_response.rb +39 -0
- data/lib/cassandra/protocol/type_converter.rb +384 -0
- data/lib/cassandra/protocol.rb +93 -0
- data/lib/cassandra/reconnection/policies/constant.rb +48 -0
- data/lib/cassandra/reconnection/policies/exponential.rb +79 -0
- data/lib/cassandra/reconnection/policies.rb +20 -0
- data/lib/cassandra/reconnection.rb +49 -0
- data/lib/cassandra/result.rb +215 -0
- data/lib/cassandra/retry/policies/default.rb +47 -0
- data/lib/cassandra/retry/policies/downgrading_consistency.rb +71 -0
- data/lib/cassandra/retry/policies/fallthrough.rb +39 -0
- data/lib/cassandra/retry/policies.rb +21 -0
- data/lib/cassandra/retry.rb +142 -0
- data/lib/cassandra/session.rb +202 -0
- data/lib/cassandra/statement.rb +22 -0
- data/lib/cassandra/statements/batch.rb +95 -0
- data/lib/cassandra/statements/bound.rb +48 -0
- data/lib/cassandra/statements/prepared.rb +81 -0
- data/lib/cassandra/statements/simple.rb +58 -0
- data/lib/cassandra/statements/void.rb +33 -0
- data/lib/cassandra/statements.rb +23 -0
- data/lib/cassandra/table.rb +299 -0
- data/lib/cassandra/time_uuid.rb +142 -0
- data/lib/cassandra/util.rb +167 -0
- data/lib/cassandra/uuid.rb +104 -0
- data/lib/cassandra/version.rb +21 -0
- data/lib/cassandra.rb +428 -0
- data/lib/cassandra_murmur3.jar +0 -0
- metadata +211 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Copyright 2013-2014 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
|
+
# Cluster represents a cassandra cluster. It serves as a {Cassandra::Session}
|
|
21
|
+
# factory and a collection of metadata.
|
|
22
|
+
#
|
|
23
|
+
# @see Cassandra::Cluster#connect Creating a new session
|
|
24
|
+
# @see Cassandra::Cluster#each_host Getting all peers in the cluster
|
|
25
|
+
# @see Cassandra::Cluster#each_keyspace Getting all existing keyspaces
|
|
26
|
+
class Cluster
|
|
27
|
+
extend Forwardable
|
|
28
|
+
|
|
29
|
+
# @!method host(address)
|
|
30
|
+
# Find a host by its address
|
|
31
|
+
# @param address [IPAddr, String] ip address
|
|
32
|
+
# @return [Cassandra::Host, nil] host or nil
|
|
33
|
+
#
|
|
34
|
+
# @!method has_host?(address)
|
|
35
|
+
# Determine if a host by a given address exists
|
|
36
|
+
# @param address [IPAddr, String] ip address
|
|
37
|
+
# @return [Boolean] true or false
|
|
38
|
+
def_delegators :@registry, :host, :has_host?
|
|
39
|
+
|
|
40
|
+
# @!method keyspace(name)
|
|
41
|
+
# Find a keyspace by name
|
|
42
|
+
# @param name [String] keyspace name
|
|
43
|
+
# @return [Cassandra::Keyspace, nil] keyspace or nil
|
|
44
|
+
#
|
|
45
|
+
# @!method has_keyspace?(name)
|
|
46
|
+
# Determine if a keyspace by a given name exists
|
|
47
|
+
# @param name [String] keyspace name
|
|
48
|
+
# @return [Boolean] true or false
|
|
49
|
+
def_delegators :@schema, :keyspace, :has_keyspace?
|
|
50
|
+
|
|
51
|
+
# @!method name
|
|
52
|
+
# Return cluster's name
|
|
53
|
+
# @return [String] cluster's name
|
|
54
|
+
#
|
|
55
|
+
# @!method find_replicas(keyspace, statement)
|
|
56
|
+
# Return replicas for a given statement and keyspace
|
|
57
|
+
# @note an empty list is returned when statement/keyspace information is
|
|
58
|
+
# not enough to determine replica list.
|
|
59
|
+
# @param keyspace [String] keyspace name
|
|
60
|
+
# @param statement [Cassandra::Statement] statement for which to find
|
|
61
|
+
# replicas
|
|
62
|
+
# @return [Array<Cassandra::Host>] a list of replicas
|
|
63
|
+
def_delegators :@metadata, :name, :find_replicas
|
|
64
|
+
|
|
65
|
+
# @private
|
|
66
|
+
def initialize(logger, io_reactor, control_connection, cluster_registry, cluster_schema, cluster_metadata, execution_options, connection_options, load_balancing_policy, reconnection_policy, retry_policy, connector, futures_factory)
|
|
67
|
+
@logger = logger
|
|
68
|
+
@io_reactor = io_reactor
|
|
69
|
+
@control_connection = control_connection
|
|
70
|
+
@registry = cluster_registry
|
|
71
|
+
@schema = cluster_schema
|
|
72
|
+
@metadata = cluster_metadata
|
|
73
|
+
@execution_options = execution_options
|
|
74
|
+
@connection_options = connection_options
|
|
75
|
+
@load_balancing_policy = load_balancing_policy
|
|
76
|
+
@reconnection_policy = reconnection_policy
|
|
77
|
+
@retry_policy = retry_policy
|
|
78
|
+
@connector = connector
|
|
79
|
+
@futures = futures_factory
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Register a cluster state listener. State listener will start receiving
|
|
83
|
+
# notifications about topology and schema changes
|
|
84
|
+
#
|
|
85
|
+
# @param listener [Cassandra::Listener] cluster state listener
|
|
86
|
+
# @return [self]
|
|
87
|
+
def register(listener)
|
|
88
|
+
@registry.add_listener(listener)
|
|
89
|
+
@schema.add_listener(listener)
|
|
90
|
+
self
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Unregister a cluster state listener. State listener will stop receiving
|
|
94
|
+
# notifications about topology and schema changes
|
|
95
|
+
#
|
|
96
|
+
# @param listener [Cassandra::Listener] cluster state listener
|
|
97
|
+
# @return [self]
|
|
98
|
+
def unregister(listener)
|
|
99
|
+
@registry.remove_listener(listener)
|
|
100
|
+
@schema.remove_listener(listener)
|
|
101
|
+
self
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Yield or enumerate each member of this cluster
|
|
105
|
+
# @overload each_host
|
|
106
|
+
# @yieldparam host [Cassandra::Host] current host
|
|
107
|
+
# @return [Cassandra::Cluster] self
|
|
108
|
+
# @overload each_host
|
|
109
|
+
# @return [Array<Cassandra::Host>] a list of hosts
|
|
110
|
+
def each_host(&block)
|
|
111
|
+
r = @registry.each_host(&block)
|
|
112
|
+
return self if r == @registry
|
|
113
|
+
r
|
|
114
|
+
end
|
|
115
|
+
alias :hosts :each_host
|
|
116
|
+
|
|
117
|
+
# Yield or enumerate each keyspace defined in this cluster
|
|
118
|
+
# @overload each_keyspace
|
|
119
|
+
# @yieldparam keyspace [Cassandra::Keyspace] current keyspace
|
|
120
|
+
# @return [Cassandra::Cluster] self
|
|
121
|
+
# @overload each_keyspace
|
|
122
|
+
# @return [Array<Cassandra::Keyspace>] a list of keyspaces
|
|
123
|
+
def each_keyspace(&block)
|
|
124
|
+
r = @schema.each_keyspace(&block)
|
|
125
|
+
return self if r == @schema
|
|
126
|
+
r
|
|
127
|
+
end
|
|
128
|
+
alias :keyspaces :each_keyspace
|
|
129
|
+
|
|
130
|
+
# Asynchronously create a new session, optionally scoped to a keyspace
|
|
131
|
+
#
|
|
132
|
+
# @param keyspace [String] optional keyspace to scope session to
|
|
133
|
+
#
|
|
134
|
+
# @return [Cassandra::Future<Cassandra::Session>] a future new session that
|
|
135
|
+
# can prepare and execute statements
|
|
136
|
+
def connect_async(keyspace = nil)
|
|
137
|
+
if !keyspace.nil? && !keyspace.is_a?(::String)
|
|
138
|
+
return @futures.error(::ArgumentError.new("keyspace must be a string, #{keyspace.inspect} given"))
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
client = Client.new(@logger, @registry, @schema, @io_reactor, @connector, @load_balancing_policy, @reconnection_policy, @retry_policy, @connection_options, @futures)
|
|
142
|
+
session = Session.new(client, @execution_options, @futures)
|
|
143
|
+
promise = @futures.promise
|
|
144
|
+
|
|
145
|
+
client.connect.on_complete do |f|
|
|
146
|
+
if f.resolved?
|
|
147
|
+
if keyspace
|
|
148
|
+
f = session.execute_async("USE #{keyspace}")
|
|
149
|
+
|
|
150
|
+
f.on_success {promise.fulfill(session)}
|
|
151
|
+
f.on_failure {|e| promise.break(e)}
|
|
152
|
+
else
|
|
153
|
+
promise.fulfill(session)
|
|
154
|
+
end
|
|
155
|
+
else
|
|
156
|
+
f.on_failure {|e| promise.break(e)}
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
promise.future
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Synchronously create a new session, optionally scoped to a keyspace
|
|
164
|
+
#
|
|
165
|
+
# @param keyspace [String] optional keyspace to scope session to
|
|
166
|
+
# @raise [ArgumentError] if keyspace is not a String
|
|
167
|
+
# @return [Cassandra::Session] a new session that can prepare and execute
|
|
168
|
+
# statements
|
|
169
|
+
#
|
|
170
|
+
# @see Cassandra::Cluster#connect_async
|
|
171
|
+
def connect(keyspace = nil)
|
|
172
|
+
connect_async(keyspace).get
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Asynchronously closes all sessions managed by this cluster
|
|
176
|
+
#
|
|
177
|
+
# @return [Cassandra::Future<Cassandra::Cluster>] a future that resolves to
|
|
178
|
+
# self once closed
|
|
179
|
+
def close_async
|
|
180
|
+
promise = @futures.promise
|
|
181
|
+
|
|
182
|
+
@control_connection.close_async.on_complete do |f|
|
|
183
|
+
if f.resolved?
|
|
184
|
+
promise.fulfill(self)
|
|
185
|
+
else
|
|
186
|
+
f.on_failure {|e| promise.break(e)}
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
promise.future
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Synchronously closes all sessions managed by this cluster
|
|
194
|
+
#
|
|
195
|
+
# @return [self] this cluster
|
|
196
|
+
#
|
|
197
|
+
# @see Cassandra::Cluster#close_async
|
|
198
|
+
def close
|
|
199
|
+
close_async.get
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# @return [String] a CLI-friendly cluster representation
|
|
203
|
+
def inspect
|
|
204
|
+
"#<#{self.class.name}:0x#{self.object_id.to_s(16)}>"
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
require 'cassandra/cluster/client'
|
|
210
|
+
require 'cassandra/cluster/connector'
|
|
211
|
+
require 'cassandra/cluster/control_connection'
|
|
212
|
+
require 'cassandra/cluster/metadata'
|
|
213
|
+
require 'cassandra/cluster/options'
|
|
214
|
+
require 'cassandra/cluster/registry'
|
|
215
|
+
require 'cassandra/cluster/schema'
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Copyright 2013-2014 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 cassandra column
|
|
21
|
+
# @see Cassandra::Table#each_column
|
|
22
|
+
# @see Cassandra::Table#column
|
|
23
|
+
class Column
|
|
24
|
+
# @private
|
|
25
|
+
class Index
|
|
26
|
+
# @return [String] index name
|
|
27
|
+
attr_reader :name
|
|
28
|
+
# @return [String] custom index class name
|
|
29
|
+
attr_reader :custom_class_name
|
|
30
|
+
|
|
31
|
+
# @private
|
|
32
|
+
def initialize(name, custom_class_name = nil)
|
|
33
|
+
@name = name
|
|
34
|
+
@custom_class_name = custom_class_name
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @return [String] column name
|
|
39
|
+
attr_reader :name
|
|
40
|
+
# @private
|
|
41
|
+
# @return [Symbol, Array(Symbol, Symbol)] column type
|
|
42
|
+
attr_reader :type
|
|
43
|
+
# @return [Symbol] column order (`:asc` or `:desc`)
|
|
44
|
+
attr_reader :order
|
|
45
|
+
# @private
|
|
46
|
+
# @return [Cassandra::Column::Index, nil] column index
|
|
47
|
+
attr_reader :index
|
|
48
|
+
# @private
|
|
49
|
+
# @return [Boolean] whether the column is static
|
|
50
|
+
attr_reader :static
|
|
51
|
+
|
|
52
|
+
# @private
|
|
53
|
+
def initialize(name, type, order, index = nil, is_static = false)
|
|
54
|
+
@name = name
|
|
55
|
+
@type = type
|
|
56
|
+
@order = order
|
|
57
|
+
@index = index
|
|
58
|
+
@static = is_static
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @return [Boolean] whether the column is static
|
|
62
|
+
def static?
|
|
63
|
+
@static
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @return [String] a cql representation of this column
|
|
67
|
+
def to_cql
|
|
68
|
+
type = case @type
|
|
69
|
+
when Array
|
|
70
|
+
type, *args = @type
|
|
71
|
+
"#{type.to_s}<#{args.map(&:to_s).join(', ')}>"
|
|
72
|
+
else
|
|
73
|
+
@type.to_s
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
cql = "#{@name} #{type}"
|
|
77
|
+
cql << ' static' if @static
|
|
78
|
+
cql
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# @return [Boolean] whether this column is equal to the other
|
|
82
|
+
def eql?(other)
|
|
83
|
+
other.is_a?(Column) &&
|
|
84
|
+
@name == other.name &&
|
|
85
|
+
@type == other.type &&
|
|
86
|
+
@order == other.order &&
|
|
87
|
+
@index == other.index &&
|
|
88
|
+
@static == other.static?
|
|
89
|
+
end
|
|
90
|
+
alias :== :eql?
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Copyright 2013-2014 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
|
+
begin
|
|
20
|
+
require 'lz4-ruby'
|
|
21
|
+
rescue LoadError => e
|
|
22
|
+
raise LoadError, %[LZ4 support requires the "lz4-ruby" gem: #{e.message}], e.backtrace
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module Cassandra
|
|
26
|
+
module Compression
|
|
27
|
+
module Compressors
|
|
28
|
+
# A compressor that uses the LZ4 compression library.
|
|
29
|
+
#
|
|
30
|
+
# @note This compressor requires the
|
|
31
|
+
# [lz4-ruby](http://rubygems.org/gems/lz4-ruby) gem (v0.3.2 or later
|
|
32
|
+
# required).
|
|
33
|
+
# @note No need to instantiate this class manually, use `compression:
|
|
34
|
+
# :lz4` option when calling {Cassandra.connect} and one will be created
|
|
35
|
+
# automatically for you.
|
|
36
|
+
class Lz4 < Compressor
|
|
37
|
+
# @return [String] `'lz4'`
|
|
38
|
+
attr_reader :algorithm
|
|
39
|
+
|
|
40
|
+
# @param [Integer] min_size (64) Don't compress frames smaller than
|
|
41
|
+
# this size (see {#compress?}).
|
|
42
|
+
def initialize(min_size=64)
|
|
43
|
+
@algorithm = 'lz4'.freeze
|
|
44
|
+
@min_size = min_size
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @return [true, false] will return false for frames smaller than the
|
|
48
|
+
# `min_size` given to the constructor.
|
|
49
|
+
# @see Cassandra::Compression::Compressor#compress?
|
|
50
|
+
def compress?(str)
|
|
51
|
+
str.bytesize > @min_size
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @see Cassandra::Compression::Compressor#compress
|
|
55
|
+
def compress(str)
|
|
56
|
+
[str.bytesize, ::LZ4::Raw.compress(str.to_s).first].pack(BUFFER_FORMAT)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @see Cassandra::Compression::Compressor#decompress
|
|
60
|
+
def decompress(str)
|
|
61
|
+
decompressed_size, compressed_data = str.to_s.unpack(BUFFER_FORMAT)
|
|
62
|
+
::LZ4::Raw.decompress(compressed_data, decompressed_size).first
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
# @private
|
|
68
|
+
BUFFER_FORMAT = 'Na*'.freeze
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Copyright 2013-2014 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
|
+
begin
|
|
20
|
+
require 'snappy'
|
|
21
|
+
rescue LoadError => e
|
|
22
|
+
raise LoadError, %[Snappy support requires the "snappy" gem: #{e.message}], e.backtrace
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module Cassandra
|
|
26
|
+
module Compression
|
|
27
|
+
module Compressors
|
|
28
|
+
# A compressor that uses the Snappy compression library.
|
|
29
|
+
#
|
|
30
|
+
# @note This compressor requires the
|
|
31
|
+
# [snappy](http://rubygems.org/gems/snappy) gem (v0.0.10 or later for
|
|
32
|
+
# JRuby support).
|
|
33
|
+
# @note No need to instantiate this class manually, use `compression:
|
|
34
|
+
# :snappy` option when calling {Cassandra.connect} and one will be
|
|
35
|
+
# created automatically for you.
|
|
36
|
+
class Snappy < Compressor
|
|
37
|
+
# @return [String] `'snappy'`
|
|
38
|
+
attr_reader :algorithm
|
|
39
|
+
|
|
40
|
+
# @param [Integer] min_size (64) Don't compress frames smaller than
|
|
41
|
+
# this size (see {#compress?}).
|
|
42
|
+
def initialize(min_size=64)
|
|
43
|
+
@algorithm = 'snappy'.freeze
|
|
44
|
+
@min_size = min_size
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @return [true, false] will return false for frames smaller than the
|
|
48
|
+
# `min_size` given to the constructor.
|
|
49
|
+
# @see Cassandra::Compression::Compressor#compress?
|
|
50
|
+
def compress?(str)
|
|
51
|
+
str.bytesize > @min_size
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @see Cassandra::Compression::Compressor#compress
|
|
55
|
+
def compress(str)
|
|
56
|
+
::Snappy.deflate(str)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @see Cassandra::Compression::Compressor#decompress
|
|
60
|
+
def decompress(str)
|
|
61
|
+
::Snappy.inflate(str)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Copyright 2013-2014 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
|
+
module Compression
|
|
21
|
+
# @abstract Compressors given to {Cassandra.connect} as the `:compressor`
|
|
22
|
+
# option don't need to be subclasses of this class, but need to implement
|
|
23
|
+
# the same methods. This class exists only for documentation purposes.
|
|
24
|
+
class Compressor
|
|
25
|
+
# @!method algorithm
|
|
26
|
+
#
|
|
27
|
+
# Returns the name of the algorithm this compressor supports,
|
|
28
|
+
# e.g. "snappy" or "lz4".
|
|
29
|
+
#
|
|
30
|
+
# @return [String] algorithm
|
|
31
|
+
|
|
32
|
+
# @!method compress?(frame)
|
|
33
|
+
#
|
|
34
|
+
# Before compressing a frame the compressor will be asked if it wants
|
|
35
|
+
# to compress it or not. One reason it could say no is if the frame is
|
|
36
|
+
# small enough that compression would be unlikely to decrease its size.
|
|
37
|
+
#
|
|
38
|
+
# If your operations consist mostly of small prepared statement
|
|
39
|
+
# executions it might not be useful to compress the frames being sent
|
|
40
|
+
# _to_ Cassandra, but enabling compression can still be useful on the
|
|
41
|
+
# frames coming _from_ Cassandra. Making this method always return
|
|
42
|
+
# false disables request compression, but will still make the client
|
|
43
|
+
# tell Cassandra that it supports compressed frames.
|
|
44
|
+
#
|
|
45
|
+
# The bytes given to {#compress?} are the same as to {#compress}
|
|
46
|
+
#
|
|
47
|
+
# @param frame [String] the bytes of the frame to be compressed
|
|
48
|
+
# @return [true, false] whether to perform compression or not
|
|
49
|
+
|
|
50
|
+
# @!method compress(frame)
|
|
51
|
+
#
|
|
52
|
+
# Compresses the raw bytes of a frame.
|
|
53
|
+
#
|
|
54
|
+
# @param frame [String] the bytes of the frame to be compressed
|
|
55
|
+
# @return [String] the compressed frame
|
|
56
|
+
|
|
57
|
+
# @!method decompress(compressed_frame)
|
|
58
|
+
#
|
|
59
|
+
# Decompresses the raw bytes of a compressed frame.
|
|
60
|
+
#
|
|
61
|
+
# @param compressed_frame [String] the bytes of the compressed frame to
|
|
62
|
+
# be uncompressed
|
|
63
|
+
# @return [String] uncompressed bytes
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Copyright 2013-2014 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
|
+
# @private
|
|
21
|
+
class Driver
|
|
22
|
+
def self.let(name, &block)
|
|
23
|
+
define_method(name) { @instances[name] ||= @defaults.fetch(name) { instance_eval(&block) } }
|
|
24
|
+
define_method(:"#{name}=") { |object| @instances[name] = object }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
let(:io_reactor) { Io::IoReactor.new }
|
|
28
|
+
let(:cluster_registry) { Cluster::Registry.new(logger) }
|
|
29
|
+
let(:cluster_schema) { Cluster::Schema.new(schema_type_parser) }
|
|
30
|
+
let(:cluster_metadata) { Cluster::Metadata.new(
|
|
31
|
+
cluster_registry,
|
|
32
|
+
cluster_schema,
|
|
33
|
+
{
|
|
34
|
+
'org.apache.cassandra.dht.Murmur3Partitioner' => murmur3_partitioner,
|
|
35
|
+
'org.apache.cassandra.dht.ByteOrderedPartitioner' => ordered_partitioner,
|
|
36
|
+
'org.apache.cassandra.dht.RandomPartitioner' => random_partitioner
|
|
37
|
+
}.freeze,
|
|
38
|
+
{
|
|
39
|
+
'org.apache.cassandra.locator.SimpleStrategy' => simple_replication_strategy,
|
|
40
|
+
'org.apache.cassandra.locator.NetworkTopologyStrategy' => network_topology_replication_strategy
|
|
41
|
+
}.freeze,
|
|
42
|
+
no_replication_strategy
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
let(:futures_factory) { Future }
|
|
46
|
+
|
|
47
|
+
let(:schema_type_parser) { Cluster::Schema::TypeParser.new }
|
|
48
|
+
|
|
49
|
+
let(:simple_replication_strategy) { Cluster::Schema::ReplicationStrategies::Simple.new }
|
|
50
|
+
let(:network_topology_replication_strategy) { Cluster::Schema::ReplicationStrategies::NetworkTopology.new }
|
|
51
|
+
let(:no_replication_strategy) { Cluster::Schema::ReplicationStrategies::None.new }
|
|
52
|
+
|
|
53
|
+
let(:murmur3_partitioner) { Cluster::Schema::Partitioners::Murmur3.new }
|
|
54
|
+
let(:ordered_partitioner) { Cluster::Schema::Partitioners::Ordered.new }
|
|
55
|
+
let(:random_partitioner) { Cluster::Schema::Partitioners::Random.new }
|
|
56
|
+
|
|
57
|
+
let(:connector) { Cluster::Connector.new(logger, io_reactor, cluster_registry, connection_options) }
|
|
58
|
+
|
|
59
|
+
let(:control_connection) { Cluster::ControlConnection.new(logger, io_reactor, cluster_registry, cluster_schema, cluster_metadata, load_balancing_policy, reconnection_policy, connector) }
|
|
60
|
+
|
|
61
|
+
let(:cluster) { Cluster.new(logger, io_reactor, control_connection, cluster_registry, cluster_schema, cluster_metadata, execution_options, connection_options, load_balancing_policy, reconnection_policy, retry_policy, connector, futures_factory) }
|
|
62
|
+
|
|
63
|
+
let(:execution_options) do
|
|
64
|
+
Execution::Options.new({
|
|
65
|
+
:consistency => consistency,
|
|
66
|
+
:trace => trace,
|
|
67
|
+
:page_size => page_size
|
|
68
|
+
})
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
let(:connection_options) { Cluster::Options.new(protocol_version, credentials, auth_provider, compressor, port, connect_timeout, ssl, connections_per_local_node, connections_per_remote_node) }
|
|
72
|
+
|
|
73
|
+
let(:port) { 9042 }
|
|
74
|
+
let(:protocol_version) { 2 }
|
|
75
|
+
let(:connect_timeout) { 10 }
|
|
76
|
+
let(:ssl) { false }
|
|
77
|
+
let(:logger) { Client::NullLogger.new }
|
|
78
|
+
let(:compressor) { nil }
|
|
79
|
+
let(:credentials) { nil }
|
|
80
|
+
let(:auth_provider) { nil }
|
|
81
|
+
let(:load_balancing_policy) { LoadBalancing::Policies::RoundRobin.new }
|
|
82
|
+
let(:reconnection_policy) { Reconnection::Policies::Exponential.new(0.5, 30, 2) }
|
|
83
|
+
let(:retry_policy) { Retry::Policies::Default.new }
|
|
84
|
+
let(:consistency) { :quorum }
|
|
85
|
+
let(:trace) { false }
|
|
86
|
+
let(:page_size) { nil }
|
|
87
|
+
|
|
88
|
+
let(:connections_per_local_node) { 2 }
|
|
89
|
+
let(:connections_per_remote_node) { 1 }
|
|
90
|
+
|
|
91
|
+
let(:listeners) { [] }
|
|
92
|
+
|
|
93
|
+
def initialize(defaults = {})
|
|
94
|
+
@defaults = defaults
|
|
95
|
+
@instances = {}
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def connect(addresses)
|
|
99
|
+
load_balancing_policy.setup(cluster)
|
|
100
|
+
cluster_registry.add_listener(load_balancing_policy)
|
|
101
|
+
cluster_registry.add_listener(control_connection)
|
|
102
|
+
listeners.each do |listener|
|
|
103
|
+
cluster.register(listener)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
addresses.each {|address| cluster_registry.host_found(address)}
|
|
107
|
+
|
|
108
|
+
control_connection.connect_async.map(cluster)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Copyright 2013-2014 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
|
+
# Base class for all Errors raised by the driver
|
|
21
|
+
# @see Cassandra::Errors
|
|
22
|
+
class Error < StandardError
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module Errors
|
|
26
|
+
# @!parse class IoError < StandardError; end
|
|
27
|
+
# @private
|
|
28
|
+
IoError = Ione::IoError
|
|
29
|
+
|
|
30
|
+
# This error type represents errors sent by the server, the `code` attribute
|
|
31
|
+
# can be used to find the exact type, and `cql` contains the request's CQL,
|
|
32
|
+
# if any. `message` contains the human readable error message sent by the
|
|
33
|
+
# server.
|
|
34
|
+
class QueryError < Error
|
|
35
|
+
# @return [Integer] error code
|
|
36
|
+
attr_reader :code
|
|
37
|
+
# @return [String] original CQL used
|
|
38
|
+
attr_reader :cql
|
|
39
|
+
# @return [Hash{Symbol => String, Integer}] various error details
|
|
40
|
+
attr_reader :details
|
|
41
|
+
|
|
42
|
+
# @private
|
|
43
|
+
def initialize(code, message, cql=nil, details=nil)
|
|
44
|
+
super(message)
|
|
45
|
+
@code = code
|
|
46
|
+
@cql = cql
|
|
47
|
+
@details = details
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# This error is thrown when not hosts could be reached during connection or query execution.
|
|
52
|
+
class NoHostsAvailable < Error
|
|
53
|
+
# @return [Hash{Cassandra::Host => Exception}] a map of hosts to underlying exceptions
|
|
54
|
+
attr_reader :errors
|
|
55
|
+
|
|
56
|
+
# @private
|
|
57
|
+
def initialize(errors = {})
|
|
58
|
+
super("no hosts available, check #errors property for details")
|
|
59
|
+
|
|
60
|
+
@errors = errors
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Client error represents bad driver state or configuration
|
|
65
|
+
#
|
|
66
|
+
# @see Cassandra::Errors::AuthenticationError
|
|
67
|
+
class ClientError < Error
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Raised when cannot authenticate to Cassandra
|
|
71
|
+
class AuthenticationError < ClientError
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# @private
|
|
75
|
+
NotConnectedError = Class.new(Error)
|
|
76
|
+
# @private
|
|
77
|
+
NotPreparedError = Class.new(Error)
|
|
78
|
+
end
|
|
79
|
+
end
|