aerospike 2.22.0 → 2.24.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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +307 -262
  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 +59 -84
  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 +65 -25
  13. data/lib/aerospike/command/field_type.rb +25 -25
  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/exp/exp.rb +1262 -0
  19. data/lib/aerospike/features.rb +9 -9
  20. data/lib/aerospike/host/parse.rb +2 -2
  21. data/lib/aerospike/key.rb +10 -1
  22. data/lib/aerospike/node/refresh/info.rb +1 -1
  23. data/lib/aerospike/node/verify/name.rb +1 -1
  24. data/lib/aerospike/node/verify/partition_generation.rb +1 -1
  25. data/lib/aerospike/node/verify/peers_generation.rb +1 -1
  26. data/lib/aerospike/node/verify/rebalance_generation.rb +1 -1
  27. data/lib/aerospike/policy/policy.rb +4 -1
  28. data/lib/aerospike/policy/query_policy.rb +35 -2
  29. data/lib/aerospike/policy/scan_policy.rb +19 -2
  30. data/lib/aerospike/privilege.rb +1 -1
  31. data/lib/aerospike/query/node_partitions.rb +39 -0
  32. data/lib/aerospike/query/partition_filter.rb +66 -0
  33. data/lib/aerospike/query/partition_status.rb +36 -0
  34. data/lib/aerospike/query/partition_tracker.rb +347 -0
  35. data/lib/aerospike/query/query_command.rb +1 -1
  36. data/lib/aerospike/query/query_executor.rb +73 -0
  37. data/lib/aerospike/query/query_partition_command.rb +266 -0
  38. data/lib/aerospike/query/scan_command.rb +3 -3
  39. data/lib/aerospike/query/scan_executor.rb +69 -0
  40. data/lib/aerospike/query/scan_partition_command.rb +49 -0
  41. data/lib/aerospike/query/statement.rb +8 -1
  42. data/lib/aerospike/query/stream_command.rb +15 -1
  43. data/lib/aerospike/result_code.rb +79 -4
  44. data/lib/aerospike/role.rb +2 -2
  45. data/lib/aerospike/task/execute_task.rb +2 -2
  46. data/lib/aerospike/task/index_task.rb +1 -1
  47. data/lib/aerospike/user_role.rb +1 -1
  48. data/lib/aerospike/utils/buffer.rb +32 -7
  49. data/lib/aerospike/utils/pool.rb +1 -1
  50. data/lib/aerospike/value/value.rb +6 -6
  51. data/lib/aerospike/version.rb +1 -1
  52. data/lib/aerospike.rb +8 -0
  53. metadata +14 -5
@@ -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,122 +642,95 @@ 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
  #--------------------------------------------------------
720
695
 
721
- # Query executes a query and returns a recordset.
722
- # The query executor puts records on a channel from separate goroutines.
723
- # The caller can concurrently pops records off the channel through the
724
- # record channel.
696
+ # Executes a query for specified partitions and returns a recordset.
697
+ # The query executor puts records on the queue from separate threads.
698
+ # The caller can concurrently pop records off the queue through the
699
+ # recordset.records API.
725
700
  #
726
- # This method is only supported by Aerospike 3 servers.
727
- # If the policy is nil, a default policy will be generated.
728
- def query(statement, options = nil)
701
+ # This method is only supported by Aerospike 4.9+ servers.
702
+ # If the policy is nil, the default relevant policy will be used.
703
+ def query_partitions(partition_filter, statement, options = nil)
729
704
  policy = create_policy(options, QueryPolicy, default_query_policy)
730
705
  new_policy = policy.clone
731
706
 
732
707
  nodes = @cluster.nodes
733
708
  if nodes.empty?
734
- raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_NOT_AVAILABLE, "Scan failed because cluster is empty.")
709
+ raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_NOT_AVAILABLE, "Query failed because cluster is empty.")
735
710
  end
736
711
 
737
- recordset = Recordset.new(policy.record_queue_size, nodes.length, :query)
738
-
739
- # Use a thread per node
740
- nodes.each do |node|
741
- partitions = node.cluster.node_partitions(node, statement.namespace)
742
- Thread.new do
743
- Thread.current.abort_on_exception = true
744
- command = QueryCommand.new(node, new_policy, statement, recordset, partitions)
745
- begin
746
- execute_command(command)
747
- rescue => e
748
- Aerospike.logger.error(e.backtrace.join("\n")) unless e == QUERY_TERMINATED_EXCEPTION
749
- recordset.cancel(e)
750
- ensure
751
- recordset.thread_finished
752
- end
753
- end
712
+ # result recordset
713
+ recordset = Recordset.new(policy.record_queue_size, 1, :query)
714
+ tracker = PartitionTracker.new(policy, nodes, partition_filter)
715
+ Thread.new do
716
+ Thread.current.abort_on_exception = true
717
+ QueryExecutor.query_partitions(@cluster, policy, tracker, statement, recordset)
754
718
  end
755
719
 
756
720
  recordset
757
721
  end
758
722
 
723
+ # Query executes a query and returns a recordset.
724
+ # The query executor puts records on a channel from separate threads.
725
+ # The caller can concurrently pops records off the channel through the
726
+ # record channel.
727
+ #
728
+ # This method is only supported by Aerospike 3 servers.
729
+ # If the policy is nil, a default policy will be generated.
730
+ def query(statement, options = nil)
731
+ query_partitions(Aerospike::PartitionFilter.all, statement, options)
732
+ end
733
+
759
734
  #-------------------------------------------------------
760
735
  # User administration
761
736
  #-------------------------------------------------------
@@ -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)
@@ -34,6 +34,8 @@ module Aerospike
34
34
  INFO1_READ = Integer(1 << 0)
35
35
  # Get all bins.
36
36
  INFO1_GET_ALL = Integer(1 << 1)
37
+ # Short query
38
+ INFO1_SHORT_QUERY = Integer(1 << 2)
37
39
 
38
40
 
39
41
  INFO1_BATCH = Integer(1 << 3)
@@ -112,7 +114,7 @@ module Aerospike
112
114
  def set_write(policy, operation, key, bins)
113
115
  begin_cmd
114
116
  field_count = estimate_key_size(key, policy)
115
-
117
+
116
118
  predexp_size = estimate_predexp(policy.predexp)
117
119
  field_count += 1 if predexp_size > 0
118
120
 
@@ -138,7 +140,7 @@ module Aerospike
138
140
  def set_delete(policy, key)
139
141
  begin_cmd
140
142
  field_count = estimate_key_size(key)
141
-
143
+
142
144
  predexp_size = estimate_predexp(policy.predexp)
143
145
  field_count += 1 if predexp_size > 0
144
146
 
@@ -153,7 +155,7 @@ module Aerospike
153
155
  def set_touch(policy, key)
154
156
  begin_cmd
155
157
  field_count = estimate_key_size(key)
156
-
158
+
157
159
  predexp_size = estimate_predexp(policy.predexp)
158
160
  field_count += 1 if predexp_size > 0
159
161
 
@@ -170,7 +172,7 @@ module Aerospike
170
172
  def set_exists(policy, key)
171
173
  begin_cmd
172
174
  field_count = estimate_key_size(key)
173
-
175
+
174
176
  predexp_size = estimate_predexp(policy.predexp)
175
177
  field_count += 1 if predexp_size > 0
176
178
 
@@ -185,7 +187,7 @@ module Aerospike
185
187
  def set_read_for_key_only(policy, key)
186
188
  begin_cmd
187
189
  field_count = estimate_key_size(key)
188
-
190
+
189
191
  predexp_size = estimate_predexp(policy.predexp)
190
192
  field_count += 1 if predexp_size > 0
191
193
 
@@ -201,7 +203,7 @@ module Aerospike
201
203
  if bin_names && bin_names.length > 0
202
204
  begin_cmd
203
205
  field_count = estimate_key_size(key)
204
-
206
+
205
207
  predexp_size = estimate_predexp(policy.predexp)
206
208
  field_count += 1 if predexp_size > 0
207
209
 
@@ -229,7 +231,7 @@ module Aerospike
229
231
  def set_read_header(policy, key)
230
232
  begin_cmd
231
233
  field_count = estimate_key_size(key)
232
-
234
+
233
235
  predexp_size = estimate_predexp(policy.predexp)
234
236
  field_count += 1 if predexp_size > 0
235
237
 
@@ -252,7 +254,7 @@ module Aerospike
252
254
  def set_operate(policy, key, operations)
253
255
  begin_cmd
254
256
  field_count = estimate_key_size(key, policy)
255
-
257
+
256
258
  predexp_size = estimate_predexp(policy.predexp)
257
259
  field_count += 1 if predexp_size > 0
258
260
 
@@ -263,7 +265,7 @@ module Aerospike
263
265
 
264
266
  operations.each do |operation|
265
267
  case operation.op_type
266
- when Aerospike::Operation::READ, Aerospike::Operation::CDT_READ,
268
+ when Aerospike::Operation::READ, Aerospike::Operation::CDT_READ,
267
269
  Aerospike::Operation::HLL_READ, Aerospike::Operation::BIT_READ
268
270
  read_attr |= INFO1_READ
269
271
 
@@ -282,7 +284,7 @@ module Aerospike
282
284
  write_attr = INFO2_WRITE
283
285
  end
284
286
 
285
- if [Aerospike::Operation::HLL_MODIFY, Aerospike::Operation::HLL_READ,
287
+ if [Aerospike::Operation::HLL_MODIFY, Aerospike::Operation::HLL_READ,
286
288
  Aerospike::Operation::BIT_MODIFY, Aerospike::Operation::BIT_READ].include?(operation.op_type)
287
289
  record_bin_multiplicity = true
288
290
  end
@@ -294,10 +296,10 @@ module Aerospike
294
296
 
295
297
  write_attr |= INFO2_RESPOND_ALL_OPS if write_attr != 0 && record_bin_multiplicity
296
298
 
297
- if write_attr != 0
298
- write_header_with_policy(policy, read_attr, write_attr, field_count, operations.length)
299
- else
299
+ if write_attr == 0
300
300
  write_header(policy, read_attr, write_attr, field_count, operations.length)
301
+ else
302
+ write_header_with_policy(policy, read_attr, write_attr, field_count, operations.length)
301
303
  end
302
304
  write_key(key, policy)
303
305
  write_predexp(policy.predexp, predexp_size)
@@ -315,7 +317,7 @@ module Aerospike
315
317
  def set_udf(policy, key, package_name, function_name, args)
316
318
  begin_cmd
317
319
  field_count = estimate_key_size(key, policy)
318
-
320
+
319
321
  predexp_size = estimate_predexp(policy.predexp)
320
322
  field_count += 1 if predexp_size > 0
321
323
 
@@ -335,11 +337,15 @@ module Aerospike
335
337
  mark_compressed(policy)
336
338
  end
337
339
 
338
- def set_scan(policy, namespace, set_name, bin_names, partitions)
340
+ def set_scan(policy, namespace, set_name, bin_names, node_partitions)
339
341
  # Estimate buffer size
340
342
  begin_cmd
341
343
  field_count = 0
342
344
 
345
+ parts_full_size = node_partitions.parts_full.length * 2
346
+ parts_partial_size = node_partitions.parts_partial.length * 20
347
+ max_records = node_partitions.record_max
348
+
343
349
  if namespace
344
350
  @data_offset += namespace.bytesize + FIELD_HEADER_SIZE
345
351
  field_count += 1
@@ -349,7 +355,22 @@ module Aerospike
349
355
  @data_offset += set_name.bytesize + FIELD_HEADER_SIZE
350
356
  field_count += 1
351
357
  end
352
-
358
+
359
+ if parts_full_size > 0
360
+ @data_offset += parts_full_size + FIELD_HEADER_SIZE
361
+ field_count += 1
362
+ end
363
+
364
+ if parts_partial_size > 0
365
+ @data_offset += parts_partial_size + FIELD_HEADER_SIZE
366
+ field_count += 1
367
+ end
368
+
369
+ if max_records > 0
370
+ @data_offset += 8 + FIELD_HEADER_SIZE
371
+ field_count += 1
372
+ end
373
+
353
374
  if policy.records_per_second > 0
354
375
  @data_offset += 4 + FIELD_HEADER_SIZE
355
376
  field_count += 1
@@ -362,9 +383,6 @@ module Aerospike
362
383
  # @data_offset += 2 + FIELD_HEADER_SIZE
363
384
  # field_count += 1
364
385
 
365
- @data_offset += partitions.length * 2 + FIELD_HEADER_SIZE
366
- field_count += 1
367
-
368
386
  # Estimate scan timeout size.
369
387
  @data_offset += 4 + FIELD_HEADER_SIZE
370
388
  field_count += 1
@@ -378,7 +396,7 @@ module Aerospike
378
396
  size_buffer
379
397
  read_attr = INFO1_READ
380
398
 
381
- if !policy.include_bin_data
399
+ unless policy.include_bin_data
382
400
  read_attr |= INFO1_NOBINDATA
383
401
  end
384
402
 
@@ -397,10 +415,26 @@ module Aerospike
397
415
  write_field_string(set_name, Aerospike::FieldType::TABLE)
398
416
  end
399
417
 
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
418
+ if parts_full_size > 0
419
+ write_field_header(parts_full_size, Aerospike::FieldType::PID_ARRAY)
420
+
421
+ node_partitions.parts_full.each do |part|
422
+ @data_buffer.write_uint16_little_endian(part.id, @data_offset)
423
+ @data_offset+=2
424
+ end
425
+ end
426
+
427
+ if parts_partial_size > 0
428
+ write_field_header(parts_partial_size, Aerospike::FieldType::DIGEST_ARRAY)
429
+
430
+ node_partitions.parts_partial.each do |part|
431
+ @data_buffer.write_binary(part.digest, @data_offset)
432
+ @data_offset+=part.digest.length
433
+ end
434
+ end
435
+
436
+ if max_records > 0
437
+ write_field_int64(max_records, Aerospike::FieldType::MAX_RECORDS)
404
438
  end
405
439
 
406
440
  if policy.records_per_second > 0
@@ -422,7 +456,7 @@ module Aerospike
422
456
  # @data_buffer.write_byte(policy.scan_percent.to_i.ord, @data_offset)
423
457
  # @data_offset += 1
424
458
 
425
- write_field_header(4, Aerospike::FieldType::SCAN_TIMEOUT)
459
+ write_field_header(4, Aerospike::FieldType::SOCKET_TIMEOUT)
426
460
  @data_buffer.write_uint32(policy.socket_timeout.to_i, @data_offset)
427
461
  @data_offset += 4
428
462
 
@@ -809,6 +843,12 @@ module Aerospike
809
843
  @data_offset += 4
810
844
  end
811
845
 
846
+ def write_field_int64(i, ftype)
847
+ @data_buffer.write_int64(i, @data_offset+FIELD_HEADER_SIZE)
848
+ write_field_header(8, ftype)
849
+ @data_offset += 8
850
+ end
851
+
812
852
  def write_field_bytes(bytes, ftype)
813
853
  @data_buffer.write_binary(bytes, @data_offset+FIELD_HEADER_SIZE)
814
854
  write_field_header(bytes.bytesize, ftype)
@@ -21,31 +21,31 @@ module Aerospike
21
21
 
22
22
  module FieldType
23
23
 
24
- NAMESPACE = 0
25
- TABLE = 1
26
- KEY = 2
27
- #BIN = 3
28
- DIGEST_RIPE = 4
29
- #GU_TID = 5
30
- DIGEST_RIPE_ARRAY = 6
31
- TRAN_ID = 7 # user supplied transaction id, which is simply passed back
32
- SCAN_OPTIONS = 8
33
- SCAN_TIMEOUT = 9
34
- RECORDS_PER_SECOND = 10
35
- PID_ARRAY = 11
36
- INDEX_NAME = 21
37
- INDEX_RANGE = 22
38
- INDEX_FILTER = 23
39
- INDEX_LIMIT = 24
40
- INDEX_ORDER_BY = 25
41
- INDEX_TYPE = 26
42
- UDF_PACKAGE_NAME = 30
43
- UDF_FUNCTION = 31
44
- UDF_ARGLIST = 32
45
- UDF_OP = 33
46
- QUERY_BINLIST = 40
47
- BATCH_INDEX = 41
48
- PREDEXP = 43
24
+ NAMESPACE = 0
25
+ TABLE = 1
26
+ KEY = 2
27
+ DIGEST_RIPE = 4
28
+ DIGEST_RIPE_ARRAY = 6
29
+ TRAN_ID = 7 # user supplied transaction id, which is simply passed back
30
+ SCAN_OPTIONS = 8
31
+ SOCKET_TIMEOUT = 9
32
+ RECORDS_PER_SECOND = 10
33
+ PID_ARRAY = 11
34
+ DIGEST_ARRAY = 12
35
+ MAX_RECORDS = 13
36
+ BVAL_ARRAY = 15
37
+ INDEX_NAME = 21
38
+ INDEX_RANGE = 22
39
+ INDEX_CONTEXT = 23
40
+ INDEX_TYPE = 26
41
+ UDF_PACKAGE_NAME = 30
42
+ UDF_FUNCTION = 31
43
+ UDF_ARGLIST = 32
44
+ UDF_OP = 33
45
+ QUERY_BINLIST = 40
46
+ BATCH_INDEX = 41
47
+ BATCH_INDEX_WITH_SET = 42
48
+ FILTER_EXP = 43
49
49
 
50
50
  end # module
51
51
 
@@ -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