aerospike 3.0.0 → 4.0.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 +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)
|