aerospike 2.21.1 → 2.23.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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -1
  3. data/lib/aerospike/atomic/atomic.rb +1 -1
  4. data/lib/aerospike/cdt/context.rb +7 -7
  5. data/lib/aerospike/cdt/list_return_type.rb +4 -0
  6. data/lib/aerospike/cdt/map_operation.rb +6 -6
  7. data/lib/aerospike/cdt/map_return_type.rb +4 -0
  8. data/lib/aerospike/client.rb +34 -59
  9. data/lib/aerospike/cluster.rb +6 -3
  10. data/lib/aerospike/command/admin_command.rb +2 -2
  11. data/lib/aerospike/command/batch_index_node.rb +1 -1
  12. data/lib/aerospike/command/batch_item.rb +1 -1
  13. data/lib/aerospike/command/command.rb +62 -30
  14. data/lib/aerospike/command/field_type.rb +3 -0
  15. data/lib/aerospike/command/login_command.rb +7 -5
  16. data/lib/aerospike/command/multi_command.rb +8 -2
  17. data/lib/aerospike/command/read_command.rb +2 -2
  18. data/lib/aerospike/connection/authenticate.rb +4 -4
  19. data/lib/aerospike/features.rb +9 -9
  20. data/lib/aerospike/host/parse.rb +2 -2
  21. data/lib/aerospike/key.rb +10 -1
  22. data/lib/aerospike/node/refresh/info.rb +1 -1
  23. data/lib/aerospike/node/verify/name.rb +1 -1
  24. data/lib/aerospike/node/verify/partition_generation.rb +1 -1
  25. data/lib/aerospike/node/verify/peers_generation.rb +1 -1
  26. data/lib/aerospike/node/verify/rebalance_generation.rb +1 -1
  27. data/lib/aerospike/node_validator.rb +6 -1
  28. data/lib/aerospike/policy/policy.rb +4 -1
  29. data/lib/aerospike/policy/scan_policy.rb +20 -1
  30. data/lib/aerospike/privilege.rb +1 -1
  31. data/lib/aerospike/query/node_partitions.rb +39 -0
  32. data/lib/aerospike/query/partition_filter.rb +66 -0
  33. data/lib/aerospike/query/partition_status.rb +36 -0
  34. data/lib/aerospike/query/partition_tracker.rb +347 -0
  35. data/lib/aerospike/query/scan_command.rb +3 -3
  36. data/lib/aerospike/query/scan_executor.rb +69 -0
  37. data/lib/aerospike/query/scan_partition_command.rb +49 -0
  38. data/lib/aerospike/query/statement.rb +1 -1
  39. data/lib/aerospike/query/stream_command.rb +14 -1
  40. data/lib/aerospike/result_code.rb +79 -4
  41. data/lib/aerospike/role.rb +2 -2
  42. data/lib/aerospike/task/execute_task.rb +2 -2
  43. data/lib/aerospike/task/index_task.rb +1 -1
  44. data/lib/aerospike/user_role.rb +1 -1
  45. data/lib/aerospike/utils/buffer.rb +12 -0
  46. data/lib/aerospike/utils/pool.rb +1 -1
  47. data/lib/aerospike/value/value.rb +6 -6
  48. data/lib/aerospike/version.rb +1 -1
  49. data/lib/aerospike.rb +6 -0
  50. metadata +11 -5
@@ -98,7 +98,7 @@ module Aerospike
98
98
  receive_size = (sz & 0xFFFFFFFFFFFF) - header_length
99
99
 
100
100
  # Read remaining message bytes.
101
- if compressed_sz
101
+ if compressed_sz
102
102
  @data_buffer.eat!(MSG_TOTAL_HEADER_SIZE)
103
103
  elsif receive_size > 0
104
104
  size_buffer_sz(receive_size)
@@ -117,7 +117,7 @@ module Aerospike
117
117
  @record = Record.new(@node, @key, nil, generation, expiration)
118
118
  return
119
119
  end
120
-
120
+
121
121
  @record = parse_record(op_count, field_count, generation, expiration)
122
122
  return
123
123
  end
@@ -38,9 +38,7 @@ module Aerospike
38
38
 
39
39
  def call(conn, cluster)
40
40
  command = LoginCommand.new
41
- if !cluster.session_valid?
42
- command.authenticate_new(conn, cluster)
43
- else
41
+ if cluster.session_valid?
44
42
  begin
45
43
  command.authenticate_via_token(conn, cluster)
46
44
  rescue => ae
@@ -49,11 +47,13 @@ module Aerospike
49
47
  if ae.is_a?(Exceptions::Aerospike)
50
48
  if INVALID_SESSION_ERR.include?(ae.result_code)
51
49
  command.authenticate_new(conn, cluster)
52
- return
50
+ return true
53
51
  end
54
52
  end
55
53
  raise ae
56
54
  end
55
+ else
56
+ command.authenticate_new(conn, cluster)
57
57
  end
58
58
 
59
59
  true
@@ -23,10 +23,10 @@ module Aerospike
23
23
  module Features
24
24
 
25
25
  # Server supports List Complex Data Type (CDT)
26
- CDT_LIST = :"cdt-list"
26
+ CDT_LIST = :'cdt-list'
27
27
 
28
28
  # Server supports Map Complex Data Type (CDT)
29
- CDT_MAP = :"cdt-map"
29
+ CDT_MAP = :'cdt-map'
30
30
 
31
31
  # Server supports Float data type
32
32
  FLOAT = :float
@@ -34,16 +34,16 @@ module Aerospike
34
34
  # Server supports geo-spatial data type and indexing
35
35
  GEO = :geo
36
36
 
37
- # Server requires "lut=now" in truncate command (AER-5955)
38
- LUT_NOW = :"lut-now"
37
+ # Server requires 'lut=now' in truncate command (AER-5955)
38
+ LUT_NOW = :'lut-now'
39
39
 
40
- # Server supports the new "peers" protocol for automatic node discovery
40
+ # Server supports the new 'peers' protocol for automatic node discovery
41
41
  PEERS = :peers
42
42
 
43
- # Server supports the "truncate-namespace" command
44
- TRUNCATE_NAMESPACE = :"truncate-namespace"
43
+ # Server supports the 'truncate-namespace' command
44
+ TRUNCATE_NAMESPACE = :'truncate-namespace'
45
45
 
46
- # Server supports the "blob-bits" command
47
- BLOB_BITS = :"blob-bits"
46
+ # Server supports the 'blob-bits' command
47
+ BLOB_BITS = :'blob-bits'
48
48
  end
49
49
  end
@@ -20,7 +20,7 @@
20
20
  module Aerospike
21
21
  class Host
22
22
  module Parse
23
- INTEGER_REGEX = /\A\d+\z/
23
+ INTEGER_REGEX = /\A\d+\z/.freeze
24
24
 
25
25
  class << self
26
26
  ##
@@ -73,4 +73,4 @@ module Aerospike
73
73
  end
74
74
  end
75
75
  end
76
- end
76
+ end
data/lib/aerospike/key.rb CHANGED
@@ -53,15 +53,20 @@ module Aerospike
53
53
 
54
54
  attr_reader :namespace, :set_name, :digest
55
55
 
56
- def initialize(ns, set, val, digest=nil, v1_compatible: self.class.v1_compatible?)
56
+ def initialize(ns, set, val, digest=nil, bval: nil, v1_compatible: self.class.v1_compatible?)
57
57
  @namespace = ns
58
58
  @set_name = set
59
59
  @user_key = Value.of(val)
60
60
  check_key!(@namespace, @set_name, @user_key, !digest.nil?)
61
61
  @digest = digest || compute_digest(v1_compatible)
62
+ @bval = bval
62
63
  end
63
64
 
64
65
 
66
+ def bval
67
+ @bval
68
+ end
69
+
65
70
  def to_s
66
71
  "#{@namespace}:#{@set_name}:#{@user_key}:#{@digest.nil? ? '' : @digest.bytes}"
67
72
  end
@@ -85,6 +90,10 @@ module Aerospike
85
90
  @digest.hash
86
91
  end
87
92
 
93
+ def partition_id
94
+ (@digest[0..3].unpack(Partition::UNPACK_FORMAT)[0] & 0xFFFF) % Node::PARTITIONS
95
+ end
96
+
88
97
  private
89
98
 
90
99
  def valid_key?(value, has_digest)
@@ -30,7 +30,7 @@ module Aerospike
30
30
  def call(node, peers)
31
31
  conn = node.tend_connection
32
32
  if peers.use_peers?
33
- cmds = node.cluster.rack_aware ? CMDS_REBALANCE : CMDS_PEERS
33
+ cmds = node.cluster.rack_aware ? CMDS_REBALANCE : CMDS_PEERS
34
34
  info_map = ::Aerospike::Info.request(conn, *cmds)
35
35
  Verify::PeersGeneration.(node, info_map, peers)
36
36
  Verify::PartitionGeneration.(node, info_map)
@@ -40,4 +40,4 @@ module Aerospike
40
40
  end
41
41
  end
42
42
  end
43
- end
43
+ end
@@ -40,4 +40,4 @@ module Aerospike
40
40
  end
41
41
  end
42
42
  end
43
- end
43
+ end
@@ -38,4 +38,4 @@ module Aerospike
38
38
  end
39
39
  end
40
40
  end
41
- end
41
+ end
@@ -40,4 +40,4 @@ module Aerospike
40
40
  end
41
41
  end
42
42
  end
43
- end
43
+ end
@@ -40,6 +40,7 @@ module Aerospike
40
40
 
41
41
  def get_hosts(address)
42
42
  aliases = [get_alias(address, host.port)]
43
+ res = []
43
44
 
44
45
  begin
45
46
  conn = Cluster::CreateConnection.(@cluster, Host.new(address, host.port, host.tls_name))
@@ -61,11 +62,15 @@ module Aerospike
61
62
  unless is_loopback?(address)
62
63
  aliases = info_map[address_command].split(',').map { |addr| get_alias(*addr.split(':')) }
63
64
  end
65
+
66
+ res = aliases.map { |al| Host.new(al[:address], al[:port], host.tls_name) }
67
+ rescue
68
+ # we don't care about the actual connection error; Just need to continue
64
69
  ensure
65
70
  conn.close if conn
66
71
  end
67
72
 
68
- aliases.map { |al| Host.new(al[:address], al[:port], host.tls_name) }
73
+ res
69
74
  end
70
75
 
71
76
  def get_alias(address, port)
@@ -26,6 +26,9 @@ module Aerospike
26
26
  attr_accessor :priority, :timeout, :max_retries, :sleep_between_retries, :consistency_level,
27
27
  :predexp, :fail_on_filtered_out, :replica, :use_compression
28
28
 
29
+ alias total_timeout timeout
30
+ alias total_timeout= timeout=
31
+
29
32
  def initialize(opt={})
30
33
  # Container object for transaction policy attributes used in all database
31
34
  # operation calls.
@@ -85,7 +88,7 @@ module Aerospike
85
88
 
86
89
 
87
90
  # Send read commands to the node containing the key's partition replica type.
88
- # Write commands are not affected by this setting, because all writes are directed
91
+ # Write commands are not affected by this setting, because all writes are directed
89
92
  # to the node containing the key's master partition.
90
93
  #
91
94
  # Default to sending read commands to the node containing the key's master partition.
@@ -22,6 +22,7 @@ module Aerospike
22
22
  # Container object for scan policy command.
23
23
  class ScanPolicy < Policy
24
24
 
25
+ attr_accessor :max_records
25
26
  attr_accessor :scan_percent
26
27
  attr_accessor :concurrent_nodes
27
28
  attr_accessor :include_bin_data
@@ -35,6 +36,16 @@ module Aerospike
35
36
 
36
37
  @max_retries = 0
37
38
 
39
+ # Approximates the number of records to return to the client. This number is divided by the
40
+ # number of nodes involved in the query. The actual number of records returned
41
+ # may be less than MaxRecords if node record counts are small and unbalanced across
42
+ # nodes.
43
+ #
44
+ # This field is supported on server versions >= 4.9.
45
+ #
46
+ # Default: 0 (do not limit record count)
47
+ @max_records = opt.fetch(:max_records) { 0 }
48
+
38
49
  # Percent of data to scan. Valid integer range is 1 to 100.
39
50
  # Default is 100.
40
51
  @scan_percent = opt[:scan_percent] || 100
@@ -51,7 +62,15 @@ module Aerospike
51
62
  # Default is true.
52
63
  @fail_on_cluster_change = opt.fetch(:fail_on_cluster_change) { true }
53
64
 
54
- @socket_timeout = opt[:socket_timeout] || 10000
65
+ # Determines network timeout for each attempt.
66
+ #
67
+ # If socket_timeout is not zero and socket_timeout is reached before an attempt completes,
68
+ # the Timeout above is checked. If Timeout is not exceeded, the transaction
69
+ # is retried. If both socket_timeout and Timeout are non-zero, socket_timeout must be less
70
+ # than or equal to Timeout, otherwise Timeout will also be used for socket_timeout.
71
+ #
72
+ # Default: 30s
73
+ @socket_timeout = opt[:socket_timeout] || 30000
55
74
 
56
75
  # Number of records to place in queue before blocking. Records received
57
76
  # from multiple server nodes will be placed in a queue. A separate thread
@@ -130,4 +130,4 @@ module Aerospike
130
130
 
131
131
  end # class
132
132
 
133
- end
133
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2014-2020 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 http:#www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
17
+
18
+ module Aerospike
19
+ class NodePartitions
20
+ attr_accessor :node, :parts_full, :parts_partial, :record_count, :record_max, :parts_unavailable
21
+
22
+ def initialize(node)
23
+ @node= node
24
+ @parts_full= []
25
+ @parts_partial= []
26
+ @record_count= 0
27
+ @parts_unavailable= 0
28
+ @record_max= 0
29
+ end
30
+
31
+ def to_s
32
+ "Node #{@node.inspect}: full: #{@parts_full.length}, partial: #{@parts_partial.length}"
33
+ end
34
+
35
+ def add_partition(partition_status)
36
+ partition_status.digest.nil? ? @parts_full << partition_status : @parts_partial << partition_status
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2014-2020 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 http:#www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
17
+
18
+ module Aerospike
19
+ class PartitionFilter
20
+ attr_reader :partition_begin, :count, :digest
21
+ attr_accessor :partitions, :done
22
+
23
+ alias done? done
24
+
25
+ # Creates a partition filter that
26
+ # reads all the partitions.
27
+ def self.all
28
+ PartitionFilter.new(0, Aerospike::Node::PARTITIONS)
29
+ end
30
+
31
+ # Creates a partition filter by partition id.
32
+ # Partition id is between 0 - 4095
33
+ def self.by_id(partition_id)
34
+ PartitionFilter.new(partition_id, 1)
35
+ end
36
+
37
+ # Creates a partition filter by partition range.
38
+ # begin partition id is between 0 - 4095
39
+ # count is the number of partitions, in the range of 1 - 4096 inclusive.
40
+ def self.by_range(partition_begin, count)
41
+ PartitionFilter.new(partition_begin, count)
42
+ end
43
+
44
+ # Creates a partition filter that will return
45
+ # records after key's digest in the partition containing the digest.
46
+ # Note that digest order is not the same as userKey order. This method
47
+ # only works for scan or query with nil filter.
48
+ def self.by_key(key)
49
+ PartitionFilter.new(key.partition_id, 1, key.digest)
50
+ end
51
+
52
+ def to_s
53
+ "PartitionFilter<begin: #{@partition_begin}, count: #{@count}, digest: #{@digest}, done: #{@done}>"
54
+ end
55
+
56
+ private
57
+
58
+ def initialize(partition_begin, count, digest = nil, partitions = nil, done = false)
59
+ @partition_begin = partition_begin
60
+ @count = count
61
+ @digest = digest
62
+ @partitions = partitions
63
+ @done = done
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2014-2020 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 http:#www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
17
+
18
+ module Aerospike
19
+
20
+ class PartitionStatus #:nodoc:
21
+ attr_accessor :bval, :id, :digest, :retry
22
+
23
+ def initialize(id)
24
+ @id = id
25
+ @retry = true
26
+ end
27
+
28
+ #
29
+ # Show the PartitionStatus as String.
30
+ #
31
+ def to_s
32
+ "PartitionStatus<bval: #{@bval}, id: #{@id}, retry: #{@retry}, digest: #{@digest}>"
33
+ end
34
+
35
+ end
36
+ end