aerospike 2.9.1 → 2.14.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +50 -4
- data/README.md +1 -1
- data/lib/aerospike.rb +17 -4
- data/lib/aerospike/aerospike_exception.rb +7 -1
- data/lib/aerospike/atomic/atomic.rb +1 -1
- data/lib/aerospike/bin.rb +1 -1
- data/lib/aerospike/cdt/list_operation.rb +1 -1
- data/lib/aerospike/cdt/map_operation.rb +1 -1
- data/lib/aerospike/cdt/map_order.rb +1 -1
- data/lib/aerospike/cdt/map_policy.rb +1 -1
- data/lib/aerospike/cdt/map_return_type.rb +1 -1
- data/lib/aerospike/cdt/map_write_mode.rb +1 -1
- data/lib/aerospike/client.rb +31 -17
- data/lib/aerospike/cluster.rb +139 -17
- data/lib/aerospike/cluster/partition.rb +1 -1
- data/lib/aerospike/cluster/partition_parser.rb +169 -0
- data/lib/aerospike/cluster/rack_parser.rb +117 -0
- data/lib/aerospike/command/admin_command.rb +1 -1
- data/lib/aerospike/command/batch_direct_command.rb +2 -1
- data/lib/aerospike/command/batch_direct_exists_command.rb +1 -1
- data/lib/aerospike/command/batch_direct_node.rb +3 -3
- data/lib/aerospike/command/batch_index_command.rb +11 -2
- data/lib/aerospike/command/batch_index_node.rb +2 -2
- data/lib/aerospike/command/batch_item.rb +1 -1
- data/lib/aerospike/command/command.rb +157 -11
- data/lib/aerospike/command/delete_command.rb +21 -5
- data/lib/aerospike/command/execute_command.rb +1 -1
- data/lib/aerospike/command/exists_command.rb +21 -5
- data/lib/aerospike/command/field_type.rb +3 -1
- data/lib/aerospike/command/multi_command.rb +55 -5
- data/lib/aerospike/command/operate_command.rb +6 -1
- data/lib/aerospike/command/read_command.rb +63 -20
- data/lib/aerospike/command/read_header_command.rb +18 -6
- data/lib/aerospike/command/roles.rb +1 -1
- data/lib/aerospike/command/single_command.rb +9 -3
- data/lib/aerospike/command/touch_command.rb +48 -4
- data/lib/aerospike/command/unsupported_particle_type_validator.rb +1 -1
- data/lib/aerospike/command/write_command.rb +13 -4
- data/lib/aerospike/connection/create.rb +1 -1
- data/lib/aerospike/features.rb +3 -1
- data/lib/aerospike/geo_json.rb +70 -1
- data/lib/aerospike/host.rb +1 -1
- data/lib/aerospike/info.rb +1 -1
- data/lib/aerospike/key.rb +1 -1
- data/lib/aerospike/language.rb +1 -1
- data/lib/aerospike/node.rb +21 -7
- data/lib/aerospike/node/rebalance.rb +50 -0
- data/lib/aerospike/node/refresh/info.rb +4 -1
- data/lib/aerospike/node/refresh/partitions.rb +6 -15
- data/lib/aerospike/node/refresh/racks.rb +47 -0
- data/lib/aerospike/node/refresh/reset.rb +1 -0
- data/lib/aerospike/node/verify/rebalance_generation.rb +43 -0
- data/lib/aerospike/node_validator.rb +45 -40
- data/lib/aerospike/operation.rb +6 -1
- data/lib/aerospike/policy/admin_policy.rb +1 -1
- data/lib/aerospike/policy/batch_policy.rb +1 -1
- data/lib/aerospike/policy/client_policy.rb +16 -1
- data/lib/aerospike/policy/commit_level.rb +1 -1
- data/lib/aerospike/policy/consistency_level.rb +1 -1
- data/lib/aerospike/policy/generation_policy.rb +1 -1
- data/lib/aerospike/policy/operate_policy.rb +1 -1
- data/lib/aerospike/policy/policy.rb +64 -2
- data/lib/aerospike/policy/priority.rb +1 -1
- data/lib/aerospike/policy/query_policy.rb +8 -1
- data/lib/aerospike/policy/record_bin_multiplicity.rb +1 -1
- data/lib/aerospike/policy/record_exists_action.rb +1 -1
- data/lib/aerospike/policy/replica.rb +45 -0
- data/lib/aerospike/policy/scan_policy.rb +8 -1
- data/lib/aerospike/policy/write_policy.rb +1 -1
- data/lib/aerospike/query/filter.rb +1 -1
- data/lib/aerospike/query/pred_exp.rb +192 -0
- data/lib/aerospike/query/pred_exp/and_or.rb +32 -0
- data/lib/aerospike/query/pred_exp/geo_json_value.rb +41 -0
- data/lib/aerospike/query/pred_exp/integer_value.rb +32 -0
- data/lib/aerospike/query/pred_exp/op.rb +27 -0
- data/lib/aerospike/query/pred_exp/regex.rb +32 -0
- data/lib/aerospike/query/pred_exp/regex_flags.rb +23 -0
- data/lib/aerospike/query/pred_exp/string_value.rb +29 -0
- data/lib/aerospike/query/query_command.rb +27 -1
- data/lib/aerospike/query/recordset.rb +5 -5
- data/lib/aerospike/query/scan_command.rb +1 -1
- data/lib/aerospike/query/statement.rb +12 -3
- data/lib/aerospike/query/stream_command.rb +1 -1
- data/lib/aerospike/record.rb +1 -1
- data/lib/aerospike/result_code.rb +13 -7
- data/lib/aerospike/socket/base.rb +4 -3
- data/lib/aerospike/task/execute_task.rb +1 -1
- data/lib/aerospike/task/index_task.rb +1 -1
- data/lib/aerospike/task/task.rb +1 -1
- data/lib/aerospike/task/udf_register_task.rb +1 -1
- data/lib/aerospike/task/udf_remove_task.rb +1 -1
- data/lib/aerospike/ttl.rb +1 -1
- data/lib/aerospike/udf.rb +1 -1
- data/lib/aerospike/user_role.rb +1 -1
- data/lib/aerospike/utils/buffer.rb +14 -4
- data/lib/aerospike/utils/packer.rb +1 -1
- data/lib/aerospike/utils/pool.rb +1 -1
- data/lib/aerospike/utils/unpacker.rb +7 -2
- data/lib/aerospike/value/particle_type.rb +1 -1
- data/lib/aerospike/value/value.rb +59 -29
- data/lib/aerospike/version.rb +1 -1
- metadata +19 -8
- data/lib/aerospike/cluster/partition_tokenizer_new.rb +0 -130
- data/lib/aerospike/cluster/partition_tokenizer_old.rb +0 -135
| @@ -0,0 +1,169 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Copyright 2014-2020 Aerospike, Inc.
         | 
| 4 | 
            +
            #
         | 
| 5 | 
            +
            # Portions may be licensed to Aerospike, Inc. under one or more contributor
         | 
| 6 | 
            +
            # license agreements.
         | 
| 7 | 
            +
            #
         | 
| 8 | 
            +
            # Licensed under the Apache License, Version 2.0 (the "License"); you may not
         | 
| 9 | 
            +
            # use this file except in compliance with the License. You may obtain a copy of
         | 
| 10 | 
            +
            # the License at http:#www.apache.org/licenses/LICENSE-2.0
         | 
| 11 | 
            +
            #
         | 
| 12 | 
            +
            # Unless required by applicable law or agreed to in writing, software
         | 
| 13 | 
            +
            # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
         | 
| 14 | 
            +
            # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
         | 
| 15 | 
            +
            # License for the specific language governing permissions and limitations under
         | 
| 16 | 
            +
            # the License.
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            require 'base64'
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            module Aerospike
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              class PartitionParser #:nodoc:
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                attr_accessor :copied, :partition_generation
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                PARTITION_GENERATION = "partition-generation";
         | 
| 27 | 
            +
                REPLICAS_ALL = "replicas-all";
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def initialize(node, conn)
         | 
| 30 | 
            +
                  @node = node
         | 
| 31 | 
            +
                  @conn = conn
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def update_partitions(current_map)
         | 
| 35 | 
            +
                  # Use low-level info methods and parse byte array directly for maximum performance.
         | 
| 36 | 
            +
                  # Receive format: replicas-all\t
         | 
| 37 | 
            +
                  #                 <ns1>:<count>,<base 64 encoded bitmap1>,<base 64 encoded bitmap2>...;
         | 
| 38 | 
            +
                  #                 <ns2>:<count>,<base 64 encoded bitmap1>,<base 64 encoded bitmap2>...;\n
         | 
| 39 | 
            +
                  info_map = Info.request(@conn, PARTITION_GENERATION, REPLICAS_ALL)
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  @partition_generation = info_map[PARTITION_GENERATION].to_i
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  info = info_map[REPLICAS_ALL]
         | 
| 44 | 
            +
                  if !info || info.length == 0
         | 
| 45 | 
            +
                    raise Aerospike::Exceptions::Connection.new("#{REPLICAS_ALL} response for node #{@node.name} is empty")
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  @buffer = info
         | 
| 49 | 
            +
                  @length = info.length
         | 
| 50 | 
            +
                  @offset = 0
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  new_map = nil
         | 
| 53 | 
            +
                  copied = false
         | 
| 54 | 
            +
                  beginning = @offset
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  while @offset < @length && @buffer[@offset] != '\n'
         | 
| 57 | 
            +
                    namespace = parse_name
         | 
| 58 | 
            +
                    replica_count = parse_replica_count
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    replica_array = current_map[namespace]
         | 
| 61 | 
            +
                    if !replica_array
         | 
| 62 | 
            +
                      if !copied
         | 
| 63 | 
            +
                        # Make shallow copy of map.
         | 
| 64 | 
            +
                        new_map = current_map.clone
         | 
| 65 | 
            +
                        copied = true
         | 
| 66 | 
            +
                      end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                      replica_array = Atomic.new(Array.new(replica_count))
         | 
| 69 | 
            +
                      new_map[namespace] = replica_array
         | 
| 70 | 
            +
                    end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                    for replica in 0...replica_count do
         | 
| 73 | 
            +
                      node_array = (replica_array.get)[replica]
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                      if !node_array
         | 
| 76 | 
            +
                        if !copied
         | 
| 77 | 
            +
                          # Make shallow copy of map.
         | 
| 78 | 
            +
                          new_map = current_map.clone
         | 
| 79 | 
            +
                          copied = true
         | 
| 80 | 
            +
                        end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                        node_array = Atomic.new(Array.new(Aerospike::Node::PARTITIONS))
         | 
| 83 | 
            +
                        new_map[namespace].update{|v| v[replica] = node_array; v}
         | 
| 84 | 
            +
                      end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                      restore_buffer = parse_bitmap
         | 
| 87 | 
            +
                      i = 0
         | 
| 88 | 
            +
                      while i < Aerospike::Node::PARTITIONS
         | 
| 89 | 
            +
                        if (restore_buffer[i>>3].ord & (0x80 >> (i & 7))) != 0
         | 
| 90 | 
            +
                          node_array.update{|v| v[i] = @node; v}
         | 
| 91 | 
            +
                        end
         | 
| 92 | 
            +
                        i = i.succ
         | 
| 93 | 
            +
                      end
         | 
| 94 | 
            +
                    end
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  copied ? new_map : nil
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                private
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                def parse_name
         | 
| 103 | 
            +
                  beginning = @offset
         | 
| 104 | 
            +
                  while @offset < @length
         | 
| 105 | 
            +
                    break if @buffer[@offset] == ':'
         | 
| 106 | 
            +
                    @offset+=1
         | 
| 107 | 
            +
                  end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                  # Parse namespace.
         | 
| 110 | 
            +
                  namespace = @buffer[beginning...@offset].strip
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                  if namespace.length <= 0 || namespace.length >= 32
         | 
| 113 | 
            +
                    response = get_truncated_response
         | 
| 114 | 
            +
                    raise Aerospike::Exceptions::Parse.new(
         | 
| 115 | 
            +
                      "Invalid partition namespace #{namespace}. Response=#{response}"
         | 
| 116 | 
            +
                    )
         | 
| 117 | 
            +
                  end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                  @offset+=1
         | 
| 120 | 
            +
                  namespace
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                def parse_replica_count
         | 
| 124 | 
            +
                  beginning = @offset
         | 
| 125 | 
            +
                  while @offset < @length
         | 
| 126 | 
            +
                    break if @buffer[@offset] == ','
         | 
| 127 | 
            +
                    @offset+=1
         | 
| 128 | 
            +
                  end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                  # Parse count
         | 
| 131 | 
            +
                  count = @buffer[beginning...@offset].strip.to_i
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                  if count < 0 || count > 4096
         | 
| 134 | 
            +
                    response = get_truncated_response
         | 
| 135 | 
            +
                    raise Aerospike::Exceptions::Parse.new(
         | 
| 136 | 
            +
                      "Invalid partition count #{count}. Response=#{response}"
         | 
| 137 | 
            +
                    )
         | 
| 138 | 
            +
                  end
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                  @offset+=1
         | 
| 141 | 
            +
                  count
         | 
| 142 | 
            +
                end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                def parse_bitmap
         | 
| 145 | 
            +
                  beginning = @offset
         | 
| 146 | 
            +
                  while @offset < @length
         | 
| 147 | 
            +
                    break if @buffer[@offset] == ','
         | 
| 148 | 
            +
                    break if @buffer[@offset] == ';'
         | 
| 149 | 
            +
                    @offset+=1
         | 
| 150 | 
            +
                  end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                  bit_map_length = @offset - beginning
         | 
| 153 | 
            +
                  restore_buffer = Base64.strict_decode64(@buffer[beginning, bit_map_length])
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                  @offset+=1
         | 
| 156 | 
            +
                  restore_buffer
         | 
| 157 | 
            +
                end
         | 
| 158 | 
            +
             | 
| 159 | 
            +
             | 
| 160 | 
            +
                def get_truncated_response
         | 
| 161 | 
            +
                  max = @length
         | 
| 162 | 
            +
                  @length = max if @length > 200
         | 
| 163 | 
            +
                  @buffer[0...max]
         | 
| 164 | 
            +
                end
         | 
| 165 | 
            +
             | 
| 166 | 
            +
             | 
| 167 | 
            +
              end # class
         | 
| 168 | 
            +
             | 
| 169 | 
            +
            end # module
         | 
| @@ -0,0 +1,117 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Copyright 2014-2020 Aerospike, Inc.
         | 
| 4 | 
            +
            #
         | 
| 5 | 
            +
            # Portions may be licensed to Aerospike, Inc. under one or more contributor
         | 
| 6 | 
            +
            # license agreements.
         | 
| 7 | 
            +
            #
         | 
| 8 | 
            +
            # Licensed under the Apache License, Version 2.0 (the "License"); you may not
         | 
| 9 | 
            +
            # use this file except in compliance with the License. You may obtain a copy of
         | 
| 10 | 
            +
            # the License at http:#www.apache.org/licenses/LICENSE-2.0
         | 
| 11 | 
            +
            #
         | 
| 12 | 
            +
            # Unless required by applicable law or agreed to in writing, software
         | 
| 13 | 
            +
            # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
         | 
| 14 | 
            +
            # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
         | 
| 15 | 
            +
            # License for the specific language governing permissions and limitations under
         | 
| 16 | 
            +
            # the License.
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            require 'base64'
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            module Aerospike
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              class RackParser #:nodoc:
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                attr_accessor :rebalance_generation, :racks
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                REBALANCE_GENERATION = "rebalance-generation"
         | 
| 27 | 
            +
                RACK_IDS = "rack-ids"
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def initialize(node, conn)
         | 
| 30 | 
            +
                  @node = node
         | 
| 31 | 
            +
                  @conn = conn
         | 
| 32 | 
            +
                  @racks = nil
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def update_racks
         | 
| 36 | 
            +
                  # Use low-level info methods and parse byte array directly for maximum performance.
         | 
| 37 | 
            +
                  # Receive format: rack-ids\t
         | 
| 38 | 
            +
                  #                 <ns1>:<rack-id>...;
         | 
| 39 | 
            +
                  #                 <ns2>:<rack-id>...; ...
         | 
| 40 | 
            +
                  info_map = Info.request(@conn, REBALANCE_GENERATION, RACK_IDS)
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  @rebalance_generation = info_map[REBALANCE_GENERATION].to_i
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  info = info_map[RACK_IDS]
         | 
| 45 | 
            +
                  if !info || info.length == 0
         | 
| 46 | 
            +
                    raise Aerospike::Exceptions::Connection.new("#{RACK_IDS} response for node #{@node.name} is empty")
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  @buffer = info
         | 
| 50 | 
            +
                  @length = info.length
         | 
| 51 | 
            +
                  @offset = 0
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  while @offset < @length && @buffer[@offset] != '\n'
         | 
| 54 | 
            +
                    namespace = parse_name
         | 
| 55 | 
            +
                    rack_id = parse_rack_id
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                    @racks = {} if !@racks
         | 
| 58 | 
            +
                    @racks[namespace] = rack_id
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  @racks
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                private
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                def parse_name
         | 
| 67 | 
            +
                  beginning = @offset
         | 
| 68 | 
            +
                  while @offset < @length
         | 
| 69 | 
            +
                    break if @buffer[@offset] == ':'
         | 
| 70 | 
            +
                    @offset+=1
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  # Parse namespace.
         | 
| 74 | 
            +
                  namespace = @buffer[beginning...@offset].strip
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  if namespace.length <= 0 || namespace.length >= 32
         | 
| 77 | 
            +
                    response = get_truncated_response
         | 
| 78 | 
            +
                    raise Aerospike::Exceptions::Parse.new(
         | 
| 79 | 
            +
                      "Invalid rack namespace #{namespace}. Response=#{response}"
         | 
| 80 | 
            +
                    )
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  @offset+=1
         | 
| 84 | 
            +
                  namespace
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                def parse_rack_id
         | 
| 88 | 
            +
                  beginning = @offset
         | 
| 89 | 
            +
                  while @offset < @length
         | 
| 90 | 
            +
                    break if @buffer[@offset] == ';'
         | 
| 91 | 
            +
                    @offset+=1
         | 
| 92 | 
            +
                  end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                  # Parse rack_id
         | 
| 95 | 
            +
                  rack_id = @buffer[beginning...@offset].strip.to_i
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  if rack_id < 0
         | 
| 98 | 
            +
                    response = get_truncated_response
         | 
| 99 | 
            +
                    raise Aerospike::Exceptions::Parse.new(
         | 
| 100 | 
            +
                      "Invalid rack_id #{rack_id}. Response=#{response}"
         | 
| 101 | 
            +
                    )
         | 
| 102 | 
            +
                  end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                  @offset+=1
         | 
| 105 | 
            +
                  rack_id
         | 
| 106 | 
            +
                end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                def get_truncated_response
         | 
| 109 | 
            +
                  max = @length
         | 
| 110 | 
            +
                  @length = max if @length > 200
         | 
| 111 | 
            +
                  @buffer[0...max]
         | 
| 112 | 
            +
                end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
             | 
| 115 | 
            +
              end # class
         | 
| 116 | 
            +
             | 
| 117 | 
            +
            end # module
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            # Copyright 2014- | 
| 1 | 
            +
            # Copyright 2014-2020 Aerospike, Inc.
         | 
| 2 2 | 
             
            #
         | 
| 3 3 | 
             
            # Portions may be licensed to Aerospike, Inc. under one or more contributor
         | 
| 4 4 | 
             
            # license agreements.
         | 
| @@ -75,6 +75,7 @@ module Aerospike | |
| 75 75 | 
             
                  end
         | 
| 76 76 |  | 
| 77 77 | 
             
                  end_cmd
         | 
| 78 | 
            +
                  mark_compressed(@policy)
         | 
| 78 79 | 
             
                end
         | 
| 79 80 |  | 
| 80 81 | 
             
                # Parse all results in the batch.  Add records to shared list.
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            # Copyright 2014- | 
| 1 | 
            +
            # Copyright 2014-2020 Aerospike, Inc.
         | 
| 2 2 | 
             
            #
         | 
| 3 3 | 
             
            # Portions may be licensed to Aerospike, Inc. under one or more contributor
         | 
| 4 4 | 
             
            # license agreements.
         | 
| @@ -24,8 +24,8 @@ module Aerospike | |
| 24 24 | 
             
                attr_accessor :node
         | 
| 25 25 | 
             
                attr_accessor :batch_namespaces
         | 
| 26 26 |  | 
| 27 | 
            -
                def self.generate_list(cluster, keys)
         | 
| 28 | 
            -
                  keys.group_by { |key| cluster.get_node_for_key(key) }
         | 
| 27 | 
            +
                def self.generate_list(cluster, replica_policy, keys)
         | 
| 28 | 
            +
                  keys.group_by { |key| cluster.get_node_for_key(replica_policy, key) }
         | 
| 29 29 | 
             
                    .map { |node, keys_for_node| BatchDirectNode.new(node, keys_for_node) }
         | 
| 30 30 | 
             
                end
         | 
| 31 31 |  | 
| @@ -39,7 +39,12 @@ module Aerospike | |
| 39 39 | 
             
                def write_buffer
         | 
| 40 40 | 
             
                  bin_name_size = 0
         | 
| 41 41 | 
             
                  operation_count = 0
         | 
| 42 | 
            +
                  field_count_row = 1
         | 
| 42 43 | 
             
                  field_count = 1
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  predexp_size = estimate_predexp(@policy.predexp)
         | 
| 46 | 
            +
                  field_count += 1 if predexp_size > 0
         | 
| 47 | 
            +
             | 
| 43 48 | 
             
                  if bin_names
         | 
| 44 49 | 
             
                    bin_names.each do |bin_name|
         | 
| 45 50 | 
             
                      bin_name_size += bin_name.bytesize + OPERATION_HEADER_SIZE
         | 
| @@ -61,7 +66,10 @@ module Aerospike | |
| 61 66 | 
             
                    end
         | 
| 62 67 | 
             
                  end
         | 
| 63 68 | 
             
                  size_buffer
         | 
| 64 | 
            -
                  write_header(policy,read_attr | INFO1_BATCH, 0,  | 
| 69 | 
            +
                  write_header(policy,read_attr | INFO1_BATCH, 0, field_count, 0)
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  write_predexp(@policy.predexp, predexp_size)
         | 
| 72 | 
            +
             | 
| 65 73 | 
             
                  write_field_header(0, Aerospike::FieldType::BATCH_INDEX)
         | 
| 66 74 | 
             
                  @data_offset += @data_buffer.write_int32(batch.keys.length, @data_offset)
         | 
| 67 75 | 
             
                  @data_offset += @data_buffer.write_byte(1, @data_offset)
         | 
| @@ -77,7 +85,7 @@ module Aerospike | |
| 77 85 | 
             
                    else
         | 
| 78 86 | 
             
                      @data_offset += @data_buffer.write_byte(0, @data_offset)
         | 
| 79 87 | 
             
                      @data_offset += @data_buffer.write_byte(read_attr, @data_offset)
         | 
| 80 | 
            -
                      @data_offset += @data_buffer.write_int16( | 
| 88 | 
            +
                      @data_offset += @data_buffer.write_int16(field_count_row, @data_offset)
         | 
| 81 89 | 
             
                      @data_offset += @data_buffer.write_int16(operation_count, @data_offset)
         | 
| 82 90 | 
             
                      write_field_string(key.namespace, Aerospike::FieldType::NAMESPACE)
         | 
| 83 91 |  | 
| @@ -90,6 +98,7 @@ module Aerospike | |
| 90 98 | 
             
                    end
         | 
| 91 99 | 
             
                  end
         | 
| 92 100 | 
             
                  end_cmd
         | 
| 101 | 
            +
                  mark_compressed(@policy)
         | 
| 93 102 | 
             
                end
         | 
| 94 103 |  | 
| 95 104 | 
             
                # Parse all results in the batch.  Add records to shared list.
         | 
| @@ -22,9 +22,9 @@ module Aerospike | |
| 22 22 | 
             
                attr_accessor :node
         | 
| 23 23 | 
             
                attr_accessor :keys_by_idx
         | 
| 24 24 |  | 
| 25 | 
            -
                def self.generate_list(cluster, keys)
         | 
| 25 | 
            +
                def self.generate_list(cluster, replica_policy, keys)
         | 
| 26 26 | 
             
                  keys.each_with_index
         | 
| 27 | 
            -
                    .group_by { |key, _| cluster.get_node_for_key(key) }
         | 
| 27 | 
            +
                    .group_by { |key, _| cluster.get_node_for_key(replica_policy, key) }
         | 
| 28 28 | 
             
                    .map { |node, keys_with_idx| BatchIndexNode.new(node, keys_with_idx) }
         | 
| 29 29 | 
             
                end
         | 
| 30 30 |  | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            # Copyright 2014- | 
| 1 | 
            +
            # Copyright 2014-2020 Aerospike, Inc.
         | 
| 2 2 | 
             
            #
         | 
| 3 3 | 
             
            # Portions may be licensed to Aerospike, Inc. under one or more contributor
         | 
| 4 4 | 
             
            # license agreements.
         | 
| @@ -16,6 +16,7 @@ | |
| 16 16 | 
             
            # the License.
         | 
| 17 17 |  | 
| 18 18 | 
             
            require 'time'
         | 
| 19 | 
            +
            require 'zlib'
         | 
| 19 20 |  | 
| 20 21 | 
             
            require 'msgpack'
         | 
| 21 22 | 
             
            require 'aerospike/result_code'
         | 
| @@ -42,6 +43,9 @@ module Aerospike | |
| 42 43 | 
             
              # Involve all replicas in read operation.
         | 
| 43 44 | 
             
              INFO1_CONSISTENCY_ALL = Integer(1 << 6)
         | 
| 44 45 |  | 
| 46 | 
            +
              # Tell server to compress it's response.
         | 
| 47 | 
            +
              INFO1_COMPRESS_RESPONSE = (1 << 7)
         | 
| 48 | 
            +
             | 
| 45 49 | 
             
              # Create or update record
         | 
| 46 50 | 
             
              INFO2_WRITE = Integer(1 << 0)
         | 
| 47 51 | 
             
              # Fling a record into the belly of Moloch.
         | 
| @@ -72,19 +76,29 @@ module Aerospike | |
| 72 76 | 
             
              OPERATION_HEADER_SIZE      = 8
         | 
| 73 77 | 
             
              MSG_REMAINING_HEADER_SIZE  = 22
         | 
| 74 78 | 
             
              DIGEST_SIZE                = 20
         | 
| 79 | 
            +
              COMPRESS_THRESHOLD         = 128
         | 
| 75 80 | 
             
              CL_MSG_VERSION             = 2
         | 
| 76 81 | 
             
              AS_MSG_TYPE                = 3
         | 
| 82 | 
            +
              AS_MSG_TYPE_COMPRESSED     = 4
         | 
| 77 83 |  | 
| 78 84 | 
             
              class Command #:nodoc:
         | 
| 79 85 |  | 
| 80 | 
            -
                def initialize(node)
         | 
| 86 | 
            +
                def initialize(node=nil)
         | 
| 87 | 
            +
                  @data_offset = 0
         | 
| 88 | 
            +
                  @data_buffer = nil
         | 
| 89 | 
            +
             | 
| 81 90 | 
             
                  @node = node
         | 
| 82 91 |  | 
| 92 | 
            +
                  @compress = false
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                  # will add before use
         | 
| 95 | 
            +
                  @sequence = Atomic.new(-1)
         | 
| 96 | 
            +
             | 
| 83 97 | 
             
                  self
         | 
| 84 98 | 
             
                end
         | 
| 85 99 |  | 
| 86 100 | 
             
                # List of all bins that this command will write to - sub-classes should
         | 
| 87 | 
            -
                #  | 
| 101 | 
            +
                # override this as appropriate.
         | 
| 88 102 | 
             
                def write_bins
         | 
| 89 103 | 
             
                  []
         | 
| 90 104 | 
             
                end
         | 
| @@ -93,6 +107,9 @@ module Aerospike | |
| 93 107 | 
             
                def set_write(policy, operation, key, bins)
         | 
| 94 108 | 
             
                  begin_cmd
         | 
| 95 109 | 
             
                  field_count = estimate_key_size(key, policy)
         | 
| 110 | 
            +
                  
         | 
| 111 | 
            +
                  predexp_size = estimate_predexp(policy.predexp)
         | 
| 112 | 
            +
                  field_count += 1 if predexp_size > 0
         | 
| 96 113 |  | 
| 97 114 | 
             
                  bins.each do |bin|
         | 
| 98 115 | 
             
                    estimate_operation_size_for_bin(bin)
         | 
| @@ -102,21 +119,28 @@ module Aerospike | |
| 102 119 |  | 
| 103 120 | 
             
                  write_header_with_policy(policy, 0, INFO2_WRITE, field_count, bins.length)
         | 
| 104 121 | 
             
                  write_key(key, policy)
         | 
| 122 | 
            +
                  write_predexp(policy.predexp, predexp_size)
         | 
| 105 123 |  | 
| 106 124 | 
             
                  bins.each do |bin|
         | 
| 107 125 | 
             
                    write_operation_for_bin(bin, operation)
         | 
| 108 126 | 
             
                  end
         | 
| 109 127 |  | 
| 110 128 | 
             
                  end_cmd
         | 
| 129 | 
            +
                  mark_compressed(policy)
         | 
| 111 130 | 
             
                end
         | 
| 112 131 |  | 
| 113 132 | 
             
                # Writes the command for delete operations
         | 
| 114 133 | 
             
                def set_delete(policy, key)
         | 
| 115 134 | 
             
                  begin_cmd
         | 
| 116 135 | 
             
                  field_count = estimate_key_size(key)
         | 
| 136 | 
            +
                  
         | 
| 137 | 
            +
                  predexp_size = estimate_predexp(policy.predexp)
         | 
| 138 | 
            +
                  field_count += 1 if predexp_size > 0
         | 
| 139 | 
            +
             | 
| 117 140 | 
             
                  size_buffer
         | 
| 118 141 | 
             
                  write_header_with_policy(policy, 0, INFO2_WRITE|INFO2_DELETE, field_count, 0)
         | 
| 119 142 | 
             
                  write_key(key)
         | 
| 143 | 
            +
                  write_predexp(policy.predexp, predexp_size)
         | 
| 120 144 | 
             
                  end_cmd
         | 
| 121 145 | 
             
                end
         | 
| 122 146 |  | 
| @@ -124,10 +148,15 @@ module Aerospike | |
| 124 148 | 
             
                def set_touch(policy, key)
         | 
| 125 149 | 
             
                  begin_cmd
         | 
| 126 150 | 
             
                  field_count = estimate_key_size(key)
         | 
| 151 | 
            +
                  
         | 
| 152 | 
            +
                  predexp_size = estimate_predexp(policy.predexp)
         | 
| 153 | 
            +
                  field_count += 1 if predexp_size > 0
         | 
| 154 | 
            +
             | 
| 127 155 | 
             
                  estimate_operation_size
         | 
| 128 156 | 
             
                  size_buffer
         | 
| 129 157 | 
             
                  write_header_with_policy(policy, 0, INFO2_WRITE, field_count, 1)
         | 
| 130 158 | 
             
                  write_key(key)
         | 
| 159 | 
            +
                  write_predexp(policy.predexp, predexp_size)
         | 
| 131 160 | 
             
                  write_operation_for_operation_type(Aerospike::Operation::TOUCH)
         | 
| 132 161 | 
             
                  end_cmd
         | 
| 133 162 | 
             
                end
         | 
| @@ -136,9 +165,14 @@ module Aerospike | |
| 136 165 | 
             
                def set_exists(policy, key)
         | 
| 137 166 | 
             
                  begin_cmd
         | 
| 138 167 | 
             
                  field_count = estimate_key_size(key)
         | 
| 168 | 
            +
                  
         | 
| 169 | 
            +
                  predexp_size = estimate_predexp(policy.predexp)
         | 
| 170 | 
            +
                  field_count += 1 if predexp_size > 0
         | 
| 171 | 
            +
             | 
| 139 172 | 
             
                  size_buffer
         | 
| 140 173 | 
             
                  write_header(policy, INFO1_READ|INFO1_NOBINDATA, 0, field_count, 0)
         | 
| 141 174 | 
             
                  write_key(key)
         | 
| 175 | 
            +
                  write_predexp(policy.predexp, predexp_size)
         | 
| 142 176 | 
             
                  end_cmd
         | 
| 143 177 | 
             
                end
         | 
| 144 178 |  | 
| @@ -146,9 +180,14 @@ module Aerospike | |
| 146 180 | 
             
                def set_read_for_key_only(policy, key)
         | 
| 147 181 | 
             
                  begin_cmd
         | 
| 148 182 | 
             
                  field_count = estimate_key_size(key)
         | 
| 183 | 
            +
                  
         | 
| 184 | 
            +
                  predexp_size = estimate_predexp(policy.predexp)
         | 
| 185 | 
            +
                  field_count += 1 if predexp_size > 0
         | 
| 186 | 
            +
             | 
| 149 187 | 
             
                  size_buffer
         | 
| 150 188 | 
             
                  write_header(policy, INFO1_READ|INFO1_GET_ALL, 0, field_count, 0)
         | 
| 151 189 | 
             
                  write_key(key)
         | 
| 190 | 
            +
                  write_predexp(policy.predexp, predexp_size)
         | 
| 152 191 | 
             
                  end_cmd
         | 
| 153 192 | 
             
                end
         | 
| 154 193 |  | 
| @@ -157,6 +196,10 @@ module Aerospike | |
| 157 196 | 
             
                  if bin_names && bin_names.length > 0
         | 
| 158 197 | 
             
                    begin_cmd
         | 
| 159 198 | 
             
                    field_count = estimate_key_size(key)
         | 
| 199 | 
            +
                    
         | 
| 200 | 
            +
                    predexp_size = estimate_predexp(policy.predexp)
         | 
| 201 | 
            +
                    field_count += 1 if predexp_size > 0
         | 
| 202 | 
            +
             | 
| 160 203 |  | 
| 161 204 | 
             
                    bin_names.each do |bin_name|
         | 
| 162 205 | 
             
                      estimate_operation_size_for_bin_name(bin_name)
         | 
| @@ -165,6 +208,7 @@ module Aerospike | |
| 165 208 | 
             
                    size_buffer
         | 
| 166 209 | 
             
                    write_header(policy, INFO1_READ, 0, field_count, bin_names.length)
         | 
| 167 210 | 
             
                    write_key(key)
         | 
| 211 | 
            +
                    write_predexp(policy.predexp, predexp_size)
         | 
| 168 212 |  | 
| 169 213 | 
             
                    bin_names.each do |bin_name|
         | 
| 170 214 | 
             
                      write_operation_for_bin_name(bin_name, Aerospike::Operation::READ)
         | 
| @@ -180,6 +224,10 @@ module Aerospike | |
| 180 224 | 
             
                def set_read_header(policy, key)
         | 
| 181 225 | 
             
                  begin_cmd
         | 
| 182 226 | 
             
                  field_count = estimate_key_size(key)
         | 
| 227 | 
            +
                  
         | 
| 228 | 
            +
                  predexp_size = estimate_predexp(policy.predexp)
         | 
| 229 | 
            +
                  field_count += 1 if predexp_size > 0
         | 
| 230 | 
            +
             | 
| 183 231 | 
             
                  estimate_operation_size_for_bin_name('')
         | 
| 184 232 | 
             
                  size_buffer
         | 
| 185 233 |  | 
| @@ -190,6 +238,7 @@ module Aerospike | |
| 190 238 | 
             
                  write_header(policy, INFO1_READ, 0, field_count, 1)
         | 
| 191 239 |  | 
| 192 240 | 
             
                  write_key(key)
         | 
| 241 | 
            +
                  write_predexp(policy.predexp, predexp_size)
         | 
| 193 242 | 
             
                  write_operation_for_bin_name('', Aerospike::Operation::READ)
         | 
| 194 243 | 
             
                  end_cmd
         | 
| 195 244 | 
             
                end
         | 
| @@ -198,6 +247,10 @@ module Aerospike | |
| 198 247 | 
             
                def set_operate(policy, key, operations)
         | 
| 199 248 | 
             
                  begin_cmd
         | 
| 200 249 | 
             
                  field_count = estimate_key_size(key, policy)
         | 
| 250 | 
            +
                  
         | 
| 251 | 
            +
                  predexp_size = estimate_predexp(policy.predexp)
         | 
| 252 | 
            +
                  field_count += 1 if predexp_size > 0
         | 
| 253 | 
            +
             | 
| 201 254 | 
             
                  read_attr = 0
         | 
| 202 255 | 
             
                  write_attr = 0
         | 
| 203 256 | 
             
                  read_header = false
         | 
| @@ -205,19 +258,22 @@ module Aerospike | |
| 205 258 | 
             
                  operations.each do |operation|
         | 
| 206 259 | 
             
                    case operation.op_type
         | 
| 207 260 | 
             
                    when Aerospike::Operation::READ
         | 
| 208 | 
            -
             | 
| 261 | 
            +
                      read_attr |= INFO1_READ
         | 
| 209 262 |  | 
| 210 263 | 
             
                      # Read all bins if no bin is specified.
         | 
| 211 264 | 
             
                      read_attr |= INFO1_GET_ALL unless operation.bin_name
         | 
| 212 265 |  | 
| 213 266 | 
             
                    when Aerospike::Operation::READ_HEADER
         | 
| 214 | 
            -
             | 
| 215 | 
            -
             | 
| 216 | 
            -
             | 
| 217 | 
            -
             | 
| 218 | 
            -
             | 
| 267 | 
            +
                      # The server does not currently return record header data with _INFO1_NOBINDATA attribute set.
         | 
| 268 | 
            +
                      # The workaround is to request a non-existent bin.
         | 
| 269 | 
            +
                      # TODO: Fix this on server.
         | 
| 270 | 
            +
                      # read_attr |= _INFO1_READ | _INFO1_NOBINDATA
         | 
| 271 | 
            +
                      read_attr |= INFO1_READ
         | 
| 219 272 | 
             
                      read_header = true
         | 
| 220 273 |  | 
| 274 | 
            +
                    when Aerospike::Operation::CDT_READ
         | 
| 275 | 
            +
                      read_attr |= INFO1_READ
         | 
| 276 | 
            +
             | 
| 221 277 | 
             
                    else
         | 
| 222 278 | 
             
                      write_attr = INFO2_WRITE
         | 
| 223 279 | 
             
                    end
         | 
| @@ -232,6 +288,7 @@ module Aerospike | |
| 232 288 | 
             
                    write_header(policy, read_attr, write_attr, field_count, operations.length)
         | 
| 233 289 | 
             
                  end
         | 
| 234 290 | 
             
                  write_key(key, policy)
         | 
| 291 | 
            +
                  write_predexp(policy.predexp, predexp_size)
         | 
| 235 292 |  | 
| 236 293 | 
             
                  operations.each do |operation|
         | 
| 237 294 | 
             
                    write_operation_for_operation(operation)
         | 
| @@ -240,11 +297,16 @@ module Aerospike | |
| 240 297 | 
             
                  write_operation_for_bin(nil, Aerospike::Operation::READ) if read_header
         | 
| 241 298 |  | 
| 242 299 | 
             
                  end_cmd
         | 
| 300 | 
            +
                  mark_compressed(policy)
         | 
| 243 301 | 
             
                end
         | 
| 244 302 |  | 
| 245 303 | 
             
                def set_udf(policy, key, package_name, function_name, args)
         | 
| 246 304 | 
             
                  begin_cmd
         | 
| 247 305 | 
             
                  field_count = estimate_key_size(key, policy)
         | 
| 306 | 
            +
                  
         | 
| 307 | 
            +
                  predexp_size = estimate_predexp(policy.predexp)
         | 
| 308 | 
            +
                  field_count += 1 if predexp_size > 0
         | 
| 309 | 
            +
             | 
| 248 310 | 
             
                  arg_bytes = args.to_bytes
         | 
| 249 311 |  | 
| 250 312 | 
             
                  field_count += estimate_udf_size(package_name, function_name, arg_bytes)
         | 
| @@ -252,11 +314,13 @@ module Aerospike | |
| 252 314 |  | 
| 253 315 | 
             
                  write_header(policy, 0, INFO2_WRITE, field_count, 0)
         | 
| 254 316 | 
             
                  write_key(key, policy)
         | 
| 317 | 
            +
                  write_predexp(policy.predexp, predexp_size)
         | 
| 255 318 | 
             
                  write_field_string(package_name, Aerospike::FieldType::UDF_PACKAGE_NAME)
         | 
| 256 319 | 
             
                  write_field_string(function_name, Aerospike::FieldType::UDF_FUNCTION)
         | 
| 257 320 | 
             
                  write_field_bytes(arg_bytes, Aerospike::FieldType::UDF_ARGLIST)
         | 
| 258 321 |  | 
| 259 322 | 
             
                  end_cmd
         | 
| 323 | 
            +
                  mark_compressed(policy)
         | 
| 260 324 | 
             
                end
         | 
| 261 325 |  | 
| 262 326 | 
             
                def set_scan(policy, namespace, set_name, bin_names)
         | 
| @@ -273,6 +337,14 @@ module Aerospike | |
| 273 337 | 
             
                    @data_offset += set_name.bytesize + FIELD_HEADER_SIZE
         | 
| 274 338 | 
             
                    field_count += 1
         | 
| 275 339 | 
             
                  end
         | 
| 340 | 
            +
                  
         | 
| 341 | 
            +
                  if policy.records_per_second > 0
         | 
| 342 | 
            +
                    @data_offset += 4 + FIELD_HEADER_SIZE
         | 
| 343 | 
            +
                    field_count += 1
         | 
| 344 | 
            +
                  end
         | 
| 345 | 
            +
             | 
| 346 | 
            +
                  predexp_size = estimate_predexp(policy.predexp)
         | 
| 347 | 
            +
                  field_count += 1 if predexp_size > 0
         | 
| 276 348 |  | 
| 277 349 | 
             
                  # Estimate scan options size.
         | 
| 278 350 | 
             
                  @data_offset += 2 + FIELD_HEADER_SIZE
         | 
| @@ -310,6 +382,12 @@ module Aerospike | |
| 310 382 | 
             
                    write_field_string(set_name, Aerospike::FieldType::TABLE)
         | 
| 311 383 | 
             
                  end
         | 
| 312 384 |  | 
| 385 | 
            +
                  if policy.records_per_second > 0
         | 
| 386 | 
            +
                    write_field_int(policy.records_per_second, Aerospike::FieldType::RECORDS_PER_SECOND)
         | 
| 387 | 
            +
                  end
         | 
| 388 | 
            +
             | 
| 389 | 
            +
                  write_predexp(policy.predexp, predexp_size)
         | 
| 390 | 
            +
             | 
| 313 391 | 
             
                  write_field_header(2, Aerospike::FieldType::SCAN_OPTIONS)
         | 
| 314 392 |  | 
| 315 393 | 
             
                  priority = policy.priority & 0xFF
         | 
| @@ -355,6 +433,7 @@ module Aerospike | |
| 355 433 | 
             
                    break if @policy.timeout > 0 && Time.now > limit
         | 
| 356 434 |  | 
| 357 435 | 
             
                    begin
         | 
| 436 | 
            +
                      @node = get_node
         | 
| 358 437 | 
             
                      @conn = @node.get_connection(@policy.timeout)
         | 
| 359 438 | 
             
                    rescue => e
         | 
| 360 439 | 
             
                      # Socket connection error has occurred. Decrease health and retry.
         | 
| @@ -498,9 +577,20 @@ module Aerospike | |
| 498 577 | 
             
                  @data_offset += OPERATION_HEADER_SIZE
         | 
| 499 578 | 
             
                end
         | 
| 500 579 |  | 
| 580 | 
            +
                def estimate_predexp(predexp)
         | 
| 581 | 
            +
                  if predexp && predexp.size > 0
         | 
| 582 | 
            +
                    @data_offset += FIELD_HEADER_SIZE
         | 
| 583 | 
            +
                    sz = Aerospike::PredExp.estimate_size(predexp)
         | 
| 584 | 
            +
                    @data_offset += sz
         | 
| 585 | 
            +
                    return sz
         | 
| 586 | 
            +
                  end
         | 
| 587 | 
            +
                  return 0
         | 
| 588 | 
            +
                end
         | 
| 589 | 
            +
             | 
| 501 590 | 
             
                # Generic header write.
         | 
| 502 591 | 
             
                def write_header(policy, read_attr, write_attr, field_count, operation_count)
         | 
| 503 592 | 
             
                  read_attr |= INFO1_CONSISTENCY_ALL if policy.consistency_level == Aerospike::ConsistencyLevel::CONSISTENCY_ALL
         | 
| 593 | 
            +
                  read_attr |= INFO1_COMPRESS_RESPONSE if policy.use_compression
         | 
| 504 594 |  | 
| 505 595 | 
             
                  # Write all header data except total size which must be written last.
         | 
| 506 596 | 
             
                  @data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message heade.length.
         | 
| @@ -550,6 +640,7 @@ module Aerospike | |
| 550 640 | 
             
                  info_attr |= INFO3_COMMIT_MASTER if policy.commit_level == Aerospike::CommitLevel::COMMIT_MASTER
         | 
| 551 641 | 
             
                  read_attr |= INFO1_CONSISTENCY_ALL if policy.consistency_level == Aerospike::ConsistencyLevel::CONSISTENCY_ALL
         | 
| 552 642 | 
             
                  write_attr |= INFO2_DURABLE_DELETE if policy.durable_delete
         | 
| 643 | 
            +
                  read_attr |= INFO1_COMPRESS_RESPONSE if policy.use_compression
         | 
| 553 644 |  | 
| 554 645 | 
             
                  # Write all header data except total size which must be written last.
         | 
| 555 646 | 
             
                  @data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message heade.length.
         | 
| @@ -681,21 +772,34 @@ module Aerospike | |
| 681 772 | 
             
                  @data_offset += len
         | 
| 682 773 | 
             
                end
         | 
| 683 774 |  | 
| 775 | 
            +
                def write_field_int(i, ftype)
         | 
| 776 | 
            +
                  @data_buffer.write_int32(i, @data_offset+FIELD_HEADER_SIZE)
         | 
| 777 | 
            +
                  write_field_header(4, ftype)
         | 
| 778 | 
            +
                  @data_offset += 4
         | 
| 779 | 
            +
                end
         | 
| 780 | 
            +
             | 
| 684 781 | 
             
                def write_field_bytes(bytes, ftype)
         | 
| 685 782 | 
             
                  @data_buffer.write_binary(bytes, @data_offset+FIELD_HEADER_SIZE)
         | 
| 686 | 
            -
             | 
| 687 783 | 
             
                  write_field_header(bytes.bytesize, ftype)
         | 
| 688 784 | 
             
                  @data_offset += bytes.bytesize
         | 
| 689 785 | 
             
                end
         | 
| 690 786 |  | 
| 691 787 | 
             
                def write_field_header(size, ftype)
         | 
| 692 | 
            -
                  # Buffer.Int32ToBytes(size+1), @data_buffer, @data_offset
         | 
| 693 788 | 
             
                  @data_buffer.write_int32(size+1, @data_offset)
         | 
| 694 789 | 
             
                  @data_offset += 4
         | 
| 695 790 | 
             
                  @data_buffer.write_byte(ftype, @data_offset)
         | 
| 696 791 | 
             
                  @data_offset += 1
         | 
| 697 792 | 
             
                end
         | 
| 698 793 |  | 
| 794 | 
            +
                def write_predexp(predexp, predexp_size)
         | 
| 795 | 
            +
                  if predexp && predexp.size > 0
         | 
| 796 | 
            +
                    write_field_header(predexp_size, Aerospike::FieldType::PREDEXP)
         | 
| 797 | 
            +
                    @data_offset = Aerospike::PredExp.write(
         | 
| 798 | 
            +
                      predexp, @data_buffer, @data_offset
         | 
| 799 | 
            +
                    )
         | 
| 800 | 
            +
                  end
         | 
| 801 | 
            +
                end
         | 
| 802 | 
            +
             | 
| 699 803 | 
             
                def begin_cmd
         | 
| 700 804 | 
             
                  @data_offset = MSG_TOTAL_HEADER_SIZE
         | 
| 701 805 | 
             
                end
         | 
| @@ -719,6 +823,48 @@ module Aerospike | |
| 719 823 | 
             
                  @data_buffer.write_int64(size, 0)
         | 
| 720 824 | 
             
                end
         | 
| 721 825 |  | 
| 826 | 
            +
                def use_compression?
         | 
| 827 | 
            +
                  @compress
         | 
| 828 | 
            +
                end
         | 
| 829 | 
            +
             | 
| 830 | 
            +
                def compress_buffer
         | 
| 831 | 
            +
                  if @data_offset > COMPRESS_THRESHOLD
         | 
| 832 | 
            +
                    compressed = Zlib::deflate(@data_buffer.buf, Zlib::DEFAULT_COMPRESSION)
         | 
| 833 | 
            +
             | 
| 834 | 
            +
                    # write original size as header
         | 
| 835 | 
            +
                    proto_s = "%08d" % 0
         | 
| 836 | 
            +
                    proto_s[0, 8] = [@data_offset].pack('q>')
         | 
| 837 | 
            +
                    compressed.prepend(proto_s)
         | 
| 838 | 
            +
             | 
| 839 | 
            +
                    # write proto
         | 
| 840 | 
            +
                    proto = (compressed.size+8) | Integer(CL_MSG_VERSION << 56) | Integer(AS_MSG_TYPE << 48)
         | 
| 841 | 
            +
                    proto_s = "%08d" % 0
         | 
| 842 | 
            +
                    proto_s[0, 8] = [proto].pack('q>')
         | 
| 843 | 
            +
                    compressed.prepend(proto_s)
         | 
| 844 | 
            +
             | 
| 845 | 
            +
                    @data_buffer = Buffer.new(-1, compressed)
         | 
| 846 | 
            +
                    @data_offset = @data_buffer.size
         | 
| 847 | 
            +
                  end
         | 
| 848 | 
            +
                end
         | 
| 849 | 
            +
             | 
| 850 | 
            +
                # isCompressed returns the length of the compressed buffer.
         | 
| 851 | 
            +
                # If the buffer is not compressed, the result will be -1
         | 
| 852 | 
            +
                def compressed_size
         | 
| 853 | 
            +
                  # A number of these are commented out because we just don't care enough to read
         | 
| 854 | 
            +
                  # that section of the header. If we do care, uncomment and check!
         | 
| 855 | 
            +
                  proto = @data_buffer.read_int64(0)
         | 
| 856 | 
            +
                  size = proto & 0xFFFFFFFFFFFF
         | 
| 857 | 
            +
                  msg_type = (proto >> 48) & 0xFF
         | 
| 858 | 
            +
             | 
| 859 | 
            +
                  return nil if msg_type != AS_MSG_TYPE_COMPRESSED
         | 
| 860 | 
            +
             | 
| 861 | 
            +
                  size
         | 
| 862 | 
            +
                end
         | 
| 863 | 
            +
             | 
| 864 | 
            +
                def mark_compressed(policy)
         | 
| 865 | 
            +
                  @compress = policy.use_compression
         | 
| 866 | 
            +
                end
         | 
| 867 | 
            +
             | 
| 722 868 | 
             
              end # class
         | 
| 723 869 |  | 
| 724 870 | 
             
            end # module
         |