aerospike 2.5.1 → 2.6.0
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 +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +3 -3
- data/lib/aerospike.rb +33 -6
- data/lib/aerospike/aerospike_exception.rb +9 -26
- data/lib/aerospike/client.rb +7 -22
- data/lib/aerospike/{cluster/cluster.rb → cluster.rb} +122 -161
- data/lib/aerospike/cluster/create_connection.rb +42 -0
- data/lib/aerospike/cluster/find_node.rb +35 -0
- data/lib/aerospike/connection/authenticate.rb +35 -0
- data/lib/aerospike/connection/create.rb +36 -0
- data/lib/aerospike/host.rb +7 -4
- data/lib/aerospike/host/parse.rb +50 -0
- data/lib/aerospike/node.rb +232 -0
- data/lib/aerospike/node/generation.rb +50 -0
- data/lib/aerospike/node/refresh/failed.rb +34 -0
- data/lib/aerospike/node/refresh/friends.rb +100 -0
- data/lib/aerospike/node/refresh/info.rb +60 -0
- data/lib/aerospike/node/refresh/partitions.rb +60 -0
- data/lib/aerospike/node/refresh/peers.rb +83 -0
- data/lib/aerospike/node/refresh/reset.rb +36 -0
- data/lib/aerospike/node/verify/cluster_name.rb +35 -0
- data/lib/aerospike/node/verify/name.rb +43 -0
- data/lib/aerospike/node/verify/partition_generation.rb +43 -0
- data/lib/aerospike/node/verify/peers_generation.rb +41 -0
- data/lib/aerospike/{cluster/node_validator.rb → node_validator.rb} +29 -47
- data/lib/aerospike/peer.rb +24 -0
- data/lib/aerospike/peers.rb +44 -0
- data/lib/aerospike/peers/fetch.rb +36 -0
- data/lib/aerospike/peers/parse.rb +88 -0
- data/lib/aerospike/policy/client_policy.rb +16 -9
- data/lib/aerospike/socket/base.rb +86 -0
- data/lib/aerospike/socket/ssl.rb +70 -0
- data/lib/aerospike/socket/tcp.rb +57 -0
- data/lib/aerospike/utils/buffer.rb +7 -6
- data/lib/aerospike/utils/string_parser.rb +53 -0
- data/lib/aerospike/value/value.rb +7 -8
- data/lib/aerospike/version.rb +1 -1
- metadata +30 -7
- data/lib/aerospike/cluster/connection.rb +0 -124
- data/lib/aerospike/cluster/node.rb +0 -274
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 Aerospike, Inc.
|
4
|
+
#
|
5
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
6
|
+
# license agreements.
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
9
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
10
|
+
# the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
16
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
17
|
+
# License for the specific language governing permissions and limitations under
|
18
|
+
# the License.
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
class Cluster
|
22
|
+
# Create connection based on cluster config and authenticate if needed
|
23
|
+
module CreateConnection
|
24
|
+
class << self
|
25
|
+
def call(cluster, host)
|
26
|
+
::Aerospike::Connection::Create.(
|
27
|
+
host.name,
|
28
|
+
host.port,
|
29
|
+
tls_name: host.tls_name,
|
30
|
+
timeout: cluster.connection_timeout,
|
31
|
+
ssl_options: cluster.ssl_options
|
32
|
+
).tap do |conn|
|
33
|
+
if cluster.credentials_given?
|
34
|
+
# Authenticate will raise and close connection if invalid credentials
|
35
|
+
Connection::Authenticate.(conn, cluster.user, cluster.password)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 Aerospike, Inc.
|
4
|
+
#
|
5
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
6
|
+
# license agreements.
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
9
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
10
|
+
# the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
16
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
17
|
+
# License for the specific language governing permissions and limitations under
|
18
|
+
# the License.
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
class Cluster
|
22
|
+
# Find node in cluster by name
|
23
|
+
module FindNode
|
24
|
+
class << self
|
25
|
+
def call(cluster, peers, node_name)
|
26
|
+
node = cluster.find_node_by_name(node_name) || peers.find_node_by_name(node_name)
|
27
|
+
return if node.nil?
|
28
|
+
node.tap do |n|
|
29
|
+
n.increase_reference_count!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 Aerospike, Inc.
|
4
|
+
#
|
5
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
6
|
+
# license agreements.
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
9
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
10
|
+
# the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
16
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
17
|
+
# License for the specific language governing permissions and limitations under
|
18
|
+
# the License.
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
module Connection # :nodoc:
|
22
|
+
module Authenticate
|
23
|
+
class << self
|
24
|
+
def call(conn, user, password)
|
25
|
+
command = AdminCommand.new
|
26
|
+
command.authenticate(conn, user, password)
|
27
|
+
true
|
28
|
+
rescue ::Aerospike::Exceptions::Aerospike
|
29
|
+
conn.close if conn
|
30
|
+
raise ::Aerospike::Exceptions::InvalidCredentials
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2014-2018 Aerospike, Inc.
|
4
|
+
#
|
5
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
6
|
+
# license agreements.
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
9
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
10
|
+
# the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
16
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
17
|
+
# License for the specific language governing permissions and limitations under
|
18
|
+
# the License.
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
module Connection # :nodoc:
|
22
|
+
module Create
|
23
|
+
class << self
|
24
|
+
def call(host, port, timeout: 30, tls_name: nil, ssl_options: nil)
|
25
|
+
if !ssl_options.nil? && ssl_options[:enable] != false
|
26
|
+
::Aerospike::Socket::SSL.connect(
|
27
|
+
host, port, timeout, tls_name, ssl_options
|
28
|
+
)
|
29
|
+
else
|
30
|
+
::Aerospike::Socket::TCP.connect(host, port, timeout)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/aerospike/host.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
# Copyright 2014-
|
2
|
+
# Copyright 2014-2018 Aerospike, Inc.
|
3
3
|
#
|
4
4
|
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
5
5
|
# license agreements.
|
6
6
|
#
|
7
7
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
8
8
|
# use this file except in compliance with the License. You may obtain a copy of
|
9
|
-
# the License at
|
9
|
+
# the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
12
|
#
|
11
13
|
# Unless required by applicable law or agreed to in writing, software
|
12
14
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
@@ -18,11 +20,12 @@ module Aerospike
|
|
18
20
|
|
19
21
|
class Host
|
20
22
|
|
21
|
-
attr_accessor :name, :port
|
23
|
+
attr_accessor :name, :port, :tls_name
|
22
24
|
|
23
|
-
def initialize(host_name, host_port)
|
25
|
+
def initialize(host_name, host_port, tls_name = nil)
|
24
26
|
@name = host_name
|
25
27
|
@port = host_port
|
28
|
+
@tls_name = tls_name
|
26
29
|
end
|
27
30
|
|
28
31
|
def to_s
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 Aerospike, Inc.
|
4
|
+
#
|
5
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
6
|
+
# license agreements.
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
9
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
10
|
+
# the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
16
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
17
|
+
# License for the specific language governing permissions and limitations under
|
18
|
+
# the License.
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
class Host
|
22
|
+
module Parse
|
23
|
+
INTEGER_REGEX = /\A\d+\z/
|
24
|
+
|
25
|
+
class << self
|
26
|
+
# Parse hosts from string format: hostname1[:tlsname1][:port1],...
|
27
|
+
def call(hosts, default_port = 3000)
|
28
|
+
case hosts
|
29
|
+
when Host
|
30
|
+
[hosts]
|
31
|
+
when Array
|
32
|
+
hosts
|
33
|
+
when String
|
34
|
+
hosts.split(?,).map { |host|
|
35
|
+
addr, tls_name, port = host.split(?:)
|
36
|
+
if port.nil? && tls_name && tls_name.match(INTEGER_REGEX)
|
37
|
+
port = tls_name
|
38
|
+
tls_name = nil
|
39
|
+
end
|
40
|
+
port ||= default_port
|
41
|
+
Host.new(addr, port.to_i, tls_name)
|
42
|
+
}
|
43
|
+
else
|
44
|
+
fail TypeError, "hosts should be a Host object, an Array of Host objects, or a String"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2014-2018 Aerospike, Inc.
|
4
|
+
#
|
5
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
6
|
+
# license agreements.
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
9
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
10
|
+
# the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
16
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
17
|
+
# License for the specific language governing permissions and limitations under
|
18
|
+
# the License.
|
19
|
+
|
20
|
+
require 'aerospike/atomic/atomic'
|
21
|
+
|
22
|
+
module Aerospike
|
23
|
+
class Node
|
24
|
+
|
25
|
+
attr_reader :reference_count, :responded, :name, :features, :cluster_name, :partition_generation, :peers_generation, :failures, :cluster, :peers_count, :host
|
26
|
+
|
27
|
+
PARTITIONS = 4096
|
28
|
+
FULL_HEALTH = 100
|
29
|
+
|
30
|
+
# Initialize server node with connection parameters.
|
31
|
+
def initialize(cluster, nv)
|
32
|
+
@cluster = cluster
|
33
|
+
@name = nv.name
|
34
|
+
@aliases = Atomic.new(nv.aliases)
|
35
|
+
@host = nv.host
|
36
|
+
@use_new_info = Atomic.new(nv.use_new_info)
|
37
|
+
@features = nv.features
|
38
|
+
@cluster_name = nv.cluster_name
|
39
|
+
|
40
|
+
# TODO: Re-use connection from node validator
|
41
|
+
@tend_connection = nil
|
42
|
+
|
43
|
+
# Assign host to first IP alias because the server identifies nodes
|
44
|
+
# by IP address (not hostname).
|
45
|
+
@host = nv.aliases[0]
|
46
|
+
@health = Atomic.new(FULL_HEALTH)
|
47
|
+
@peers_count = Atomic.new(0)
|
48
|
+
@peers_generation = ::Aerospike::Node::Generation.new
|
49
|
+
@partition_generation = ::Aerospike::Node::Generation.new
|
50
|
+
@reference_count = Atomic.new(0)
|
51
|
+
@responded = Atomic.new(false)
|
52
|
+
@active = Atomic.new(true)
|
53
|
+
@failures = Atomic.new(0)
|
54
|
+
|
55
|
+
@connections = Pool.new(@cluster.connection_queue_size)
|
56
|
+
|
57
|
+
# TODO: put in separate methods
|
58
|
+
@connections.create_block = Proc.new do
|
59
|
+
conn = nil
|
60
|
+
loop do
|
61
|
+
conn = Cluster::CreateConnection.(cluster, host)
|
62
|
+
break if conn.connected?
|
63
|
+
end
|
64
|
+
conn
|
65
|
+
end
|
66
|
+
|
67
|
+
@connections.cleanup_block = Proc.new { |conn| conn.close if conn }
|
68
|
+
end
|
69
|
+
|
70
|
+
# Get a connection to the node. If no cached connection is not available,
|
71
|
+
# a new connection will be created
|
72
|
+
def get_connection(timeout)
|
73
|
+
loop do
|
74
|
+
conn = @connections.poll
|
75
|
+
if conn.connected?
|
76
|
+
conn.timeout = timeout.to_f
|
77
|
+
return conn
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Put back a connection to the cache. If cache is full, the connection will be
|
83
|
+
# closed and discarded
|
84
|
+
def put_connection(conn)
|
85
|
+
conn.close if !active?
|
86
|
+
@connections.offer(conn)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Separate connection for refreshing
|
90
|
+
def tend_connection
|
91
|
+
if @tend_connection.nil? || @tend_connection.closed?
|
92
|
+
@tend_connection = Cluster::CreateConnection.(cluster, host)
|
93
|
+
end
|
94
|
+
@tend_connection
|
95
|
+
end
|
96
|
+
|
97
|
+
# Mark the node as healthy
|
98
|
+
def restore_health
|
99
|
+
# There can be cases where health is full, but active is false.
|
100
|
+
# Once a node has been marked inactive, it stays inactive.
|
101
|
+
@health.value = FULL_HEALTH
|
102
|
+
end
|
103
|
+
|
104
|
+
# Decrease node Health as a result of bad connection or communication
|
105
|
+
def decrease_health
|
106
|
+
@health.update { |v| v - 1 }
|
107
|
+
end
|
108
|
+
|
109
|
+
# Check if the node is unhealthy
|
110
|
+
def unhealthy?
|
111
|
+
@health.value <= 0
|
112
|
+
end
|
113
|
+
|
114
|
+
# Retrieves host for the node
|
115
|
+
def get_host
|
116
|
+
@host
|
117
|
+
end
|
118
|
+
|
119
|
+
# Sets node as active
|
120
|
+
def active!
|
121
|
+
@active.update { |_| true }
|
122
|
+
end
|
123
|
+
|
124
|
+
# Sets node as inactive
|
125
|
+
def inactive!
|
126
|
+
@active.update { |_| false }
|
127
|
+
end
|
128
|
+
|
129
|
+
# Checks if the node is active
|
130
|
+
def active?
|
131
|
+
@active.value
|
132
|
+
end
|
133
|
+
|
134
|
+
def increase_reference_count!
|
135
|
+
@reference_count.update { |v| v + 1 }
|
136
|
+
end
|
137
|
+
|
138
|
+
def reset_reference_count!
|
139
|
+
@reference_count.value = 0
|
140
|
+
end
|
141
|
+
|
142
|
+
def responded!
|
143
|
+
@responded.value = true
|
144
|
+
end
|
145
|
+
|
146
|
+
def responded?
|
147
|
+
@responded.value == true
|
148
|
+
end
|
149
|
+
|
150
|
+
def reset_responded!
|
151
|
+
@responded.value = false
|
152
|
+
end
|
153
|
+
|
154
|
+
def has_peers?
|
155
|
+
@peers_count.value > 0
|
156
|
+
end
|
157
|
+
|
158
|
+
def failed?
|
159
|
+
@failures.value > 0
|
160
|
+
end
|
161
|
+
|
162
|
+
def failed!
|
163
|
+
@failures.update { |v| v + 1 }
|
164
|
+
end
|
165
|
+
|
166
|
+
def reset_failures!
|
167
|
+
@failures.value = 0
|
168
|
+
end
|
169
|
+
|
170
|
+
def aliases
|
171
|
+
@aliases.value
|
172
|
+
end
|
173
|
+
|
174
|
+
# Marks node as inactice and closes all cached connections
|
175
|
+
def close
|
176
|
+
inactive!
|
177
|
+
close_connections
|
178
|
+
end
|
179
|
+
|
180
|
+
def supports_feature?(feature)
|
181
|
+
@features.include?(feature.to_s)
|
182
|
+
end
|
183
|
+
|
184
|
+
def ==(other)
|
185
|
+
other && other.is_a?(Node) && (@name == other.name)
|
186
|
+
end
|
187
|
+
alias eql? ==
|
188
|
+
|
189
|
+
def use_new_info?
|
190
|
+
@use_new_info.value
|
191
|
+
end
|
192
|
+
|
193
|
+
def hash
|
194
|
+
@name.hash
|
195
|
+
end
|
196
|
+
|
197
|
+
def inspect
|
198
|
+
"#<Aerospike::Node: @name=#{@name}, @host=#{@host}>"
|
199
|
+
end
|
200
|
+
|
201
|
+
##
|
202
|
+
# Convenience wrappers for applying refresh operations to a node
|
203
|
+
##
|
204
|
+
|
205
|
+
def refresh_info(peers)
|
206
|
+
Node::Refresh::Info.(self, peers)
|
207
|
+
end
|
208
|
+
|
209
|
+
def refresh_partitions(peers)
|
210
|
+
Node::Refresh::Partitions.(self, peers)
|
211
|
+
end
|
212
|
+
|
213
|
+
def refresh_peers(peers)
|
214
|
+
Node::Refresh::Peers.(self, peers)
|
215
|
+
end
|
216
|
+
|
217
|
+
def refresh_reset
|
218
|
+
Node::Refresh::Reset.(self)
|
219
|
+
end
|
220
|
+
|
221
|
+
private
|
222
|
+
|
223
|
+
def close_connections
|
224
|
+
@tend_connection.close if @tend_connection
|
225
|
+
# drain connections and close all of them
|
226
|
+
# non-blocking, does not call create_block when passed false
|
227
|
+
while conn = @connections.poll(false)
|
228
|
+
conn.close if conn
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end # class Node
|
232
|
+
end # module
|