aerospike 2.21.1 → 2.23.0

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