aerospike 4.0.0 → 4.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/lib/aerospike/aerospike_exception.rb +22 -22
- data/lib/aerospike/batch_attr.rb +2 -2
- data/lib/aerospike/batch_read.rb +2 -2
- data/lib/aerospike/client.rb +1 -1
- data/lib/aerospike/cluster/partition_parser.rb +5 -3
- data/lib/aerospike/cluster/rack_parser.rb +6 -4
- data/lib/aerospike/cluster.rb +15 -15
- data/lib/aerospike/command/batch_index_command.rb +1 -1
- data/lib/aerospike/command/batch_index_exists_command.rb +1 -1
- data/lib/aerospike/command/batch_operate_command.rb +1 -1
- data/lib/aerospike/command/command.rb +33 -15
- data/lib/aerospike/command/delete_command.rb +2 -2
- data/lib/aerospike/command/exists_command.rb +2 -2
- data/lib/aerospike/command/multi_command.rb +11 -11
- data/lib/aerospike/command/read_command.rb +7 -7
- data/lib/aerospike/command/read_header_command.rb +3 -3
- data/lib/aerospike/command/touch_command.rb +3 -3
- data/lib/aerospike/command/write_command.rb +2 -3
- data/lib/aerospike/exp/exp_map.rb +5 -5
- data/lib/aerospike/node/verify/cluster_name.rb +1 -1
- data/lib/aerospike/node/verify/name.rb +4 -4
- data/lib/aerospike/node/verify/partition_generation.rb +1 -1
- data/lib/aerospike/node/verify/peers_generation.rb +1 -1
- data/lib/aerospike/node/verify/rebalance_generation.rb +1 -1
- data/lib/aerospike/policy/batch_read_policy.rb +18 -1
- data/lib/aerospike/policy/policy.rb +18 -1
- data/lib/aerospike/policy/query_duration.rb +48 -0
- data/lib/aerospike/policy/query_policy.rb +13 -8
- data/lib/aerospike/query/partition_tracker.rb +1 -1
- data/lib/aerospike/query/server_command.rb +1 -1
- data/lib/aerospike/query/stream_command.rb +10 -11
- data/lib/aerospike/result_code.rb +7 -1
- data/lib/aerospike/version.rb +1 -1
- data/lib/aerospike.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6807e226bf4278fb49b9b27a13ddca657120fff617e4a9e2fd0553fd9479f7f6
|
4
|
+
data.tar.gz: 07d35bca9861064b0528ef7f9f7d3fefd1930deb868ab6e45f8f1ddf57eded6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f027d16fc67b814e135fc831b7d0b5effce98ea18255df72dc8d33fd63ed1a86c181566fd38211257390576af3306b027eb3213937b31b846b62b0cad69a17e6
|
7
|
+
data.tar.gz: e7125a75bef40d4d5b021408ba09fce58ade3c5b039a81e18241d72ca82936c71df826289131c9416630b2ad6022d85ba136069ea6514d1bac54ba12f461d13e
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,25 @@
|
|
2
2
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
|
5
|
+
## [4.2.0] 2024-12-18
|
6
|
+
|
7
|
+
- **Fixes**
|
8
|
+
- [CLIENT-3195] Fix ruby client does not return failed nodes on timeout.
|
9
|
+
|
10
|
+
## [4.1.0] 2024-10-22
|
11
|
+
|
12
|
+
- **New Features**
|
13
|
+
- [CLIENT-2833] Support `Policy#ReadTouchTtlPercent`.
|
14
|
+
- [CLIENT-2826] Support `QueryDuration` in `QueryPolicy#ExpectedDuration`.
|
15
|
+
- [CLIENT-3103] Support `XDR_KEY_BUSY`.
|
16
|
+
|
17
|
+
- **Fixes**
|
18
|
+
- [CLIENT-3144] Various fixes. PR #132 and #133 Thanks to [Igor Pstyga](https://github.com/opti)
|
19
|
+
- Fix `BatchRead` for multiple records with operations.
|
20
|
+
- Use correct namespace for the `MapReturnType`.
|
21
|
+
- `BatchRead` with operations would throw an exception.
|
22
|
+
- Fix a test with invalid map key in Server v7.1.
|
23
|
+
|
5
24
|
## [4.0.0] 2024-08-14
|
6
25
|
|
7
26
|
- **New Features**
|
@@ -21,79 +21,79 @@ require 'aerospike/result_code'
|
|
21
21
|
module Aerospike
|
22
22
|
module Exceptions
|
23
23
|
class Aerospike < StandardError
|
24
|
-
attr_reader :result_code
|
24
|
+
attr_reader :result_code, :failed_nodes
|
25
25
|
|
26
|
-
def initialize(result_code, message = nil)
|
26
|
+
def initialize(result_code, message = nil, failed_nodes = nil)
|
27
27
|
@result_code = result_code
|
28
|
+
@failed_nodes = failed_nodes
|
28
29
|
message ||= ResultCode.message(result_code)
|
29
30
|
super(message)
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
33
34
|
class Timeout < Aerospike
|
34
|
-
attr_reader :timeout, :iterations, :
|
35
|
+
attr_reader :timeout, :iterations, :failed_connections
|
35
36
|
|
36
37
|
def initialize(timeout, iterations, failed_nodes=nil, failed_connections=nil)
|
37
38
|
@timeout = timeout
|
38
39
|
@iterations = iterations
|
39
|
-
@failed_nodes = failed_nodes
|
40
40
|
@failed_connections = failed_connections
|
41
41
|
|
42
|
-
super(ResultCode::TIMEOUT)
|
42
|
+
super(ResultCode::TIMEOUT, nil, failed_nodes)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
46
|
class InvalidCredentials < Aerospike
|
47
|
-
def initialize(msg = nil)
|
48
|
-
super(ResultCode::NOT_AUTHENTICATED, msg)
|
47
|
+
def initialize(msg = nil, node=nil)
|
48
|
+
super(ResultCode::NOT_AUTHENTICATED, msg, [node])
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
52
|
class Serialize < Aerospike
|
53
53
|
def initialize(msg=nil)
|
54
|
-
super(ResultCode::SERIALIZE_ERROR, msg)
|
54
|
+
super(ResultCode::SERIALIZE_ERROR, msg, [node])
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
class Parse < Aerospike
|
59
|
-
def initialize(msg=nil)
|
60
|
-
super(ResultCode::PARSE_ERROR, msg)
|
59
|
+
def initialize(msg=nil, node=nil)
|
60
|
+
super(ResultCode::PARSE_ERROR, msg, [node])
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
64
|
class Connection < Aerospike
|
65
|
-
def initialize(msg=nil)
|
66
|
-
super(ResultCode::SERVER_NOT_AVAILABLE, msg)
|
65
|
+
def initialize(msg=nil, node=nil)
|
66
|
+
super(ResultCode::SERVER_NOT_AVAILABLE, msg, [node])
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
70
|
class InvalidNode < Aerospike
|
71
|
-
def initialize(msg=nil)
|
72
|
-
super(ResultCode::INVALID_NODE_ERROR, msg)
|
71
|
+
def initialize(msg=nil, node=nil)
|
72
|
+
super(ResultCode::INVALID_NODE_ERROR, msg, [node])
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
76
|
class ScanTerminated < Aerospike
|
77
|
-
def initialize(msg=nil)
|
78
|
-
super(ResultCode::SCAN_TERMINATED, msg)
|
77
|
+
def initialize(msg=nil, node=nil)
|
78
|
+
super(ResultCode::SCAN_TERMINATED, msg, [node])
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
82
|
class QueryTerminated < Aerospike
|
83
|
-
def initialize(msg=nil)
|
84
|
-
super(ResultCode::QUERY_TERMINATED, msg)
|
83
|
+
def initialize(msg=nil, node=nil)
|
84
|
+
super(ResultCode::QUERY_TERMINATED, msg, [node])
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
88
|
class CommandRejected < Aerospike
|
89
|
-
def initialize(msg=nil)
|
90
|
-
super(ResultCode::COMMAND_REJECTED, msg)
|
89
|
+
def initialize(msg=nil, node=nil)
|
90
|
+
super(ResultCode::COMMAND_REJECTED, msg, [node])
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
94
|
class InvalidNamespace < Aerospike
|
95
|
-
def initialize(msg=nil)
|
96
|
-
super(ResultCode::INVALID_NAMESPACE, msg)
|
95
|
+
def initialize(msg=nil, node=nil)
|
96
|
+
super(ResultCode::INVALID_NAMESPACE, msg, [node])
|
97
97
|
end
|
98
98
|
end
|
99
99
|
end
|
data/lib/aerospike/batch_attr.rb
CHANGED
@@ -75,7 +75,7 @@ module Aerospike
|
|
75
75
|
@write_attr = 0
|
76
76
|
@info_attr = 0
|
77
77
|
|
78
|
-
@expiration =
|
78
|
+
@expiration = rp.read_touch_ttl_percent
|
79
79
|
@generation = 0
|
80
80
|
@has_write = false
|
81
81
|
@send_key = false
|
@@ -88,7 +88,7 @@ module Aerospike
|
|
88
88
|
@write_attr = 0
|
89
89
|
@info_attr = 0
|
90
90
|
|
91
|
-
@expiration =
|
91
|
+
@expiration = rp.read_touch_ttl_percent
|
92
92
|
@generation = 0
|
93
93
|
@has_write = false
|
94
94
|
@send_key = false
|
data/lib/aerospike/batch_read.rb
CHANGED
@@ -68,7 +68,7 @@ module Aerospike
|
|
68
68
|
# For internal use only.
|
69
69
|
def ==(other) # :nodoc:
|
70
70
|
other && other.instance_of?(self.class) &&
|
71
|
-
@bin_names
|
71
|
+
@bin_names&.sort == other.bin_names&.sort && @ops == other.ops &&
|
72
72
|
@policy == other.policy && @read_all_bins == other.read_all_bins
|
73
73
|
end
|
74
74
|
|
@@ -88,7 +88,7 @@ module Aerospike
|
|
88
88
|
raise AerospikeException.new(ResultCode::PARAMETER_ERROR, "Write operations not allowed in batch read")
|
89
89
|
end
|
90
90
|
size += op.bin_name.bytesize + Aerospike::OPERATION_HEADER_SIZE
|
91
|
-
size += op.
|
91
|
+
size += op.bin_value.estimate_size
|
92
92
|
end
|
93
93
|
|
94
94
|
size
|
data/lib/aerospike/client.rb
CHANGED
@@ -239,7 +239,7 @@ module Aerospike
|
|
239
239
|
|
240
240
|
response = send_info_command(policy, str_cmd, node).upcase
|
241
241
|
return if response == "OK"
|
242
|
-
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_ERROR, "Truncate failed: #{response}")
|
242
|
+
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_ERROR, "Truncate failed: #{response}", [node])
|
243
243
|
end
|
244
244
|
|
245
245
|
#-------------------------------------------------------
|
@@ -42,7 +42,7 @@ module Aerospike
|
|
42
42
|
|
43
43
|
info = info_map[REPLICAS_ALL]
|
44
44
|
if !info || info.length == 0
|
45
|
-
raise Aerospike::Exceptions::Connection.new("#{REPLICAS_ALL} response for node #{@node.name} is empty")
|
45
|
+
raise Aerospike::Exceptions::Connection.new("#{REPLICAS_ALL} response for node #{@node.name} is empty", @node)
|
46
46
|
end
|
47
47
|
|
48
48
|
@buffer = info
|
@@ -112,7 +112,8 @@ module Aerospike
|
|
112
112
|
if namespace.length <= 0 || namespace.length >= 32
|
113
113
|
response = get_truncated_response
|
114
114
|
raise Aerospike::Exceptions::Parse.new(
|
115
|
-
"Invalid partition namespace #{namespace}. Response=#{response}"
|
115
|
+
"Invalid partition namespace #{namespace}. Response=#{response}",
|
116
|
+
@node
|
116
117
|
)
|
117
118
|
end
|
118
119
|
|
@@ -133,7 +134,8 @@ module Aerospike
|
|
133
134
|
if count < 0 || count > 4096
|
134
135
|
response = get_truncated_response
|
135
136
|
raise Aerospike::Exceptions::Parse.new(
|
136
|
-
"Invalid partition count #{count}. Response=#{response}"
|
137
|
+
"Invalid partition count #{count}. Response=#{response}",
|
138
|
+
@node
|
137
139
|
)
|
138
140
|
end
|
139
141
|
|
@@ -43,7 +43,7 @@ module Aerospike
|
|
43
43
|
|
44
44
|
info = info_map[RACK_IDS]
|
45
45
|
if !info || info.length == 0
|
46
|
-
raise Aerospike::Exceptions::Connection.new("#{RACK_IDS} response for node #{@node.name} is empty")
|
46
|
+
raise Aerospike::Exceptions::Connection.new("#{RACK_IDS} response for node #{@node.name} is empty", @node)
|
47
47
|
end
|
48
48
|
|
49
49
|
@buffer = info
|
@@ -54,7 +54,7 @@ module Aerospike
|
|
54
54
|
namespace = parse_name
|
55
55
|
rack_id = parse_rack_id
|
56
56
|
|
57
|
-
@racks
|
57
|
+
@racks ||= {}
|
58
58
|
@racks[namespace] = rack_id
|
59
59
|
end
|
60
60
|
|
@@ -76,7 +76,8 @@ module Aerospike
|
|
76
76
|
if namespace.length <= 0 || namespace.length >= 32
|
77
77
|
response = get_truncated_response
|
78
78
|
raise Aerospike::Exceptions::Parse.new(
|
79
|
-
"Invalid rack namespace #{namespace}. Response=#{response}"
|
79
|
+
"Invalid rack namespace #{namespace}. Response=#{response}",
|
80
|
+
@node
|
80
81
|
)
|
81
82
|
end
|
82
83
|
|
@@ -97,7 +98,8 @@ module Aerospike
|
|
97
98
|
if rack_id < 0
|
98
99
|
response = get_truncated_response
|
99
100
|
raise Aerospike::Exceptions::Parse.new(
|
100
|
-
"Invalid rack_id #{rack_id}. Response=#{response}"
|
101
|
+
"Invalid rack_id #{rack_id}. Response=#{response}",
|
102
|
+
@node
|
101
103
|
)
|
102
104
|
end
|
103
105
|
|
data/lib/aerospike/cluster.rb
CHANGED
@@ -129,7 +129,7 @@ module Aerospike
|
|
129
129
|
when Aerospike::Replica::RANDOM
|
130
130
|
random_node
|
131
131
|
else
|
132
|
-
raise Aerospike::Exceptions::InvalidNode("invalid policy.replica value")
|
132
|
+
raise Aerospike::Exceptions::InvalidNode.new("invalid policy.replica value")
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
@@ -147,7 +147,7 @@ module Aerospike
|
|
147
147
|
when Aerospike::Replica::RANDOM
|
148
148
|
random_node
|
149
149
|
else
|
150
|
-
raise Aerospike::Exceptions::InvalidNode("invalid policy.replica value")
|
150
|
+
raise Aerospike::Exceptions::InvalidNode.new("invalid policy.replica value")
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
@@ -155,13 +155,13 @@ module Aerospike
|
|
155
155
|
def master_node(partition)
|
156
156
|
partition_map = partitions
|
157
157
|
replica_array = partition_map[partition.namespace]
|
158
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless replica_array
|
158
|
+
raise Aerospike::Exceptions::InvalidNamespace.new("namespace not found in the partition map") unless replica_array
|
159
159
|
|
160
160
|
node_array = replica_array.get[0]
|
161
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless node_array
|
161
|
+
raise Aerospike::Exceptions::InvalidNamespace.new("namespace not found in the partition map") unless node_array
|
162
162
|
|
163
163
|
node = node_array.get[partition.partition_id]
|
164
|
-
raise Aerospike::Exceptions::InvalidNode if !node || !node.active?
|
164
|
+
raise Aerospike::Exceptions::InvalidNode.new("no active node found") if !node || !node.active?
|
165
165
|
|
166
166
|
node
|
167
167
|
end
|
@@ -170,7 +170,7 @@ module Aerospike
|
|
170
170
|
def rack_node(partition, seq)
|
171
171
|
partition_map = partitions
|
172
172
|
replica_array = partition_map[partition.namespace]
|
173
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless replica_array
|
173
|
+
raise Aerospike::Exceptions::InvalidNamespace.new("namespace not found in the partition map") unless replica_array
|
174
174
|
|
175
175
|
replica_array = replica_array.get
|
176
176
|
|
@@ -195,14 +195,14 @@ module Aerospike
|
|
195
195
|
|
196
196
|
return fallback if fallback
|
197
197
|
|
198
|
-
raise Aerospike::Exceptions::InvalidNode
|
198
|
+
raise Aerospike::Exceptions::InvalidNode.new("no active node found")
|
199
199
|
end
|
200
200
|
|
201
201
|
# Returns a node on the cluster for read operations
|
202
202
|
def master_proles_node(partition)
|
203
203
|
partition_map = partitions
|
204
204
|
replica_array = partition_map[partition.namespace]
|
205
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless replica_array
|
205
|
+
raise Aerospike::Exceptions::InvalidNamespace.new("namespace not found in the partition map") unless replica_array
|
206
206
|
|
207
207
|
replica_array = replica_array.get
|
208
208
|
|
@@ -214,14 +214,14 @@ module Aerospike
|
|
214
214
|
return node if node && node.active?
|
215
215
|
end
|
216
216
|
|
217
|
-
raise Aerospike::Exceptions::InvalidNode
|
217
|
+
raise Aerospike::Exceptions::InvalidNode.new("no active node found")
|
218
218
|
end
|
219
219
|
|
220
220
|
# Returns a random node on the cluster
|
221
221
|
def sequence_node(partition, seq)
|
222
222
|
partition_map = partitions
|
223
223
|
replica_array = partition_map[partition.namespace]
|
224
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless replica_array
|
224
|
+
raise Aerospike::Exceptions::InvalidNamespace.new("namespace not found in the partition map") unless replica_array
|
225
225
|
|
226
226
|
replica_array = replica_array.get
|
227
227
|
|
@@ -233,7 +233,7 @@ module Aerospike
|
|
233
233
|
return node if node && node.active?
|
234
234
|
end
|
235
235
|
|
236
|
-
raise Aerospike::Exceptions::InvalidNode
|
236
|
+
raise Aerospike::Exceptions::InvalidNode.new("node active node found")
|
237
237
|
end
|
238
238
|
|
239
239
|
def get_node_for_key(replica_policy, key, is_write: false)
|
@@ -251,10 +251,10 @@ module Aerospike
|
|
251
251
|
|
252
252
|
partition_map = partitions
|
253
253
|
replica_array = partition_map[namespace]
|
254
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless replica_array
|
254
|
+
raise Aerospike::Exceptions::InvalidNamespace.new("namespace not found in the partition map") unless replica_array
|
255
255
|
|
256
256
|
node_array = replica_array.get[0]
|
257
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") unless node_array
|
257
|
+
raise Aerospike::Exceptions::InvalidNamespace.new("namespace not found in the partition map") unless node_array
|
258
258
|
|
259
259
|
|
260
260
|
pid = 0
|
@@ -281,7 +281,7 @@ module Aerospike
|
|
281
281
|
|
282
282
|
i = i.succ
|
283
283
|
end
|
284
|
-
raise Aerospike::Exceptions::InvalidNode
|
284
|
+
raise Aerospike::Exceptions::InvalidNode.new("no active node found")
|
285
285
|
end
|
286
286
|
|
287
287
|
# Returns a list of all nodes in the cluster
|
@@ -296,7 +296,7 @@ module Aerospike
|
|
296
296
|
def get_node_by_name(node_name)
|
297
297
|
node = find_node_by_name(node_name)
|
298
298
|
|
299
|
-
raise Aerospike::Exceptions::InvalidNode unless node
|
299
|
+
raise Aerospike::Exceptions::InvalidNode.new("node `#{node_name}` not found") unless node
|
300
300
|
|
301
301
|
node
|
302
302
|
end
|
@@ -33,7 +33,7 @@ module Aerospike
|
|
33
33
|
op_count = @data_buffer.read_int16(20)
|
34
34
|
|
35
35
|
if op_count > 0
|
36
|
-
raise Aerospike::Exceptions::Parse.new('Received bins that were not requested!')
|
36
|
+
raise Aerospike::Exceptions::Parse.new('Received bins that were not requested!', @node)
|
37
37
|
end
|
38
38
|
|
39
39
|
skip_key(field_count)
|
@@ -92,7 +92,7 @@ module Aerospike
|
|
92
92
|
if record.bin_names&.length&.> 0
|
93
93
|
write_batch_bin_names(key, record.bin_names, attr, attr.filter_exp)
|
94
94
|
elsif record.ops&.length&.> 0
|
95
|
-
attr.adjust_read(
|
95
|
+
attr.adjust_read(record.ops)
|
96
96
|
write_batch_operations(key, record.ops, attr, attr.filter_exp)
|
97
97
|
else
|
98
98
|
attr.adjust_read_all_bins(record.read_all_bins)
|
@@ -58,7 +58,8 @@ module Aerospike
|
|
58
58
|
INFO2_DURABLE_DELETE = Integer(1 << 4)
|
59
59
|
# Create only. Fail if record already exists.
|
60
60
|
INFO2_CREATE_ONLY = Integer(1 << 5)
|
61
|
-
|
61
|
+
# Treat as long query, but relax read consistency.
|
62
|
+
INFO2_RELAX_AP_LONG_QUERY = (1 << 6)
|
62
63
|
# Return a result for every operation.
|
63
64
|
INFO2_RESPOND_ALL_OPS = Integer(1 << 7)
|
64
65
|
|
@@ -195,7 +196,7 @@ module Aerospike
|
|
195
196
|
field_count += 1 if exp_size > 0
|
196
197
|
|
197
198
|
size_buffer
|
198
|
-
write_header_read(policy, INFO1_READ | INFO1_GET_ALL, 0, field_count, 0)
|
199
|
+
write_header_read(policy, INFO1_READ | INFO1_GET_ALL, 0, 0, field_count, 0)
|
199
200
|
write_key(key)
|
200
201
|
write_filter_exp(@policy.filter_exp, exp_size)
|
201
202
|
end_cmd
|
@@ -220,7 +221,7 @@ module Aerospike
|
|
220
221
|
attr |= INFO1_GET_ALL
|
221
222
|
end
|
222
223
|
|
223
|
-
write_header_read(policy, attr, 0, field_count, bin_names.length)
|
224
|
+
write_header_read(policy, attr, 0, 0, field_count, bin_names.length)
|
224
225
|
write_key(key)
|
225
226
|
write_filter_exp(@policy.filter_exp, exp_size)
|
226
227
|
|
@@ -269,7 +270,7 @@ module Aerospike
|
|
269
270
|
|
270
271
|
size_buffer
|
271
272
|
|
272
|
-
write_header_read_write(policy, args
|
273
|
+
write_header_read_write(policy, args, field_count)
|
273
274
|
write_key(key, policy)
|
274
275
|
write_filter_exp(policy.filter_exp, exp_size)
|
275
276
|
|
@@ -377,7 +378,7 @@ module Aerospike
|
|
377
378
|
operation_count = bin_names.length
|
378
379
|
end
|
379
380
|
|
380
|
-
write_header_read(policy, read_attr, info_attr, field_count, operation_count)
|
381
|
+
write_header_read(policy, read_attr, 0, info_attr, field_count, operation_count)
|
381
382
|
|
382
383
|
if namespace
|
383
384
|
write_field_string(namespace, Aerospike::FieldType::NAMESPACE)
|
@@ -570,7 +571,7 @@ module Aerospike
|
|
570
571
|
if operations
|
571
572
|
|
572
573
|
unless background
|
573
|
-
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::PARAMETER_ERROR)
|
574
|
+
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::PARAMETER_ERROR, nil, [@node])
|
574
575
|
end
|
575
576
|
|
576
577
|
operations.each do |operation|
|
@@ -591,10 +592,16 @@ module Aerospike
|
|
591
592
|
write_header_write(policy, INFO2_WRITE, field_count, operation_count)
|
592
593
|
else
|
593
594
|
read_attr = INFO1_READ
|
595
|
+
write_attr = 0
|
596
|
+
|
594
597
|
read_attr |= INFO1_NOBINDATA unless policy.include_bin_data
|
595
|
-
|
598
|
+
if policy.short_query || policy.expected_duration == QueryDuration::SHORT
|
599
|
+
read_attr |= INFO1_SHORT_QUERY
|
600
|
+
elsif policy.expected_duration == QueryDuration::LONG_RELAX_AP
|
601
|
+
write_attr |= INFO2_RELAX_AP_LONG_QUERY
|
602
|
+
end
|
596
603
|
info_attr = INFO3_PARTITION_DONE if is_new
|
597
|
-
write_header_read(policy, read_attr, info_attr, field_count, operation_count)
|
604
|
+
write_header_read(policy, read_attr, write_attr, info_attr, field_count, operation_count)
|
598
605
|
end
|
599
606
|
|
600
607
|
|
@@ -678,6 +685,7 @@ module Aerospike
|
|
678
685
|
|
679
686
|
def execute
|
680
687
|
iterations = 0
|
688
|
+
failed_nodes = []
|
681
689
|
|
682
690
|
# set timeout outside the loop
|
683
691
|
limit = Time.now + @policy.timeout
|
@@ -698,6 +706,7 @@ module Aerospike
|
|
698
706
|
@node = get_node
|
699
707
|
@conn = @node.get_connection(@policy.timeout)
|
700
708
|
rescue => e
|
709
|
+
failed_nodes << @node if @node
|
701
710
|
if @node
|
702
711
|
# Socket connection error has occurred. Decrease health and retry.
|
703
712
|
@node.decrease_health
|
@@ -717,6 +726,7 @@ module Aerospike
|
|
717
726
|
begin
|
718
727
|
write_buffer
|
719
728
|
rescue => e
|
729
|
+
failed_nodes << @node if @node
|
720
730
|
Aerospike.logger.error(e)
|
721
731
|
|
722
732
|
# All runtime exceptions are considered fatal. Do not retry.
|
@@ -731,6 +741,7 @@ module Aerospike
|
|
731
741
|
begin
|
732
742
|
@conn.write(@data_buffer, @data_offset)
|
733
743
|
rescue => e
|
744
|
+
failed_nodes << @node if @node
|
734
745
|
# IO errors are considered temporary anomalies. Retry.
|
735
746
|
# Close socket to flush out possible garbage. Do not put back in pool.
|
736
747
|
@conn.close if @conn
|
@@ -746,6 +757,7 @@ module Aerospike
|
|
746
757
|
begin
|
747
758
|
parse_result
|
748
759
|
rescue => e
|
760
|
+
failed_nodes << @node if @node
|
749
761
|
case e
|
750
762
|
# do not log the following exceptions
|
751
763
|
when Aerospike::Exceptions::ScanTerminated
|
@@ -776,7 +788,7 @@ module Aerospike
|
|
776
788
|
end # while
|
777
789
|
|
778
790
|
# execution timeout
|
779
|
-
raise Aerospike::Exceptions::Timeout.new(limit, iterations)
|
791
|
+
raise Aerospike::Exceptions::Timeout.new(limit, iterations, failed_nodes)
|
780
792
|
end
|
781
793
|
|
782
794
|
protected
|
@@ -903,10 +915,14 @@ module Aerospike
|
|
903
915
|
end
|
904
916
|
|
905
917
|
# Header write for write operations.
|
906
|
-
def write_header_read_write(policy,
|
918
|
+
def write_header_read_write(policy, args, field_count)
|
907
919
|
# Set flags.
|
908
920
|
generation = Integer(0)
|
921
|
+
ttl = args.has_write ? policy.expiration : policy.read_touch_ttl_percent
|
922
|
+
read_attr = args.read_attr
|
923
|
+
write_attr = args.write_attr
|
909
924
|
info_attr = Integer(0)
|
925
|
+
operation_count = args.operations.length
|
910
926
|
|
911
927
|
case policy.record_exists_action
|
912
928
|
when Aerospike::RecordExistsAction::UPDATE
|
@@ -942,7 +958,7 @@ module Aerospike
|
|
942
958
|
@data_buffer.write_byte(0, 12) # unused
|
943
959
|
@data_buffer.write_byte(0, 13) # clear the result code
|
944
960
|
@data_buffer.write_uint32(generation, 14)
|
945
|
-
@data_buffer.write_uint32(
|
961
|
+
@data_buffer.write_uint32(ttl, 18)
|
946
962
|
|
947
963
|
# Initialize timeout. It will be written later.
|
948
964
|
@data_buffer.write_byte(0, 22)
|
@@ -956,18 +972,19 @@ module Aerospike
|
|
956
972
|
@data_offset = MSG_TOTAL_HEADER_SIZE
|
957
973
|
end
|
958
974
|
|
959
|
-
def write_header_read(policy, read_attr, info_attr, field_count, operation_count)
|
975
|
+
def write_header_read(policy, read_attr, write_attr, info_attr, field_count, operation_count)
|
960
976
|
read_attr |= INFO1_COMPRESS_RESPONSE if policy.use_compression
|
961
977
|
#TODO: Add SC Mode
|
962
978
|
|
963
979
|
@data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message header.length.
|
964
980
|
@data_buffer.write_byte(read_attr, 9)
|
965
|
-
@data_buffer.write_byte(
|
981
|
+
@data_buffer.write_byte(write_attr, 10)
|
966
982
|
@data_buffer.write_byte(info_attr, 11)
|
967
983
|
|
968
|
-
(12...
|
984
|
+
(12...18).each { |i| @data_buffer.write_byte(0, i) }
|
969
985
|
|
970
986
|
# Initialize timeout. It will be written later.
|
987
|
+
@data_buffer.write_int32(policy.read_touch_ttl_percent, 18)
|
971
988
|
@data_buffer.write_byte(0, 22)
|
972
989
|
@data_buffer.write_byte(0, 23)
|
973
990
|
@data_buffer.write_byte(0, 24)
|
@@ -988,9 +1005,10 @@ module Aerospike
|
|
988
1005
|
@data_buffer.write_byte(0, 10)
|
989
1006
|
@data_buffer.write_byte(info_attr, 11)
|
990
1007
|
|
991
|
-
(12...
|
1008
|
+
(12...18).each { |i| @data_buffer.write_byte(0, i) }
|
992
1009
|
|
993
1010
|
# Initialize timeout. It will be written later.
|
1011
|
+
@data_buffer.write_int32(policy.read_touch_ttl_percent, 18)
|
994
1012
|
@data_buffer.write_byte(0, 22)
|
995
1013
|
@data_buffer.write_byte(0, 23)
|
996
1014
|
@data_buffer.write_byte(0, 24)
|
@@ -59,13 +59,13 @@ module Aerospike
|
|
59
59
|
|
60
60
|
if result_code == Aerospike::ResultCode::FILTERED_OUT
|
61
61
|
if @policy.fail_on_filtered_out
|
62
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
62
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
63
63
|
end
|
64
64
|
@existed = true
|
65
65
|
return
|
66
66
|
end
|
67
67
|
|
68
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
68
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
69
69
|
end
|
70
70
|
|
71
71
|
end # class
|
@@ -59,13 +59,13 @@ module Aerospike
|
|
59
59
|
|
60
60
|
if result_code == Aerospike::ResultCode::FILTERED_OUT
|
61
61
|
if @policy.fail_on_filtered_out
|
62
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
62
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
63
63
|
end
|
64
64
|
@exists = true
|
65
65
|
return
|
66
66
|
end
|
67
67
|
|
68
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
68
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
69
69
|
end
|
70
70
|
|
71
71
|
end # class
|
@@ -24,7 +24,7 @@ module Aerospike
|
|
24
24
|
class MultiCommand < Command #:nodoc:
|
25
25
|
|
26
26
|
def initialize(node)
|
27
|
-
super
|
27
|
+
super
|
28
28
|
|
29
29
|
@valid = true
|
30
30
|
@mutex = Mutex.new
|
@@ -69,7 +69,7 @@ module Aerospike
|
|
69
69
|
|
70
70
|
# inflate the results
|
71
71
|
# TODO: reuse the current buffer
|
72
|
-
uncompressed = Zlib
|
72
|
+
uncompressed = Zlib.inflate(@data_buffer.buf)
|
73
73
|
receive_size = uncompressed.size - 8
|
74
74
|
|
75
75
|
@compressed_data_buffer = Buffer.new(-1, uncompressed)
|
@@ -83,11 +83,11 @@ module Aerospike
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
-
if receive_size > 0
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
86
|
+
status = if receive_size > 0
|
87
|
+
parse_group(receive_size)
|
88
|
+
else
|
89
|
+
false
|
90
|
+
end
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
@@ -101,10 +101,10 @@ module Aerospike
|
|
101
101
|
# The only valid server return codes are "ok", "not found" and "filtered out".
|
102
102
|
# If other return codes are received, then abort the batch.
|
103
103
|
if result_code != 0
|
104
|
-
if
|
104
|
+
if [Aerospike::ResultCode::KEY_NOT_FOUND_ERROR, Aerospike::ResultCode::FILTERED_OUT].include?(result_code)
|
105
105
|
# NOOP
|
106
106
|
else
|
107
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
107
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
@@ -145,7 +145,7 @@ module Aerospike
|
|
145
145
|
when Aerospike::FieldType::TABLE
|
146
146
|
set_name = @data_buffer.read(1, size).force_encoding('utf-8')
|
147
147
|
when Aerospike::FieldType::KEY
|
148
|
-
user_key = Aerospike
|
148
|
+
user_key = Aerospike.bytes_to_key_value(@data_buffer.read(1).ord, @data_buffer, 2, size-1)
|
149
149
|
when Aerospike::FieldType::BVAL_ARRAY
|
150
150
|
bval = @data_buffer.read_uint64_little_endian(1)
|
151
151
|
end
|
@@ -207,7 +207,7 @@ module Aerospike
|
|
207
207
|
# Corrupted data streams can result in a huge length.
|
208
208
|
# Do a sanity check here.
|
209
209
|
if length > Aerospike::Buffer::MAX_BUFFER_SIZE
|
210
|
-
raise Aerospike::Exceptions::Parse.new("Invalid read_bytes length: #{length}")
|
210
|
+
raise Aerospike::Exceptions::Parse.new("Invalid read_bytes length: #{length}", [@node])
|
211
211
|
end
|
212
212
|
@data_buffer = Buffer.new(length)
|
213
213
|
end
|
@@ -70,7 +70,7 @@ module Aerospike
|
|
70
70
|
|
71
71
|
# inflate the results
|
72
72
|
# TODO: reuse the current buffer
|
73
|
-
uncompressed = Zlib
|
73
|
+
uncompressed = Zlib.inflate(@data_buffer.buf)
|
74
74
|
|
75
75
|
@data_buffer = Buffer.new(-1, uncompressed)
|
76
76
|
rescue => e
|
@@ -126,7 +126,7 @@ module Aerospike
|
|
126
126
|
|
127
127
|
if result_code == Aerospike::ResultCode::FILTERED_OUT
|
128
128
|
if @policy.fail_on_filtered_out
|
129
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
129
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
130
130
|
end
|
131
131
|
return
|
132
132
|
end
|
@@ -141,19 +141,19 @@ module Aerospike
|
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
144
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
144
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
145
145
|
end
|
146
146
|
|
147
147
|
def handle_udf_error(result_code)
|
148
148
|
ret = @record.bins['FAILURE']
|
149
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code, ret) if ret
|
150
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
149
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, ret, [@node]) if ret
|
150
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
151
151
|
end
|
152
152
|
|
153
153
|
def parse_record(op_count, field_count, generation, expiration)
|
154
154
|
bins = op_count > 0 ? {} : nil
|
155
155
|
receive_offset = 0
|
156
|
-
single_bin_value =
|
156
|
+
single_bin_value = !policy.is_a?(OperatePolicy) || policy.record_bin_multiplicity == RecordBinMultiplicity::SINGLE
|
157
157
|
|
158
158
|
# There can be fields in the response (setname etc).
|
159
159
|
# But for now, ignore them. Expose them to the API if needed in the future.
|
@@ -181,7 +181,7 @@ module Aerospike
|
|
181
181
|
|
182
182
|
if single_bin_value || !bins.has_key?(name)
|
183
183
|
bins[name] = value
|
184
|
-
elsif (prev = bins[name]).
|
184
|
+
elsif (prev = bins[name]).is_a?(OpResults)
|
185
185
|
prev << value
|
186
186
|
else
|
187
187
|
bins[name] = OpResults.new << prev << value
|
@@ -50,7 +50,7 @@ module Aerospike
|
|
50
50
|
if result_code == 0
|
51
51
|
generation = @data_buffer.read_int32(14)
|
52
52
|
expiration = @data_buffer.read_int32(18)
|
53
|
-
@record = Record.new(@node, @key, nil,
|
53
|
+
@record = Record.new(@node, @key, nil, generation, expiration)
|
54
54
|
return
|
55
55
|
end
|
56
56
|
|
@@ -62,12 +62,12 @@ module Aerospike
|
|
62
62
|
if result_code == Aerospike::ResultCode::FILTERED_OUT
|
63
63
|
@record = nil
|
64
64
|
if @policy.fail_on_filtered_out
|
65
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
65
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
66
66
|
end
|
67
67
|
return
|
68
68
|
end
|
69
69
|
|
70
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
70
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
71
71
|
end
|
72
72
|
|
73
73
|
end # class
|
@@ -59,7 +59,7 @@ module Aerospike
|
|
59
59
|
|
60
60
|
# inflate the results
|
61
61
|
# TODO: reuse the current buffer
|
62
|
-
uncompressed = Zlib
|
62
|
+
uncompressed = Zlib.inflate(@data_buffer.buf)
|
63
63
|
|
64
64
|
@data_buffer = Buffer.new(-1, uncompressed)
|
65
65
|
rescue => e
|
@@ -81,12 +81,12 @@ module Aerospike
|
|
81
81
|
|
82
82
|
if result_code == Aerospike::ResultCode::FILTERED_OUT
|
83
83
|
if @policy.fail_on_filtered_out
|
84
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
84
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
85
85
|
end
|
86
86
|
return
|
87
87
|
end
|
88
88
|
|
89
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
89
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
90
90
|
end
|
91
91
|
|
92
92
|
end # class
|
@@ -23,7 +23,6 @@ module Aerospike
|
|
23
23
|
class WriteCommand < SingleCommand #:nodoc:
|
24
24
|
|
25
25
|
def initialize(cluster, policy, key, bins, operation)
|
26
|
-
|
27
26
|
super(cluster, key)
|
28
27
|
|
29
28
|
@bins = bins
|
@@ -60,12 +59,12 @@ module Aerospike
|
|
60
59
|
|
61
60
|
if result_code == Aerospike::ResultCode::FILTERED_OUT
|
62
61
|
if @policy.fail_on_filtered_out
|
63
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
62
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
64
63
|
end
|
65
64
|
return
|
66
65
|
end
|
67
66
|
|
68
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
67
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
69
68
|
end
|
70
69
|
|
71
70
|
end # class
|
@@ -476,21 +476,21 @@ module Aerospike
|
|
476
476
|
def self.get_value_type(return_type)
|
477
477
|
t = return_type & ~CDT::MapReturnType::INVERTED
|
478
478
|
case t
|
479
|
-
when MapReturnType::INDEX, MapReturnType::REVERSE_INDEX, MapReturnType::RANK, MapReturnType::REVERSE_RANK
|
479
|
+
when CDT::MapReturnType::INDEX, CDT::MapReturnType::REVERSE_INDEX, CDT::MapReturnType::RANK, CDT::MapReturnType::REVERSE_RANK
|
480
480
|
# This method only called from expressions that can return multiple integers (ie list).
|
481
481
|
Exp::Type::LIST
|
482
482
|
|
483
|
-
when MapReturnType::COUNT
|
483
|
+
when CDT::MapReturnType::COUNT
|
484
484
|
Exp::Type::INT
|
485
485
|
|
486
|
-
when MapReturnType::KEY, MapReturnType::VALUE
|
486
|
+
when CDT::MapReturnType::KEY, CDT::MapReturnType::VALUE
|
487
487
|
# This method only called from expressions that can return multiple objects (ie list).
|
488
488
|
Exp::Type::LIST
|
489
489
|
|
490
|
-
when MapReturnType::KEY_VALUE, MapReturnType::ORDERED_MAP, MapReturnType::UNORDERED_MAP
|
490
|
+
when CDT::MapReturnType::KEY_VALUE, CDT::MapReturnType::ORDERED_MAP, CDT::MapReturnType::UNORDERED_MAP
|
491
491
|
Exp::Type::MAP
|
492
492
|
|
493
|
-
when MapReturnType::EXISTS
|
493
|
+
when CDT::MapReturnType::EXISTS
|
494
494
|
Exp::Type::BOOL
|
495
495
|
|
496
496
|
else
|
@@ -25,7 +25,7 @@ module Aerospike
|
|
25
25
|
def call(node, info_map)
|
26
26
|
if node.cluster_name && node.cluster_name != info_map['cluster-name']
|
27
27
|
node.inactive!
|
28
|
-
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INVALID_NODE_ERROR, "Cluster name does not match. expected: #{node.cluster_name}, got: #{info_map['cluster-name']}")
|
28
|
+
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INVALID_NODE_ERROR, "Cluster name does not match. expected: #{node.cluster_name}, got: #{info_map['cluster-name']}", [node])
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -25,15 +25,15 @@ module Aerospike
|
|
25
25
|
def call(node, info_map)
|
26
26
|
info_name = info_map['node']
|
27
27
|
|
28
|
-
|
28
|
+
unless info_name
|
29
29
|
node.decrease_health
|
30
|
-
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INVALID_NODE_ERROR, 'Node name is empty')
|
30
|
+
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INVALID_NODE_ERROR, 'Node name is empty', [node])
|
31
31
|
end
|
32
32
|
|
33
|
-
|
33
|
+
unless node.name == info_name
|
34
34
|
# Set node to inactive immediately.
|
35
35
|
node.inactive!
|
36
|
-
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INVALID_NODE_ERROR, "Node name has changed. Old=#{node.name} New= #{info_name}")
|
36
|
+
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INVALID_NODE_ERROR, "Node name has changed. Old=#{node.name} New= #{info_name}", [node])
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
@@ -27,7 +27,7 @@ module Aerospike
|
|
27
27
|
def call(node, info_map)
|
28
28
|
gen_string = info_map.fetch('partition-generation', nil)
|
29
29
|
|
30
|
-
raise Aerospike::Exceptions::Parse.new('partition-generation is empty') if gen_string.to_s.empty?
|
30
|
+
raise Aerospike::Exceptions::Parse.new('partition-generation is empty', [node]) if gen_string.to_s.empty?
|
31
31
|
|
32
32
|
generation = gen_string.to_i
|
33
33
|
|
@@ -25,7 +25,7 @@ module Aerospike
|
|
25
25
|
def call(node, info_map, peers)
|
26
26
|
gen_string = info_map.fetch('peers-generation', nil)
|
27
27
|
|
28
|
-
raise Aerospike::Exceptions::Parse.new('peers-generation is empty') if gen_string.to_s.empty?
|
28
|
+
raise Aerospike::Exceptions::Parse.new('peers-generation is empty', node) if gen_string.to_s.empty?
|
29
29
|
|
30
30
|
generation = gen_string.to_i
|
31
31
|
|
@@ -27,7 +27,7 @@ module Aerospike
|
|
27
27
|
def call(node, info_map)
|
28
28
|
gen_string = info_map.fetch('rebalance-generation', nil)
|
29
29
|
|
30
|
-
raise Aerospike::Exceptions::Parse.new('rebalance-generation is empty') if gen_string.to_s.empty?
|
30
|
+
raise Aerospike::Exceptions::Parse.new('rebalance-generation is empty', node) if gen_string.to_s.empty?
|
31
31
|
|
32
32
|
generation = gen_string.to_i
|
33
33
|
|
@@ -20,7 +20,7 @@ module Aerospike
|
|
20
20
|
# Policy attributes used in batch read commands.
|
21
21
|
class BatchReadPolicy
|
22
22
|
|
23
|
-
attr_accessor :filter_exp
|
23
|
+
attr_accessor :filter_exp, :read_touch_ttl_percent
|
24
24
|
|
25
25
|
def initialize(opt={})
|
26
26
|
# Optional expression filter. If filter_exp exists and evaluates to false, the specific batch key
|
@@ -33,6 +33,23 @@ module Aerospike
|
|
33
33
|
#
|
34
34
|
# Default: nil
|
35
35
|
@filter_exp = opt[:filter_exp]
|
36
|
+
|
37
|
+
# Determines how record TTL (time to live) is affected on reads. When enabled, the server can
|
38
|
+
# efficiently operate as a read-based LRU cache where the least recently used records are expired.
|
39
|
+
# The value is expressed as a percentage of the TTL sent on the most recent write such that a read
|
40
|
+
# within this interval of the record’s end of life will generate a touch.
|
41
|
+
#
|
42
|
+
# For example, if the most recent write had a TTL of 10 hours and read_touch_ttl_percent is set to
|
43
|
+
# 80, the next read within 8 hours of the record's end of life (equivalent to 2 hours after the most
|
44
|
+
# recent write) will result in a touch, resetting the TTL to another 10 hours.
|
45
|
+
#
|
46
|
+
# Values:
|
47
|
+
#
|
48
|
+
# 0 : Use server config default-read-touch-ttl-pct for the record's namespace/set.
|
49
|
+
# -1 : Do not reset record TTL on reads.
|
50
|
+
# 1 - 100 : Reset record TTL on reads when within this percentage of the most recent write TTL.
|
51
|
+
# Default: 0
|
52
|
+
@read_touch_ttl_percent = opt[:read_touch_ttl_percent] || 0
|
36
53
|
end
|
37
54
|
end
|
38
55
|
end
|
@@ -22,7 +22,7 @@ module Aerospike
|
|
22
22
|
# Container object for client policy command.
|
23
23
|
class Policy
|
24
24
|
attr_accessor :filter_exp, :priority, :timeout, :max_retries, :sleep_between_retries, :consistency_level,
|
25
|
-
:fail_on_filtered_out, :replica, :use_compression, :socket_timeout
|
25
|
+
:fail_on_filtered_out, :replica, :use_compression, :socket_timeout, :read_touch_ttl_percent
|
26
26
|
|
27
27
|
alias total_timeout timeout
|
28
28
|
alias total_timeout= timeout=
|
@@ -95,6 +95,23 @@ module Aerospike
|
|
95
95
|
# has not yet been exceeded.
|
96
96
|
@max_retries = opt[:max_retries] || 2
|
97
97
|
|
98
|
+
# Determines how record TTL (time to live) is affected on reads. When enabled, the server can
|
99
|
+
# efficiently operate as a read-based LRU cache where the least recently used records are expired.
|
100
|
+
# The value is expressed as a percentage of the TTL sent on the most recent write such that a read
|
101
|
+
# within this interval of the record’s end of life will generate a touch.
|
102
|
+
#
|
103
|
+
# For example, if the most recent write had a TTL of 10 hours and read_touch_ttl_percent is set to
|
104
|
+
# 80, the next read within 8 hours of the record's end of life (equivalent to 2 hours after the most
|
105
|
+
# recent write) will result in a touch, resetting the TTL to another 10 hours.
|
106
|
+
#
|
107
|
+
# Values:
|
108
|
+
#
|
109
|
+
# 0 : Use server config default-read-touch-ttl-pct for the record's namespace/set.
|
110
|
+
# -1 : Do not reset record TTL on reads.
|
111
|
+
# 1 - 100 : Reset record TTL on reads when within this percentage of the most recent write TTL.
|
112
|
+
# Default: 0
|
113
|
+
@read_touch_ttl_percent = opt[:read_touch_ttl_percent] || 0
|
114
|
+
|
98
115
|
# Duration to sleep between retries if a transaction fails and the
|
99
116
|
# timeout was not exceeded. Enter zero to skip sleep.
|
100
117
|
@sleep_between_retries = opt[:sleep_between_retries] || 0.5
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Copyright 2014-2024 Aerospike, Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http:#www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
module Aerospike
|
17
|
+
|
18
|
+
# Defines the expected query duration. The server treats the query in different ways depending on the expected duration.
|
19
|
+
# This enum is ignored for aggregation queries, background queries and server versions < 6.0.
|
20
|
+
module QueryDuration
|
21
|
+
|
22
|
+
# The query is expected to return more than 100 records per node. The server optimizes for a large record set in
|
23
|
+
# the following ways:
|
24
|
+
#
|
25
|
+
# Allow query to be run in multiple threads using the server's query threading configuration.
|
26
|
+
# Do not relax read consistency for AP namespaces.
|
27
|
+
# Add the query to the server's query monitor.
|
28
|
+
# Do not add the overall latency to the server's latency histogram.
|
29
|
+
# Do not allow server timeouts.
|
30
|
+
LONG = 0
|
31
|
+
|
32
|
+
# The query is expected to return less than 100 records per node. The server optimizes for a small record set in
|
33
|
+
# the following ways:
|
34
|
+
# Always run the query in one thread and ignore the server's query threading configuration.
|
35
|
+
# Allow query to be inlined directly on the server's service thread.
|
36
|
+
# Relax read consistency for AP namespaces.
|
37
|
+
# Do not add the query to the server's query monitor.
|
38
|
+
# Add the overall latency to the server's latency histogram.
|
39
|
+
# Allow server timeouts. The default server timeout for a short query is 1 second.
|
40
|
+
SHORT = 1
|
41
|
+
|
42
|
+
# Treat query as a LONG query, but relax read consistency for AP namespaces.
|
43
|
+
# This value is treated exactly like LONG for server versions < 7.1.
|
44
|
+
LONG_RELAX_AP = 2
|
45
|
+
|
46
|
+
end # module
|
47
|
+
|
48
|
+
end # module
|
@@ -15,6 +15,7 @@
|
|
15
15
|
# License for the specific language governing permissions and limitations under
|
16
16
|
# the License.
|
17
17
|
|
18
|
+
require 'aerospike/policy/query_duration'
|
18
19
|
require 'aerospike/policy/policy'
|
19
20
|
|
20
21
|
module Aerospike
|
@@ -22,16 +23,10 @@ module Aerospike
|
|
22
23
|
# Container object for query policy command.
|
23
24
|
class QueryPolicy < Policy
|
24
25
|
|
25
|
-
attr_accessor :concurrent_nodes
|
26
|
-
attr_accessor :max_records
|
27
|
-
attr_accessor :include_bin_data
|
28
|
-
attr_accessor :record_queue_size
|
29
|
-
attr_accessor :records_per_second
|
30
|
-
attr_accessor :socket_timeout
|
31
|
-
attr_accessor :short_query
|
26
|
+
attr_accessor :concurrent_nodes, :max_records, :include_bin_data, :record_queue_size, :records_per_second, :socket_timeout, :short_query, :expected_duration
|
32
27
|
|
33
28
|
def initialize(opt={})
|
34
|
-
super
|
29
|
+
super
|
35
30
|
|
36
31
|
# Indicates if bin data is retrieved. If false, only record digests (and
|
37
32
|
# user keys if stored on the server) are retrieved.
|
@@ -74,11 +69,21 @@ module Aerospike
|
|
74
69
|
# Default is 0
|
75
70
|
@records_per_second = opt[:records_per_second] || 0
|
76
71
|
|
72
|
+
# Expected query duration. The server treats the query in different ways depending on the expected duration.
|
73
|
+
# This field is ignored for aggregation queries, background queries and server versions < 6.0.
|
74
|
+
#
|
75
|
+
# Default: QueryDuration::LONG
|
76
|
+
@expected_duration = opt[:expected_duration] || QueryDuration::LONG
|
77
|
+
|
78
|
+
# DEPRECATED
|
77
79
|
# Detemine wether query expected to return less than 100 records.
|
78
80
|
# If true, the server will optimize the query for a small record set.
|
79
81
|
# This field is ignored for aggregation queries, background queries
|
80
82
|
# and server versions 6.0+.
|
81
83
|
#
|
84
|
+
# This field is deprecated and will eventually be removed. Use {expected_duration} instead.
|
85
|
+
# For backwards compatibility: If ShortQuery is true, the query is treated as a short query and
|
86
|
+
# {expected_duration} is ignored. If {short_query} is false, {expected_duration} is used as defaults to {Policy#QueryDuration#LONG}.
|
82
87
|
# Default: false
|
83
88
|
@short_query = opt[:short_query] ||false
|
84
89
|
|
@@ -77,7 +77,7 @@ module Aerospike
|
|
77
77
|
|
78
78
|
pmap = cluster.partitions
|
79
79
|
replica_array = pmap[namespace]
|
80
|
-
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") if !replica_array
|
80
|
+
raise Aerospike::Exceptions::InvalidNamespace.new("namespace not found in the partition map") if !replica_array
|
81
81
|
|
82
82
|
master = (replica_array.get)[0]
|
83
83
|
master = master.get
|
@@ -45,7 +45,7 @@ module Aerospike
|
|
45
45
|
if result_code == Aerospike::ResultCode::KEY_NOT_FOUND_ERROR
|
46
46
|
return false
|
47
47
|
end
|
48
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
48
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
49
49
|
end
|
50
50
|
op_count = @data_buffer.read_int16(20)
|
51
51
|
if op_count <= 0
|
@@ -46,7 +46,7 @@ module Aerospike
|
|
46
46
|
read_bytes(receive_size - @data_offset) if @data_offset < receive_size
|
47
47
|
return nil
|
48
48
|
else
|
49
|
-
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
49
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code, nil, [@node])
|
50
50
|
end
|
51
51
|
|
52
52
|
info3 = @data_buffer.read(3).ord
|
@@ -72,17 +72,16 @@ module Aerospike
|
|
72
72
|
next
|
73
73
|
end
|
74
74
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
# UDF results do not return a key
|
84
|
-
@tracker&.set_last(@node_partitions, key, key.bval) if key
|
75
|
+
next unless result_code == 0
|
76
|
+
if @recordset.active?
|
77
|
+
@recordset.records.enq(parse_record(key, op_count, generation, expiration))
|
78
|
+
else
|
79
|
+
expn = @recordset.is_scan? ? SCAN_TERMINATED_EXCEPTION : QUERY_TERMINATED_EXCEPTION
|
80
|
+
raise expn
|
85
81
|
end
|
82
|
+
|
83
|
+
# UDF results do not return a key
|
84
|
+
@tracker&.set_last(@node_partitions, key, key.bval) if key
|
86
85
|
end # while
|
87
86
|
|
88
87
|
true
|
@@ -168,6 +168,9 @@ module Aerospike
|
|
168
168
|
# Write command loses conflict to XDR.
|
169
169
|
LOST_CONFLICT = 28
|
170
170
|
|
171
|
+
# Write can't complete until XDR finishes shipping.
|
172
|
+
XDR_KEY_BUSY = 32
|
173
|
+
|
171
174
|
# There are no more records left for query.
|
172
175
|
QUERY_END = 50
|
173
176
|
|
@@ -445,6 +448,10 @@ module Aerospike
|
|
445
448
|
when LOST_CONFLICT
|
446
449
|
"Write command loses conflict to XDR."
|
447
450
|
|
451
|
+
# Write can't complete until XDR finishes shipping.
|
452
|
+
when XDR_KEY_BUSY
|
453
|
+
"XDR key busy"
|
454
|
+
|
448
455
|
when QUERY_END
|
449
456
|
"Query end"
|
450
457
|
|
@@ -580,7 +587,6 @@ module Aerospike
|
|
580
587
|
else
|
581
588
|
"ResultCode #{code} unknown in the client. Please file a github issue."
|
582
589
|
end # case
|
583
|
-
|
584
590
|
end
|
585
591
|
|
586
592
|
end # class
|
data/lib/aerospike/version.rb
CHANGED
data/lib/aerospike.rb
CHANGED
@@ -90,6 +90,7 @@ require "aerospike/cdt/bit_policy"
|
|
90
90
|
require "aerospike/geo_json"
|
91
91
|
require "aerospike/ttl"
|
92
92
|
|
93
|
+
require "aerospike/policy/query_duration"
|
93
94
|
require "aerospike/policy/client_policy"
|
94
95
|
require "aerospike/policy/priority"
|
95
96
|
require "aerospike/policy/record_exists_action"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aerospike
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Khosrow Afroozeh
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2024-
|
13
|
+
date: 2024-12-17 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: msgpack
|
@@ -166,6 +166,7 @@ files:
|
|
166
166
|
- lib/aerospike/policy/operate_policy.rb
|
167
167
|
- lib/aerospike/policy/policy.rb
|
168
168
|
- lib/aerospike/policy/priority.rb
|
169
|
+
- lib/aerospike/policy/query_duration.rb
|
169
170
|
- lib/aerospike/policy/query_policy.rb
|
170
171
|
- lib/aerospike/policy/record_bin_multiplicity.rb
|
171
172
|
- lib/aerospike/policy/record_exists_action.rb
|