aerospike 2.10.0 → 2.15.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 +20 -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/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 +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 +34 -18
- 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 -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 +4 -19
- data/lib/aerospike/operation.rb +8 -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 +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 +7 -2
- data/lib/aerospike/value/particle_type.rb +2 -2
- data/lib/aerospike/value/value.rb +106 -29
- data/lib/aerospike/version.rb +1 -1
- metadata +22 -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,56 @@ 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
264
|
when Aerospike::Operation::READ
|
208
|
-
|
265
|
+
read_attr |= INFO1_READ
|
209
266
|
|
210
267
|
# Read all bins if no bin is specified.
|
211
268
|
read_attr |= INFO1_GET_ALL unless operation.bin_name
|
212
269
|
|
213
270
|
when Aerospike::Operation::READ_HEADER
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
271
|
+
# The server does not currently return record header data with _INFO1_NOBINDATA attribute set.
|
272
|
+
# The workaround is to request a non-existent bin.
|
273
|
+
# TODO: Fix this on server.
|
274
|
+
# read_attr |= _INFO1_READ | _INFO1_NOBINDATA
|
275
|
+
read_attr |= INFO1_READ
|
219
276
|
read_header = true
|
220
277
|
|
278
|
+
when Aerospike::Operation::CDT_READ,Aerospike::Operation::HLL_READ
|
279
|
+
read_attr |= INFO1_READ
|
280
|
+
|
221
281
|
else
|
222
282
|
write_attr = INFO2_WRITE
|
223
283
|
end
|
224
284
|
|
285
|
+
if [Aerospike::Operation::HLL_MODIFY, Aerospike::Operation::HLL_READ].include?(operation.op_type)
|
286
|
+
record_bin_multiplicity = true
|
287
|
+
end
|
288
|
+
|
225
289
|
estimate_operation_size_for_operation(operation)
|
226
290
|
end
|
227
291
|
size_buffer
|
228
292
|
|
293
|
+
|
294
|
+
write_attr |= INFO2_RESPOND_ALL_OPS if write_attr != 0 && record_bin_multiplicity
|
295
|
+
|
229
296
|
if write_attr != 0
|
230
297
|
write_header_with_policy(policy, read_attr, write_attr, field_count, operations.length)
|
231
298
|
else
|
232
299
|
write_header(policy, read_attr, write_attr, field_count, operations.length)
|
233
300
|
end
|
234
301
|
write_key(key, policy)
|
302
|
+
write_predexp(policy.predexp, predexp_size)
|
235
303
|
|
236
304
|
operations.each do |operation|
|
237
305
|
write_operation_for_operation(operation)
|
@@ -240,11 +308,16 @@ module Aerospike
|
|
240
308
|
write_operation_for_bin(nil, Aerospike::Operation::READ) if read_header
|
241
309
|
|
242
310
|
end_cmd
|
311
|
+
mark_compressed(policy)
|
243
312
|
end
|
244
313
|
|
245
314
|
def set_udf(policy, key, package_name, function_name, args)
|
246
315
|
begin_cmd
|
247
316
|
field_count = estimate_key_size(key, policy)
|
317
|
+
|
318
|
+
predexp_size = estimate_predexp(policy.predexp)
|
319
|
+
field_count += 1 if predexp_size > 0
|
320
|
+
|
248
321
|
arg_bytes = args.to_bytes
|
249
322
|
|
250
323
|
field_count += estimate_udf_size(package_name, function_name, arg_bytes)
|
@@ -252,11 +325,13 @@ module Aerospike
|
|
252
325
|
|
253
326
|
write_header(policy, 0, INFO2_WRITE, field_count, 0)
|
254
327
|
write_key(key, policy)
|
328
|
+
write_predexp(policy.predexp, predexp_size)
|
255
329
|
write_field_string(package_name, Aerospike::FieldType::UDF_PACKAGE_NAME)
|
256
330
|
write_field_string(function_name, Aerospike::FieldType::UDF_FUNCTION)
|
257
331
|
write_field_bytes(arg_bytes, Aerospike::FieldType::UDF_ARGLIST)
|
258
332
|
|
259
333
|
end_cmd
|
334
|
+
mark_compressed(policy)
|
260
335
|
end
|
261
336
|
|
262
337
|
def set_scan(policy, namespace, set_name, bin_names)
|
@@ -273,6 +348,14 @@ module Aerospike
|
|
273
348
|
@data_offset += set_name.bytesize + FIELD_HEADER_SIZE
|
274
349
|
field_count += 1
|
275
350
|
end
|
351
|
+
|
352
|
+
if policy.records_per_second > 0
|
353
|
+
@data_offset += 4 + FIELD_HEADER_SIZE
|
354
|
+
field_count += 1
|
355
|
+
end
|
356
|
+
|
357
|
+
predexp_size = estimate_predexp(policy.predexp)
|
358
|
+
field_count += 1 if predexp_size > 0
|
276
359
|
|
277
360
|
# Estimate scan options size.
|
278
361
|
@data_offset += 2 + FIELD_HEADER_SIZE
|
@@ -310,6 +393,12 @@ module Aerospike
|
|
310
393
|
write_field_string(set_name, Aerospike::FieldType::TABLE)
|
311
394
|
end
|
312
395
|
|
396
|
+
if policy.records_per_second > 0
|
397
|
+
write_field_int(policy.records_per_second, Aerospike::FieldType::RECORDS_PER_SECOND)
|
398
|
+
end
|
399
|
+
|
400
|
+
write_predexp(policy.predexp, predexp_size)
|
401
|
+
|
313
402
|
write_field_header(2, Aerospike::FieldType::SCAN_OPTIONS)
|
314
403
|
|
315
404
|
priority = policy.priority & 0xFF
|
@@ -355,6 +444,7 @@ module Aerospike
|
|
355
444
|
break if @policy.timeout > 0 && Time.now > limit
|
356
445
|
|
357
446
|
begin
|
447
|
+
@node = get_node
|
358
448
|
@conn = @node.get_connection(@policy.timeout)
|
359
449
|
rescue => e
|
360
450
|
# Socket connection error has occurred. Decrease health and retry.
|
@@ -498,9 +588,20 @@ module Aerospike
|
|
498
588
|
@data_offset += OPERATION_HEADER_SIZE
|
499
589
|
end
|
500
590
|
|
591
|
+
def estimate_predexp(predexp)
|
592
|
+
if predexp && predexp.size > 0
|
593
|
+
@data_offset += FIELD_HEADER_SIZE
|
594
|
+
sz = Aerospike::PredExp.estimate_size(predexp)
|
595
|
+
@data_offset += sz
|
596
|
+
return sz
|
597
|
+
end
|
598
|
+
return 0
|
599
|
+
end
|
600
|
+
|
501
601
|
# Generic header write.
|
502
602
|
def write_header(policy, read_attr, write_attr, field_count, operation_count)
|
503
603
|
read_attr |= INFO1_CONSISTENCY_ALL if policy.consistency_level == Aerospike::ConsistencyLevel::CONSISTENCY_ALL
|
604
|
+
read_attr |= INFO1_COMPRESS_RESPONSE if policy.use_compression
|
504
605
|
|
505
606
|
# Write all header data except total size which must be written last.
|
506
607
|
@data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message heade.length.
|
@@ -550,6 +651,7 @@ module Aerospike
|
|
550
651
|
info_attr |= INFO3_COMMIT_MASTER if policy.commit_level == Aerospike::CommitLevel::COMMIT_MASTER
|
551
652
|
read_attr |= INFO1_CONSISTENCY_ALL if policy.consistency_level == Aerospike::ConsistencyLevel::CONSISTENCY_ALL
|
552
653
|
write_attr |= INFO2_DURABLE_DELETE if policy.durable_delete
|
654
|
+
read_attr |= INFO1_COMPRESS_RESPONSE if policy.use_compression
|
553
655
|
|
554
656
|
# Write all header data except total size which must be written last.
|
555
657
|
@data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message heade.length.
|
@@ -681,21 +783,34 @@ module Aerospike
|
|
681
783
|
@data_offset += len
|
682
784
|
end
|
683
785
|
|
786
|
+
def write_field_int(i, ftype)
|
787
|
+
@data_buffer.write_int32(i, @data_offset+FIELD_HEADER_SIZE)
|
788
|
+
write_field_header(4, ftype)
|
789
|
+
@data_offset += 4
|
790
|
+
end
|
791
|
+
|
684
792
|
def write_field_bytes(bytes, ftype)
|
685
793
|
@data_buffer.write_binary(bytes, @data_offset+FIELD_HEADER_SIZE)
|
686
|
-
|
687
794
|
write_field_header(bytes.bytesize, ftype)
|
688
795
|
@data_offset += bytes.bytesize
|
689
796
|
end
|
690
797
|
|
691
798
|
def write_field_header(size, ftype)
|
692
|
-
# Buffer.Int32ToBytes(size+1), @data_buffer, @data_offset
|
693
799
|
@data_buffer.write_int32(size+1, @data_offset)
|
694
800
|
@data_offset += 4
|
695
801
|
@data_buffer.write_byte(ftype, @data_offset)
|
696
802
|
@data_offset += 1
|
697
803
|
end
|
698
804
|
|
805
|
+
def write_predexp(predexp, predexp_size)
|
806
|
+
if predexp && predexp.size > 0
|
807
|
+
write_field_header(predexp_size, Aerospike::FieldType::PREDEXP)
|
808
|
+
@data_offset = Aerospike::PredExp.write(
|
809
|
+
predexp, @data_buffer, @data_offset
|
810
|
+
)
|
811
|
+
end
|
812
|
+
end
|
813
|
+
|
699
814
|
def begin_cmd
|
700
815
|
@data_offset = MSG_TOTAL_HEADER_SIZE
|
701
816
|
end
|
@@ -719,6 +834,48 @@ module Aerospike
|
|
719
834
|
@data_buffer.write_int64(size, 0)
|
720
835
|
end
|
721
836
|
|
837
|
+
def use_compression?
|
838
|
+
@compress
|
839
|
+
end
|
840
|
+
|
841
|
+
def compress_buffer
|
842
|
+
if @data_offset > COMPRESS_THRESHOLD
|
843
|
+
compressed = Zlib::deflate(@data_buffer.buf, Zlib::DEFAULT_COMPRESSION)
|
844
|
+
|
845
|
+
# write original size as header
|
846
|
+
proto_s = "%08d" % 0
|
847
|
+
proto_s[0, 8] = [@data_offset].pack('q>')
|
848
|
+
compressed.prepend(proto_s)
|
849
|
+
|
850
|
+
# write proto
|
851
|
+
proto = (compressed.size+8) | Integer(CL_MSG_VERSION << 56) | Integer(AS_MSG_TYPE << 48)
|
852
|
+
proto_s = "%08d" % 0
|
853
|
+
proto_s[0, 8] = [proto].pack('q>')
|
854
|
+
compressed.prepend(proto_s)
|
855
|
+
|
856
|
+
@data_buffer = Buffer.new(-1, compressed)
|
857
|
+
@data_offset = @data_buffer.size
|
858
|
+
end
|
859
|
+
end
|
860
|
+
|
861
|
+
# isCompressed returns the length of the compressed buffer.
|
862
|
+
# If the buffer is not compressed, the result will be -1
|
863
|
+
def compressed_size
|
864
|
+
# A number of these are commented out because we just don't care enough to read
|
865
|
+
# that section of the header. If we do care, uncomment and check!
|
866
|
+
proto = @data_buffer.read_int64(0)
|
867
|
+
size = proto & 0xFFFFFFFFFFFF
|
868
|
+
msg_type = (proto >> 48) & 0xFF
|
869
|
+
|
870
|
+
return nil if msg_type != AS_MSG_TYPE_COMPRESSED
|
871
|
+
|
872
|
+
size
|
873
|
+
end
|
874
|
+
|
875
|
+
def mark_compressed(policy)
|
876
|
+
@compress = policy.use_compression
|
877
|
+
end
|
878
|
+
|
722
879
|
end # class
|
723
880
|
|
724
881
|
end # module
|