aerospike 2.11.0 → 2.16.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 -1
- 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/bit_operation.rb +376 -0
- data/lib/aerospike/cdt/bit_overflow_action.rb +46 -0
- data/lib/aerospike/cdt/bit_policy.rb +36 -0
- data/lib/aerospike/cdt/bit_resize_flags.rb +44 -0
- data/lib/aerospike/cdt/bit_write_flags.rb +51 -0
- data/lib/aerospike/cdt/context.rb +101 -0
- data/lib/aerospike/cdt/hll_operation.rb +200 -0
- data/lib/aerospike/cdt/hll_policy.rb +34 -0
- data/lib/aerospike/cdt/hll_write_flags.rb +53 -0
- data/lib/aerospike/cdt/list_operation.rb +127 -97
- data/lib/aerospike/cdt/list_sort_flags.rb +10 -2
- data/lib/aerospike/cdt/map_operation.rb +154 -93
- 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 +33 -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 +168 -12
- 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 +2 -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 +6 -1
- data/lib/aerospike/geo_json.rb +1 -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 +4 -19
- data/lib/aerospike/operation.rb +13 -3
- 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/query_command.rb +16 -5
- data/lib/aerospike/query/recordset.rb +1 -1
- data/lib/aerospike/query/scan_command.rb +1 -1
- data/lib/aerospike/query/statement.rb +9 -2
- data/lib/aerospike/query/stream_command.rb +1 -1
- data/lib/aerospike/record.rb +1 -1
- data/lib/aerospike/result_code.rb +26 -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 +1 -1
- data/lib/aerospike/value/particle_type.rb +2 -2
- data/lib/aerospike/value/value.rb +165 -33
- data/lib/aerospike/version.rb +1 -1
- metadata +20 -8
- data/lib/aerospike/cluster/partition_tokenizer_new.rb +0 -130
- data/lib/aerospike/cluster/partition_tokenizer_old.rb +0 -135
@@ -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.
|
@@ -55,6 +59,9 @@ module Aerospike
|
|
55
59
|
# Create only. Fail if record already exists.
|
56
60
|
INFO2_CREATE_ONLY = Integer(1 << 5)
|
57
61
|
|
62
|
+
# Return a result for every operation.
|
63
|
+
INFO2_RESPOND_ALL_OPS = Integer(1 << 7)
|
64
|
+
|
58
65
|
# This is the last of a multi-part message.
|
59
66
|
INFO3_LAST = Integer(1 << 0)
|
60
67
|
# Commit to master only before declaring success.
|
@@ -72,19 +79,29 @@ module Aerospike
|
|
72
79
|
OPERATION_HEADER_SIZE = 8
|
73
80
|
MSG_REMAINING_HEADER_SIZE = 22
|
74
81
|
DIGEST_SIZE = 20
|
82
|
+
COMPRESS_THRESHOLD = 128
|
75
83
|
CL_MSG_VERSION = 2
|
76
84
|
AS_MSG_TYPE = 3
|
85
|
+
AS_MSG_TYPE_COMPRESSED = 4
|
77
86
|
|
78
87
|
class Command #:nodoc:
|
79
88
|
|
80
|
-
def initialize(node)
|
89
|
+
def initialize(node=nil)
|
90
|
+
@data_offset = 0
|
91
|
+
@data_buffer = nil
|
92
|
+
|
81
93
|
@node = node
|
82
94
|
|
95
|
+
@compress = false
|
96
|
+
|
97
|
+
# will add before use
|
98
|
+
@sequence = Atomic.new(-1)
|
99
|
+
|
83
100
|
self
|
84
101
|
end
|
85
102
|
|
86
103
|
# List of all bins that this command will write to - sub-classes should
|
87
|
-
#
|
104
|
+
# override this as appropriate.
|
88
105
|
def write_bins
|
89
106
|
[]
|
90
107
|
end
|
@@ -93,6 +110,9 @@ module Aerospike
|
|
93
110
|
def set_write(policy, operation, key, bins)
|
94
111
|
begin_cmd
|
95
112
|
field_count = estimate_key_size(key, policy)
|
113
|
+
|
114
|
+
predexp_size = estimate_predexp(policy.predexp)
|
115
|
+
field_count += 1 if predexp_size > 0
|
96
116
|
|
97
117
|
bins.each do |bin|
|
98
118
|
estimate_operation_size_for_bin(bin)
|
@@ -102,21 +122,28 @@ module Aerospike
|
|
102
122
|
|
103
123
|
write_header_with_policy(policy, 0, INFO2_WRITE, field_count, bins.length)
|
104
124
|
write_key(key, policy)
|
125
|
+
write_predexp(policy.predexp, predexp_size)
|
105
126
|
|
106
127
|
bins.each do |bin|
|
107
128
|
write_operation_for_bin(bin, operation)
|
108
129
|
end
|
109
130
|
|
110
131
|
end_cmd
|
132
|
+
mark_compressed(policy)
|
111
133
|
end
|
112
134
|
|
113
135
|
# Writes the command for delete operations
|
114
136
|
def set_delete(policy, key)
|
115
137
|
begin_cmd
|
116
138
|
field_count = estimate_key_size(key)
|
139
|
+
|
140
|
+
predexp_size = estimate_predexp(policy.predexp)
|
141
|
+
field_count += 1 if predexp_size > 0
|
142
|
+
|
117
143
|
size_buffer
|
118
144
|
write_header_with_policy(policy, 0, INFO2_WRITE|INFO2_DELETE, field_count, 0)
|
119
145
|
write_key(key)
|
146
|
+
write_predexp(policy.predexp, predexp_size)
|
120
147
|
end_cmd
|
121
148
|
end
|
122
149
|
|
@@ -124,10 +151,15 @@ module Aerospike
|
|
124
151
|
def set_touch(policy, key)
|
125
152
|
begin_cmd
|
126
153
|
field_count = estimate_key_size(key)
|
154
|
+
|
155
|
+
predexp_size = estimate_predexp(policy.predexp)
|
156
|
+
field_count += 1 if predexp_size > 0
|
157
|
+
|
127
158
|
estimate_operation_size
|
128
159
|
size_buffer
|
129
160
|
write_header_with_policy(policy, 0, INFO2_WRITE, field_count, 1)
|
130
161
|
write_key(key)
|
162
|
+
write_predexp(policy.predexp, predexp_size)
|
131
163
|
write_operation_for_operation_type(Aerospike::Operation::TOUCH)
|
132
164
|
end_cmd
|
133
165
|
end
|
@@ -136,9 +168,14 @@ module Aerospike
|
|
136
168
|
def set_exists(policy, key)
|
137
169
|
begin_cmd
|
138
170
|
field_count = estimate_key_size(key)
|
171
|
+
|
172
|
+
predexp_size = estimate_predexp(policy.predexp)
|
173
|
+
field_count += 1 if predexp_size > 0
|
174
|
+
|
139
175
|
size_buffer
|
140
176
|
write_header(policy, INFO1_READ|INFO1_NOBINDATA, 0, field_count, 0)
|
141
177
|
write_key(key)
|
178
|
+
write_predexp(policy.predexp, predexp_size)
|
142
179
|
end_cmd
|
143
180
|
end
|
144
181
|
|
@@ -146,9 +183,14 @@ module Aerospike
|
|
146
183
|
def set_read_for_key_only(policy, key)
|
147
184
|
begin_cmd
|
148
185
|
field_count = estimate_key_size(key)
|
186
|
+
|
187
|
+
predexp_size = estimate_predexp(policy.predexp)
|
188
|
+
field_count += 1 if predexp_size > 0
|
189
|
+
|
149
190
|
size_buffer
|
150
191
|
write_header(policy, INFO1_READ|INFO1_GET_ALL, 0, field_count, 0)
|
151
192
|
write_key(key)
|
193
|
+
write_predexp(policy.predexp, predexp_size)
|
152
194
|
end_cmd
|
153
195
|
end
|
154
196
|
|
@@ -157,6 +199,10 @@ module Aerospike
|
|
157
199
|
if bin_names && bin_names.length > 0
|
158
200
|
begin_cmd
|
159
201
|
field_count = estimate_key_size(key)
|
202
|
+
|
203
|
+
predexp_size = estimate_predexp(policy.predexp)
|
204
|
+
field_count += 1 if predexp_size > 0
|
205
|
+
|
160
206
|
|
161
207
|
bin_names.each do |bin_name|
|
162
208
|
estimate_operation_size_for_bin_name(bin_name)
|
@@ -165,6 +211,7 @@ module Aerospike
|
|
165
211
|
size_buffer
|
166
212
|
write_header(policy, INFO1_READ, 0, field_count, bin_names.length)
|
167
213
|
write_key(key)
|
214
|
+
write_predexp(policy.predexp, predexp_size)
|
168
215
|
|
169
216
|
bin_names.each do |bin_name|
|
170
217
|
write_operation_for_bin_name(bin_name, Aerospike::Operation::READ)
|
@@ -180,6 +227,10 @@ module Aerospike
|
|
180
227
|
def set_read_header(policy, key)
|
181
228
|
begin_cmd
|
182
229
|
field_count = estimate_key_size(key)
|
230
|
+
|
231
|
+
predexp_size = estimate_predexp(policy.predexp)
|
232
|
+
field_count += 1 if predexp_size > 0
|
233
|
+
|
183
234
|
estimate_operation_size_for_bin_name('')
|
184
235
|
size_buffer
|
185
236
|
|
@@ -190,6 +241,7 @@ module Aerospike
|
|
190
241
|
write_header(policy, INFO1_READ, 0, field_count, 1)
|
191
242
|
|
192
243
|
write_key(key)
|
244
|
+
write_predexp(policy.predexp, predexp_size)
|
193
245
|
write_operation_for_bin_name('', Aerospike::Operation::READ)
|
194
246
|
end_cmd
|
195
247
|
end
|
@@ -198,40 +250,55 @@ module Aerospike
|
|
198
250
|
def set_operate(policy, key, operations)
|
199
251
|
begin_cmd
|
200
252
|
field_count = estimate_key_size(key, policy)
|
253
|
+
|
254
|
+
predexp_size = estimate_predexp(policy.predexp)
|
255
|
+
field_count += 1 if predexp_size > 0
|
256
|
+
|
201
257
|
read_attr = 0
|
202
258
|
write_attr = 0
|
203
259
|
read_header = false
|
260
|
+
record_bin_multiplicity = policy.record_bin_multiplicity == RecordBinMultiplicity::ARRAY
|
204
261
|
|
205
262
|
operations.each do |operation|
|
206
263
|
case operation.op_type
|
207
|
-
when Aerospike::Operation::READ
|
208
|
-
|
264
|
+
when Aerospike::Operation::READ, Aerospike::Operation::CDT_READ,
|
265
|
+
Aerospike::Operation::HLL_READ, Aerospike::Operation::BIT_READ
|
266
|
+
read_attr |= INFO1_READ
|
209
267
|
|
210
268
|
# Read all bins if no bin is specified.
|
211
269
|
read_attr |= INFO1_GET_ALL unless operation.bin_name
|
212
270
|
|
213
271
|
when Aerospike::Operation::READ_HEADER
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
272
|
+
# The server does not currently return record header data with _INFO1_NOBINDATA attribute set.
|
273
|
+
# The workaround is to request a non-existent bin.
|
274
|
+
# TODO: Fix this on server.
|
275
|
+
# read_attr |= _INFO1_READ | _INFO1_NOBINDATA
|
276
|
+
read_attr |= INFO1_READ
|
219
277
|
read_header = true
|
220
278
|
|
221
279
|
else
|
222
280
|
write_attr = INFO2_WRITE
|
223
281
|
end
|
224
282
|
|
283
|
+
if [Aerospike::Operation::HLL_MODIFY, Aerospike::Operation::HLL_READ,
|
284
|
+
Aerospike::Operation::BIT_MODIFY, Aerospike::Operation::BIT_READ].include?(operation.op_type)
|
285
|
+
record_bin_multiplicity = true
|
286
|
+
end
|
287
|
+
|
225
288
|
estimate_operation_size_for_operation(operation)
|
226
289
|
end
|
227
290
|
size_buffer
|
228
291
|
|
292
|
+
|
293
|
+
write_attr |= INFO2_RESPOND_ALL_OPS if write_attr != 0 && record_bin_multiplicity
|
294
|
+
|
229
295
|
if write_attr != 0
|
230
296
|
write_header_with_policy(policy, read_attr, write_attr, field_count, operations.length)
|
231
297
|
else
|
232
298
|
write_header(policy, read_attr, write_attr, field_count, operations.length)
|
233
299
|
end
|
234
300
|
write_key(key, policy)
|
301
|
+
write_predexp(policy.predexp, predexp_size)
|
235
302
|
|
236
303
|
operations.each do |operation|
|
237
304
|
write_operation_for_operation(operation)
|
@@ -240,11 +307,16 @@ module Aerospike
|
|
240
307
|
write_operation_for_bin(nil, Aerospike::Operation::READ) if read_header
|
241
308
|
|
242
309
|
end_cmd
|
310
|
+
mark_compressed(policy)
|
243
311
|
end
|
244
312
|
|
245
313
|
def set_udf(policy, key, package_name, function_name, args)
|
246
314
|
begin_cmd
|
247
315
|
field_count = estimate_key_size(key, policy)
|
316
|
+
|
317
|
+
predexp_size = estimate_predexp(policy.predexp)
|
318
|
+
field_count += 1 if predexp_size > 0
|
319
|
+
|
248
320
|
arg_bytes = args.to_bytes
|
249
321
|
|
250
322
|
field_count += estimate_udf_size(package_name, function_name, arg_bytes)
|
@@ -252,11 +324,13 @@ module Aerospike
|
|
252
324
|
|
253
325
|
write_header(policy, 0, INFO2_WRITE, field_count, 0)
|
254
326
|
write_key(key, policy)
|
327
|
+
write_predexp(policy.predexp, predexp_size)
|
255
328
|
write_field_string(package_name, Aerospike::FieldType::UDF_PACKAGE_NAME)
|
256
329
|
write_field_string(function_name, Aerospike::FieldType::UDF_FUNCTION)
|
257
330
|
write_field_bytes(arg_bytes, Aerospike::FieldType::UDF_ARGLIST)
|
258
331
|
|
259
332
|
end_cmd
|
333
|
+
mark_compressed(policy)
|
260
334
|
end
|
261
335
|
|
262
336
|
def set_scan(policy, namespace, set_name, bin_names)
|
@@ -273,6 +347,14 @@ module Aerospike
|
|
273
347
|
@data_offset += set_name.bytesize + FIELD_HEADER_SIZE
|
274
348
|
field_count += 1
|
275
349
|
end
|
350
|
+
|
351
|
+
if policy.records_per_second > 0
|
352
|
+
@data_offset += 4 + FIELD_HEADER_SIZE
|
353
|
+
field_count += 1
|
354
|
+
end
|
355
|
+
|
356
|
+
predexp_size = estimate_predexp(policy.predexp)
|
357
|
+
field_count += 1 if predexp_size > 0
|
276
358
|
|
277
359
|
# Estimate scan options size.
|
278
360
|
@data_offset += 2 + FIELD_HEADER_SIZE
|
@@ -310,6 +392,12 @@ module Aerospike
|
|
310
392
|
write_field_string(set_name, Aerospike::FieldType::TABLE)
|
311
393
|
end
|
312
394
|
|
395
|
+
if policy.records_per_second > 0
|
396
|
+
write_field_int(policy.records_per_second, Aerospike::FieldType::RECORDS_PER_SECOND)
|
397
|
+
end
|
398
|
+
|
399
|
+
write_predexp(policy.predexp, predexp_size)
|
400
|
+
|
313
401
|
write_field_header(2, Aerospike::FieldType::SCAN_OPTIONS)
|
314
402
|
|
315
403
|
priority = policy.priority & 0xFF
|
@@ -355,6 +443,7 @@ module Aerospike
|
|
355
443
|
break if @policy.timeout > 0 && Time.now > limit
|
356
444
|
|
357
445
|
begin
|
446
|
+
@node = get_node
|
358
447
|
@conn = @node.get_connection(@policy.timeout)
|
359
448
|
rescue => e
|
360
449
|
# Socket connection error has occurred. Decrease health and retry.
|
@@ -498,9 +587,20 @@ module Aerospike
|
|
498
587
|
@data_offset += OPERATION_HEADER_SIZE
|
499
588
|
end
|
500
589
|
|
590
|
+
def estimate_predexp(predexp)
|
591
|
+
if predexp && predexp.size > 0
|
592
|
+
@data_offset += FIELD_HEADER_SIZE
|
593
|
+
sz = Aerospike::PredExp.estimate_size(predexp)
|
594
|
+
@data_offset += sz
|
595
|
+
return sz
|
596
|
+
end
|
597
|
+
return 0
|
598
|
+
end
|
599
|
+
|
501
600
|
# Generic header write.
|
502
601
|
def write_header(policy, read_attr, write_attr, field_count, operation_count)
|
503
602
|
read_attr |= INFO1_CONSISTENCY_ALL if policy.consistency_level == Aerospike::ConsistencyLevel::CONSISTENCY_ALL
|
603
|
+
read_attr |= INFO1_COMPRESS_RESPONSE if policy.use_compression
|
504
604
|
|
505
605
|
# Write all header data except total size which must be written last.
|
506
606
|
@data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message heade.length.
|
@@ -550,6 +650,7 @@ module Aerospike
|
|
550
650
|
info_attr |= INFO3_COMMIT_MASTER if policy.commit_level == Aerospike::CommitLevel::COMMIT_MASTER
|
551
651
|
read_attr |= INFO1_CONSISTENCY_ALL if policy.consistency_level == Aerospike::ConsistencyLevel::CONSISTENCY_ALL
|
552
652
|
write_attr |= INFO2_DURABLE_DELETE if policy.durable_delete
|
653
|
+
read_attr |= INFO1_COMPRESS_RESPONSE if policy.use_compression
|
553
654
|
|
554
655
|
# Write all header data except total size which must be written last.
|
555
656
|
@data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message heade.length.
|
@@ -681,21 +782,34 @@ module Aerospike
|
|
681
782
|
@data_offset += len
|
682
783
|
end
|
683
784
|
|
785
|
+
def write_field_int(i, ftype)
|
786
|
+
@data_buffer.write_int32(i, @data_offset+FIELD_HEADER_SIZE)
|
787
|
+
write_field_header(4, ftype)
|
788
|
+
@data_offset += 4
|
789
|
+
end
|
790
|
+
|
684
791
|
def write_field_bytes(bytes, ftype)
|
685
792
|
@data_buffer.write_binary(bytes, @data_offset+FIELD_HEADER_SIZE)
|
686
|
-
|
687
793
|
write_field_header(bytes.bytesize, ftype)
|
688
794
|
@data_offset += bytes.bytesize
|
689
795
|
end
|
690
796
|
|
691
797
|
def write_field_header(size, ftype)
|
692
|
-
# Buffer.Int32ToBytes(size+1), @data_buffer, @data_offset
|
693
798
|
@data_buffer.write_int32(size+1, @data_offset)
|
694
799
|
@data_offset += 4
|
695
800
|
@data_buffer.write_byte(ftype, @data_offset)
|
696
801
|
@data_offset += 1
|
697
802
|
end
|
698
803
|
|
804
|
+
def write_predexp(predexp, predexp_size)
|
805
|
+
if predexp && predexp.size > 0
|
806
|
+
write_field_header(predexp_size, Aerospike::FieldType::PREDEXP)
|
807
|
+
@data_offset = Aerospike::PredExp.write(
|
808
|
+
predexp, @data_buffer, @data_offset
|
809
|
+
)
|
810
|
+
end
|
811
|
+
end
|
812
|
+
|
699
813
|
def begin_cmd
|
700
814
|
@data_offset = MSG_TOTAL_HEADER_SIZE
|
701
815
|
end
|
@@ -719,6 +833,48 @@ module Aerospike
|
|
719
833
|
@data_buffer.write_int64(size, 0)
|
720
834
|
end
|
721
835
|
|
836
|
+
def use_compression?
|
837
|
+
@compress
|
838
|
+
end
|
839
|
+
|
840
|
+
def compress_buffer
|
841
|
+
if @data_offset > COMPRESS_THRESHOLD
|
842
|
+
compressed = Zlib::deflate(@data_buffer.buf, Zlib::DEFAULT_COMPRESSION)
|
843
|
+
|
844
|
+
# write original size as header
|
845
|
+
proto_s = "%08d" % 0
|
846
|
+
proto_s[0, 8] = [@data_offset].pack('q>')
|
847
|
+
compressed.prepend(proto_s)
|
848
|
+
|
849
|
+
# write proto
|
850
|
+
proto = (compressed.size+8) | Integer(CL_MSG_VERSION << 56) | Integer(AS_MSG_TYPE << 48)
|
851
|
+
proto_s = "%08d" % 0
|
852
|
+
proto_s[0, 8] = [proto].pack('q>')
|
853
|
+
compressed.prepend(proto_s)
|
854
|
+
|
855
|
+
@data_buffer = Buffer.new(-1, compressed)
|
856
|
+
@data_offset = @data_buffer.size
|
857
|
+
end
|
858
|
+
end
|
859
|
+
|
860
|
+
# isCompressed returns the length of the compressed buffer.
|
861
|
+
# If the buffer is not compressed, the result will be -1
|
862
|
+
def compressed_size
|
863
|
+
# A number of these are commented out because we just don't care enough to read
|
864
|
+
# that section of the header. If we do care, uncomment and check!
|
865
|
+
proto = @data_buffer.read_int64(0)
|
866
|
+
size = proto & 0xFFFFFFFFFFFF
|
867
|
+
msg_type = (proto >> 48) & 0xFF
|
868
|
+
|
869
|
+
return nil if msg_type != AS_MSG_TYPE_COMPRESSED
|
870
|
+
|
871
|
+
size
|
872
|
+
end
|
873
|
+
|
874
|
+
def mark_compressed(policy)
|
875
|
+
@compress = policy.use_compression
|
876
|
+
end
|
877
|
+
|
722
878
|
end # class
|
723
879
|
|
724
880
|
end # module
|