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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/README.md +13 -9
  4. data/lib/aerospike/batch_attr.rb +292 -0
  5. data/lib/aerospike/batch_delete.rb +48 -0
  6. data/lib/aerospike/batch_read.rb +97 -0
  7. data/lib/aerospike/batch_record.rb +83 -0
  8. data/lib/aerospike/batch_results.rb +38 -0
  9. data/lib/aerospike/batch_udf.rb +76 -0
  10. data/lib/aerospike/batch_write.rb +79 -0
  11. data/lib/aerospike/cdt/bit_operation.rb +4 -5
  12. data/lib/aerospike/cdt/map_return_type.rb +8 -0
  13. data/lib/aerospike/client.rb +37 -51
  14. data/lib/aerospike/cluster.rb +50 -46
  15. data/lib/aerospike/command/batch_index_command.rb +6 -10
  16. data/lib/aerospike/command/batch_index_node.rb +3 -4
  17. data/lib/aerospike/command/batch_operate_command.rb +151 -0
  18. data/lib/aerospike/command/batch_operate_node.rb +51 -0
  19. data/lib/aerospike/command/command.rb +101 -87
  20. data/lib/aerospike/command/single_command.rb +1 -1
  21. data/lib/aerospike/exp/exp.rb +39 -41
  22. data/lib/aerospike/exp/exp_bit.rb +24 -24
  23. data/lib/aerospike/exp/exp_hll.rb +12 -12
  24. data/lib/aerospike/exp/exp_list.rb +101 -92
  25. data/lib/aerospike/exp/exp_map.rb +118 -121
  26. data/lib/aerospike/exp/operation.rb +2 -2
  27. data/lib/aerospike/info.rb +2 -4
  28. data/lib/aerospike/node.rb +7 -3
  29. data/lib/aerospike/operation.rb +38 -0
  30. data/lib/aerospike/policy/batch_delete_policy.rb +71 -0
  31. data/lib/aerospike/policy/batch_policy.rb +53 -4
  32. data/lib/aerospike/{command/batch_direct_node.rb → policy/batch_read_policy.rb} +17 -19
  33. data/lib/aerospike/policy/batch_udf_policy.rb +75 -0
  34. data/lib/aerospike/policy/batch_write_policy.rb +105 -0
  35. data/lib/aerospike/policy/policy.rb +3 -40
  36. data/lib/aerospike/query/server_command.rb +1 -0
  37. data/lib/aerospike/query/statement.rb +5 -21
  38. data/lib/aerospike/utils/buffer.rb +15 -15
  39. data/lib/aerospike/version.rb +1 -1
  40. data/lib/aerospike.rb +13 -12
  41. metadata +16 -14
  42. data/lib/aerospike/command/batch_direct_command.rb +0 -105
  43. data/lib/aerospike/command/batch_direct_exists_command.rb +0 -51
  44. data/lib/aerospike/query/pred_exp/and_or.rb +0 -32
  45. data/lib/aerospike/query/pred_exp/geo_json_value.rb +0 -41
  46. data/lib/aerospike/query/pred_exp/integer_value.rb +0 -32
  47. data/lib/aerospike/query/pred_exp/op.rb +0 -27
  48. data/lib/aerospike/query/pred_exp/regex.rb +0 -32
  49. data/lib/aerospike/query/pred_exp/regex_flags.rb +0 -23
  50. data/lib/aerospike/query/pred_exp/string_value.rb +0 -29
  51. 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 {@link BitResizeFlags}).
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, {@link BitOverflowAction} is used.
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, {@link BitOverflowAction} is used.
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 @ctx != nil && @ctx.length > 0
353
+ if !@ctx.nil? && @ctx.length > 0
355
354
  packer.write_array_header(3)
356
355
  Value.of(0xff).pack(packer)
357
356
 
@@ -69,6 +69,14 @@ module Aerospike
69
69
  # Return true if count > 0.
70
70
  EXISTS = 13
71
71
 
72
+ ##
73
+ # Return an unordered map.
74
+ UNORDERED_MAP = 16
75
+
76
+ ##
77
+ # Return an ordered map.
78
+ ORDERED_MAP = 17
79
+
72
80
  ##
73
81
  # :private
74
82
  #
@@ -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
- str_cmd = "truncate-namespace:namespace=#{namespace}"
235
- else
236
- str_cmd = "truncate:namespace=#{namespace}"
237
- end
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
- if policy.use_batch_direct
333
- key_map = BatchItem.generate_map(keys)
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
- if policy.use_batch_direct
362
- key_map = BatchItem.generate_map(keys)
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["error"]}\nFile: #{res["file"]}\nLine: #{res["line"]}\nMessage: #{res["message"]}")
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, collection_type = collection_type, nil
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
- fail TypeError, "policy should be a #{policy_klass.name} instance or a Hash"
940
+ raise TypeError, "policy should be a #{policy_klass.name} instance or a Hash"
947
941
  end
948
942
  end
949
943
 
950
- def cluster=(cluster)
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 execute_batch_direct_commands(policy, keys)
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 Direct command failed because cluster is empty.")
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 = BatchDirectNode.generate_list(@cluster, policy.replica, keys)
999
+ batch_nodes = BatchOperateNode.generate_list(@cluster, policy.replica, records)
1008
1000
  threads = []
1009
1001
 
1010
- # Use a thread per namespace per node
1011
- batch_nodes.each do |batch_node|
1012
- # copy to avoid race condition
1013
- bn = batch_node
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
 
@@ -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
- when Aerospike::Replica::MASTER, Aerospike::Replica::SEQUENCE
124
- return master_node(partition)
125
- when Aerospike::Replica::MASTER_PROLES
126
- return master_proles_node(partition)
127
- when Aerospike::Replica::PREFER_RACK
128
- return rack_node(partition, seq)
129
- when Aerospike::Replica::RANDOM
130
- return random_node
131
- else
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
- when Aerospike::Replica::MASTER
140
- return master_node(partition)
141
- when Aerospike::Replica::MASTER_PROLES
142
- return master_proles_node(partition)
143
- when Aerospike::Replica::PREFER_RACK
144
- return rack_node(partition, seq)
145
- when Aerospike::Replica::SEQUENCE
146
- return sequence_node(partition, seq)
147
- when Aerospike::Replica::RANDOM
148
- return random_node
149
- else
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") if !replica_array
158
+ raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless replica_array
159
159
 
160
- node_array = (replica_array.get)[0]
161
- raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") if !node_array
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 = (node_array.get)[partition.partition_id]
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") if !replica_array
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 = (replica_array[idx].get)[partition.partition_id]
182
+ idx = (seq.update { |v| v.succ } % replica_array.size).abs
183
+ node = replica_array[idx].get[partition.partition_id]
184
184
 
185
- next if !node
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") if !replica_array
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 = (replica_array[idx].get)[partition.partition_id]
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") if !replica_array
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 = (replica_array[idx].get)[partition.partition_id]
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
- batch_read_node(partition, replica_policy)
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") if !replica_array
254
+ raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless replica_array
251
255
 
252
- node_array = (replica_array.get)[0]
253
- raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") if !node_array
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
- begin
373
+
370
374
  tend
371
375
  sleep(@tend_interval / 1000.0)
372
- rescue => e
376
+ rescue => e
373
377
  Aerospike.logger.error("Exception occured during tend: #{e}")
374
378
  Aerospike.logger.debug { e.backtrace.join("\n") }
375
- end
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 ? "node has" : "nodes have"} #{diff > 0 ? "joined" : "left"} the cluster."
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
- predexp_size = estimate_predexp(@policy.predexp)
46
- field_count += 1 if predexp_size > 0
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 != nil && prev.namespace == key.namespace
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
- write_predexp(@policy.predexp, predexp_size)
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 (prev != nil && prev.namespace == key.namespace)
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
- .group_by { |key, _| cluster.get_node_for_key(replica_policy, key) }
28
- .map { |node, keys_with_idx| BatchIndexNode.new(node, keys_with_idx) }
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)