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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +3 -3
  4. data/lib/aerospike.rb +33 -6
  5. data/lib/aerospike/aerospike_exception.rb +9 -26
  6. data/lib/aerospike/client.rb +7 -22
  7. data/lib/aerospike/{cluster/cluster.rb → cluster.rb} +122 -161
  8. data/lib/aerospike/cluster/create_connection.rb +42 -0
  9. data/lib/aerospike/cluster/find_node.rb +35 -0
  10. data/lib/aerospike/connection/authenticate.rb +35 -0
  11. data/lib/aerospike/connection/create.rb +36 -0
  12. data/lib/aerospike/host.rb +7 -4
  13. data/lib/aerospike/host/parse.rb +50 -0
  14. data/lib/aerospike/node.rb +232 -0
  15. data/lib/aerospike/node/generation.rb +50 -0
  16. data/lib/aerospike/node/refresh/failed.rb +34 -0
  17. data/lib/aerospike/node/refresh/friends.rb +100 -0
  18. data/lib/aerospike/node/refresh/info.rb +60 -0
  19. data/lib/aerospike/node/refresh/partitions.rb +60 -0
  20. data/lib/aerospike/node/refresh/peers.rb +83 -0
  21. data/lib/aerospike/node/refresh/reset.rb +36 -0
  22. data/lib/aerospike/node/verify/cluster_name.rb +35 -0
  23. data/lib/aerospike/node/verify/name.rb +43 -0
  24. data/lib/aerospike/node/verify/partition_generation.rb +43 -0
  25. data/lib/aerospike/node/verify/peers_generation.rb +41 -0
  26. data/lib/aerospike/{cluster/node_validator.rb → node_validator.rb} +29 -47
  27. data/lib/aerospike/peer.rb +24 -0
  28. data/lib/aerospike/peers.rb +44 -0
  29. data/lib/aerospike/peers/fetch.rb +36 -0
  30. data/lib/aerospike/peers/parse.rb +88 -0
  31. data/lib/aerospike/policy/client_policy.rb +16 -9
  32. data/lib/aerospike/socket/base.rb +86 -0
  33. data/lib/aerospike/socket/ssl.rb +70 -0
  34. data/lib/aerospike/socket/tcp.rb +57 -0
  35. data/lib/aerospike/utils/buffer.rb +7 -6
  36. data/lib/aerospike/utils/string_parser.rb +53 -0
  37. data/lib/aerospike/value/value.rb +7 -8
  38. data/lib/aerospike/version.rb +1 -1
  39. metadata +30 -7
  40. data/lib/aerospike/cluster/connection.rb +0 -124
  41. data/lib/aerospike/cluster/node.rb +0 -274
@@ -0,0 +1,43 @@
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 Node
22
+ module Verify
23
+ module Name
24
+ class << self
25
+ def call(node, info_map)
26
+ info_name = info_map['node']
27
+
28
+ if !info_name
29
+ node.decrease_health
30
+ raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INVALID_NODE_ERROR, 'Node name is empty')
31
+ end
32
+
33
+ if !(node.name == info_name)
34
+ # Set node to inactive immediately.
35
+ node.inactive!
36
+ raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INVALID_NODE_ERROR, "Node name has changed. Old=#{node.name} New= #{info_name}")
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,43 @@
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 Node
22
+ module Verify
23
+ # Fetch and set partition generation. If partitions needs to be refreshed
24
+ # this will be indicated in node.partition_changed
25
+ module PartitionGeneration
26
+ class << self
27
+ def call(node, info_map)
28
+ gen_string = info_map.fetch('partition-generation', nil)
29
+
30
+ raise Aerospike::Exceptions::Parse.new('partition-generation is empty') if gen_string.to_s.empty?
31
+
32
+ generation = gen_string.to_i
33
+
34
+ node.partition_generation.update(generation)
35
+
36
+ return unless node.partition_generation.changed?
37
+ Aerospike.logger.info("Node #{node.name} partition generation #{generation} changed")
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,41 @@
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 Node
22
+ module Verify
23
+ module PeersGeneration
24
+ class << self
25
+ def call(node, info_map, peers)
26
+ gen_string = info_map.fetch('peers-generation', nil)
27
+
28
+ raise Aerospike::Exceptions::Parse.new('peers-generation is empty') if gen_string.to_s.empty?
29
+
30
+ generation = gen_string.to_i
31
+
32
+ return if node.peers_generation.eql?(generation)
33
+
34
+ Aerospike.logger.info("Node #{node.name} peers generation #{generation} changed")
35
+ peers.generation_changed = true
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,12 +1,15 @@
1
- # encoding: utf-8
2
- # Copyright 2014-2017 Aerospike, Inc.
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 http:#www.apache.org/licenses/LICENSE-2.0
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,62 +18,35 @@
15
18
  # the License.
16
19
 
17
20
  module Aerospike
18
-
19
- private
20
-
21
21
  class NodeValidator # :nodoc:
22
+ VERSION_REGEXP = /(?<v1>\d+)\.(?<v2>\d+)\.(?<v3>\d+).*/.freeze
22
23
 
23
- attr_reader :host, :aliases, :name, :use_new_info, :features, :cluster_name
24
+ attr_reader :host, :aliases, :name, :use_new_info, :features, :cluster_name, :ssl_options, :conn
24
25
 
25
- def initialize(cluster, host, timeout, cluster_name)
26
+ def initialize(cluster, host, timeout, cluster_name, ssl_options = {})
26
27
  @cluster = cluster
27
28
  @use_new_info = true
28
29
  @features = Set.new
29
30
  @host = host
30
31
  @cluster_name = cluster_name
32
+ @ssl_options = ssl_options
31
33
 
32
34
  set_aliases(host)
33
35
  set_address(timeout)
34
-
35
- self
36
36
  end
37
37
 
38
- def set_aliases(host)
39
- is_ip = !!((host =~ Resolv::IPv4::Regex) || (host =~ Resolv::IPv6::Regex))
40
-
41
- if is_ip
42
- # don't try to resolve IP addresses. May fail in different OS or network setups
43
- addresses = host
44
- else
45
- addresses = Resolv.getaddresses(host.name)
46
- end
47
-
48
- aliases = []
49
- addresses.each do |addr|
50
- aliases << Host.new(addr, host.port)
51
- end
52
-
53
- @aliases = aliases
38
+ private
54
39
 
55
- Aerospike.logger.debug("Node Validator has #{aliases.length} nodes.")
40
+ def set_aliases(host)
41
+ addresses = resolve(host.name)
42
+ @aliases = addresses.map { |addr| Host.new(addr, host.port, host.tls_name) }
43
+ Aerospike.logger.debug("Node Validator found #{aliases.length} addresses for host #{host}: #{@aliases}")
56
44
  end
57
45
 
58
46
  def set_address(timeout)
59
47
  @aliases.each do |aliass|
60
48
  begin
61
- conn = Connection.new(aliass.name, aliass.port, timeout)
62
-
63
- # need to authenticate
64
- if @cluster.user && @cluster.user != ''
65
- begin
66
- command = AdminCommand.new
67
- command.authenticate(conn, @cluster.user, @cluster.password)
68
- rescue => e
69
- # Socket not authenticated. Do not put back into pool.
70
- conn.close if conn
71
- raise e
72
- end
73
- end
49
+ conn = Cluster::CreateConnection.(@cluster, @host)
74
50
 
75
51
  info_map = Info.request(conn, 'node', 'build', 'features')
76
52
  if node_name = info_map['node']
@@ -90,23 +66,29 @@ module Aerospike
90
66
  ensure
91
67
  conn.close if conn
92
68
  end
93
-
94
69
  end
95
70
  end
96
71
 
97
- protected
72
+ def resolve(hostname)
73
+ if is_ip?(hostname)
74
+ # Don't try to resolve IP addresses.
75
+ # May fail in different OS or network setups
76
+ [hostname]
77
+ else
78
+ Resolv.getaddresses(hostname)
79
+ end
80
+ end
98
81
 
99
- # parses a version string
100
- @@version_regexp = /(?<v1>\d+)\.(?<v2>\d+)\.(?<v3>\d+).*/
82
+ def is_ip?(hostname)
83
+ !!((hostname =~ Resolv::IPv4::Regex) || (hostname =~ Resolv::IPv6::Regex))
84
+ end
101
85
 
102
86
  def parse_version_string(version)
103
- if v = @@version_regexp.match(version)
87
+ if v = VERSION_REGEXP.match(version)
104
88
  return v['v1'], v['v2'], v['v3']
105
89
  end
106
90
 
107
91
  raise Aerospike::Exceptions::Parse.new("Invalid build version string in Info: #{version}")
108
92
  end
109
-
110
93
  end # class
111
-
112
94
  end #module
@@ -0,0 +1,24 @@
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 Peer
22
+ attr_accessor :node_name, :tls_name, :hosts
23
+ end
24
+ end
@@ -0,0 +1,44 @@
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 Peers
22
+ attr_accessor :peers, :hosts, :nodes, :refresh_count, :use_peers, :generation_changed
23
+
24
+ def initialize
25
+ @peers = ::Array.new
26
+ @hosts = ::Set.new
27
+ @nodes = {}
28
+ @use_peers = true
29
+ @refresh_count = 0
30
+ end
31
+
32
+ def find_node_by_name(node_name)
33
+ @nodes[node_name]
34
+ end
35
+
36
+ def generation_changed?
37
+ @generation_changed == true
38
+ end
39
+
40
+ def use_peers?
41
+ @use_peers == true
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,36 @@
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 Peers
22
+ module Fetch
23
+ class << self
24
+ def call(cluster, conn)
25
+ cmd = cluster.tls_enabled? ? 'peers-tls-std' : 'peers-clear-std'
26
+
27
+ response = Info.request(conn, cmd)
28
+
29
+ raise if response.size.zero?
30
+
31
+ ::Aerospike::Peers::Parse.(response.fetch(cmd))
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,88 @@
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 Peers
22
+ # Parse the response from peers command
23
+ module Parse
24
+ # Object representing the parsed response from peers command
25
+ Object = ::Struct.new(:generation, :port_default, :peers)
26
+
27
+ class << self
28
+
29
+ BASE_REGEX = /(\d+),(\d*),\[(.*)\]/.freeze
30
+
31
+ def call(response)
32
+ gen, port, peers = parse_base(response)
33
+
34
+ ::Aerospike::Peers::Parse::Object.new.tap do |obj|
35
+ obj.generation = gen.to_i
36
+ obj.port_default = port.empty? ? nil : port.to_i
37
+ obj.peers = parse_peers(peers, obj)
38
+ end
39
+ end
40
+
41
+ def parse_base(response)
42
+ BASE_REGEX.match(response).to_a.last(3).tap do |parsed|
43
+ # Expect three pieces parsed from the Regex
44
+ raise ::Aerospike::Exceptions::Parse if parsed.size != 3
45
+ end
46
+ end
47
+
48
+ def parse_peers(response, obj)
49
+ return [] if response.empty?
50
+ parser = ::Aerospike::Utils::StringParser.new(response)
51
+ [].tap do |result|
52
+ loop do
53
+ result << parse_peer(parser, obj)
54
+ break unless parser.current == ','
55
+ parser.step
56
+ end
57
+ end
58
+ end
59
+
60
+ def parse_peer(parser, obj)
61
+ ::Aerospike::Peer.new.tap do |peer|
62
+ parser.expect('[')
63
+ peer.node_name = parser.read_until(',')
64
+ peer.tls_name = parser.read_until(',')
65
+ peer.hosts = parse_hosts(parser, peer)
66
+ # Assign default port if missing
67
+ peer.hosts.each do |host|
68
+ host.port ||= obj.port_default
69
+ end
70
+ parser.expect(']')
71
+ end
72
+ end
73
+
74
+ def parse_hosts(parser, peer)
75
+ parser.expect('[')
76
+ return [] if parser.current == ']'
77
+
78
+ # TODO(wallin): handle IPv6
79
+ raise ::Aerospike::Exceptions::Parse if parser.current == '['
80
+ parser.read_until(']').split(',').map do |host|
81
+ hostname, port = host.split(':')
82
+ ::Aerospike::Host.new(hostname, port, peer.tls_name)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end