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,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 Node
22
+ # generic class for representing changes in eg. peer and partition generation
23
+ class Generation
24
+ attr_reader :number
25
+
26
+ def initialize(number = -1)
27
+ @number = ::Aerospike::Atomic.new(number)
28
+ @changed = ::Aerospike::Atomic.new(false)
29
+ end
30
+
31
+ def changed?
32
+ @changed.value == true
33
+ end
34
+
35
+ def eql?(number)
36
+ @number.value == number
37
+ end
38
+
39
+ def reset_changed!
40
+ @changed.value = false
41
+ end
42
+
43
+ def update(new_number)
44
+ return if @number.value == new_number
45
+ @number.value = new_number
46
+ @changed.value = true
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,34 @@
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 Refresh
23
+ module Failed
24
+ class << self
25
+ def call(node, e)
26
+ Aerospike.logger.info("Node #{node.name} refresh failed: #{e.inspect}")
27
+ Aerospike.logger.debug { e.backtrace.join("\n") }
28
+ node.failed!
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,100 @@
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 Refresh
23
+ # Refresh peers/friends based on old service protocol
24
+ module Friends
25
+ class << self
26
+ def call(node, peers, info_map)
27
+ friend_string = info_map['services']
28
+ cluster = node.cluster
29
+
30
+ Aerospike.logger.debug("Refreshing friends for node #{node.name}: services=#{friend_string}")
31
+
32
+ if friend_string.to_s.empty?
33
+ node.peers_count.value = 0
34
+ return
35
+ end
36
+
37
+ friend_names = friend_string.split(';')
38
+ node.peers_count.value = friend_names.size
39
+
40
+ friend_names.each do |friend|
41
+ hostname, port = friend.split(':')
42
+ host = Host.new(hostname, port.to_i)
43
+ found_node = cluster.find_alias(host)
44
+
45
+ if found_node
46
+ found_node.increase_reference_count!
47
+ Aerospike.logger.debug("Found existing node #{found_node.name} for host #{host}: Increased ref count to #{found_node.reference_count.value}")
48
+ else
49
+ unless peers.hosts.include?(host)
50
+ prepare(cluster, peers, host)
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ def prepare(cluster, peers, host)
57
+ Aerospike.logger.debug("Preparing to add new node for host #{host}")
58
+ nv = NodeValidator.new(
59
+ cluster,
60
+ host,
61
+ cluster.connection_timeout,
62
+ cluster.cluster_name,
63
+ cluster.ssl_options
64
+ )
65
+
66
+ node = peers.find_node_by_name(nv.name)
67
+
68
+ unless node.nil?
69
+ Aerospike.logger.debug("Found existing node #{node.name} among peers for host #{host}")
70
+ peers.hosts << host
71
+ node.aliases << host
72
+ return true
73
+ end
74
+
75
+ node = cluster.find_node_by_name(nv.name)
76
+
77
+ unless node.nil?
78
+ Aerospike.logger.debug("Found existing node #{node.name} in cluster for host #{host}")
79
+ peers.hosts << host
80
+ node.aliases << host
81
+ # Only increase reference count if found in cluster
82
+ node.increase_reference_count!
83
+ cluster.add_alias(host, node)
84
+ return true
85
+ end
86
+
87
+ Aerospike.logger.debug("No existing node found - creating new node #{nv.name} for host #{host}")
88
+ node = cluster.create_node(nv)
89
+ peers.hosts << host
90
+ peers.nodes[nv.name] = node
91
+ true
92
+ rescue ::Aerospike::Exceptions::Aerospike => e
93
+ ::Aerospike.logger.warn("Add node for host #{host} failed: #{e}")
94
+ false
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,60 @@
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 Refresh
23
+ module Info
24
+ CMDS_BASE = %w[node partition-generation cluster-name].freeze
25
+ CMDS_PEERS = (CMDS_BASE + ['peers-generation']).freeze
26
+ CMDS_SERVICES = (CMDS_BASE + ['services']).freeze
27
+
28
+ class << self
29
+ def call(node, peers)
30
+ conn = node.tend_connection
31
+ if peers.use_peers?
32
+ info_map = ::Aerospike::Info.request(conn, *CMDS_PEERS)
33
+ Verify::PeersGeneration.(node, info_map, peers)
34
+ Verify::PartitionGeneration.(node, info_map)
35
+ Verify::Name.(node, info_map)
36
+ Verify::ClusterName.(node, info_map)
37
+ else
38
+ info_map = ::Aerospike::Info.request(conn, *CMDS_SERVICES)
39
+ Verify::PartitionGeneration.(node, info_map)
40
+ Verify::Name.(node, info_map)
41
+ Verify::ClusterName.(node, info_map)
42
+ Refresh::Friends.(node, peers, info_map)
43
+ end
44
+
45
+ node.restore_health
46
+ node.responded!
47
+
48
+ peers.refresh_count += 1
49
+ node.reset_failures!
50
+ rescue ::Aerospike::Exceptions::Aerospike => e
51
+ conn.close if conn
52
+ node.decrease_health
53
+ peers.generation_changed = true if peers.use_peers?
54
+ Refresh::Failed.(node, e)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,60 @@
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 Refresh
23
+ module Partitions
24
+ class << self
25
+ def call(node, peers)
26
+ return unless should_refresh?(node, peers)
27
+
28
+ node.cluster.update_partitions(tokenizer(node), node)
29
+ rescue ::Aerospike::Exceptions::Aerospike => e
30
+ node.tend_connection.close
31
+ Refresh::Failed.(node, e)
32
+ end
33
+
34
+ # Return correct tokenizer depending on version
35
+ def tokenizer(node)
36
+ conn = node.tend_connection
37
+ if node.use_new_info?
38
+ Aerospike.logger.info("Updating partitions for node #{node.name} using new protocol")
39
+ PartitionTokenizerNew.new(conn)
40
+ else
41
+ Aerospike.logger.info("Updating partitions for node #{node.name} using old protocol")
42
+ PartitionTokenizerOld.new(conn)
43
+ end
44
+ end
45
+
46
+ # Do not refresh partitions when node connection has already failed
47
+ # during this cluster tend iteration. Also, avoid "split cluster"
48
+ # case where this node thinks it's a 1-node cluster. Unchecked, such
49
+ # a node can dominate the partition map and cause all other nodes to
50
+ # be dropped.
51
+ def should_refresh?(node, peers)
52
+ return false if node.failed? || !node.active?
53
+ return false if !node.has_peers? && peers.refresh_count > 1
54
+ true
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,83 @@
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 Refresh
23
+ module Peers
24
+ class << self
25
+ def call(node, peers)
26
+ return unless should_refresh?(node)
27
+
28
+ ::Aerospike.logger.debug("Update peers for node #{node.name}")
29
+
30
+ cluster = node.cluster
31
+
32
+ collection = ::Aerospike::Peers::Fetch.(cluster, node.tend_connection)
33
+ peers.peers = collection.peers
34
+ node.peers_count.value = peers.peers.size
35
+ peers_validated = true
36
+
37
+ peers.peers.each do |peer|
38
+ next if ::Aerospike::Cluster::FindNode.(cluster, peers, peer.node_name)
39
+
40
+ node_validated = false
41
+
42
+ peer.hosts.each do |host|
43
+ begin
44
+ nv = NodeValidator.new(cluster, host, cluster.connection_timeout, cluster.cluster_name, cluster.ssl_options)
45
+
46
+ if nv.name != peer.node_name
47
+ ::Aerospike.logger.warn("Peer node #{peer.node_name} is different than actual node #{nv.name} for host #{host}");
48
+ # Must look for new node name in the unlikely event that node names do not agree.
49
+ # Node already exists. Do not even try to connect to hosts.
50
+ if Cluster::FindNode.(cluster, peers, nv.name)
51
+ node_validated = true
52
+ break;
53
+ end
54
+ end
55
+
56
+ new_node = cluster.create_node(nv)
57
+ peers.nodes[nv.name] = new_node
58
+ node_validated = true
59
+ break;
60
+ rescue ::Aerospike::Exceptions::Aerospike => e
61
+ Aerospike.logger.warn("Add node #{host} failed: #{e.inspect}")
62
+ end
63
+
64
+ peers_validated = false unless node_validated
65
+ end
66
+ end
67
+
68
+ # Only set new peers generation if all referenced peers are added to
69
+ # the cluster.
70
+ node.peers_generation.update(collection.generation) if peers_validated
71
+ peers.refresh_count += 1
72
+ rescue ::Aerospike::Exceptions::Aerospike => e
73
+ Refresh::Failed.(node, e)
74
+ end
75
+
76
+ def should_refresh?(node)
77
+ node.failures.value == 0 && node.active?
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ 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
+
21
+ module Aerospike
22
+ class Node
23
+ module Refresh
24
+ # Reset a node before running a refresh cycle
25
+ module Reset
26
+ class << self
27
+ def call(node)
28
+ node.reset_reference_count!
29
+ node.reset_responded!
30
+ node.partition_generation.reset_changed!
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ 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 Node
22
+ module Verify
23
+ module ClusterName
24
+ class << self
25
+ def call(node, info_map)
26
+ if node.cluster_name && node.cluster_name != info_map['cluster-name']
27
+ node.inactive!
28
+ raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INVALID_NODE_ERROR, "Cluster name does not match. expected: #{node.cluster_name}, got: #{info_map['cluster-name']}")
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end