aerospike 2.22.0 → 2.24.0

Sign up to get free protection for your applications and to get access to all the features.
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