aerospike 2.5.1 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
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