aerospike 2.6.0 → 2.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +3 -1
- data/lib/aerospike.rb +9 -5
- data/lib/aerospike/client.rb +101 -83
- data/lib/aerospike/cluster.rb +11 -50
- data/lib/aerospike/cluster/create_connection.rb +1 -1
- data/lib/aerospike/cluster/find_nodes_to_remove.rb +66 -0
- data/lib/aerospike/cluster/partition.rb +5 -2
- data/lib/aerospike/command/batch_direct_command.rb +104 -0
- data/lib/aerospike/command/batch_direct_exists_command.rb +51 -0
- data/lib/aerospike/command/batch_direct_node.rb +40 -0
- data/lib/aerospike/command/batch_index_command.rb +119 -0
- data/lib/aerospike/command/batch_index_exists_command.rb +45 -0
- data/lib/aerospike/command/batch_index_node.rb +52 -0
- data/lib/aerospike/command/batch_item.rb +18 -47
- data/lib/aerospike/command/command.rb +6 -65
- data/lib/aerospike/command/field_type.rb +13 -10
- data/lib/aerospike/command/{batch_command.rb → multi_command.rb} +29 -9
- data/lib/aerospike/command/read_command.rb +4 -2
- data/lib/aerospike/command/single_command.rb +6 -9
- data/lib/aerospike/connection/create.rb +3 -3
- data/lib/aerospike/host/parse.rb +28 -2
- data/lib/aerospike/node.rb +6 -2
- data/lib/aerospike/node/refresh/friends.rb +1 -1
- data/lib/aerospike/node/refresh/peers.rb +1 -1
- data/lib/aerospike/node_validator.rb +3 -3
- data/lib/aerospike/peers.rb +4 -0
- data/lib/aerospike/peers/parse.rb +26 -6
- data/lib/aerospike/policy/batch_policy.rb +25 -15
- data/lib/aerospike/policy/client_policy.rb +2 -2
- data/lib/aerospike/policy/query_policy.rb +25 -12
- data/lib/aerospike/policy/scan_policy.rb +39 -16
- data/lib/aerospike/query/stream_command.rb +6 -5
- data/lib/aerospike/record.rb +4 -3
- data/lib/aerospike/socket/ssl.rb +13 -13
- data/lib/aerospike/socket/tcp.rb +8 -1
- data/lib/aerospike/utils/string_parser.rb +7 -3
- data/lib/aerospike/version.rb +1 -1
- metadata +11 -7
- data/lib/aerospike/command/batch_command_exists.rb +0 -93
- data/lib/aerospike/command/batch_command_get.rb +0 -84
- data/lib/aerospike/command/batch_node.rb +0 -82
data/lib/aerospike/cluster.rb
CHANGED
@@ -25,7 +25,7 @@ require 'aerospike/atomic/atomic'
|
|
25
25
|
module Aerospike
|
26
26
|
class Cluster
|
27
27
|
attr_reader :connection_timeout, :connection_queue_size, :user, :password
|
28
|
-
attr_reader :features, :
|
28
|
+
attr_reader :features, :tls_options
|
29
29
|
attr_reader :cluster_id, :aliases
|
30
30
|
attr_reader :cluster_name
|
31
31
|
|
@@ -36,7 +36,7 @@ module Aerospike
|
|
36
36
|
@connection_timeout = policy.timeout
|
37
37
|
@tend_interval = policy.tend_interval
|
38
38
|
@cluster_name = policy.cluster_name
|
39
|
-
@
|
39
|
+
@tls_options = policy.tls
|
40
40
|
|
41
41
|
@aliases = {}
|
42
42
|
@cluster_nodes = []
|
@@ -75,7 +75,7 @@ module Aerospike
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def tls_enabled?
|
78
|
-
!
|
78
|
+
!tls_options.nil? && tls_options[:enable] != false
|
79
79
|
end
|
80
80
|
|
81
81
|
def initialize_tls_host_names(hosts)
|
@@ -102,7 +102,9 @@ module Aerospike
|
|
102
102
|
(node_array.length > 0) && !@closed.value
|
103
103
|
end
|
104
104
|
|
105
|
-
def
|
105
|
+
def get_node_for_key(key)
|
106
|
+
partition = Partition.new_by_key(key)
|
107
|
+
|
106
108
|
# Must copy hashmap reference for copy on write semantics to work.
|
107
109
|
nmap = partitions
|
108
110
|
if node_array = nmap[partition.namespace]
|
@@ -268,6 +270,8 @@ module Aerospike
|
|
268
270
|
if peers.generation_changed?
|
269
271
|
# Refresh peers for all nodes that responded the first time even if only
|
270
272
|
# one node's peers changed.
|
273
|
+
peers.reset_refresh_count!
|
274
|
+
|
271
275
|
nodes.each do |node|
|
272
276
|
node.refresh_peers(peers)
|
273
277
|
end
|
@@ -371,7 +375,7 @@ module Aerospike
|
|
371
375
|
|
372
376
|
seed_array.each do |seed|
|
373
377
|
begin
|
374
|
-
seed_node_validator = NodeValidator.new(self, seed, @connection_timeout, @cluster_name,
|
378
|
+
seed_node_validator = NodeValidator.new(self, seed, @connection_timeout, @cluster_name, tls_options)
|
375
379
|
rescue => e
|
376
380
|
Aerospike.logger.error("Seed #{seed} failed: #{e}\n#{e.backtrace.join("\n")}")
|
377
381
|
next
|
@@ -384,7 +388,7 @@ module Aerospike
|
|
384
388
|
nv = seed_node_validator
|
385
389
|
else
|
386
390
|
begin
|
387
|
-
nv = NodeValidator.new(self, aliass, @connection_timeout, @cluster_name,
|
391
|
+
nv = NodeValidator.new(self, aliass, @connection_timeout, @cluster_name, tls_options)
|
388
392
|
rescue => e
|
389
393
|
Aerospike.logger.error("Seed #{seed} failed: #{e}")
|
390
394
|
next
|
@@ -427,50 +431,7 @@ module Aerospike
|
|
427
431
|
end
|
428
432
|
|
429
433
|
def find_nodes_to_remove(refresh_count)
|
430
|
-
|
431
|
-
|
432
|
-
remove_list = []
|
433
|
-
|
434
|
-
node_list.each do |node|
|
435
|
-
if !node.active?
|
436
|
-
# Inactive nodes must be removed.
|
437
|
-
remove_list << node
|
438
|
-
next
|
439
|
-
end
|
440
|
-
|
441
|
-
case node_list.length
|
442
|
-
when 1
|
443
|
-
# Single node clusters rely solely on node health.
|
444
|
-
remove_list << node if node.unhealthy?
|
445
|
-
|
446
|
-
when 2
|
447
|
-
# Two node clusters require at least one successful refresh before removing.
|
448
|
-
if refresh_count == 2 && node.reference_count.value == 0 && !node.responded?
|
449
|
-
# Node is not referenced nor did it respond.
|
450
|
-
remove_list << node
|
451
|
-
end
|
452
|
-
|
453
|
-
else
|
454
|
-
# Multi-node clusters require two successful node refreshes before removing.
|
455
|
-
if refresh_count >= 2 && node.reference_count.value == 0
|
456
|
-
# Node is not referenced by other nodes.
|
457
|
-
# Check if node responded to info request.
|
458
|
-
if node.responded?
|
459
|
-
# Node is alive, but not referenced by other nodes. Check if mapped.
|
460
|
-
unless find_node_in_partition_map(node)
|
461
|
-
# Node doesn't have any partitions mapped to it.
|
462
|
-
# There is not point in keeping it in the cluster.
|
463
|
-
remove_list << node
|
464
|
-
end
|
465
|
-
else
|
466
|
-
# Node not responding. Remove it.
|
467
|
-
remove_list << node
|
468
|
-
end
|
469
|
-
end
|
470
|
-
end
|
471
|
-
end
|
472
|
-
|
473
|
-
remove_list
|
434
|
+
FindNodesToRemove.(self, refresh_count)
|
474
435
|
end
|
475
436
|
|
476
437
|
def find_node_in_partition_map(filter)
|
@@ -28,7 +28,7 @@ module Aerospike
|
|
28
28
|
host.port,
|
29
29
|
tls_name: host.tls_name,
|
30
30
|
timeout: cluster.connection_timeout,
|
31
|
-
|
31
|
+
tls_options: cluster.tls_options
|
32
32
|
).tap do |conn|
|
33
33
|
if cluster.credentials_given?
|
34
34
|
# Authenticate will raise and close connection if invalid credentials
|
@@ -0,0 +1,66 @@
|
|
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 Cluster
|
22
|
+
# Calculates which nodes that should be removed from the cluster
|
23
|
+
module FindNodesToRemove
|
24
|
+
class << self
|
25
|
+
def call(cluster, refresh_count)
|
26
|
+
node_list = cluster.nodes
|
27
|
+
|
28
|
+
remove_list = []
|
29
|
+
|
30
|
+
node_list.each do |node|
|
31
|
+
unless node.active?
|
32
|
+
# Inactive nodes must be removed.
|
33
|
+
remove_list << node
|
34
|
+
next
|
35
|
+
end
|
36
|
+
|
37
|
+
if refresh_count.zero? && node.failed?(5) # 5 or more failures counts as failed
|
38
|
+
# All node info requests failed and this node had 5 consecutive failures.
|
39
|
+
# Remove node. If no nodes are left, seeds will be tried in next cluster
|
40
|
+
# tend iteration.
|
41
|
+
remove_list << node
|
42
|
+
next
|
43
|
+
end
|
44
|
+
|
45
|
+
if node_list.size > 1 && refresh_count >= 1 && !node.referenced?
|
46
|
+
# Node is not referenced by other nodes.
|
47
|
+
# Check if node responded to info request.
|
48
|
+
if node.failed?
|
49
|
+
remove_list << node
|
50
|
+
else
|
51
|
+
# Node is alive, but not referenced by other nodes. Check if mapped.
|
52
|
+
unless cluster.find_node_in_partition_map(node)
|
53
|
+
# Node doesn't have any partitions mapped to it.
|
54
|
+
# There is no point in keeping it in the cluster.
|
55
|
+
remove_list << node
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
remove_list
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
# Copyright 2014-2017 Aerospike, Inc.
|
3
4
|
#
|
4
5
|
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
@@ -19,6 +20,8 @@ module Aerospike
|
|
19
20
|
private
|
20
21
|
|
21
22
|
class Partition # :nodoc:
|
23
|
+
UNPACK_FORMAT = 'l<'
|
24
|
+
|
22
25
|
attr_reader :namespace, :partition_id
|
23
26
|
|
24
27
|
def initialize(namespace, partition_id)
|
@@ -31,7 +34,7 @@ module Aerospike
|
|
31
34
|
def self.new_by_key(key)
|
32
35
|
Partition.new(
|
33
36
|
key.namespace,
|
34
|
-
(key.digest[0..3].unpack(
|
37
|
+
(key.digest[0..3].unpack(UNPACK_FORMAT)[0] & 0xFFFF) % Node::PARTITIONS
|
35
38
|
)
|
36
39
|
end
|
37
40
|
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# Copyright 2014-2018 Aerospike, Inc.
|
2
|
+
#
|
3
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
4
|
+
# license agreements.
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
7
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
8
|
+
# the License at
|
9
|
+
#
|
10
|
+
# 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
|
+
require 'aerospike/command/multi_command'
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
|
22
|
+
class BatchDirectCommand < MultiCommand #:nodoc:
|
23
|
+
|
24
|
+
attr_accessor :batch
|
25
|
+
attr_accessor :policy
|
26
|
+
attr_accessor :key_map
|
27
|
+
attr_accessor :bin_names
|
28
|
+
attr_accessor :results
|
29
|
+
attr_accessor :read_attr
|
30
|
+
|
31
|
+
def initialize(node, batch, policy, key_map, bin_names, results, read_attr)
|
32
|
+
super(node)
|
33
|
+
|
34
|
+
@batch = batch
|
35
|
+
@policy = policy
|
36
|
+
@key_map = key_map
|
37
|
+
@bin_names = bin_names
|
38
|
+
@results = results
|
39
|
+
@read_attr = read_attr
|
40
|
+
end
|
41
|
+
|
42
|
+
def write_buffer
|
43
|
+
# Estimate buffer size
|
44
|
+
begin_cmd
|
45
|
+
byte_size = batch.keys.length * DIGEST_SIZE
|
46
|
+
|
47
|
+
@data_offset += batch.namespace.bytesize +
|
48
|
+
FIELD_HEADER_SIZE + byte_size + FIELD_HEADER_SIZE
|
49
|
+
|
50
|
+
if bin_names
|
51
|
+
bin_names.each do |bin_name|
|
52
|
+
estimate_operation_size_for_bin_name(bin_name)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
size_buffer
|
57
|
+
|
58
|
+
operation_count = 0
|
59
|
+
if bin_names
|
60
|
+
operation_count = bin_names.length
|
61
|
+
end
|
62
|
+
|
63
|
+
write_header(policy, read_attr, 0, 2, operation_count)
|
64
|
+
write_field_string(batch.namespace, Aerospike::FieldType::NAMESPACE)
|
65
|
+
write_field_header(byte_size, Aerospike::FieldType::DIGEST_RIPE_ARRAY)
|
66
|
+
|
67
|
+
batch.keys.each do |key|
|
68
|
+
@data_offset += @data_buffer.write_binary(key.digest, @data_offset)
|
69
|
+
end
|
70
|
+
|
71
|
+
if bin_names
|
72
|
+
bin_names.each do |bin_name|
|
73
|
+
write_operation_for_bin_name(bin_name, Aerospike::Operation::READ)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end_cmd
|
78
|
+
end
|
79
|
+
|
80
|
+
# Parse all results in the batch. Add records to shared list.
|
81
|
+
# If the record was not found, the bins will be nil.
|
82
|
+
def parse_row(result_code)
|
83
|
+
generation = @data_buffer.read_int32(6)
|
84
|
+
expiration = @data_buffer.read_int32(10)
|
85
|
+
field_count = @data_buffer.read_int16(18)
|
86
|
+
op_count = @data_buffer.read_int16(20)
|
87
|
+
|
88
|
+
key = parse_key(field_count)
|
89
|
+
|
90
|
+
item = key_map[key.digest]
|
91
|
+
if item
|
92
|
+
if result_code == 0
|
93
|
+
index = item.index
|
94
|
+
key = item.key
|
95
|
+
results[index] = parse_record(key, op_count, generation, expiration)
|
96
|
+
end
|
97
|
+
else
|
98
|
+
Aerospike.logger.warn("Unexpected batch key returned: #{key}")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end # class
|
103
|
+
|
104
|
+
end # module
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Copyright 2014-2018 Aerospike, Inc.
|
2
|
+
#
|
3
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
4
|
+
# license agreements.
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
7
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
8
|
+
# the License at
|
9
|
+
#
|
10
|
+
# 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
|
+
require 'aerospike/command/batch_direct_command'
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
|
22
|
+
class BatchDirectExistsCommand < BatchDirectCommand #:nodoc:
|
23
|
+
|
24
|
+
def initialize(node, batch, policy, key_map, results)
|
25
|
+
super(node, batch, policy, key_map, nil, results, INFO1_READ | INFO1_NOBINDATA)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Parse all results in the batch. Add records to shared list.
|
29
|
+
# If the record was not found, the bins will be nil.
|
30
|
+
def parse_row(result_code)
|
31
|
+
field_count = @data_buffer.read_int16(18)
|
32
|
+
op_count = @data_buffer.read_int16(20)
|
33
|
+
|
34
|
+
if op_count > 0
|
35
|
+
raise Aerospike::Exceptions::Parse.new('Received bins that were not requested!')
|
36
|
+
end
|
37
|
+
|
38
|
+
key = parse_key(field_count)
|
39
|
+
item = key_map[key.digest]
|
40
|
+
|
41
|
+
if item
|
42
|
+
index = item.index
|
43
|
+
results[index] = (result_code == 0)
|
44
|
+
else
|
45
|
+
Aerospike::logger.debug("Unexpected batch key returned: #{key.namespace}, #{key.digest}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end # class
|
50
|
+
|
51
|
+
end # module
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Copyright 2014-2018 Aerospike, Inc.
|
2
|
+
#
|
3
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
4
|
+
# license agreements.
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
7
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
8
|
+
# the License at
|
9
|
+
#
|
10
|
+
# 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
|
+
BatchNamespace = Struct.new :namespace, :keys
|
21
|
+
|
22
|
+
class BatchDirectNode #:nodoc:
|
23
|
+
|
24
|
+
attr_accessor :node
|
25
|
+
attr_accessor :batch_namespaces
|
26
|
+
|
27
|
+
def self.generate_list(cluster, keys)
|
28
|
+
keys.group_by { |key| cluster.get_node_for_key(key) }
|
29
|
+
.map { |node, keys_for_node| BatchDirectNode.new(node, keys_for_node) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize(node, keys)
|
33
|
+
@node = node
|
34
|
+
@batch_namespaces = keys.group_by(&:namespace)
|
35
|
+
.map { |ns, keys_for_ns| BatchNamespace.new(ns, keys_for_ns) }
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# Copyright 2018 Aerospike, Inc.
|
2
|
+
#
|
3
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
4
|
+
# license agreements.
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
7
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
8
|
+
# the License at
|
9
|
+
#
|
10
|
+
# 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
|
+
require 'aerospike/command/multi_command'
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
|
22
|
+
class BatchIndexCommand < MultiCommand #:nodoc:
|
23
|
+
|
24
|
+
attr_accessor :batch
|
25
|
+
attr_accessor :policy
|
26
|
+
attr_accessor :bin_names
|
27
|
+
attr_accessor :results
|
28
|
+
attr_accessor :read_attr
|
29
|
+
|
30
|
+
def initialize(node, batch, policy, bin_names, results, read_attr)
|
31
|
+
super(node)
|
32
|
+
@batch = batch
|
33
|
+
@policy = policy
|
34
|
+
@bin_names = bin_names
|
35
|
+
@results = results
|
36
|
+
@read_attr = read_attr
|
37
|
+
end
|
38
|
+
|
39
|
+
def write_buffer
|
40
|
+
bin_name_size = 0
|
41
|
+
operation_count = 0
|
42
|
+
field_count = 1
|
43
|
+
if bin_names
|
44
|
+
bin_names.each do |bin_name|
|
45
|
+
bin_name_size += bin_name.bytesize + OPERATION_HEADER_SIZE
|
46
|
+
end
|
47
|
+
operation_count = bin_names.length
|
48
|
+
end
|
49
|
+
begin_cmd
|
50
|
+
@data_offset += FIELD_HEADER_SIZE + 4 + 1 # batch.keys.length + flags
|
51
|
+
|
52
|
+
prev = nil
|
53
|
+
batch.keys.each do |key|
|
54
|
+
@data_offset += key.digest.length + 4 # 4 byte batch offset
|
55
|
+
|
56
|
+
if prev != nil && prev.namespace == key.namespace
|
57
|
+
@data_offset += 1
|
58
|
+
else
|
59
|
+
@data_offset += key.namespace.bytesize + FIELD_HEADER_SIZE + 1 + 1 + 2 + 2 # repeat/no-repeat flag + read_attr flags + field_count + operation_count
|
60
|
+
@data_offset += bin_name_size
|
61
|
+
end
|
62
|
+
end
|
63
|
+
size_buffer
|
64
|
+
write_header(policy,read_attr | INFO1_BATCH, 0, 1, 0)
|
65
|
+
write_field_header(0, Aerospike::FieldType::BATCH_INDEX)
|
66
|
+
@data_offset += @data_buffer.write_int32(batch.keys.length, @data_offset)
|
67
|
+
@data_offset += @data_buffer.write_byte(1, @data_offset)
|
68
|
+
|
69
|
+
prev = nil
|
70
|
+
|
71
|
+
batch.each_key_with_index do |key, index|
|
72
|
+
@data_offset += @data_buffer.write_int32(index, @data_offset)
|
73
|
+
@data_offset += @data_buffer.write_binary(key.digest, @data_offset)
|
74
|
+
|
75
|
+
if (prev != nil && prev.namespace == key.namespace)
|
76
|
+
@data_offset += @data_buffer.write_byte(1, @data_offset)
|
77
|
+
else
|
78
|
+
@data_offset += @data_buffer.write_byte(0, @data_offset)
|
79
|
+
@data_offset += @data_buffer.write_byte(read_attr, @data_offset)
|
80
|
+
@data_offset += @data_buffer.write_int16(field_count, @data_offset)
|
81
|
+
@data_offset += @data_buffer.write_int16(operation_count, @data_offset)
|
82
|
+
write_field_string(key.namespace, Aerospike::FieldType::NAMESPACE)
|
83
|
+
|
84
|
+
if bin_names
|
85
|
+
bin_names.each do |bin_name|
|
86
|
+
write_operation_for_bin_name(bin_name, Aerospike::Operation::READ)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
prev = key
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end_cmd
|
93
|
+
end
|
94
|
+
|
95
|
+
# Parse all results in the batch. Add records to shared list.
|
96
|
+
# If the record was not found, the bins will be nil.
|
97
|
+
def parse_row(result_code)
|
98
|
+
generation = @data_buffer.read_int32(6)
|
99
|
+
expiration = @data_buffer.read_int32(10)
|
100
|
+
batch_index = @data_buffer.read_int32(14)
|
101
|
+
field_count = @data_buffer.read_int16(18)
|
102
|
+
op_count = @data_buffer.read_int16(20)
|
103
|
+
|
104
|
+
key = parse_key(field_count)
|
105
|
+
req_key = batch.key_for_index(batch_index)
|
106
|
+
|
107
|
+
if key.digest == req_key.digest
|
108
|
+
if result_code == 0
|
109
|
+
record = parse_record(req_key, op_count, generation, expiration)
|
110
|
+
results[batch_index] = record
|
111
|
+
end
|
112
|
+
else
|
113
|
+
Aerospike.logger.warn("Unexpected batch key returned: #{key}")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end # class
|
118
|
+
|
119
|
+
end # module
|