aerospike 2.23.0 → 2.25.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.
@@ -17,8 +17,8 @@
17
17
  module Aerospike
18
18
  module CDT
19
19
  class MapPolicy
20
-
21
20
  attr_accessor :order, :write_mode, :flags
21
+ attr_accessor :item_command, :items_command, :attributes
22
22
 
23
23
  def initialize(order: nil, write_mode: nil, flags: nil)
24
24
  if write_mode && flags
@@ -28,10 +28,24 @@ module Aerospike
28
28
  @order = order || MapOrder::DEFAULT
29
29
  @write_mode = write_mode || MapWriteMode::DEFAULT
30
30
  @flags = flags || MapWriteFlags::DEFAULT
31
+ @attributes = order ? order[:attr] : 0
32
+
33
+ case @write_mode
34
+ when CDT::MapWriteMode::DEFAULT
35
+ @item_command = CDT::MapOperation::PUT
36
+ @items_command = CDT::MapOperation::PUT_ITEMS
37
+ when CDT::MapWriteMode::UPDATE_ONLY
38
+ @item_command = CDT::MapOperation::REPLACE
39
+ @items_command = CDT::MapOperation::REPLACE_ITEMS
40
+ when CDT::MapWriteMode::CREATE_ONLY
41
+ @item_command = CDT::MapOperation::ADD
42
+ @items_command = CDT::MapOperation::ADD_ITEMS
43
+ else
44
+ raise Exceptions.new(ResultCode::PARAMETER_ERROR, "invalid value for MapWriteMode #{write_mode}")
45
+ end
31
46
  end
32
47
 
33
48
  DEFAULT = MapPolicy.new
34
-
35
49
  end
36
50
  end
37
51
  end
@@ -69,10 +69,18 @@ module Aerospike
69
69
  # Return true if count > 0.
70
70
  EXISTS = 13
71
71
 
72
+ ##
73
+ # :private
74
+ #
75
+ # TODO: Should be like ListOperation and Implement InvertibleMapOperation
76
+ # Inverts meaning of map command and return values. For example:
77
+ # map_remove_by_key_range(bin_name, key_begin, key_end, MapReturnType::KEY | MapReturnType::INVERTED)
78
+ # With the INVERTED flag enabled, the keys outside of the specified key range will be removed and returned.
79
+ INVERTED = 0x10000
80
+
72
81
  ##
73
82
  # Default return type: NONE
74
83
  DEFAULT_RETURN_TYPE = NONE
75
-
76
84
  end
77
85
  end
78
86
  end
@@ -15,8 +15,8 @@
15
15
  # License for the specific language governing permissions and limitations under
16
16
  # the License.
17
17
 
18
- require 'digest'
19
- require 'base64'
18
+ require "digest"
19
+ require "base64"
20
20
 
21
21
  module Aerospike
22
22
 
@@ -36,7 +36,6 @@ module Aerospike
36
36
  # +:fail_if_not_connected+ set to true
37
37
 
38
38
  class Client
39
-
40
39
  attr_accessor :default_admin_policy
41
40
  attr_accessor :default_batch_policy
42
41
  attr_accessor :default_info_policy
@@ -48,8 +47,7 @@ module Aerospike
48
47
  attr_accessor :cluster
49
48
 
50
49
  def initialize(hosts = nil, policy: ClientPolicy.new, connect: true)
51
-
52
- hosts = ::Aerospike::Host::Parse.(hosts || ENV['AEROSPIKE_HOSTS'] || 'localhost')
50
+ hosts = ::Aerospike::Host::Parse.(hosts || ENV["AEROSPIKE_HOSTS"] || "localhost")
53
51
  policy = create_policy(policy, ClientPolicy)
54
52
  set_default_policies(policy.policies)
55
53
  @cluster = Cluster.new(policy, hosts)
@@ -249,7 +247,7 @@ module Aerospike
249
247
  end
250
248
 
251
249
  response = send_info_command(policy, str_cmd, node).upcase
252
- return if response == 'OK'
250
+ return if response == "OK"
253
251
  raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_ERROR, "Truncate failed: #{response}")
254
252
  end
255
253
 
@@ -386,7 +384,8 @@ module Aerospike
386
384
  def operate(key, operations, options = nil)
387
385
  policy = create_policy(options, OperatePolicy, default_operate_policy)
388
386
 
389
- command = OperateCommand.new(@cluster, policy, key, operations)
387
+ args = OperateArgs.new(cluster, policy, default_write_policy, default_operate_policy, key, operations)
388
+ command = OperateCommand.new(@cluster, key, args)
390
389
  execute_command(command)
391
390
  command.record
392
391
  end
@@ -415,7 +414,7 @@ module Aerospike
415
414
  def register_udf(udf_body, server_path, language, options = nil)
416
415
  policy = create_policy(options, Policy, default_info_policy)
417
416
 
418
- content = Base64.strict_encode64(udf_body).force_encoding('binary')
417
+ content = Base64.strict_encode64(udf_body).force_encoding("binary")
419
418
  str_cmd = "udf-put:filename=#{server_path};content=#{content};"
420
419
  str_cmd << "content-len=#{content.length};udf-type=#{language};"
421
420
 
@@ -424,15 +423,15 @@ module Aerospike
424
423
 
425
424
  res = {}
426
425
  response_map.each do |k, response|
427
- vals = response.to_s.split(';')
426
+ vals = response.to_s.split(";")
428
427
  vals.each do |pair|
429
428
  k, v = pair.split("=", 2)
430
429
  res[k] = v
431
430
  end
432
431
  end
433
432
 
434
- if res['error']
435
- raise Aerospike::Exceptions::CommandRejected.new("Registration failed: #{res['error']}\nFile: #{res['file']}\nLine: #{res['line']}\nMessage: #{res['message']}")
433
+ if res["error"]
434
+ raise Aerospike::Exceptions::CommandRejected.new("Registration failed: #{res["error"]}\nFile: #{res["file"]}\nLine: #{res["line"]}\nMessage: #{res["message"]}")
436
435
  end
437
436
 
438
437
  UdfRegisterTask.new(@cluster, server_path)
@@ -454,7 +453,7 @@ module Aerospike
454
453
  response_map = @cluster.request_info(policy, str_cmd)
455
454
  _, response = response_map.first
456
455
 
457
- if response == 'ok'
456
+ if response == "ok"
458
457
  UdfRemoveTask.new(@cluster, udf_name)
459
458
  else
460
459
  raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_ERROR, response)
@@ -466,27 +465,27 @@ module Aerospike
466
465
  def list_udf(options = nil)
467
466
  policy = create_policy(options, Policy, default_info_policy)
468
467
 
469
- str_cmd = 'udf-list'
468
+ str_cmd = "udf-list"
470
469
 
471
470
  # Send command to one node. That node will distribute it to other nodes.
472
471
  response_map = @cluster.request_info(policy, str_cmd)
473
472
  _, response = response_map.first
474
473
 
475
- vals = response.split(';')
474
+ vals = response.split(";")
476
475
 
477
476
  vals.map do |udf_info|
478
- next if udf_info.strip! == ''
477
+ next if udf_info.strip! == ""
479
478
 
480
- udf_parts = udf_info.split(',')
479
+ udf_parts = udf_info.split(",")
481
480
  udf = UDF.new
482
481
  udf_parts.each do |values|
483
- k, v = values.split('=', 2)
482
+ k, v = values.split("=", 2)
484
483
  case k
485
- when 'filename'
484
+ when "filename"
486
485
  udf.filename = v
487
- when 'hash'
486
+ when "hash"
488
487
  udf.hash = v
489
- when 'type'
488
+ when "type"
490
489
  udf.language = v
491
490
  end
492
491
  end
@@ -501,7 +500,7 @@ module Aerospike
501
500
  # udf file = <server udf dir>/<package name>.lua
502
501
  #
503
502
  # This method is only supported by Aerospike 3 servers.
504
- def execute_udf(key, package_name, function_name, args=[], options = nil)
503
+ def execute_udf(key, package_name, function_name, args = [], options = nil)
505
504
  policy = create_policy(options, WritePolicy, default_write_policy)
506
505
 
507
506
  command = ExecuteCommand.new(@cluster, policy, key, package_name, function_name, args)
@@ -514,10 +513,10 @@ module Aerospike
514
513
  result_map = record.bins
515
514
 
516
515
  # User defined functions don't have to return a value.
517
- key, obj = result_map.detect{ |k, _| k.include?('SUCCESS') }
516
+ key, obj = result_map.detect { |k, _| k.include?("SUCCESS") }
518
517
  return obj if key
519
518
 
520
- key, obj = result_map.detect{ |k, _| k.include?('FAILURE') }
519
+ key, obj = result_map.detect { |k, _| k.include?("FAILURE") }
521
520
  message = key ? obj.to_s : "Invalid UDF return value"
522
521
  raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::UDF_BAD_RESPONSE, message)
523
522
  end
@@ -530,7 +529,7 @@ module Aerospike
530
529
  #
531
530
  # This method is only supported by Aerospike 3 servers.
532
531
  # If the policy is nil, the default relevant policy will be used.
533
- def execute_udf_on_query(statement, package_name, function_name, function_args=[], options = nil)
532
+ def execute_udf_on_query(statement, package_name, function_name, function_args = [], options = nil)
534
533
  policy = create_policy(options, QueryPolicy, default_query_policy)
535
534
 
536
535
  nodes = @cluster.nodes
@@ -559,7 +558,6 @@ module Aerospike
559
558
  ExecuteTask.new(@cluster, statement)
560
559
  end
561
560
 
562
-
563
561
  # Create secondary index.
564
562
  # This asynchronous server call will return before command is complete.
565
563
  # The user can optionally wait for command completion by using the returned
@@ -583,12 +581,12 @@ module Aerospike
583
581
 
584
582
  # Send index command to one node. That node will distribute the command to other nodes.
585
583
  response = send_info_command(policy, str_cmd).upcase
586
- if response == 'OK'
584
+ if response == "OK"
587
585
  # Return task that could optionally be polled for completion.
588
586
  return IndexTask.new(@cluster, namespace, index_name)
589
587
  end
590
588
 
591
- if response.start_with?('FAIL:200')
589
+ if response.start_with?("FAIL:200")
592
590
  # Index has already been created. Do not need to poll for completion.
593
591
  return IndexTask.new(@cluster, namespace, index_name, true)
594
592
  end
@@ -607,10 +605,10 @@ module Aerospike
607
605
 
608
606
  # Send index command to one node. That node will distribute the command to other nodes.
609
607
  response = send_info_command(policy, str_cmd).upcase
610
- return if response == 'OK'
608
+ return if response == "OK"
611
609
 
612
610
  # Index did not previously exist. Return without error.
613
- return if response.start_with?('FAIL:201')
611
+ return if response.start_with?("FAIL:201")
614
612
 
615
613
  raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INDEX_GENERIC, "Drop index failed: #{response}")
616
614
  end
@@ -693,44 +691,44 @@ module Aerospike
693
691
  # Query functions (Supported by Aerospike 3 servers only)
694
692
  #--------------------------------------------------------
695
693
 
696
- # Query executes a query and returns a recordset.
697
- # The query executor puts records on a channel from separate goroutines.
698
- # The caller can concurrently pops records off the channel through the
699
- # record channel.
694
+ # Executes a query for specified partitions and returns a recordset.
695
+ # The query executor puts records on the queue from separate threads.
696
+ # The caller can concurrently pop records off the queue through the
697
+ # recordset.records API.
700
698
  #
701
- # This method is only supported by Aerospike 3 servers.
702
- # If the policy is nil, a default policy will be generated.
703
- def query(statement, options = nil)
699
+ # This method is only supported by Aerospike 4.9+ servers.
700
+ # If the policy is nil, the default relevant policy will be used.
701
+ def query_partitions(partition_filter, statement, options = nil)
704
702
  policy = create_policy(options, QueryPolicy, default_query_policy)
705
703
  new_policy = policy.clone
706
704
 
707
705
  nodes = @cluster.nodes
708
706
  if nodes.empty?
709
- raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_NOT_AVAILABLE, "Scan failed because cluster is empty.")
707
+ raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_NOT_AVAILABLE, "Query failed because cluster is empty.")
710
708
  end
711
709
 
712
- recordset = Recordset.new(policy.record_queue_size, nodes.length, :query)
713
-
714
- # Use a thread per node
715
- nodes.each do |node|
716
- partitions = node.cluster.node_partitions(node, statement.namespace)
717
- Thread.new do
718
- Thread.current.abort_on_exception = true
719
- command = QueryCommand.new(node, new_policy, statement, recordset, partitions)
720
- begin
721
- execute_command(command)
722
- rescue => e
723
- Aerospike.logger.error(e.backtrace.join("\n")) unless e == QUERY_TERMINATED_EXCEPTION
724
- recordset.cancel(e)
725
- ensure
726
- recordset.thread_finished
727
- end
728
- end
710
+ # result recordset
711
+ recordset = Recordset.new(policy.record_queue_size, 1, :query)
712
+ tracker = PartitionTracker.new(policy, nodes, partition_filter)
713
+ Thread.new do
714
+ Thread.current.abort_on_exception = true
715
+ QueryExecutor.query_partitions(@cluster, policy, tracker, statement, recordset)
729
716
  end
730
717
 
731
718
  recordset
732
719
  end
733
720
 
721
+ # Query executes a query and returns a recordset.
722
+ # The query executor puts records on a channel from separate threads.
723
+ # The caller can concurrently pops records off the channel through the
724
+ # record channel.
725
+ #
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)
729
+ query_partitions(Aerospike::PartitionFilter.all, statement, options)
730
+ end
731
+
734
732
  #-------------------------------------------------------
735
733
  # User administration
736
734
  #-------------------------------------------------------
@@ -966,7 +964,5 @@ module Aerospike
966
964
 
967
965
  threads.each(&:join)
968
966
  end
969
-
970
967
  end # class
971
-
972
968
  end # module