aerospike 2.22.0 → 2.23.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -1
  3. data/lib/aerospike/atomic/atomic.rb +1 -1
  4. data/lib/aerospike/cdt/context.rb +7 -7
  5. data/lib/aerospike/cdt/list_return_type.rb +4 -0
  6. data/lib/aerospike/cdt/map_operation.rb +6 -6
  7. data/lib/aerospike/cdt/map_return_type.rb +4 -0
  8. data/lib/aerospike/client.rb +34 -59
  9. data/lib/aerospike/command/admin_command.rb +1 -1
  10. data/lib/aerospike/command/batch_index_node.rb +1 -1
  11. data/lib/aerospike/command/batch_item.rb +1 -1
  12. data/lib/aerospike/command/command.rb +62 -24
  13. data/lib/aerospike/command/field_type.rb +3 -0
  14. data/lib/aerospike/command/login_command.rb +4 -4
  15. data/lib/aerospike/command/multi_command.rb +8 -2
  16. data/lib/aerospike/command/read_command.rb +2 -2
  17. data/lib/aerospike/connection/authenticate.rb +3 -3
  18. data/lib/aerospike/features.rb +9 -9
  19. data/lib/aerospike/host/parse.rb +2 -2
  20. data/lib/aerospike/key.rb +10 -1
  21. data/lib/aerospike/node/refresh/info.rb +1 -1
  22. data/lib/aerospike/node/verify/name.rb +1 -1
  23. data/lib/aerospike/node/verify/partition_generation.rb +1 -1
  24. data/lib/aerospike/node/verify/peers_generation.rb +1 -1
  25. data/lib/aerospike/node/verify/rebalance_generation.rb +1 -1
  26. data/lib/aerospike/policy/policy.rb +4 -1
  27. data/lib/aerospike/policy/scan_policy.rb +20 -1
  28. data/lib/aerospike/privilege.rb +1 -1
  29. data/lib/aerospike/query/node_partitions.rb +39 -0
  30. data/lib/aerospike/query/partition_filter.rb +66 -0
  31. data/lib/aerospike/query/partition_status.rb +36 -0
  32. data/lib/aerospike/query/partition_tracker.rb +347 -0
  33. data/lib/aerospike/query/scan_command.rb +3 -3
  34. data/lib/aerospike/query/scan_executor.rb +69 -0
  35. data/lib/aerospike/query/scan_partition_command.rb +49 -0
  36. data/lib/aerospike/query/statement.rb +1 -1
  37. data/lib/aerospike/query/stream_command.rb +14 -1
  38. data/lib/aerospike/result_code.rb +79 -4
  39. data/lib/aerospike/role.rb +2 -2
  40. data/lib/aerospike/task/execute_task.rb +2 -2
  41. data/lib/aerospike/task/index_task.rb +1 -1
  42. data/lib/aerospike/user_role.rb +1 -1
  43. data/lib/aerospike/utils/buffer.rb +6 -0
  44. data/lib/aerospike/utils/pool.rb +1 -1
  45. data/lib/aerospike/value/value.rb +6 -6
  46. data/lib/aerospike/version.rb +1 -1
  47. data/lib/aerospike.rb +6 -0
  48. metadata +11 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ad4dc9000e94d5dc8b3c4404e2b68907ba935c196e4061a843f49ec8ad54378
4
- data.tar.gz: b55b74f657f46946eccd2ea4005075424234c5d12fa5a9bf77416870c2246928
3
+ metadata.gz: ee4d21995440d0ab8667220405ddc187b0f9f411563fd5998d7b0b15b6da2be9
4
+ data.tar.gz: d6e101e2b87b669f7d930b83b19e472d0ddf94ea4e9a1e974425540f273b047a
5
5
  SHA512:
6
- metadata.gz: 37a3fb668569cbe8ff16318847cd99588f7d54afd342f3d45e397bcf2a241d44c7b1f3f5b2cfe6d98978b65d0babf812d6d51bb5051d9cc6a1aef43845e48c65
7
- data.tar.gz: 3c13ca332594f6edc7cafb4eb68aa996afca8d09436053c31f0faf97b3005f011fa97afeb037aa17bc3a0bc9fcb48cfdad22a20639860dada568433055d47d09
6
+ metadata.gz: d2619ef3fa2d999a0b27211f0859b8b3d62b35ea4dd0f64b76fef6606c1f3ef026aa8cc89bffb63af688b0056e4add4ea189ebcc288c07ad05c18e0cc1445470
7
+ data.tar.gz: 3461927918426fcc829a81728938db3e5a61788b7c2d22f674f3f5ca011f7e4f71dc87f4953818dbbaa9d1d9bafbffc115d9238401180f00b560a989438bfb63
data/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [2.23.0] 2022-10-25
6
+
7
+ * **New Features**
8
+ * [CLIENT-1752] Add 'EXISTS' return type for CDT read operations.
9
+ * [CLIENT-1195] Support partition scans.
10
+ * [CLIENT-1238] Support max_records on partition scans.
11
+ * [CLIENT-1940] Lint and Clean up using Rubocop.
12
+
5
13
  ## [2.22.0] 2022-07-14
6
14
 
7
15
  * **Fixes**
@@ -10,7 +18,7 @@ All notable changes to this project will be documented in this file.
10
18
  * [CLIENT-1789] Authentication Retry fails in certain conditions.
11
19
 
12
20
  ## [2.21.1] - 2022-06-21
13
-
21
+
14
22
  This s hotfix release. It is recommended to upgrade your client if you use authentication.
15
23
 
16
24
  * **Bug Fixes**
@@ -48,7 +48,7 @@ module Aerospike
48
48
  @value = value
49
49
  end
50
50
  end
51
- alias_method 'value='.to_sym, :set
51
+ alias_method :value=, :set
52
52
 
53
53
  end # class
54
54
 
@@ -52,7 +52,7 @@ module Aerospike
52
52
  def self.list_index(index)
53
53
  Context.new(0x10, index)
54
54
  end
55
-
55
+
56
56
  ##
57
57
  # Lookup list by rank.
58
58
  # 0 = smallest value
@@ -61,13 +61,13 @@ module Aerospike
61
61
  def self.list_rank(rank)
62
62
  Context.new(0x11, rank)
63
63
  end
64
-
64
+
65
65
  ##
66
66
  # Lookup list by value.
67
67
  def self.list_value(key)
68
68
  Context.new(0x13, key)
69
69
  end
70
-
70
+
71
71
  ##
72
72
  # Lookup map by index offset.
73
73
  # If the index is negative, the resolved index starts backwards from end of list.
@@ -80,7 +80,7 @@ module Aerospike
80
80
  def self.map_index(index)
81
81
  Context.new(0x20, index)
82
82
  end
83
-
83
+
84
84
  ##
85
85
  # Lookup map by rank.
86
86
  # 0 = smallest value
@@ -89,13 +89,13 @@ module Aerospike
89
89
  def self.map_rank(rank)
90
90
  Context.new(0x21, rank)
91
91
  end
92
-
92
+
93
93
  ##
94
94
  # Lookup map by key.
95
95
  def self.map_key(key)
96
96
  Context.new(0x22, key)
97
97
  end
98
-
98
+
99
99
  ##
100
100
  # Create map with given type at map key.
101
101
  def self.map_key_create(key, order)
@@ -106,7 +106,7 @@ module Aerospike
106
106
  # Lookup map by value.
107
107
  def self.map_value(key)
108
108
  Context.new(0x23, key)
109
- end
109
+ end
110
110
 
111
111
  end
112
112
  end
@@ -60,6 +60,10 @@ module Aerospike
60
60
  # Return value for single key read and value list for range read.
61
61
  VALUE = 7
62
62
 
63
+ ##
64
+ # Return true if count > 0.
65
+ EXISTS = 13
66
+
63
67
  ##
64
68
  # :private
65
69
  #
@@ -138,9 +138,7 @@ module Aerospike
138
138
  # The map policy dictates the type of map to create when it does not exist.
139
139
  # The map policy also specifies the flags used when writing items to the map.
140
140
  def self.put(bin_name, key, value, ctx: nil, policy: MapPolicy::DEFAULT)
141
- if policy.flags != MapWriteFlags::DEFAULT
142
- MapOperation.new(Operation::CDT_MODIFY, PUT, bin_name, key, value, policy.order[:attr], policy.flags, ctx: ctx)
143
- else
141
+ if policy.flags == MapWriteFlags::DEFAULT
144
142
  case policy.write_mode
145
143
  when MapWriteMode::UPDATE_ONLY
146
144
  # Replace doesn't allow map order because it does not create on non-existing key.
@@ -150,6 +148,8 @@ module Aerospike
150
148
  else
151
149
  MapOperation.new(Operation::CDT_MODIFY, PUT, bin_name, key, value, policy.order[:attr], ctx: ctx)
152
150
  end
151
+ else
152
+ MapOperation.new(Operation::CDT_MODIFY, PUT, bin_name, key, value, policy.order[:attr], policy.flags, ctx: ctx)
153
153
  end
154
154
  end
155
155
 
@@ -160,9 +160,7 @@ module Aerospike
160
160
  # The map policy dictates the type of map to create when it does not exist.
161
161
  # The map policy also specifies the flags used when writing items to the map.
162
162
  def self.put_items(bin_name, values, ctx: nil, policy: MapPolicy::DEFAULT)
163
- if policy.flags != MapWriteFlags::DEFAULT
164
- MapOperation.new(Operation::CDT_MODIFY, PUT_ITEMS, bin_name, values, policy.order[:attr], policy.flags, ctx: ctx)
165
- else
163
+ if policy.flags == MapWriteFlags::DEFAULT
166
164
  case policy.write_mode
167
165
  when MapWriteMode::UPDATE_ONLY
168
166
  # Replace doesn't allow map order because it does not create on non-existing key.
@@ -172,6 +170,8 @@ module Aerospike
172
170
  else
173
171
  MapOperation.new(Operation::CDT_MODIFY, PUT_ITEMS, bin_name, values, policy.order[:attr], ctx: ctx)
174
172
  end
173
+ else
174
+ MapOperation.new(Operation::CDT_MODIFY, PUT_ITEMS, bin_name, values, policy.order[:attr], policy.flags, ctx: ctx)
175
175
  end
176
176
  end
177
177
 
@@ -65,6 +65,10 @@ module Aerospike
65
65
  # Return key/value items.
66
66
  KEY_VALUE = 8
67
67
 
68
+ ##
69
+ # Return true if count > 0.
70
+ EXISTS = 13
71
+
68
72
  ##
69
73
  # Default return type: NONE
70
74
  DEFAULT_RETURN_TYPE = NONE
@@ -624,13 +624,15 @@ module Aerospike
624
624
  # Scan Operations
625
625
  #-------------------------------------------------------
626
626
 
627
- def scan_all(namespace, set_name, bin_names = nil, options = nil)
627
+ # Reads records in specified namespace and set using partition filter.
628
+ # If the policy's concurrent_nodes is specified, each server node will be read in
629
+ # parallel. Otherwise, server nodes are read sequentially.
630
+ # If partition_filter is nil, all partitions will be scanned.
631
+ # If the policy is nil, the default relevant policy will be used.
632
+ # This method is only supported by Aerospike 4.9+ servers.
633
+ def scan_partitions(partition_filter, namespace, set_name, bin_names = nil, options = nil)
628
634
  policy = create_policy(options, ScanPolicy, default_scan_policy)
629
635
 
630
- # wait until all migrations are finished
631
- # TODO: implement
632
- # @cluster.WaitUntillMigrationIsFinished(policy.timeout)
633
-
634
636
  # Retry policy must be one-shot for scans.
635
637
  # copy on write for policy
636
638
  new_policy = policy.clone
@@ -640,80 +642,53 @@ module Aerospike
640
642
  raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_NOT_AVAILABLE, "Scan failed because cluster is empty.")
641
643
  end
642
644
 
643
- recordset = Recordset.new(policy.record_queue_size, nodes.length, :scan)
644
-
645
- if policy.concurrent_nodes
646
- # Use a thread per node
647
- nodes.each do |node|
648
- partitions = node.cluster.node_partitions(node, namespace)
649
- Thread.new do
650
- Thread.current.abort_on_exception = true
651
- command = ScanCommand.new(node, new_policy, namespace, set_name, bin_names, recordset, partitions)
652
- begin
653
- execute_command(command)
654
- rescue => e
655
- Aerospike.logger.error(e.backtrace.join("\n")) unless e == SCAN_TERMINATED_EXCEPTION
656
- recordset.cancel(e)
657
- ensure
658
- recordset.thread_finished
659
- end
660
- end
661
- end
662
- else
663
- Thread.new do
664
- Thread.current.abort_on_exception = true
665
- nodes.each do |node|
666
- partitions = node.cluster.node_partitions(node, namespace)
667
- command = ScanCommand.new(node, new_policy, namespace, set_name, bin_names, recordset, partitions)
668
- begin
669
- execute_command(command)
670
- rescue => e
671
- Aerospike.logger.error(e.backtrace.join("\n")) unless e == SCAN_TERMINATED_EXCEPTION
672
- recordset.cancel(e)
673
- ensure
674
- recordset.thread_finished
675
- end
676
- end
677
- end
645
+ tracker = Aerospike::PartitionTracker.new(policy, nodes, partition_filter)
646
+ recordset = Recordset.new(policy.record_queue_size, 1, :scan)
647
+ Thread.new do
648
+ Thread.current.abort_on_exception = true
649
+ ScanExecutor.scan_partitions(policy, @cluster, tracker, namespace, set_name, recordset, bin_names)
678
650
  end
679
651
 
680
652
  recordset
681
653
  end
682
654
 
683
- # ScanNode reads all records in specified namespace and set, from one node only.
684
- # The policy can be used to specify timeouts.
685
- def scan_node(node, namespace, set_name, bin_names = nil, options = nil)
655
+ # Reads all records in specified namespace and set for one node only.
656
+ # If the policy is nil, the default relevant policy will be used.
657
+ def scan_node_partitions(node, namespace, set_name, bin_names = nil, options = nil)
686
658
  policy = create_policy(options, ScanPolicy, default_scan_policy)
687
- # wait until all migrations are finished
688
- # TODO: implement
689
- # @cluster.WaitUntillMigrationIsFinished(policy.timeout)
690
659
 
691
660
  # Retry policy must be one-shot for scans.
692
661
  # copy on write for policy
693
662
  new_policy = policy.clone
694
- new_policy.max_retries = 0
695
663
 
696
- node = @cluster.get_node_by_name(node) unless node.is_a?(Aerospike::Node)
664
+ unless node.active?
665
+ raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_NOT_AVAILABLE, "Scan failed because cluster is empty.")
666
+ end
697
667
 
668
+ tracker = Aerospike::PartitionTracker.new(policy, [node])
698
669
  recordset = Recordset.new(policy.record_queue_size, 1, :scan)
699
-
700
- partitions = node.cluster.node_partitions(node, namespace)
701
670
  Thread.new do
702
671
  Thread.current.abort_on_exception = true
703
- command = ScanCommand.new(node, new_policy, namespace, set_name, bin_names, recordset, partitions)
704
- begin
705
- execute_command(command)
706
- rescue => e
707
- Aerospike.logger.error(e.backtrace.join("\n")) unless e == SCAN_TERMINATED_EXCEPTION
708
- recordset.cancel(e)
709
- ensure
710
- recordset.thread_finished
711
- end
672
+ ScanExecutor.scan_partitions(policy, @cluster, tracker, namespace, set_name, recordset, bin_names)
712
673
  end
713
674
 
714
675
  recordset
715
676
  end
716
677
 
678
+ # Reads all records in specified namespace and set from all nodes.
679
+ # If the policy's concurrent_nodes is specified, each server node will be read in
680
+ # parallel. Otherwise, server nodes are read sequentially.
681
+ # If the policy is nil, the default relevant policy will be used.
682
+ def scan_all(namespace, set_name, bin_names = nil, options = nil)
683
+ scan_partitions(Aerospike::PartitionFilter.all, namespace, set_name, bin_names, options)
684
+ end
685
+
686
+ # ScanNode reads all records in specified namespace and set, from one node only.
687
+ # The policy can be used to specify timeouts.
688
+ def scan_node(node, namespace, set_name, bin_names = nil, options = nil)
689
+ scan_node_partitions(node, namespace, set_name, bin_names, options)
690
+ end
691
+
717
692
  #--------------------------------------------------------
718
693
  # Query functions (Supported by Aerospike 3 servers only)
719
694
  #--------------------------------------------------------
@@ -653,7 +653,7 @@ module Aerospike
653
653
  list << s
654
654
  end
655
655
 
656
- list
656
+ list
657
657
  end
658
658
 
659
659
  end
@@ -30,7 +30,7 @@ module Aerospike
30
30
 
31
31
  def initialize(node, keys_with_idx)
32
32
  @node = node
33
- @keys_by_idx = Hash[keys_with_idx.map(&:reverse)]
33
+ @keys_by_idx = keys_with_idx.map(&:reverse).to_h
34
34
  end
35
35
 
36
36
  def keys
@@ -28,7 +28,7 @@ module Aerospike
28
28
  .map { |key, keys_with_idx|
29
29
  [key.digest, BatchItem.new(key, keys_with_idx.map(&:last))]
30
30
  }
31
- Hash[map]
31
+ map.to_h
32
32
  end
33
33
 
34
34
  def initialize(key, indexes)
@@ -112,7 +112,7 @@ module Aerospike
112
112
  def set_write(policy, operation, key, bins)
113
113
  begin_cmd
114
114
  field_count = estimate_key_size(key, policy)
115
-
115
+
116
116
  predexp_size = estimate_predexp(policy.predexp)
117
117
  field_count += 1 if predexp_size > 0
118
118
 
@@ -138,7 +138,7 @@ module Aerospike
138
138
  def set_delete(policy, key)
139
139
  begin_cmd
140
140
  field_count = estimate_key_size(key)
141
-
141
+
142
142
  predexp_size = estimate_predexp(policy.predexp)
143
143
  field_count += 1 if predexp_size > 0
144
144
 
@@ -153,7 +153,7 @@ module Aerospike
153
153
  def set_touch(policy, key)
154
154
  begin_cmd
155
155
  field_count = estimate_key_size(key)
156
-
156
+
157
157
  predexp_size = estimate_predexp(policy.predexp)
158
158
  field_count += 1 if predexp_size > 0
159
159
 
@@ -170,7 +170,7 @@ module Aerospike
170
170
  def set_exists(policy, key)
171
171
  begin_cmd
172
172
  field_count = estimate_key_size(key)
173
-
173
+
174
174
  predexp_size = estimate_predexp(policy.predexp)
175
175
  field_count += 1 if predexp_size > 0
176
176
 
@@ -185,7 +185,7 @@ module Aerospike
185
185
  def set_read_for_key_only(policy, key)
186
186
  begin_cmd
187
187
  field_count = estimate_key_size(key)
188
-
188
+
189
189
  predexp_size = estimate_predexp(policy.predexp)
190
190
  field_count += 1 if predexp_size > 0
191
191
 
@@ -201,7 +201,7 @@ module Aerospike
201
201
  if bin_names && bin_names.length > 0
202
202
  begin_cmd
203
203
  field_count = estimate_key_size(key)
204
-
204
+
205
205
  predexp_size = estimate_predexp(policy.predexp)
206
206
  field_count += 1 if predexp_size > 0
207
207
 
@@ -229,7 +229,7 @@ module Aerospike
229
229
  def set_read_header(policy, key)
230
230
  begin_cmd
231
231
  field_count = estimate_key_size(key)
232
-
232
+
233
233
  predexp_size = estimate_predexp(policy.predexp)
234
234
  field_count += 1 if predexp_size > 0
235
235
 
@@ -252,7 +252,7 @@ module Aerospike
252
252
  def set_operate(policy, key, operations)
253
253
  begin_cmd
254
254
  field_count = estimate_key_size(key, policy)
255
-
255
+
256
256
  predexp_size = estimate_predexp(policy.predexp)
257
257
  field_count += 1 if predexp_size > 0
258
258
 
@@ -263,7 +263,7 @@ module Aerospike
263
263
 
264
264
  operations.each do |operation|
265
265
  case operation.op_type
266
- when Aerospike::Operation::READ, Aerospike::Operation::CDT_READ,
266
+ when Aerospike::Operation::READ, Aerospike::Operation::CDT_READ,
267
267
  Aerospike::Operation::HLL_READ, Aerospike::Operation::BIT_READ
268
268
  read_attr |= INFO1_READ
269
269
 
@@ -282,7 +282,7 @@ module Aerospike
282
282
  write_attr = INFO2_WRITE
283
283
  end
284
284
 
285
- if [Aerospike::Operation::HLL_MODIFY, Aerospike::Operation::HLL_READ,
285
+ if [Aerospike::Operation::HLL_MODIFY, Aerospike::Operation::HLL_READ,
286
286
  Aerospike::Operation::BIT_MODIFY, Aerospike::Operation::BIT_READ].include?(operation.op_type)
287
287
  record_bin_multiplicity = true
288
288
  end
@@ -294,10 +294,10 @@ module Aerospike
294
294
 
295
295
  write_attr |= INFO2_RESPOND_ALL_OPS if write_attr != 0 && record_bin_multiplicity
296
296
 
297
- if write_attr != 0
298
- write_header_with_policy(policy, read_attr, write_attr, field_count, operations.length)
299
- else
297
+ if write_attr == 0
300
298
  write_header(policy, read_attr, write_attr, field_count, operations.length)
299
+ else
300
+ write_header_with_policy(policy, read_attr, write_attr, field_count, operations.length)
301
301
  end
302
302
  write_key(key, policy)
303
303
  write_predexp(policy.predexp, predexp_size)
@@ -315,7 +315,7 @@ module Aerospike
315
315
  def set_udf(policy, key, package_name, function_name, args)
316
316
  begin_cmd
317
317
  field_count = estimate_key_size(key, policy)
318
-
318
+
319
319
  predexp_size = estimate_predexp(policy.predexp)
320
320
  field_count += 1 if predexp_size > 0
321
321
 
@@ -335,11 +335,15 @@ module Aerospike
335
335
  mark_compressed(policy)
336
336
  end
337
337
 
338
- def set_scan(policy, namespace, set_name, bin_names, partitions)
338
+ def set_scan(policy, namespace, set_name, bin_names, node_partitions)
339
339
  # Estimate buffer size
340
340
  begin_cmd
341
341
  field_count = 0
342
342
 
343
+ parts_full_size = node_partitions.parts_full.length * 2
344
+ parts_partial_size = node_partitions.parts_partial.length * 20
345
+ max_records = node_partitions.record_max
346
+
343
347
  if namespace
344
348
  @data_offset += namespace.bytesize + FIELD_HEADER_SIZE
345
349
  field_count += 1
@@ -349,7 +353,22 @@ module Aerospike
349
353
  @data_offset += set_name.bytesize + FIELD_HEADER_SIZE
350
354
  field_count += 1
351
355
  end
352
-
356
+
357
+ if parts_full_size > 0
358
+ @data_offset += parts_full_size + FIELD_HEADER_SIZE
359
+ field_count += 1
360
+ end
361
+
362
+ if parts_partial_size > 0
363
+ @data_offset += parts_partial_size + FIELD_HEADER_SIZE
364
+ field_count += 1
365
+ end
366
+
367
+ if max_records > 0
368
+ @data_offset += 8 + FIELD_HEADER_SIZE
369
+ field_count += 1
370
+ end
371
+
353
372
  if policy.records_per_second > 0
354
373
  @data_offset += 4 + FIELD_HEADER_SIZE
355
374
  field_count += 1
@@ -362,9 +381,6 @@ module Aerospike
362
381
  # @data_offset += 2 + FIELD_HEADER_SIZE
363
382
  # field_count += 1
364
383
 
365
- @data_offset += partitions.length * 2 + FIELD_HEADER_SIZE
366
- field_count += 1
367
-
368
384
  # Estimate scan timeout size.
369
385
  @data_offset += 4 + FIELD_HEADER_SIZE
370
386
  field_count += 1
@@ -378,7 +394,7 @@ module Aerospike
378
394
  size_buffer
379
395
  read_attr = INFO1_READ
380
396
 
381
- if !policy.include_bin_data
397
+ unless policy.include_bin_data
382
398
  read_attr |= INFO1_NOBINDATA
383
399
  end
384
400
 
@@ -397,10 +413,26 @@ module Aerospike
397
413
  write_field_string(set_name, Aerospike::FieldType::TABLE)
398
414
  end
399
415
 
400
- write_field_header(partitions.length * 2, Aerospike::FieldType::PID_ARRAY)
401
- for pid in partitions
402
- @data_buffer.write_uint16_little_endian(pid, @data_offset)
403
- @data_offset += 2
416
+ if parts_full_size > 0
417
+ write_field_header(parts_full_size, Aerospike::FieldType::PID_ARRAY)
418
+
419
+ node_partitions.parts_full.each do |part|
420
+ @data_buffer.write_uint16_little_endian(part.id, @data_offset)
421
+ @data_offset+=2
422
+ end
423
+ end
424
+
425
+ if parts_partial_size > 0
426
+ write_field_header(parts_partial_size, Aerospike::FieldType::DIGEST_ARRAY)
427
+
428
+ node_partitions.parts_partial.each do |part|
429
+ @data_buffer.write_binary(part.digest, @data_offset)
430
+ @data_offset+=part.digest.length
431
+ end
432
+ end
433
+
434
+ if max_records > 0
435
+ write_field_int64(max_records, Aerospike::FieldType::MAX_RECORDS)
404
436
  end
405
437
 
406
438
  if policy.records_per_second > 0
@@ -809,6 +841,12 @@ module Aerospike
809
841
  @data_offset += 4
810
842
  end
811
843
 
844
+ def write_field_int64(i, ftype)
845
+ @data_buffer.write_int64(i, @data_offset+FIELD_HEADER_SIZE)
846
+ write_field_header(8, ftype)
847
+ @data_offset += 8
848
+ end
849
+
812
850
  def write_field_bytes(bytes, ftype)
813
851
  @data_buffer.write_binary(bytes, @data_offset+FIELD_HEADER_SIZE)
814
852
  write_field_header(bytes.bytesize, ftype)
@@ -33,6 +33,9 @@ module Aerospike
33
33
  SCAN_TIMEOUT = 9
34
34
  RECORDS_PER_SECOND = 10
35
35
  PID_ARRAY = 11
36
+ DIGEST_ARRAY = 12
37
+ MAX_RECORDS = 13
38
+ BVAL_ARRAY = 15
36
39
  INDEX_NAME = 21
37
40
  INDEX_RANGE = 22
38
41
  INDEX_FILTER = 23
@@ -69,7 +69,7 @@ module Aerospike
69
69
 
70
70
  result = @data_buffer.read(RESULT_CODE)
71
71
 
72
- if result != 0
72
+ if result != 0
73
73
  return if result == Aerospike::ResultCode::SECURITY_NOT_ENABLED
74
74
  raise Exceptions::Aerospike.new(result, "Authentication failed")
75
75
  end
@@ -128,11 +128,11 @@ module Aerospike
128
128
  def authenticate_via_token(conn, cluster)
129
129
  @data_offset = 8
130
130
  policy = cluster.client_policy
131
- if policy.auth_mode != Aerospike::AuthMode::PKI
131
+ if policy.auth_mode == Aerospike::AuthMode::PKI
132
+ write_header(AUTHENTICATE, 1)
133
+ else
132
134
  write_header(AUTHENTICATE, 2)
133
135
  write_field_str(USER, policy.user)
134
- else
135
- write_header(AUTHENTICATE, 1)
136
136
  end
137
137
 
138
138
  write_field_bytes(SESSION_TOKEN, cluster.session_token) if cluster.session_token
@@ -32,6 +32,9 @@ module Aerospike
32
32
  @compressed_data_buffer = nil
33
33
  @compressed_data_offset = nil
34
34
 
35
+ @node_partitions = nil
36
+ @tracker = nil
37
+
35
38
  self
36
39
  end
37
40
 
@@ -97,8 +100,9 @@ module Aerospike
97
100
 
98
101
  # The only valid server return codes are "ok", "not found" and "filtered out".
99
102
  # If other return codes are received, then abort the batch.
100
- if result_code != 0
103
+ if result_code != 0
101
104
  if result_code == Aerospike::ResultCode::KEY_NOT_FOUND_ERROR || result_code == Aerospike::ResultCode::FILTERED_OUT
105
+ # NOOP
102
106
  else
103
107
  raise Aerospike::Exceptions::Aerospike.new(result_code)
104
108
  end
@@ -142,12 +146,14 @@ module Aerospike
142
146
  set_name = @data_buffer.read(1, size).force_encoding('utf-8')
143
147
  when Aerospike::FieldType::KEY
144
148
  user_key = Aerospike::bytes_to_key_value(@data_buffer.read(1).ord, @data_buffer, 2, size-1)
149
+ when Aerospike::FieldType::BVAL_ARRAY
150
+ bval = @data_buffer.read_uint64_little_endian(1)
145
151
  end
146
152
 
147
153
  i = i.succ
148
154
  end
149
155
 
150
- Aerospike::Key.new(namespace, set_name, user_key, digest)
156
+ Aerospike::Key.new(namespace, set_name, user_key, digest, bval: bval)
151
157
  end
152
158
 
153
159
  def skip_key(field_count)
@@ -98,7 +98,7 @@ module Aerospike
98
98
  receive_size = (sz & 0xFFFFFFFFFFFF) - header_length
99
99
 
100
100
  # Read remaining message bytes.
101
- if compressed_sz
101
+ if compressed_sz
102
102
  @data_buffer.eat!(MSG_TOTAL_HEADER_SIZE)
103
103
  elsif receive_size > 0
104
104
  size_buffer_sz(receive_size)
@@ -117,7 +117,7 @@ module Aerospike
117
117
  @record = Record.new(@node, @key, nil, generation, expiration)
118
118
  return
119
119
  end
120
-
120
+
121
121
  @record = parse_record(op_count, field_count, generation, expiration)
122
122
  return
123
123
  end
@@ -38,9 +38,7 @@ module Aerospike
38
38
 
39
39
  def call(conn, cluster)
40
40
  command = LoginCommand.new
41
- if !cluster.session_valid?
42
- command.authenticate_new(conn, cluster)
43
- else
41
+ if cluster.session_valid?
44
42
  begin
45
43
  command.authenticate_via_token(conn, cluster)
46
44
  rescue => ae
@@ -54,6 +52,8 @@ module Aerospike
54
52
  end
55
53
  raise ae
56
54
  end
55
+ else
56
+ command.authenticate_new(conn, cluster)
57
57
  end
58
58
 
59
59
  true