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,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