aerospike 4.0.0 → 4.2.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 +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
|