aerospike 2.29.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -0
- data/README.md +13 -9
- data/lib/aerospike/batch_attr.rb +292 -0
- data/lib/aerospike/batch_delete.rb +48 -0
- data/lib/aerospike/batch_read.rb +97 -0
- data/lib/aerospike/batch_record.rb +83 -0
- data/lib/aerospike/batch_results.rb +38 -0
- data/lib/aerospike/batch_udf.rb +76 -0
- data/lib/aerospike/batch_write.rb +79 -0
- data/lib/aerospike/cdt/bit_operation.rb +4 -5
- data/lib/aerospike/cdt/map_operation.rb +24 -10
- data/lib/aerospike/cdt/map_policy.rb +6 -3
- data/lib/aerospike/cdt/map_return_type.rb +8 -0
- data/lib/aerospike/client.rb +39 -56
- data/lib/aerospike/cluster.rb +50 -46
- data/lib/aerospike/command/batch_index_command.rb +7 -11
- data/lib/aerospike/command/batch_index_node.rb +3 -4
- data/lib/aerospike/command/batch_operate_command.rb +151 -0
- data/lib/aerospike/command/batch_operate_node.rb +51 -0
- data/lib/aerospike/command/command.rb +231 -128
- data/lib/aerospike/exp/exp.rb +54 -27
- data/lib/aerospike/exp/exp_bit.rb +24 -24
- data/lib/aerospike/exp/exp_hll.rb +12 -12
- data/lib/aerospike/exp/exp_list.rb +101 -86
- data/lib/aerospike/exp/exp_map.rb +118 -110
- data/lib/aerospike/exp/operation.rb +2 -2
- data/lib/aerospike/info.rb +2 -4
- data/lib/aerospike/node.rb +20 -3
- data/lib/aerospike/operation.rb +38 -0
- data/lib/aerospike/policy/batch_delete_policy.rb +71 -0
- data/lib/aerospike/policy/batch_policy.rb +53 -4
- data/lib/aerospike/{command/batch_direct_node.rb → policy/batch_read_policy.rb} +17 -19
- data/lib/aerospike/policy/batch_udf_policy.rb +75 -0
- data/lib/aerospike/policy/batch_write_policy.rb +105 -0
- data/lib/aerospike/policy/policy.rb +3 -40
- data/lib/aerospike/query/query_command.rb +3 -205
- data/lib/aerospike/query/query_executor.rb +2 -2
- data/lib/aerospike/query/query_partition_command.rb +4 -230
- data/lib/aerospike/query/scan_executor.rb +2 -2
- data/lib/aerospike/query/scan_partition_command.rb +3 -3
- data/lib/aerospike/query/server_command.rb +2 -2
- data/lib/aerospike/query/statement.rb +5 -21
- data/lib/aerospike/task/execute_task.rb +2 -2
- data/lib/aerospike/utils/buffer.rb +15 -15
- data/lib/aerospike/version.rb +1 -1
- data/lib/aerospike.rb +13 -12
- metadata +16 -14
- data/lib/aerospike/command/batch_direct_command.rb +0 -105
- data/lib/aerospike/command/batch_direct_exists_command.rb +0 -51
- data/lib/aerospike/query/pred_exp/and_or.rb +0 -32
- data/lib/aerospike/query/pred_exp/geo_json_value.rb +0 -41
- data/lib/aerospike/query/pred_exp/integer_value.rb +0 -32
- data/lib/aerospike/query/pred_exp/op.rb +0 -27
- data/lib/aerospike/query/pred_exp/regex.rb +0 -32
- data/lib/aerospike/query/pred_exp/regex_flags.rb +0 -23
- data/lib/aerospike/query/pred_exp/string_value.rb +0 -29
- data/lib/aerospike/query/pred_exp.rb +0 -192
data/lib/aerospike/cluster.rb
CHANGED
@@ -120,15 +120,15 @@ module Aerospike
|
|
120
120
|
# Returns a node on the cluster for read operations
|
121
121
|
def batch_read_node(partition, replica_policy)
|
122
122
|
case replica_policy
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
123
|
+
when Aerospike::Replica::MASTER, Aerospike::Replica::SEQUENCE
|
124
|
+
master_node(partition)
|
125
|
+
when Aerospike::Replica::MASTER_PROLES
|
126
|
+
master_proles_node(partition)
|
127
|
+
when Aerospike::Replica::PREFER_RACK
|
128
|
+
rack_node(partition, seq)
|
129
|
+
when Aerospike::Replica::RANDOM
|
130
|
+
random_node
|
131
|
+
else
|
132
132
|
raise Aerospike::Exceptions::InvalidNode("invalid policy.replica value")
|
133
133
|
end
|
134
134
|
end
|
@@ -136,17 +136,17 @@ module Aerospike
|
|
136
136
|
# Returns a node on the cluster for read operations
|
137
137
|
def read_node(partition, replica_policy, seq)
|
138
138
|
case replica_policy
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
139
|
+
when Aerospike::Replica::MASTER
|
140
|
+
master_node(partition)
|
141
|
+
when Aerospike::Replica::MASTER_PROLES
|
142
|
+
master_proles_node(partition)
|
143
|
+
when Aerospike::Replica::PREFER_RACK
|
144
|
+
rack_node(partition, seq)
|
145
|
+
when Aerospike::Replica::SEQUENCE
|
146
|
+
sequence_node(partition, seq)
|
147
|
+
when Aerospike::Replica::RANDOM
|
148
|
+
random_node
|
149
|
+
else
|
150
150
|
raise Aerospike::Exceptions::InvalidNode("invalid policy.replica value")
|
151
151
|
end
|
152
152
|
end
|
@@ -155,12 +155,12 @@ module Aerospike
|
|
155
155
|
def master_node(partition)
|
156
156
|
partition_map = partitions
|
157
157
|
replica_array = partition_map[partition.namespace]
|
158
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map")
|
158
|
+
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless replica_array
|
159
159
|
|
160
|
-
node_array =
|
161
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map")
|
160
|
+
node_array = replica_array.get[0]
|
161
|
+
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless node_array
|
162
162
|
|
163
|
-
node =
|
163
|
+
node = node_array.get[partition.partition_id]
|
164
164
|
raise Aerospike::Exceptions::InvalidNode if !node || !node.active?
|
165
165
|
|
166
166
|
node
|
@@ -170,7 +170,7 @@ module Aerospike
|
|
170
170
|
def rack_node(partition, seq)
|
171
171
|
partition_map = partitions
|
172
172
|
replica_array = partition_map[partition.namespace]
|
173
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map")
|
173
|
+
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless replica_array
|
174
174
|
|
175
175
|
replica_array = replica_array.get
|
176
176
|
|
@@ -179,10 +179,10 @@ module Aerospike
|
|
179
179
|
node = nil
|
180
180
|
fallback = nil
|
181
181
|
for i in 1..replica_array.length
|
182
|
-
idx = (seq.update{|v| v.succ} % replica_array.size).abs
|
183
|
-
node =
|
182
|
+
idx = (seq.update { |v| v.succ } % replica_array.size).abs
|
183
|
+
node = replica_array[idx].get[partition.partition_id]
|
184
184
|
|
185
|
-
next
|
185
|
+
next unless node
|
186
186
|
|
187
187
|
fallback = node
|
188
188
|
|
@@ -202,14 +202,14 @@ module Aerospike
|
|
202
202
|
def master_proles_node(partition)
|
203
203
|
partition_map = partitions
|
204
204
|
replica_array = partition_map[partition.namespace]
|
205
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map")
|
205
|
+
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless replica_array
|
206
206
|
|
207
207
|
replica_array = replica_array.get
|
208
208
|
|
209
209
|
node = nil
|
210
210
|
for replica in replica_array
|
211
|
-
idx = (@replica_index.update{|v| v.succ} % replica_array.size).abs
|
212
|
-
node =
|
211
|
+
idx = (@replica_index.update { |v| v.succ } % replica_array.size).abs
|
212
|
+
node = replica_array[idx].get[partition.partition_id]
|
213
213
|
|
214
214
|
return node if node && node.active?
|
215
215
|
end
|
@@ -221,14 +221,14 @@ module Aerospike
|
|
221
221
|
def sequence_node(partition, seq)
|
222
222
|
partition_map = partitions
|
223
223
|
replica_array = partition_map[partition.namespace]
|
224
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map")
|
224
|
+
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless replica_array
|
225
225
|
|
226
226
|
replica_array = replica_array.get
|
227
227
|
|
228
228
|
node = nil
|
229
229
|
for replica in replica_array
|
230
|
-
idx = (seq.update{|v| v.succ} % replica_array.size).abs
|
231
|
-
node =
|
230
|
+
idx = (seq.update { |v| v.succ } % replica_array.size).abs
|
231
|
+
node = replica_array[idx].get[partition.partition_id]
|
232
232
|
|
233
233
|
return node if node && node.active?
|
234
234
|
end
|
@@ -236,9 +236,13 @@ module Aerospike
|
|
236
236
|
raise Aerospike::Exceptions::InvalidNode
|
237
237
|
end
|
238
238
|
|
239
|
-
def get_node_for_key(replica_policy, key)
|
239
|
+
def get_node_for_key(replica_policy, key, is_write: false)
|
240
240
|
partition = Partition.new_by_key(key)
|
241
|
-
|
241
|
+
if is_write
|
242
|
+
master_node(partition)
|
243
|
+
else
|
244
|
+
batch_read_node(partition, replica_policy)
|
245
|
+
end
|
242
246
|
end
|
243
247
|
|
244
248
|
# Returns partitions pertaining to a node
|
@@ -247,10 +251,10 @@ module Aerospike
|
|
247
251
|
|
248
252
|
partition_map = partitions
|
249
253
|
replica_array = partition_map[namespace]
|
250
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map")
|
254
|
+
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless replica_array
|
251
255
|
|
252
|
-
node_array =
|
253
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map")
|
256
|
+
node_array = replica_array.get[0]
|
257
|
+
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless node_array
|
254
258
|
|
255
259
|
|
256
260
|
pid = 0
|
@@ -270,7 +274,7 @@ module Aerospike
|
|
270
274
|
i = 0
|
271
275
|
while i < length
|
272
276
|
# Must handle concurrency with other non-tending threads, so node_index is consistent.
|
273
|
-
idx = (@node_index.update{ |v| v.succ } % node_array.length).abs
|
277
|
+
idx = (@node_index.update { |v| v.succ } % node_array.length).abs
|
274
278
|
node = node_array[idx]
|
275
279
|
|
276
280
|
return node if node.active?
|
@@ -366,13 +370,13 @@ module Aerospike
|
|
366
370
|
@tend_thread = Thread.new do
|
367
371
|
Thread.current.abort_on_exception = false
|
368
372
|
loop do
|
369
|
-
|
373
|
+
|
370
374
|
tend
|
371
375
|
sleep(@tend_interval / 1000.0)
|
372
|
-
|
376
|
+
rescue => e
|
373
377
|
Aerospike.logger.error("Exception occured during tend: #{e}")
|
374
378
|
Aerospike.logger.debug { e.backtrace.join("\n") }
|
375
|
-
|
379
|
+
|
376
380
|
end
|
377
381
|
end
|
378
382
|
end
|
@@ -453,7 +457,7 @@ module Aerospike
|
|
453
457
|
|
454
458
|
def log_tend_stats(nodes)
|
455
459
|
diff = nodes.size - @old_node_count
|
456
|
-
action = "#{diff.abs} #{diff.abs == 1 ?
|
460
|
+
action = "#{diff.abs} #{diff.abs == 1 ? 'node has' : 'nodes have'} #{diff > 0 ? 'joined' : 'left'} the cluster."
|
457
461
|
Aerospike.logger.info("Tend finished. #{action} Old node count: #{@old_node_count}, New node count: #{nodes.size}")
|
458
462
|
@old_node_count = nodes.size
|
459
463
|
end
|
@@ -689,11 +693,11 @@ module Aerospike
|
|
689
693
|
end
|
690
694
|
|
691
695
|
def node_exists(search, node_list)
|
692
|
-
node_list.any? {|node| node == search }
|
696
|
+
node_list.any? { |node| node == search }
|
693
697
|
end
|
694
698
|
|
695
699
|
def find_node_by_name(node_name)
|
696
|
-
nodes.detect{|node| node.name == node_name }
|
700
|
+
nodes.detect { |node| node.name == node_name }
|
697
701
|
end
|
698
702
|
end
|
699
703
|
end
|
@@ -21,11 +21,7 @@ module Aerospike
|
|
21
21
|
|
22
22
|
class BatchIndexCommand < MultiCommand #:nodoc:
|
23
23
|
|
24
|
-
attr_accessor :batch
|
25
|
-
attr_accessor :policy
|
26
|
-
attr_accessor :bin_names
|
27
|
-
attr_accessor :results
|
28
|
-
attr_accessor :read_attr
|
24
|
+
attr_accessor :batch, :policy, :bin_names, :results, :read_attr
|
29
25
|
|
30
26
|
def initialize(node, batch, policy, bin_names, results, read_attr)
|
31
27
|
super(node)
|
@@ -42,8 +38,8 @@ module Aerospike
|
|
42
38
|
field_count_row = 1
|
43
39
|
field_count = 1
|
44
40
|
|
45
|
-
|
46
|
-
field_count += 1 if
|
41
|
+
exp_size = estimate_expression_size(@policy.filter_exp)
|
42
|
+
field_count += 1 if exp_size > 0
|
47
43
|
|
48
44
|
if bin_names
|
49
45
|
bin_names.each do |bin_name|
|
@@ -58,7 +54,7 @@ module Aerospike
|
|
58
54
|
batch.keys.each do |key|
|
59
55
|
@data_offset += key.digest.length + 4 # 4 byte batch offset
|
60
56
|
|
61
|
-
if prev
|
57
|
+
if !prev.nil? && prev.namespace == key.namespace
|
62
58
|
@data_offset += 1
|
63
59
|
else
|
64
60
|
@data_offset += key.namespace.bytesize + FIELD_HEADER_SIZE + 1 + 1 + 2 + 2 # repeat/no-repeat flag + read_attr flags + field_count + operation_count
|
@@ -66,9 +62,9 @@ module Aerospike
|
|
66
62
|
end
|
67
63
|
end
|
68
64
|
size_buffer
|
69
|
-
|
65
|
+
write_header_read(policy, read_attr | INFO1_BATCH, 0, field_count, 0)
|
70
66
|
|
71
|
-
|
67
|
+
write_filter_exp(@policy.filter_exp, exp_size)
|
72
68
|
|
73
69
|
write_field_header(0, Aerospike::FieldType::BATCH_INDEX)
|
74
70
|
@data_offset += @data_buffer.write_int32(batch.keys.length, @data_offset)
|
@@ -80,7 +76,7 @@ module Aerospike
|
|
80
76
|
@data_offset += @data_buffer.write_int32(index, @data_offset)
|
81
77
|
@data_offset += @data_buffer.write_binary(key.digest, @data_offset)
|
82
78
|
|
83
|
-
if
|
79
|
+
if !prev.nil? && prev.namespace == key.namespace
|
84
80
|
@data_offset += @data_buffer.write_byte(1, @data_offset)
|
85
81
|
else
|
86
82
|
@data_offset += @data_buffer.write_byte(0, @data_offset)
|
@@ -19,13 +19,12 @@ module Aerospike
|
|
19
19
|
|
20
20
|
class BatchIndexNode #:nodoc:
|
21
21
|
|
22
|
-
attr_accessor :node
|
23
|
-
attr_accessor :keys_by_idx
|
22
|
+
attr_accessor :node, :keys_by_idx
|
24
23
|
|
25
24
|
def self.generate_list(cluster, replica_policy, keys)
|
26
25
|
keys.each_with_index
|
27
|
-
|
28
|
-
|
26
|
+
.group_by { |key, _| cluster.get_node_for_key(replica_policy, key) }
|
27
|
+
.map { |node, keys_with_idx| BatchIndexNode.new(node, keys_with_idx) }
|
29
28
|
end
|
30
29
|
|
31
30
|
def initialize(node, keys_with_idx)
|
@@ -0,0 +1,151 @@
|
|
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 BatchOperateCommand < MultiCommand #:nodoc:
|
23
|
+
|
24
|
+
attr_accessor :batch, :policy, :attr, :records
|
25
|
+
|
26
|
+
def initialize(node, batch, policy, records)
|
27
|
+
super(node)
|
28
|
+
@batch = batch
|
29
|
+
@policy = policy
|
30
|
+
@records = records
|
31
|
+
end
|
32
|
+
|
33
|
+
def batch_flags
|
34
|
+
flags = 0
|
35
|
+
# flags |= 0x1 if @policy.allow_inline
|
36
|
+
flags |= 0x2 if @policy.allow_inline_ssd
|
37
|
+
flags |= 0x4 if @policy.respond_all_keys
|
38
|
+
flags
|
39
|
+
end
|
40
|
+
|
41
|
+
def write_buffer
|
42
|
+
field_count = 1
|
43
|
+
|
44
|
+
exp_size = estimate_expression_size(@policy.filter_exp)
|
45
|
+
@data_offset += exp_size
|
46
|
+
field_count += 1 if exp_size > 0
|
47
|
+
|
48
|
+
@data_buffer.reset
|
49
|
+
begin_cmd
|
50
|
+
@data_offset += FIELD_HEADER_SIZE + 4 + 1 # batch.keys.length + flags
|
51
|
+
|
52
|
+
prev = nil
|
53
|
+
@records.each do |record|
|
54
|
+
key = record.key
|
55
|
+
@data_offset += key.digest.length + 4 # 4 byte batch offset
|
56
|
+
|
57
|
+
if !@policy.send_key && !prev.nil? && prev.key.namespace == key.namespace && prev.key.set_name == key.set_name && record == prev
|
58
|
+
@data_offset += 1
|
59
|
+
else
|
60
|
+
@data_offset += 12
|
61
|
+
@data_offset += key.namespace.bytesize + FIELD_HEADER_SIZE
|
62
|
+
@data_offset += key.set_name.bytesize + FIELD_HEADER_SIZE
|
63
|
+
@data_offset += record.size
|
64
|
+
end
|
65
|
+
|
66
|
+
prev = record
|
67
|
+
end
|
68
|
+
size_buffer
|
69
|
+
write_batch_header(policy, field_count)
|
70
|
+
|
71
|
+
write_filter_exp(@policy.filter_exp, exp_size)
|
72
|
+
|
73
|
+
field_size_offset = @data_offset
|
74
|
+
|
75
|
+
write_field_header(0, Aerospike::FieldType::BATCH_INDEX)
|
76
|
+
@data_offset += @data_buffer.write_int32(batch.records.length, @data_offset)
|
77
|
+
@data_offset += @data_buffer.write_byte(batch_flags, @data_offset)
|
78
|
+
|
79
|
+
prev = nil
|
80
|
+
attr = BatchAttr.new
|
81
|
+
batch.records.each_with_index do |record, index|
|
82
|
+
@data_offset += @data_buffer.write_int32(index, @data_offset)
|
83
|
+
key = record.key
|
84
|
+
@data_offset += @data_buffer.write_binary(key.digest, @data_offset)
|
85
|
+
|
86
|
+
if !@policy.send_key && !prev.nil? && prev.key.namespace == key.namespace && prev.key.set_name == key.set_name && record == prev
|
87
|
+
@data_offset += @data_buffer.write_byte(BATCH_MSG_REPEAT, @data_offset)
|
88
|
+
else
|
89
|
+
case record
|
90
|
+
when BatchRead
|
91
|
+
attr.set_batch_read(record.policy)
|
92
|
+
if record.bin_names&.length&.> 0
|
93
|
+
write_batch_bin_names(key, record.bin_names, attr, attr.filter_exp)
|
94
|
+
elsif record.ops&.length&.> 0
|
95
|
+
attr.adjust_read(br.ops)
|
96
|
+
write_batch_operations(key, record.ops, attr, attr.filter_exp)
|
97
|
+
else
|
98
|
+
attr.adjust_read_all_bins(record.read_all_bins)
|
99
|
+
write_batch_read(key, attr, attr.filter_exp, 0)
|
100
|
+
end
|
101
|
+
|
102
|
+
when BatchWrite
|
103
|
+
attr.set_batch_write(record.policy)
|
104
|
+
attr.adjust_write(record.ops)
|
105
|
+
write_batch_operations(key, record.ops, attr, attr.filter_exp)
|
106
|
+
|
107
|
+
when BatchUDF
|
108
|
+
attr.set_batch_udf(record.policy)
|
109
|
+
write_batch_write(key, attr, attr.filter_exp, 3, 0)
|
110
|
+
write_field_string(record.package_name, Aerospike::FieldType::UDF_PACKAGE_NAME)
|
111
|
+
write_field_string(record.function_name, Aerospike::FieldType::UDF_FUNCTION)
|
112
|
+
write_field_bytes(record.arg_bytes, Aerospike::FieldType::UDF_ARGLIST)
|
113
|
+
|
114
|
+
when BatchDelete
|
115
|
+
attr.set_batch_delete(record.policy)
|
116
|
+
write_batch_write(key, attr, attr.filter_exp, 0, 0)
|
117
|
+
end
|
118
|
+
|
119
|
+
prev = record
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
@data_buffer.write_uint32(@data_offset-MSG_TOTAL_HEADER_SIZE-4, field_size_offset)
|
124
|
+
|
125
|
+
end_cmd
|
126
|
+
mark_compressed(@policy)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Parse all results in the batch. Add records to shared list.
|
130
|
+
# If the record was not found, the bins will be nil.
|
131
|
+
def parse_row(result_code)
|
132
|
+
generation = @data_buffer.read_int32(6)
|
133
|
+
expiration = @data_buffer.read_int32(10)
|
134
|
+
batch_index = @data_buffer.read_int32(14)
|
135
|
+
field_count = @data_buffer.read_int16(18)
|
136
|
+
op_count = @data_buffer.read_int16(20)
|
137
|
+
|
138
|
+
skip_key(field_count)
|
139
|
+
req_key = records[batch_index].key
|
140
|
+
|
141
|
+
records[batch_index].result_code = result_code
|
142
|
+
case result_code
|
143
|
+
when 0, ResultCode::UDF_BAD_RESPONSE
|
144
|
+
record = parse_record(req_key, op_count, generation, expiration)
|
145
|
+
records[batch_index].record = record
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
end # class
|
150
|
+
|
151
|
+
end # module
|
@@ -0,0 +1,51 @@
|
|
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
|
+
module Aerospike
|
19
|
+
|
20
|
+
class BatchOperateNode #:nodoc:
|
21
|
+
|
22
|
+
attr_accessor :node, :records_by_idx
|
23
|
+
|
24
|
+
def self.generate_list(cluster, replica_policy, records)
|
25
|
+
records.each_with_index
|
26
|
+
.group_by { |record, _| cluster.get_node_for_key(replica_policy, record.key, is_write: record.has_write) }
|
27
|
+
.map { |node, records_with_idx| BatchOperateNode.new(node, records_with_idx) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(node, records_with_idx)
|
31
|
+
@node = node
|
32
|
+
@records_by_idx = records_with_idx.map(&:reverse).to_h
|
33
|
+
end
|
34
|
+
|
35
|
+
def records
|
36
|
+
records_by_idx.values
|
37
|
+
end
|
38
|
+
|
39
|
+
def each_record_with_index
|
40
|
+
records_by_idx.each do |idx, rec|
|
41
|
+
yield rec, idx
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def record_for_index(idx)
|
46
|
+
@records_by_idx[idx]
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|