aerospike 3.0.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 +21 -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_return_type.rb +8 -0
- data/lib/aerospike/client.rb +37 -51
- data/lib/aerospike/cluster.rb +50 -46
- data/lib/aerospike/command/batch_index_command.rb +6 -10
- 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 +101 -87
- data/lib/aerospike/command/single_command.rb +1 -1
- data/lib/aerospike/exp/exp.rb +39 -41
- 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 -92
- data/lib/aerospike/exp/exp_map.rb +118 -121
- data/lib/aerospike/exp/operation.rb +2 -2
- data/lib/aerospike/info.rb +2 -4
- data/lib/aerospike/node.rb +7 -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/server_command.rb +1 -0
- data/lib/aerospike/query/statement.rb +5 -21
- 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
@@ -0,0 +1,76 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Copyright 2014-2024 Aerospike, Inc.
|
3
|
+
#
|
4
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
5
|
+
# license agreements.
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License") you may not
|
8
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
9
|
+
# the License at http:#www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
13
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
14
|
+
# License for the specific language governing permissions and limitations under
|
15
|
+
# the License.
|
16
|
+
|
17
|
+
# Batch key and read only operations with default policy.
|
18
|
+
# Used in batch read commands where different bins are needed for each key.
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
|
22
|
+
# Batch user defined functions.
|
23
|
+
class BatchUDF < BatchRecord
|
24
|
+
|
25
|
+
# Optional UDF policy.
|
26
|
+
attr_accessor :policy
|
27
|
+
|
28
|
+
# Package or lua module name.
|
29
|
+
attr_accessor :package_name
|
30
|
+
|
31
|
+
# Lua function name.
|
32
|
+
attr_accessor :function_name
|
33
|
+
|
34
|
+
# Optional arguments to lua function.
|
35
|
+
attr_accessor :function_args
|
36
|
+
|
37
|
+
# Wire protocol bytes for function args. For internal use only.
|
38
|
+
attr_reader :arg_bytes
|
39
|
+
|
40
|
+
# Constructor using default policy.
|
41
|
+
def initialize(key, package_name, function_name, function_args, opt = {})
|
42
|
+
super(key, has_write: true)
|
43
|
+
@policy = BatchRecord.create_policy(opt, BatchUDFPolicy, DEFAULT_BATCH_UDF_POLICY)
|
44
|
+
@package_name = package_name
|
45
|
+
@function_name = function_name
|
46
|
+
@function_args = ListValue.new(function_args)
|
47
|
+
# Do not set arg_bytes here because may not be necessary if batch repeat flag is used.
|
48
|
+
end
|
49
|
+
|
50
|
+
# Optimized reference equality check to determine batch wire protocol repeat flag.
|
51
|
+
# For internal use only.
|
52
|
+
def ==(other) # :nodoc:
|
53
|
+
other && other.instance_of?(self.class) &&
|
54
|
+
@function_name == other.function_name && @function_args == other.function_args &&
|
55
|
+
@package_name == other.package_name && @policy == other.policy
|
56
|
+
end
|
57
|
+
|
58
|
+
DEFAULT_BATCH_UDF_POLICY = BatchUDFPolicy.new
|
59
|
+
|
60
|
+
# Return wire protocol size. For internal use only.
|
61
|
+
def size # :nodoc:
|
62
|
+
size = 6 # gen(2) + exp(4) = 6
|
63
|
+
|
64
|
+
size += @policy&.filter_exp&.size if @policy&.filter_exp
|
65
|
+
|
66
|
+
if @policy&.send_key
|
67
|
+
size += @key.user_key.estimate_size + Aerospike::FIELD_HEADER_SIZE + 1
|
68
|
+
end
|
69
|
+
size += @package_name.bytesize + Aerospike::FIELD_HEADER_SIZE
|
70
|
+
size += @function_name.bytesize + Aerospike::FIELD_HEADER_SIZE
|
71
|
+
@arg_bytes = @function_args.to_bytes
|
72
|
+
size += @arg_bytes.bytesize + Aerospike::FIELD_HEADER_SIZE
|
73
|
+
size
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Copyright 2014-2024 Aerospike, Inc.
|
3
|
+
#
|
4
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
5
|
+
# license agreements.
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License") you may not
|
8
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
9
|
+
# the License at http:#www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
13
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
14
|
+
# License for the specific language governing permissions and limitations under
|
15
|
+
# the License.
|
16
|
+
|
17
|
+
# Batch key and read only operations with default policy.
|
18
|
+
# Used in batch read commands where different bins are needed for each key.
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# Batch key and read/write operations with write policy.
|
25
|
+
class BatchWrite < BatchRecord
|
26
|
+
# Optional write policy.
|
27
|
+
attr_accessor :policy
|
28
|
+
|
29
|
+
# Required operations for this key.
|
30
|
+
attr_accessor :ops
|
31
|
+
|
32
|
+
# Initialize batch key and read/write operations.
|
33
|
+
#
|
34
|
+
# {Operation#get()} is not allowed because it returns a variable number of bins and
|
35
|
+
# makes it difficult (sometimes impossible) to lineup operations with results. Instead,
|
36
|
+
# use {Operation#get(bin_name)} for each bin name.
|
37
|
+
def initialize(key, ops, opt = {})
|
38
|
+
super(key, has_write: true)
|
39
|
+
@policy = BatchRecord.create_policy(opt, BatchWritePolicy, DEFAULT_BATCH_WRITE_POLICY)
|
40
|
+
@ops = ops
|
41
|
+
end
|
42
|
+
|
43
|
+
# Optimized reference equality check to determine batch wire protocol repeat flag.
|
44
|
+
# For internal use only.
|
45
|
+
def ==(other) # :nodoc:
|
46
|
+
other && other.instance_of?(self.class) &&
|
47
|
+
@ops == other.ops && @policy == other.policy && (@policy.nil? || !@policy.send_key)
|
48
|
+
end
|
49
|
+
|
50
|
+
DEFAULT_BATCH_WRITE_POLICY = BatchWritePolicy.new
|
51
|
+
|
52
|
+
# Return wire protocol size. For internal use only.
|
53
|
+
def size # :nodoc:
|
54
|
+
size = 6 # gen(2) + exp(4) = 6
|
55
|
+
|
56
|
+
size += @policy&.filter_exp&.size if @policy&.filter_exp
|
57
|
+
|
58
|
+
if @policy&.send_key
|
59
|
+
size += @key.user_key.estimate_size + Aerospike::FIELD_HEADER_SIZE + 1
|
60
|
+
end
|
61
|
+
|
62
|
+
has_write = false
|
63
|
+
@ops&.each do |op|
|
64
|
+
if op.is_write?
|
65
|
+
has_write = true
|
66
|
+
end
|
67
|
+
|
68
|
+
size += op.bin_name.bytesize + Aerospike::OPERATION_HEADER_SIZE if op.bin_name
|
69
|
+
size += op.bin_value.estimate_size if op.bin_value
|
70
|
+
end
|
71
|
+
|
72
|
+
unless has_write
|
73
|
+
raise AerospikeException.new(ResultCode::PARAMETER_ERROR, "Batch write operations do not contain a write")
|
74
|
+
end
|
75
|
+
|
76
|
+
size
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -65,9 +65,8 @@ module Aerospike
|
|
65
65
|
@arguments = arguments
|
66
66
|
end
|
67
67
|
|
68
|
-
|
69
68
|
# BitResizeOp creates byte "resize" operation.
|
70
|
-
# Server resizes byte[] to byte_size according to resize_flags (See {
|
69
|
+
# Server resizes byte[] to byte_size according to resize_flags (See {BitResizeFlags}).
|
71
70
|
# Server does not return a value.
|
72
71
|
# Example:
|
73
72
|
# bin = [0b00000001, 0b01000010]
|
@@ -195,7 +194,7 @@ module Aerospike
|
|
195
194
|
# BitAddOp creates bit "add" operation.
|
196
195
|
# Server adds value to byte[] bin starting at bit_offset for bit_size. Bit_size must be <= 64.
|
197
196
|
# Signed indicates if bits should be treated as a signed number.
|
198
|
-
# If add overflows/underflows, {
|
197
|
+
# If add overflows/underflows, {BitOverflowAction} is used.
|
199
198
|
# Server does not return a value.
|
200
199
|
# Example:
|
201
200
|
# bin = [0b00000001, 0b01000010, 0b00000011, 0b00000100, 0b00000101]
|
@@ -223,7 +222,7 @@ module Aerospike
|
|
223
222
|
# BitSubtractOp creates bit "subtract" operation.
|
224
223
|
# Server subtracts value from byte[] bin starting at bit_offset for bit_size. Bit_size must be <= 64.
|
225
224
|
# Signed indicates if bits should be treated as a signed number.
|
226
|
-
# If add overflows/underflows, {
|
225
|
+
# If add overflows/underflows, {BitOverflowAction} is used.
|
227
226
|
# Server does not return a value.
|
228
227
|
# Example:
|
229
228
|
# bin = [0b00000001, 0b01000010, 0b00000011, 0b00000100, 0b00000101]
|
@@ -351,7 +350,7 @@ module Aerospike
|
|
351
350
|
bytes = nil
|
352
351
|
args = arguments.dup
|
353
352
|
Packer.use do |packer|
|
354
|
-
if
|
353
|
+
if !@ctx.nil? && @ctx.length > 0
|
355
354
|
packer.write_array_header(3)
|
356
355
|
Value.of(0xff).pack(packer)
|
357
356
|
|
data/lib/aerospike/client.rb
CHANGED
@@ -36,15 +36,7 @@ module Aerospike
|
|
36
36
|
# +:fail_if_not_connected+ set to true
|
37
37
|
|
38
38
|
class Client
|
39
|
-
attr_accessor :default_admin_policy
|
40
|
-
attr_accessor :default_batch_policy
|
41
|
-
attr_accessor :default_info_policy
|
42
|
-
attr_accessor :default_query_policy
|
43
|
-
attr_accessor :default_read_policy
|
44
|
-
attr_accessor :default_scan_policy
|
45
|
-
attr_accessor :default_write_policy
|
46
|
-
attr_accessor :default_operate_policy
|
47
|
-
attr_accessor :cluster
|
39
|
+
attr_accessor :default_admin_policy, :default_batch_policy, :default_info_policy, :default_query_policy, :default_read_policy, :default_scan_policy, :default_write_policy, :default_operate_policy, :cluster
|
48
40
|
|
49
41
|
def initialize(hosts = nil, policy: ClientPolicy.new, connect: true)
|
50
42
|
hosts = ::Aerospike::Host::Parse.(hosts || ENV["AEROSPIKE_HOSTS"] || "localhost")
|
@@ -230,11 +222,11 @@ module Aerospike
|
|
230
222
|
str_cmd = "truncate:namespace=#{namespace}"
|
231
223
|
str_cmd << ";set=#{set_name}" unless set_name.to_s.strip.empty?
|
232
224
|
else
|
233
|
-
if node.supports_feature?(Aerospike::Features::TRUNCATE_NAMESPACE)
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
225
|
+
str_cmd = if node.supports_feature?(Aerospike::Features::TRUNCATE_NAMESPACE)
|
226
|
+
"truncate-namespace:namespace=#{namespace}"
|
227
|
+
else
|
228
|
+
"truncate:namespace=#{namespace}"
|
229
|
+
end
|
238
230
|
end
|
239
231
|
|
240
232
|
if before_last_update
|
@@ -329,15 +321,8 @@ module Aerospike
|
|
329
321
|
bin_names = nil
|
330
322
|
end
|
331
323
|
|
332
|
-
|
333
|
-
|
334
|
-
execute_batch_direct_commands(policy, keys) do |node, batch|
|
335
|
-
BatchDirectCommand.new(node, batch, policy, key_map, bin_names, results, info_flags)
|
336
|
-
end
|
337
|
-
else
|
338
|
-
execute_batch_index_commands(policy, keys) do |node, batch|
|
339
|
-
BatchIndexCommand.new(node, batch, policy, bin_names, results, info_flags)
|
340
|
-
end
|
324
|
+
execute_batch_index_commands(policy, keys) do |node, batch|
|
325
|
+
BatchIndexCommand.new(node, batch, policy, bin_names, results, info_flags)
|
341
326
|
end
|
342
327
|
|
343
328
|
results
|
@@ -351,6 +336,21 @@ module Aerospike
|
|
351
336
|
batch_get(keys, :none, options)
|
352
337
|
end
|
353
338
|
|
339
|
+
# Operate on multiple records for specified batch keys in one batch call.
|
340
|
+
# This method allows different namespaces/bins for each key in the batch.
|
341
|
+
# The returned records are located in the same list.
|
342
|
+
#
|
343
|
+
# records can be BatchRead, BatchWrite, BatchDelete or BatchUDF.
|
344
|
+
#
|
345
|
+
# Requires server version 6.0+
|
346
|
+
def batch_operate(records, options = nil)
|
347
|
+
policy = create_policy(options, BatchPolicy, default_batch_policy)
|
348
|
+
|
349
|
+
execute_batch_operate_commands(policy, records) do |node, batch|
|
350
|
+
BatchOperateCommand.new(node, batch, policy, records)
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
354
|
# Check if multiple record keys exist in one batch call.
|
355
355
|
# The returned boolean array is in positional order with the original key array order.
|
356
356
|
# The policy can be used to specify timeouts and protocol type.
|
@@ -358,15 +358,8 @@ module Aerospike
|
|
358
358
|
policy = create_policy(options, BatchPolicy, default_batch_policy)
|
359
359
|
results = Array.new(keys.length)
|
360
360
|
|
361
|
-
|
362
|
-
|
363
|
-
execute_batch_direct_commands(policy, keys) do |node, batch|
|
364
|
-
BatchDirectExistsCommand.new(node, batch, policy, key_map, results)
|
365
|
-
end
|
366
|
-
else
|
367
|
-
execute_batch_index_commands(policy, keys) do |node, batch|
|
368
|
-
BatchIndexExistsCommand.new(node, batch, policy, results)
|
369
|
-
end
|
361
|
+
execute_batch_index_commands(policy, keys) do |node, batch|
|
362
|
+
BatchIndexExistsCommand.new(node, batch, policy, results)
|
370
363
|
end
|
371
364
|
|
372
365
|
results
|
@@ -430,7 +423,7 @@ module Aerospike
|
|
430
423
|
end
|
431
424
|
|
432
425
|
if res["error"]
|
433
|
-
raise Aerospike::Exceptions::CommandRejected.new("Registration failed: #{res[
|
426
|
+
raise Aerospike::Exceptions::CommandRejected.new("Registration failed: #{res['error']}\nFile: #{res['file']}\nLine: #{res['line']}\nMessage: #{res['message']}")
|
434
427
|
end
|
435
428
|
|
436
429
|
UdfRegisterTask.new(@cluster, server_path)
|
@@ -566,7 +559,8 @@ module Aerospike
|
|
566
559
|
# ctx is an optional list of context. Supported on server v6.1+.
|
567
560
|
def create_index(namespace, set_name, index_name, bin_name, index_type, collection_type = nil, options = nil, ctx: nil)
|
568
561
|
if options.nil? && collection_type.is_a?(Hash)
|
569
|
-
options
|
562
|
+
options = collection_type
|
563
|
+
collection_type = nil
|
570
564
|
end
|
571
565
|
policy = create_policy(options, Policy, default_info_policy)
|
572
566
|
|
@@ -943,13 +937,11 @@ module Aerospike
|
|
943
937
|
when Hash
|
944
938
|
policy_klass.new(policy)
|
945
939
|
else
|
946
|
-
|
940
|
+
raise TypeError, "policy should be a #{policy_klass.name} instance or a Hash"
|
947
941
|
end
|
948
942
|
end
|
949
943
|
|
950
|
-
|
951
|
-
@cluster = cluster
|
952
|
-
end
|
944
|
+
attr_writer :cluster
|
953
945
|
|
954
946
|
def cluster_config_changed(cluster)
|
955
947
|
Aerospike.logger.debug { "Cluster config change detected; active nodes: #{cluster.nodes.map(&:name)}" }
|
@@ -999,24 +991,18 @@ module Aerospike
|
|
999
991
|
threads.each(&:join)
|
1000
992
|
end
|
1001
993
|
|
1002
|
-
def
|
994
|
+
def execute_batch_operate_commands(policy, records)
|
1003
995
|
if @cluster.nodes.empty?
|
1004
|
-
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_NOT_AVAILABLE, "Executing Batch
|
996
|
+
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_NOT_AVAILABLE, "Executing Batch Index command failed because cluster is empty.")
|
1005
997
|
end
|
1006
998
|
|
1007
|
-
batch_nodes =
|
999
|
+
batch_nodes = BatchOperateNode.generate_list(@cluster, policy.replica, records)
|
1008
1000
|
threads = []
|
1009
1001
|
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
bn.batch_namespaces.each do |batch|
|
1015
|
-
threads << Thread.new do
|
1016
|
-
Thread.current.abort_on_exception = true
|
1017
|
-
command = yield batch_node.node, batch
|
1018
|
-
execute_command(command)
|
1019
|
-
end
|
1002
|
+
batch_nodes.each do |batch|
|
1003
|
+
threads << Thread.new do
|
1004
|
+
command = yield batch.node, batch
|
1005
|
+
execute_command(command)
|
1020
1006
|
end
|
1021
1007
|
end
|
1022
1008
|
|
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
|
@@ -68,7 +64,7 @@ module Aerospike
|
|
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)
|