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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2cf4004182c5166b136433e8be338b9187718684c2783808d18b3ed31f1dbd17
|
4
|
+
data.tar.gz: 3a18cdde5294fb88ee0d4d710fb870c29db3273f5e29bd2d2ea92fd824857f00
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab75f0c1d0d57c37f3d3f16966a27017b706067e414306c25a3388ad4a02571cdb18b1f019d67472e35386ad659db1d23d8685664ea6a7f2279e904b4c52383b
|
7
|
+
data.tar.gz: 501dabb13c9eb471e83cbda40aa22f2df7ae7e2c6083d447917a02e71017b9b64abe4bbff37798ef2517bced052c17347a109c842b97ab6b16f921939c6ebe23
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
v2.6.0 / 2018-03-27
|
2
|
+
===================
|
3
|
+
|
4
|
+
* **New Features**
|
5
|
+
* Support for peers protocol for cluster discovery. Requires Aerospike server version 3.10 or later. Thanks to [@wallin](https://github.com/wallin) of [castle.io](https://castle.io/)! [[#59](https://github.com/aerospike/aerospike-client-ruby/pull/59)]
|
6
|
+
* TLS encryption support for client <-> server connections. Requires Aerospike Enterprise Edition version 3.11 or later. Thanks to [@wallin](https://github.com/wallin) of [castle.io](https://castle.io/)! [[#59](https://github.com/aerospike/aerospike-client-ruby/pull/59)]
|
7
|
+
|
8
|
+
* **Bug Fixes**
|
9
|
+
* Fix min./max. boundary check for Integer bin values and improve performance. Thanks to [@wallin](https://github.com/wallin) of [castle.io](https://castle.io/)! [[#60](https://github.com/aerospike/aerospike-client-ruby/pull/60)]
|
10
|
+
|
11
|
+
* **Updates**
|
12
|
+
* Update minimum required Ruby version to v2.3.
|
13
|
+
|
1
14
|
v2.5.1 / 2018-01-25
|
2
15
|
===================
|
3
16
|
|
data/README.md
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
|
8
8
|
An Aerospike library for Ruby.
|
9
9
|
|
10
|
-
This library is compatible with Ruby 2.
|
10
|
+
This library is compatible with Ruby 2.3+ and supports Linux, Mac OS X and various other BSDs.
|
11
11
|
|
12
12
|
- [Usage](#Usage)
|
13
13
|
- [Prerequisites](#Prerequisites)
|
@@ -61,7 +61,7 @@ Details about the API are available in the [`docs`](docs) directory.
|
|
61
61
|
<a name="Prerequisites"></a>
|
62
62
|
## Prerequisites
|
63
63
|
|
64
|
-
[Ruby](https://ruby-lang.org) version v2.
|
64
|
+
[Ruby](https://ruby-lang.org) version v2.3+ is required.
|
65
65
|
|
66
66
|
Aerospike Ruby client implements the wire protocol, and does not depend on the C client.
|
67
67
|
It is thread friendly.
|
@@ -81,7 +81,7 @@ Supported operating systems:
|
|
81
81
|
|
82
82
|
### Installation from source
|
83
83
|
|
84
|
-
1. Install Ruby 2.
|
84
|
+
1. Install Ruby 2.3+
|
85
85
|
2. Install RubyGems
|
86
86
|
3. Install Bundler: ```gem install bundler```
|
87
87
|
4. Install dependencies: ```bundler install```
|
data/lib/aerospike.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
|
@@ -29,7 +31,9 @@ require 'aerospike/utils/pool'
|
|
29
31
|
require 'aerospike/utils/packer'
|
30
32
|
require 'aerospike/utils/unpacker'
|
31
33
|
require 'aerospike/utils/buffer'
|
34
|
+
require 'aerospike/utils/string_parser'
|
32
35
|
require 'aerospike/host'
|
36
|
+
require 'aerospike/host/parse'
|
33
37
|
require 'aerospike/loggable'
|
34
38
|
require 'aerospike/record'
|
35
39
|
require 'aerospike/result_code'
|
@@ -77,13 +81,36 @@ require 'aerospike/policy/consistency_level'
|
|
77
81
|
require 'aerospike/policy/commit_level'
|
78
82
|
require 'aerospike/policy/admin_policy'
|
79
83
|
|
80
|
-
require 'aerospike/
|
81
|
-
require 'aerospike/
|
82
|
-
require 'aerospike/
|
84
|
+
require 'aerospike/socket/base'
|
85
|
+
require 'aerospike/socket/ssl'
|
86
|
+
require 'aerospike/socket/tcp'
|
87
|
+
|
88
|
+
require 'aerospike/connection/authenticate'
|
89
|
+
require 'aerospike/connection/create'
|
90
|
+
|
91
|
+
require 'aerospike/cluster'
|
92
|
+
require 'aerospike/cluster/create_connection'
|
83
93
|
require 'aerospike/cluster/partition'
|
84
|
-
require 'aerospike/cluster/
|
94
|
+
require 'aerospike/cluster/find_node'
|
85
95
|
require 'aerospike/cluster/partition_tokenizer_new'
|
86
96
|
require 'aerospike/cluster/partition_tokenizer_old'
|
97
|
+
require 'aerospike/node'
|
98
|
+
require 'aerospike/node/generation'
|
99
|
+
require 'aerospike/node/refresh/failed'
|
100
|
+
require 'aerospike/node/refresh/friends'
|
101
|
+
require 'aerospike/node/refresh/info'
|
102
|
+
require 'aerospike/node/refresh/partitions'
|
103
|
+
require 'aerospike/node/refresh/peers'
|
104
|
+
require 'aerospike/node/refresh/reset'
|
105
|
+
require 'aerospike/node/verify/cluster_name'
|
106
|
+
require 'aerospike/node/verify/name'
|
107
|
+
require 'aerospike/node/verify/partition_generation'
|
108
|
+
require 'aerospike/node/verify/peers_generation'
|
109
|
+
require 'aerospike/node_validator'
|
110
|
+
require 'aerospike/peer'
|
111
|
+
require 'aerospike/peers'
|
112
|
+
require 'aerospike/peers/fetch'
|
113
|
+
require 'aerospike/peers/parse'
|
87
114
|
require 'aerospike/info'
|
88
115
|
require 'aerospike/udf'
|
89
116
|
require 'aerospike/bin'
|
@@ -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
|
@@ -17,95 +19,76 @@
|
|
17
19
|
require 'aerospike/result_code'
|
18
20
|
|
19
21
|
module Aerospike
|
20
|
-
|
21
22
|
module Exceptions
|
22
|
-
|
23
23
|
class Aerospike < StandardError
|
24
|
-
|
25
24
|
attr_reader :result_code
|
26
25
|
|
27
26
|
def initialize(result_code, message = nil)
|
28
27
|
@result_code = result_code
|
29
28
|
message ||= ResultCode.message(result_code)
|
30
29
|
super(message)
|
31
|
-
|
32
|
-
self
|
33
30
|
end
|
34
|
-
|
35
31
|
end
|
36
32
|
|
37
33
|
class Timeout < Aerospike
|
38
|
-
|
39
34
|
attr_reader :timeout, :iterations, :failed_nodes, :failed_connections
|
40
35
|
|
41
36
|
def initialize(timeout, iterations, failed_nodes=nil, failed_connections=nil)
|
42
|
-
|
43
37
|
@timeout = timeout
|
44
38
|
@iterations = iterations
|
45
39
|
@failed_nodes = failed_nodes
|
46
40
|
@failed_connections = failed_connections
|
47
41
|
|
48
42
|
super(ResultCode::TIMEOUT)
|
49
|
-
|
50
43
|
end
|
44
|
+
end
|
51
45
|
|
46
|
+
class InvalidCredentials < Aerospike
|
47
|
+
def initialize(msg = nil)
|
48
|
+
super(ResultCode::NOT_AUTHENTICATED, msg)
|
49
|
+
end
|
52
50
|
end
|
53
51
|
|
54
52
|
class Serialize < Aerospike
|
55
|
-
|
56
53
|
def initialize(msg=nil)
|
57
54
|
super(ResultCode::SERIALIZE_ERROR, msg)
|
58
55
|
end
|
59
|
-
|
60
56
|
end
|
61
57
|
|
62
58
|
class Parse < Aerospike
|
63
|
-
|
64
59
|
def initialize(msg=nil)
|
65
60
|
super(ResultCode::PARSE_ERROR, msg)
|
66
61
|
end
|
67
|
-
|
68
62
|
end
|
69
63
|
|
70
64
|
class Connection < Aerospike
|
71
|
-
|
72
65
|
def initialize(msg=nil)
|
73
66
|
super(ResultCode::SERVER_NOT_AVAILABLE, msg)
|
74
67
|
end
|
75
|
-
|
76
68
|
end
|
77
69
|
|
78
70
|
class InvalidNode < Aerospike
|
79
|
-
|
80
71
|
def initialize(msg=nil)
|
81
72
|
super(ResultCode::INVALID_NODE_ERROR, msg)
|
82
73
|
end
|
83
|
-
|
84
74
|
end
|
85
75
|
|
86
76
|
class ScanTerminated < Aerospike
|
87
|
-
|
88
77
|
def initialize(msg=nil)
|
89
78
|
super(ResultCode::SCAN_TERMINATED, msg)
|
90
79
|
end
|
91
|
-
|
92
80
|
end
|
93
81
|
|
94
82
|
class QueryTerminated < Aerospike
|
95
|
-
|
96
83
|
def initialize(msg=nil)
|
97
84
|
super(ResultCode::QUERY_TERMINATED, msg)
|
98
85
|
end
|
99
|
-
|
100
86
|
end
|
101
87
|
|
102
88
|
class CommandRejected < Aerospike
|
103
|
-
|
104
89
|
def initialize(msg=nil)
|
105
90
|
super(ResultCode::COMMAND_REJECTED, msg)
|
106
91
|
end
|
107
|
-
|
108
92
|
end
|
109
|
-
|
110
93
|
end
|
111
94
|
end
|
data/lib/aerospike/client.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
|
@@ -46,9 +48,9 @@ module Aerospike
|
|
46
48
|
@default_query_policy = QueryPolicy.new
|
47
49
|
@default_admin_policy = QueryPolicy.new
|
48
50
|
|
49
|
-
hosts =
|
51
|
+
hosts = ::Aerospike::Host::Parse.(hosts || ENV['AEROSPIKE_HOSTS'] || 'localhost')
|
50
52
|
policy = create_policy(policy, ClientPolicy)
|
51
|
-
@cluster = Cluster.new(policy,
|
53
|
+
@cluster = Cluster.new(policy, hosts)
|
52
54
|
@cluster.add_cluster_config_change_listener(self)
|
53
55
|
|
54
56
|
self.connect if connect
|
@@ -88,7 +90,7 @@ module Aerospike
|
|
88
90
|
# Returns list of active server node names in the cluster.
|
89
91
|
|
90
92
|
def node_names
|
91
|
-
@cluster.nodes.map(&:
|
93
|
+
@cluster.nodes.map(&:name)
|
92
94
|
end
|
93
95
|
|
94
96
|
def supports_feature?(feature)
|
@@ -826,23 +828,6 @@ module Aerospike
|
|
826
828
|
end
|
827
829
|
end
|
828
830
|
|
829
|
-
def parse_hosts(hosts)
|
830
|
-
case hosts
|
831
|
-
when Host
|
832
|
-
[hosts]
|
833
|
-
when Array
|
834
|
-
hosts
|
835
|
-
when String
|
836
|
-
hosts.split(?,).map { |host|
|
837
|
-
(addr, port) = host.split(?:)
|
838
|
-
port ||= 3000
|
839
|
-
Host.new(addr, port.to_i)
|
840
|
-
}
|
841
|
-
else
|
842
|
-
fail TypeError, "hosts should be a Host object, an Array of Host objects, or a String"
|
843
|
-
end
|
844
|
-
end
|
845
|
-
|
846
831
|
def cluster=(cluster)
|
847
832
|
@cluster = cluster
|
848
833
|
end
|
@@ -1,12 +1,15 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2014-2018 Aerospike, Inc.
|
3
4
|
#
|
4
5
|
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
5
6
|
# license agreements.
|
6
7
|
#
|
7
8
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
8
9
|
# use this file except in compliance with the License. You may obtain a copy of
|
9
|
-
# the License at
|
10
|
+
# the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
13
|
#
|
11
14
|
# Unless required by applicable law or agreed to in writing, software
|
12
15
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
@@ -15,27 +18,26 @@
|
|
15
18
|
# the License.
|
16
19
|
|
17
20
|
require 'set'
|
18
|
-
require 'thread'
|
19
21
|
require 'timeout'
|
20
22
|
|
21
23
|
require 'aerospike/atomic/atomic'
|
22
24
|
|
23
25
|
module Aerospike
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
26
|
class Cluster
|
28
|
-
|
29
27
|
attr_reader :connection_timeout, :connection_queue_size, :user, :password
|
30
|
-
attr_reader :features
|
28
|
+
attr_reader :features, :ssl_options
|
29
|
+
attr_reader :cluster_id, :aliases
|
30
|
+
attr_reader :cluster_name
|
31
31
|
|
32
|
-
def initialize(policy,
|
32
|
+
def initialize(policy, hosts)
|
33
33
|
@cluster_seeds = hosts
|
34
34
|
@fail_if_not_connected = policy.fail_if_not_connected
|
35
35
|
@connection_queue_size = policy.connection_queue_size
|
36
36
|
@connection_timeout = policy.timeout
|
37
37
|
@tend_interval = policy.tend_interval
|
38
38
|
@cluster_name = policy.cluster_name
|
39
|
+
@ssl_options = policy.ssl_options
|
40
|
+
|
39
41
|
@aliases = {}
|
40
42
|
@cluster_nodes = []
|
41
43
|
@partition_write_map = {}
|
@@ -53,21 +55,33 @@ module Aerospike
|
|
53
55
|
@password = AdminCommand.hash_password(policy.password)
|
54
56
|
end
|
55
57
|
|
56
|
-
|
58
|
+
initialize_tls_host_names(hosts) if tls_enabled?
|
57
59
|
end
|
58
60
|
|
59
61
|
def connect
|
60
62
|
wait_till_stablized
|
61
63
|
|
62
64
|
if @fail_if_not_connected && !connected?
|
63
|
-
raise Aerospike::Exceptions::Aerospike
|
65
|
+
raise Aerospike::Exceptions::Aerospike, Aerospike::ResultCode::SERVER_NOT_AVAILABLE
|
64
66
|
end
|
65
67
|
|
66
68
|
launch_tend_thread
|
67
69
|
|
68
70
|
Aerospike.logger.info('New cluster initialized and ready to be used...')
|
71
|
+
end
|
69
72
|
|
70
|
-
|
73
|
+
def credentials_given?
|
74
|
+
!(@user.nil? || @user.empty?)
|
75
|
+
end
|
76
|
+
|
77
|
+
def tls_enabled?
|
78
|
+
!ssl_options.nil? && ssl_options[:enable] != false
|
79
|
+
end
|
80
|
+
|
81
|
+
def initialize_tls_host_names(hosts)
|
82
|
+
hosts.each do |host|
|
83
|
+
host.tls_name ||= cluster_id.nil? ? host.name : cluster_id
|
84
|
+
end
|
71
85
|
end
|
72
86
|
|
73
87
|
def add_seeds(hosts)
|
@@ -94,12 +108,10 @@ module Aerospike
|
|
94
108
|
if node_array = nmap[partition.namespace]
|
95
109
|
node = node_array.value[partition.partition_id]
|
96
110
|
|
97
|
-
if node && node.active?
|
98
|
-
return node
|
99
|
-
end
|
111
|
+
return node if node && node.active?
|
100
112
|
end
|
101
113
|
|
102
|
-
|
114
|
+
random_node
|
103
115
|
end
|
104
116
|
|
105
117
|
# Returns a random node on the cluster
|
@@ -110,16 +122,14 @@ module Aerospike
|
|
110
122
|
i = 0
|
111
123
|
while i < length
|
112
124
|
# Must handle concurrency with other non-tending threads, so node_index is consistent.
|
113
|
-
index = (@node_index.update{|v| v+1} % node_array.length).abs
|
125
|
+
index = (@node_index.update{ |v| v+1 } % node_array.length).abs
|
114
126
|
node = node_array[index]
|
115
127
|
|
116
|
-
if node.active?
|
117
|
-
return node
|
118
|
-
end
|
128
|
+
return node if node.active?
|
119
129
|
|
120
130
|
i = i.succ
|
121
131
|
end
|
122
|
-
raise Aerospike::Exceptions::InvalidNode
|
132
|
+
raise Aerospike::Exceptions::InvalidNode
|
123
133
|
end
|
124
134
|
|
125
135
|
# Returns a list of all nodes in the cluster
|
@@ -134,23 +144,19 @@ module Aerospike
|
|
134
144
|
def get_node_by_name(node_name)
|
135
145
|
node = find_node_by_name(node_name)
|
136
146
|
|
137
|
-
raise Aerospike::Exceptions::InvalidNode
|
147
|
+
raise Aerospike::Exceptions::InvalidNode unless node
|
138
148
|
|
139
149
|
node
|
140
150
|
end
|
141
151
|
|
142
152
|
# Closes all cached connections to the cluster nodes and stops the tend thread
|
143
153
|
def close
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
nodes.each do |node|
|
150
|
-
node.close
|
151
|
-
end
|
152
|
-
end
|
154
|
+
return if @closed.value
|
155
|
+
# send close signal to maintenance channel
|
156
|
+
@closed.value = true
|
157
|
+
@tend_thread.kill
|
153
158
|
|
159
|
+
nodes.each(&:close)
|
154
160
|
end
|
155
161
|
|
156
162
|
def find_alias(aliass)
|
@@ -159,25 +165,12 @@ module Aerospike
|
|
159
165
|
end
|
160
166
|
end
|
161
167
|
|
162
|
-
def update_partitions(
|
163
|
-
|
164
|
-
# decouple clstr interface
|
165
|
-
nmap = {}
|
166
|
-
if node.use_new_info?
|
167
|
-
Aerospike.logger.info("Updating partitions using new protocol...")
|
168
|
-
|
169
|
-
tokens = PartitionTokenizerNew.new(conn)
|
170
|
-
nmap = tokens.update_partition(partitions, node)
|
171
|
-
else
|
172
|
-
Aerospike.logger.info("Updating partitions using old protocol...")
|
173
|
-
tokens = PartitionTokenizerOld.new(conn)
|
174
|
-
nmap = tokens.update_partition(partitions, node)
|
175
|
-
end
|
176
|
-
|
168
|
+
def update_partitions(tokens, node)
|
169
|
+
nmap = tokens.update_partition(partitions, node)
|
177
170
|
# update partition write map
|
178
171
|
set_partitions(nmap) if nmap
|
179
172
|
|
180
|
-
Aerospike.logger.info("Partitions updated
|
173
|
+
Aerospike.logger.info("Partitions for node #{node.name} updated")
|
181
174
|
end
|
182
175
|
|
183
176
|
def request_info(policy, *commands)
|
@@ -192,9 +185,13 @@ module Aerospike
|
|
192
185
|
@features.get.include?(feature.to_s)
|
193
186
|
end
|
194
187
|
|
188
|
+
def supports_peers_protocol?
|
189
|
+
nodes.all? { |node| node.supports_feature?('peers') }
|
190
|
+
end
|
191
|
+
|
195
192
|
def change_password(user, password)
|
196
|
-
|
197
|
-
|
193
|
+
# change password ONLY if the user is the same
|
194
|
+
@password = password if @user == user
|
198
195
|
end
|
199
196
|
|
200
197
|
def add_cluster_config_change_listener(listener)
|
@@ -213,85 +210,96 @@ module Aerospike
|
|
213
210
|
"#<Aerospike::Cluster @cluster_nodes=#{@cluster_nodes}>"
|
214
211
|
end
|
215
212
|
|
216
|
-
private
|
217
|
-
|
218
213
|
def launch_tend_thread
|
219
214
|
@tend_thread = Thread.new do
|
220
215
|
Thread.current.abort_on_exception = false
|
221
|
-
|
216
|
+
loop do
|
222
217
|
begin
|
223
218
|
tend
|
224
219
|
sleep(@tend_interval / 1000.0)
|
225
220
|
rescue => e
|
226
221
|
Aerospike.logger.error("Exception occured during tend: #{e}")
|
222
|
+
Aerospike.logger.debug { e.backtrace.join("\n") }
|
227
223
|
end
|
228
224
|
end
|
229
225
|
end
|
230
226
|
end
|
231
227
|
|
228
|
+
# Check health of all nodes in cluster
|
232
229
|
def tend
|
233
|
-
|
230
|
+
was_changed = refresh_nodes
|
231
|
+
|
232
|
+
return unless was_changed
|
233
|
+
|
234
|
+
update_cluster_features
|
235
|
+
notify_cluster_config_changed
|
236
|
+
# only log the tend finish IF the number of nodes has been changed.
|
237
|
+
# This prevents spamming the log on every tend interval
|
238
|
+
log_tend_stats(nodes)
|
239
|
+
end
|
240
|
+
|
241
|
+
# Refresh status of all nodes in cluster. Adds new nodes and/or removes
|
242
|
+
# unhealty ones
|
243
|
+
def refresh_nodes
|
234
244
|
cluster_config_changed = false
|
235
245
|
|
236
|
-
|
237
|
-
# If active nodes don't exist, seed cluster.
|
246
|
+
nodes = self.nodes
|
238
247
|
if nodes.empty?
|
239
|
-
Aerospike.logger.info("No connections available; seeding...")
|
240
248
|
seed_nodes
|
241
249
|
cluster_config_changed = true
|
242
|
-
|
243
|
-
# refresh nodes list after seeding
|
244
250
|
nodes = self.nodes
|
245
251
|
end
|
246
252
|
|
247
|
-
|
248
|
-
friend_list = []
|
249
|
-
refresh_count = 0
|
253
|
+
peers = Peers.new
|
250
254
|
|
251
|
-
# Clear node reference
|
255
|
+
# Clear node reference count
|
252
256
|
nodes.each do |node|
|
253
|
-
node.
|
254
|
-
|
257
|
+
node.refresh_reset
|
258
|
+
end
|
255
259
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
260
|
+
peers.use_peers = supports_peers_protocol?
|
261
|
+
|
262
|
+
# refresh all known nodes
|
263
|
+
nodes.each do |node|
|
264
|
+
node.refresh_info(peers)
|
265
|
+
end
|
266
|
+
|
267
|
+
# refresh peers when necessary
|
268
|
+
if peers.generation_changed?
|
269
|
+
# Refresh peers for all nodes that responded the first time even if only
|
270
|
+
# one node's peers changed.
|
271
|
+
nodes.each do |node|
|
272
|
+
node.refresh_peers(peers)
|
265
273
|
end
|
266
274
|
end
|
267
275
|
|
268
|
-
|
269
|
-
|
270
|
-
unless add_list.empty?
|
271
|
-
add_nodes(add_list)
|
272
|
-
cluster_config_changed = true
|
276
|
+
nodes.each do |node|
|
277
|
+
node.refresh_partitions(peers) if node.partition_generation.changed?
|
273
278
|
end
|
274
279
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
280
|
+
if peers.generation_changed? || !peers.use_peers?
|
281
|
+
nodes_to_remove = find_nodes_to_remove(peers.refresh_count)
|
282
|
+
if nodes_to_remove.any?
|
283
|
+
remove_nodes(nodes_to_remove)
|
284
|
+
cluster_config_changed = true
|
285
|
+
end
|
281
286
|
end
|
282
287
|
|
283
|
-
|
284
|
-
|
288
|
+
# Add any new nodes from peer refresh
|
289
|
+
if peers.nodes.any?
|
290
|
+
# peers.nodes is a Hash. Pass only values, ie. the array of nodes
|
291
|
+
add_nodes(peers.nodes.values)
|
292
|
+
cluster_config_changed = true
|
293
|
+
end
|
285
294
|
|
286
|
-
|
287
|
-
|
288
|
-
diff = nodes.length - @old_node_count
|
289
|
-
action = "#{diff.abs} #{diff.abs == 1 ? "node has" : "nodes have"} #{diff > 0 ? "joined" : "left"} the cluster."
|
290
|
-
Aerospike.logger.info("Tend finished. #{action} Old node count: #{@old_node_count}, New node count: #{nodes.length}")
|
291
|
-
@old_node_count = nodes.length
|
295
|
+
cluster_config_changed
|
296
|
+
end
|
292
297
|
|
293
|
-
|
294
|
-
|
298
|
+
def log_tend_stats(nodes)
|
299
|
+
diff = nodes.size - @old_node_count
|
300
|
+
action = "#{diff.abs} #{diff.abs == 1 ? "node has" : "nodes have"} #{diff > 0 ? "joined" : "left"} the cluster."
|
301
|
+
Aerospike.logger.info("Tend finished. #{action} Old node count: #{@old_node_count}, New node count: #{nodes.size}")
|
302
|
+
@old_node_count = nodes.size
|
295
303
|
end
|
296
304
|
|
297
305
|
def wait_till_stablized
|
@@ -299,14 +307,12 @@ module Aerospike
|
|
299
307
|
|
300
308
|
# will run until the cluster is stablized
|
301
309
|
thr = Thread.new do
|
302
|
-
|
310
|
+
loop do
|
303
311
|
tend
|
304
312
|
|
305
313
|
# Check to see if cluster has changed since the last Tend.
|
306
314
|
# If not, assume cluster has stabilized and return.
|
307
|
-
if count == nodes.length
|
308
|
-
break
|
309
|
-
end
|
315
|
+
break if count == nodes.length
|
310
316
|
|
311
317
|
sleep(0.001) # sleep for a miliseconds
|
312
318
|
|
@@ -324,13 +330,12 @@ module Aerospike
|
|
324
330
|
end
|
325
331
|
|
326
332
|
@closed.value = false if @cluster_nodes.length > 0
|
327
|
-
|
328
333
|
end
|
329
334
|
|
330
335
|
def update_cluster_features
|
331
336
|
# Cluster supports features that are supported by all nodes
|
332
337
|
@features.update do
|
333
|
-
node_features =
|
338
|
+
node_features = nodes.map(&:features)
|
334
339
|
node_features.reduce(&:intersection) || Set.new
|
335
340
|
end
|
336
341
|
end
|
@@ -366,45 +371,39 @@ module Aerospike
|
|
366
371
|
|
367
372
|
seed_array.each do |seed|
|
368
373
|
begin
|
369
|
-
seed_node_validator = NodeValidator.new(self, seed, @connection_timeout, @cluster_name)
|
374
|
+
seed_node_validator = NodeValidator.new(self, seed, @connection_timeout, @cluster_name, ssl_options)
|
370
375
|
rescue => e
|
371
|
-
Aerospike.logger.error("Seed #{seed
|
376
|
+
Aerospike.logger.error("Seed #{seed} failed: #{e}\n#{e.backtrace.join("\n")}")
|
372
377
|
next
|
373
378
|
end
|
374
379
|
|
375
380
|
nv = nil
|
376
381
|
# Seed host may have multiple aliases in the case of round-robin dns configurations.
|
377
382
|
seed_node_validator.aliases.each do |aliass|
|
378
|
-
|
379
383
|
if aliass == seed
|
380
384
|
nv = seed_node_validator
|
381
385
|
else
|
382
386
|
begin
|
383
|
-
nv = NodeValidator.new(self, aliass, @connection_timeout, @cluster_name)
|
387
|
+
nv = NodeValidator.new(self, aliass, @connection_timeout, @cluster_name, ssl_options)
|
384
388
|
rescue => e
|
385
|
-
Aerospike.logger.error("Seed #{seed
|
389
|
+
Aerospike.logger.error("Seed #{seed} failed: #{e}")
|
386
390
|
next
|
387
391
|
end
|
388
392
|
end
|
393
|
+
next if find_node_name(list, nv.name)
|
389
394
|
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
list << node
|
394
|
-
end
|
395
|
+
node = create_node(nv)
|
396
|
+
add_aliases(node)
|
397
|
+
list << node
|
395
398
|
end
|
396
|
-
|
397
|
-
end
|
398
|
-
|
399
|
-
if list.length > 0
|
400
|
-
add_nodes_copy(list)
|
401
399
|
end
|
402
400
|
|
401
|
+
add_nodes_copy(list) if list.length > 0
|
403
402
|
end
|
404
403
|
|
405
404
|
# Finds a node by name in a list of nodes
|
406
405
|
def find_node_name(list, name)
|
407
|
-
list.any?{|node| node.name == name}
|
406
|
+
list.any? { |node| node.name == name }
|
408
407
|
end
|
409
408
|
|
410
409
|
def add_alias(host, node)
|
@@ -423,44 +422,8 @@ module Aerospike
|
|
423
422
|
end
|
424
423
|
end
|
425
424
|
|
426
|
-
def find_nodes_to_add(hosts)
|
427
|
-
list = []
|
428
|
-
|
429
|
-
hosts.each do |host|
|
430
|
-
begin
|
431
|
-
nv = NodeValidator.new(self, host, @connection_timeout, @cluster_name)
|
432
|
-
|
433
|
-
# if node is already in cluster's node list,
|
434
|
-
# or already included in the list to be added, we should skip it
|
435
|
-
node = find_node_by_name(nv.name)
|
436
|
-
node ||= list.detect{|n| n.name == nv.name}
|
437
|
-
|
438
|
-
# make sure node is not already in the list to add
|
439
|
-
if node
|
440
|
-
# Duplicate node name found. This usually occurs when the server
|
441
|
-
# services list contains both internal and external IP addresses
|
442
|
-
# for the same node. Add new host to list of alias filters
|
443
|
-
# and do not add new node.
|
444
|
-
node.reference_count.update{|v| v + 1}
|
445
|
-
node.add_alias(host)
|
446
|
-
add_alias(host, node)
|
447
|
-
next
|
448
|
-
end
|
449
|
-
|
450
|
-
node = create_node(nv)
|
451
|
-
list << node
|
452
|
-
|
453
|
-
rescue => e
|
454
|
-
Aerospike.logger.error("Add node #{node} failed: #{e}")
|
455
|
-
Aerospike.logger.error(e.backtrace.join("\n"))
|
456
|
-
end
|
457
|
-
end
|
458
|
-
|
459
|
-
list
|
460
|
-
end
|
461
|
-
|
462
425
|
def create_node(nv)
|
463
|
-
Node.new(self, nv)
|
426
|
+
::Aerospike::Node.new(self, nv)
|
464
427
|
end
|
465
428
|
|
466
429
|
def find_nodes_to_remove(refresh_count)
|
@@ -482,7 +445,7 @@ module Aerospike
|
|
482
445
|
|
483
446
|
when 2
|
484
447
|
# Two node clusters require at least one successful refresh before removing.
|
485
|
-
if refresh_count == 2 && node.reference_count.value == 0 && !node.responded
|
448
|
+
if refresh_count == 2 && node.reference_count.value == 0 && !node.responded?
|
486
449
|
# Node is not referenced nor did it respond.
|
487
450
|
remove_list << node
|
488
451
|
end
|
@@ -492,9 +455,9 @@ module Aerospike
|
|
492
455
|
if refresh_count >= 2 && node.reference_count.value == 0
|
493
456
|
# Node is not referenced by other nodes.
|
494
457
|
# Check if node responded to info request.
|
495
|
-
if node.responded
|
458
|
+
if node.responded?
|
496
459
|
# Node is alive, but not referenced by other nodes. Check if mapped.
|
497
|
-
|
460
|
+
unless find_node_in_partition_map(node)
|
498
461
|
# Node doesn't have any partitions mapped to it.
|
499
462
|
# There is not point in keeping it in the cluster.
|
500
463
|
remove_list << node
|
@@ -531,7 +494,7 @@ module Aerospike
|
|
531
494
|
def add_aliases(node)
|
532
495
|
# Add node's aliases to global alias set.
|
533
496
|
# Aliases are only used in tend thread, so synchronization is not necessary.
|
534
|
-
node.
|
497
|
+
node.aliases.each do |aliass|
|
535
498
|
@aliases[aliass] = node
|
536
499
|
end
|
537
500
|
end
|
@@ -551,7 +514,7 @@ module Aerospike
|
|
551
514
|
nodes_to_remove.each do |node|
|
552
515
|
# Remove node's aliases from cluster alias set.
|
553
516
|
# Aliases are only used in tend thread, so synchronization is not necessary.
|
554
|
-
node.
|
517
|
+
node.aliases.each do |aliass|
|
555
518
|
Aerospike.logger.debug("Removing alias #{aliass}")
|
556
519
|
remove_alias(aliass)
|
557
520
|
end
|
@@ -607,7 +570,5 @@ module Aerospike
|
|
607
570
|
def find_node_by_name(node_name)
|
608
571
|
nodes.detect{|node| node.name == node_name }
|
609
572
|
end
|
610
|
-
|
611
573
|
end
|
612
|
-
|
613
574
|
end
|