aerospike 2.13.0 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/aerospike.rb +5 -0
- data/lib/aerospike/client.rb +21 -6
- data/lib/aerospike/cluster.rb +47 -0
- data/lib/aerospike/cluster/rack_parser.rb +117 -0
- data/lib/aerospike/command/batch_direct_command.rb +1 -0
- data/lib/aerospike/command/batch_index_command.rb +1 -0
- data/lib/aerospike/command/command.rb +55 -0
- data/lib/aerospike/command/multi_command.rb +44 -1
- data/lib/aerospike/command/read_command.rb +34 -2
- data/lib/aerospike/command/touch_command.rb +34 -1
- data/lib/aerospike/features.rb +2 -0
- data/lib/aerospike/node.rb +18 -1
- data/lib/aerospike/node/rebalance.rb +50 -0
- data/lib/aerospike/node/refresh/info.rb +4 -1
- data/lib/aerospike/node/refresh/racks.rb +47 -0
- data/lib/aerospike/node/refresh/reset.rb +1 -0
- data/lib/aerospike/node/verify/rebalance_generation.rb +43 -0
- data/lib/aerospike/policy/client_policy.rb +15 -0
- data/lib/aerospike/policy/policy.rb +11 -3
- data/lib/aerospike/policy/replica.rb +7 -0
- data/lib/aerospike/socket/base.rb +3 -2
- data/lib/aerospike/utils/buffer.rb +13 -3
- data/lib/aerospike/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0452d4d35ee6d5ce56586cc99b3a68c7e1b4a6c4f6334c6794414a483e2ef01
|
4
|
+
data.tar.gz: 328a5672510bb68e044a92c39fc1f04059daa53b4332eaa5a64dda04f5b3de78
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44c883336f3993d532c7989e1c6bf737deca2773cb444a4cfa6021bca35311c9d4fe5c74ddb73fa1274661435a127892f9a368bd1d94120e6965bee38b870216
|
7
|
+
data.tar.gz: ebac442b5b2ddc345b7d7713b0e8d7f0aaaba9da24aabe811e1a10a26555c2a85ba1d2bad0a0266674fdcc1c3deb573ed1839ffe98294dc979ccc69e42eab187
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
|
5
|
+
## [2.14.0] - 2019-08-06
|
6
|
+
|
7
|
+
* **New Features**
|
8
|
+
* Adds support for rake-aware reads.
|
9
|
+
* Adds support for client-server compression.
|
10
|
+
|
11
|
+
* **Improvements**
|
12
|
+
* Adds support for `truncate-namespace` command.
|
13
|
+
|
5
14
|
## [2.13.0] - 2019-07-17
|
6
15
|
|
7
16
|
* **New Features**
|
data/lib/aerospike.rb
CHANGED
@@ -22,6 +22,7 @@ require "timeout"
|
|
22
22
|
require 'resolv'
|
23
23
|
require 'msgpack'
|
24
24
|
require 'bcrypt'
|
25
|
+
require 'zlib'
|
25
26
|
|
26
27
|
require 'aerospike/atomic/atomic'
|
27
28
|
|
@@ -105,17 +106,21 @@ require 'aerospike/cluster/find_nodes_to_remove'
|
|
105
106
|
require 'aerospike/cluster/find_node'
|
106
107
|
require 'aerospike/cluster/partition'
|
107
108
|
require 'aerospike/cluster/partition_parser'
|
109
|
+
require 'aerospike/cluster/rack_parser'
|
108
110
|
require 'aerospike/node'
|
109
111
|
require 'aerospike/node/generation'
|
112
|
+
require 'aerospike/node/rebalance'
|
110
113
|
require 'aerospike/node/refresh/failed'
|
111
114
|
require 'aerospike/node/refresh/friends'
|
112
115
|
require 'aerospike/node/refresh/info'
|
113
116
|
require 'aerospike/node/refresh/partitions'
|
117
|
+
require 'aerospike/node/refresh/racks'
|
114
118
|
require 'aerospike/node/refresh/peers'
|
115
119
|
require 'aerospike/node/refresh/reset'
|
116
120
|
require 'aerospike/node/verify/cluster_name'
|
117
121
|
require 'aerospike/node/verify/name'
|
118
122
|
require 'aerospike/node/verify/partition_generation'
|
123
|
+
require 'aerospike/node/verify/rebalance_generation'
|
119
124
|
require 'aerospike/node/verify/peers_generation'
|
120
125
|
require 'aerospike/node_validator'
|
121
126
|
require 'aerospike/peer'
|
data/lib/aerospike/client.rb
CHANGED
@@ -44,6 +44,7 @@ module Aerospike
|
|
44
44
|
attr_accessor :default_read_policy
|
45
45
|
attr_accessor :default_scan_policy
|
46
46
|
attr_accessor :default_write_policy
|
47
|
+
attr_accessor :cluster
|
47
48
|
|
48
49
|
def initialize(hosts = nil, policy: ClientPolicy.new, connect: true)
|
49
50
|
|
@@ -224,8 +225,19 @@ module Aerospike
|
|
224
225
|
def truncate(namespace, set_name = nil, before_last_update = nil, options = {})
|
225
226
|
policy = create_policy(options, Policy, default_info_policy)
|
226
227
|
|
227
|
-
|
228
|
-
|
228
|
+
node = @cluster.random_node
|
229
|
+
conn = node.get_connection(policy.timeout)
|
230
|
+
|
231
|
+
if set_name && !set_name.to_s.strip.empty?
|
232
|
+
str_cmd = "truncate:namespace=#{namespace}"
|
233
|
+
str_cmd << ";set=#{set_name}" unless set_name.to_s.strip.empty?
|
234
|
+
else
|
235
|
+
if node.supports_feature(Aerospike::Features::TRUNCATE_NAMESPACE)
|
236
|
+
str_cmd = "truncate-namespace:namespace=#{namespace}"
|
237
|
+
else
|
238
|
+
str_cmd = "truncate:namespace=#{namespace}"
|
239
|
+
end
|
240
|
+
end
|
229
241
|
|
230
242
|
if before_last_update
|
231
243
|
lut_nanos = (before_last_update.to_f * 1_000_000_000.0).round
|
@@ -235,8 +247,7 @@ module Aerospike
|
|
235
247
|
str_cmd << ";lut=now"
|
236
248
|
end
|
237
249
|
|
238
|
-
|
239
|
-
response = send_info_command(policy, str_cmd).upcase
|
250
|
+
response = send_info_command(policy, str_cmd, node).upcase
|
240
251
|
return if response == 'OK'
|
241
252
|
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_ERROR, "Truncate failed: #{response}")
|
242
253
|
end
|
@@ -818,9 +829,13 @@ module Aerospike
|
|
818
829
|
self.default_write_policy = create_policy(policies[:write], WritePolicy)
|
819
830
|
end
|
820
831
|
|
821
|
-
def send_info_command(policy, command)
|
832
|
+
def send_info_command(policy, command, node = nil)
|
822
833
|
Aerospike.logger.debug { "Sending info command: #{command}" }
|
823
|
-
|
834
|
+
if node
|
835
|
+
_, response = @cluster.request_node_info(node, policy, command).first
|
836
|
+
else
|
837
|
+
_, response = @cluster.request_info(policy, command).first
|
838
|
+
end
|
824
839
|
response.to_s
|
825
840
|
end
|
826
841
|
|
data/lib/aerospike/cluster.rb
CHANGED
@@ -28,6 +28,7 @@ module Aerospike
|
|
28
28
|
attr_reader :features, :tls_options
|
29
29
|
attr_reader :cluster_id, :aliases
|
30
30
|
attr_reader :cluster_name
|
31
|
+
attr_accessor :rack_aware, :rack_id
|
31
32
|
|
32
33
|
def initialize(policy, hosts)
|
33
34
|
@cluster_seeds = hosts
|
@@ -37,6 +38,8 @@ module Aerospike
|
|
37
38
|
@tend_interval = policy.tend_interval
|
38
39
|
@cluster_name = policy.cluster_name
|
39
40
|
@tls_options = policy.tls
|
41
|
+
@rack_aware = policy.rack_aware
|
42
|
+
@rack_id = policy.rack_id
|
40
43
|
|
41
44
|
@replica_index = Atomic.new(0)
|
42
45
|
|
@@ -111,6 +114,8 @@ module Aerospike
|
|
111
114
|
return master_node(partition)
|
112
115
|
when Aerospike::Replica::MASTER_PROLES
|
113
116
|
return master_proles_node(partition)
|
117
|
+
when Aerospike::Replica::PREFER_RACK
|
118
|
+
return rack_node(partition, seq)
|
114
119
|
when Aerospike::Replica::RANDOM
|
115
120
|
return random_node
|
116
121
|
else
|
@@ -125,6 +130,8 @@ module Aerospike
|
|
125
130
|
return master_node(partition)
|
126
131
|
when Aerospike::Replica::MASTER_PROLES
|
127
132
|
return master_proles_node(partition)
|
133
|
+
when Aerospike::Replica::PREFER_RACK
|
134
|
+
return rack_node(partition, seq)
|
128
135
|
when Aerospike::Replica::SEQUENCE
|
129
136
|
return sequence_node(partition, seq)
|
130
137
|
when Aerospike::Replica::RANDOM
|
@@ -149,6 +156,38 @@ module Aerospike
|
|
149
156
|
node
|
150
157
|
end
|
151
158
|
|
159
|
+
# Returns a node on the cluster
|
160
|
+
def rack_node(partition, seq)
|
161
|
+
partition_map = partitions
|
162
|
+
replica_array = partition_map[partition.namespace]
|
163
|
+
raise Aerospike::Exceptions::InvalidNamespace("namespace not found in the partition map") if !replica_array
|
164
|
+
|
165
|
+
replica_array = replica_array.get
|
166
|
+
|
167
|
+
is_retry = seq.value > -1
|
168
|
+
|
169
|
+
node = nil
|
170
|
+
fallback = nil
|
171
|
+
for i in 1..replica_array.length
|
172
|
+
idx = (seq.update{|v| v.succ} % replica_array.size).abs
|
173
|
+
node = (replica_array[idx].get)[partition.partition_id]
|
174
|
+
|
175
|
+
next if !node
|
176
|
+
|
177
|
+
fallback = node
|
178
|
+
|
179
|
+
# If fallback exists, do not retry on node where command failed,
|
180
|
+
# even if fallback is not on the same rack.
|
181
|
+
return fallback if is_retry && fallback && i == replica_array.length
|
182
|
+
|
183
|
+
return node if node && node.active? && node.has_rack(partition.namespace, @rack_id)
|
184
|
+
end
|
185
|
+
|
186
|
+
return fallback if fallback
|
187
|
+
|
188
|
+
raise Aerospike::Exceptions::InvalidNode
|
189
|
+
end
|
190
|
+
|
152
191
|
# Returns a node on the cluster for read operations
|
153
192
|
def master_proles_node(partition)
|
154
193
|
partition_map = partitions
|
@@ -256,6 +295,13 @@ module Aerospike
|
|
256
295
|
end
|
257
296
|
end
|
258
297
|
|
298
|
+
def request_node_info(node, policy, *commands)
|
299
|
+
conn = node.get_connection(policy.timeout)
|
300
|
+
Info.request(conn, *commands).tap do
|
301
|
+
node.put_connection(conn)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
259
305
|
def supports_feature?(feature)
|
260
306
|
@features.get.include?(feature.to_s)
|
261
307
|
end
|
@@ -352,6 +398,7 @@ module Aerospike
|
|
352
398
|
|
353
399
|
nodes.each do |node|
|
354
400
|
node.refresh_partitions(peers) if node.partition_generation.changed?
|
401
|
+
node.refresh_racks if node.rebalance_generation.changed?
|
355
402
|
end
|
356
403
|
|
357
404
|
if peers.generation_changed? || !peers.use_peers?
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2014-2020 Aerospike, Inc.
|
4
|
+
#
|
5
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
6
|
+
# license agreements.
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
9
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
10
|
+
# the License at http:#www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
14
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
15
|
+
# License for the specific language governing permissions and limitations under
|
16
|
+
# the License.
|
17
|
+
|
18
|
+
require 'base64'
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
|
22
|
+
class RackParser #:nodoc:
|
23
|
+
|
24
|
+
attr_accessor :rebalance_generation, :racks
|
25
|
+
|
26
|
+
REBALANCE_GENERATION = "rebalance-generation"
|
27
|
+
RACK_IDS = "rack-ids"
|
28
|
+
|
29
|
+
def initialize(node, conn)
|
30
|
+
@node = node
|
31
|
+
@conn = conn
|
32
|
+
@racks = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def update_racks
|
36
|
+
# Use low-level info methods and parse byte array directly for maximum performance.
|
37
|
+
# Receive format: rack-ids\t
|
38
|
+
# <ns1>:<rack-id>...;
|
39
|
+
# <ns2>:<rack-id>...; ...
|
40
|
+
info_map = Info.request(@conn, REBALANCE_GENERATION, RACK_IDS)
|
41
|
+
|
42
|
+
@rebalance_generation = info_map[REBALANCE_GENERATION].to_i
|
43
|
+
|
44
|
+
info = info_map[RACK_IDS]
|
45
|
+
if !info || info.length == 0
|
46
|
+
raise Aerospike::Exceptions::Connection.new("#{RACK_IDS} response for node #{@node.name} is empty")
|
47
|
+
end
|
48
|
+
|
49
|
+
@buffer = info
|
50
|
+
@length = info.length
|
51
|
+
@offset = 0
|
52
|
+
|
53
|
+
while @offset < @length && @buffer[@offset] != '\n'
|
54
|
+
namespace = parse_name
|
55
|
+
rack_id = parse_rack_id
|
56
|
+
|
57
|
+
@racks = {} if !@racks
|
58
|
+
@racks[namespace] = rack_id
|
59
|
+
end
|
60
|
+
|
61
|
+
@racks
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def parse_name
|
67
|
+
beginning = @offset
|
68
|
+
while @offset < @length
|
69
|
+
break if @buffer[@offset] == ':'
|
70
|
+
@offset+=1
|
71
|
+
end
|
72
|
+
|
73
|
+
# Parse namespace.
|
74
|
+
namespace = @buffer[beginning...@offset].strip
|
75
|
+
|
76
|
+
if namespace.length <= 0 || namespace.length >= 32
|
77
|
+
response = get_truncated_response
|
78
|
+
raise Aerospike::Exceptions::Parse.new(
|
79
|
+
"Invalid rack namespace #{namespace}. Response=#{response}"
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
@offset+=1
|
84
|
+
namespace
|
85
|
+
end
|
86
|
+
|
87
|
+
def parse_rack_id
|
88
|
+
beginning = @offset
|
89
|
+
while @offset < @length
|
90
|
+
break if @buffer[@offset] == ';'
|
91
|
+
@offset+=1
|
92
|
+
end
|
93
|
+
|
94
|
+
# Parse rack_id
|
95
|
+
rack_id = @buffer[beginning...@offset].strip.to_i
|
96
|
+
|
97
|
+
if rack_id < 0
|
98
|
+
response = get_truncated_response
|
99
|
+
raise Aerospike::Exceptions::Parse.new(
|
100
|
+
"Invalid rack_id #{rack_id}. Response=#{response}"
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
@offset+=1
|
105
|
+
rack_id
|
106
|
+
end
|
107
|
+
|
108
|
+
def get_truncated_response
|
109
|
+
max = @length
|
110
|
+
@length = max if @length > 200
|
111
|
+
@buffer[0...max]
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
end # class
|
116
|
+
|
117
|
+
end # module
|
@@ -16,6 +16,7 @@
|
|
16
16
|
# the License.
|
17
17
|
|
18
18
|
require 'time'
|
19
|
+
require 'zlib'
|
19
20
|
|
20
21
|
require 'msgpack'
|
21
22
|
require 'aerospike/result_code'
|
@@ -42,6 +43,9 @@ module Aerospike
|
|
42
43
|
# Involve all replicas in read operation.
|
43
44
|
INFO1_CONSISTENCY_ALL = Integer(1 << 6)
|
44
45
|
|
46
|
+
# Tell server to compress it's response.
|
47
|
+
INFO1_COMPRESS_RESPONSE = (1 << 7)
|
48
|
+
|
45
49
|
# Create or update record
|
46
50
|
INFO2_WRITE = Integer(1 << 0)
|
47
51
|
# Fling a record into the belly of Moloch.
|
@@ -72,8 +76,10 @@ module Aerospike
|
|
72
76
|
OPERATION_HEADER_SIZE = 8
|
73
77
|
MSG_REMAINING_HEADER_SIZE = 22
|
74
78
|
DIGEST_SIZE = 20
|
79
|
+
COMPRESS_THRESHOLD = 128
|
75
80
|
CL_MSG_VERSION = 2
|
76
81
|
AS_MSG_TYPE = 3
|
82
|
+
AS_MSG_TYPE_COMPRESSED = 4
|
77
83
|
|
78
84
|
class Command #:nodoc:
|
79
85
|
|
@@ -83,6 +89,8 @@ module Aerospike
|
|
83
89
|
|
84
90
|
@node = node
|
85
91
|
|
92
|
+
@compress = false
|
93
|
+
|
86
94
|
# will add before use
|
87
95
|
@sequence = Atomic.new(-1)
|
88
96
|
|
@@ -118,6 +126,7 @@ module Aerospike
|
|
118
126
|
end
|
119
127
|
|
120
128
|
end_cmd
|
129
|
+
mark_compressed(policy)
|
121
130
|
end
|
122
131
|
|
123
132
|
# Writes the command for delete operations
|
@@ -288,6 +297,7 @@ module Aerospike
|
|
288
297
|
write_operation_for_bin(nil, Aerospike::Operation::READ) if read_header
|
289
298
|
|
290
299
|
end_cmd
|
300
|
+
mark_compressed(policy)
|
291
301
|
end
|
292
302
|
|
293
303
|
def set_udf(policy, key, package_name, function_name, args)
|
@@ -310,6 +320,7 @@ module Aerospike
|
|
310
320
|
write_field_bytes(arg_bytes, Aerospike::FieldType::UDF_ARGLIST)
|
311
321
|
|
312
322
|
end_cmd
|
323
|
+
mark_compressed(policy)
|
313
324
|
end
|
314
325
|
|
315
326
|
def set_scan(policy, namespace, set_name, bin_names)
|
@@ -579,6 +590,7 @@ module Aerospike
|
|
579
590
|
# Generic header write.
|
580
591
|
def write_header(policy, read_attr, write_attr, field_count, operation_count)
|
581
592
|
read_attr |= INFO1_CONSISTENCY_ALL if policy.consistency_level == Aerospike::ConsistencyLevel::CONSISTENCY_ALL
|
593
|
+
read_attr |= INFO1_COMPRESS_RESPONSE if policy.use_compression
|
582
594
|
|
583
595
|
# Write all header data except total size which must be written last.
|
584
596
|
@data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message heade.length.
|
@@ -628,6 +640,7 @@ module Aerospike
|
|
628
640
|
info_attr |= INFO3_COMMIT_MASTER if policy.commit_level == Aerospike::CommitLevel::COMMIT_MASTER
|
629
641
|
read_attr |= INFO1_CONSISTENCY_ALL if policy.consistency_level == Aerospike::ConsistencyLevel::CONSISTENCY_ALL
|
630
642
|
write_attr |= INFO2_DURABLE_DELETE if policy.durable_delete
|
643
|
+
read_attr |= INFO1_COMPRESS_RESPONSE if policy.use_compression
|
631
644
|
|
632
645
|
# Write all header data except total size which must be written last.
|
633
646
|
@data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message heade.length.
|
@@ -810,6 +823,48 @@ module Aerospike
|
|
810
823
|
@data_buffer.write_int64(size, 0)
|
811
824
|
end
|
812
825
|
|
826
|
+
def use_compression?
|
827
|
+
@compress
|
828
|
+
end
|
829
|
+
|
830
|
+
def compress_buffer
|
831
|
+
if @data_offset > COMPRESS_THRESHOLD
|
832
|
+
compressed = Zlib::deflate(@data_buffer.buf, Zlib::DEFAULT_COMPRESSION)
|
833
|
+
|
834
|
+
# write original size as header
|
835
|
+
proto_s = "%08d" % 0
|
836
|
+
proto_s[0, 8] = [@data_offset].pack('q>')
|
837
|
+
compressed.prepend(proto_s)
|
838
|
+
|
839
|
+
# write proto
|
840
|
+
proto = (compressed.size+8) | Integer(CL_MSG_VERSION << 56) | Integer(AS_MSG_TYPE << 48)
|
841
|
+
proto_s = "%08d" % 0
|
842
|
+
proto_s[0, 8] = [proto].pack('q>')
|
843
|
+
compressed.prepend(proto_s)
|
844
|
+
|
845
|
+
@data_buffer = Buffer.new(-1, compressed)
|
846
|
+
@data_offset = @data_buffer.size
|
847
|
+
end
|
848
|
+
end
|
849
|
+
|
850
|
+
# isCompressed returns the length of the compressed buffer.
|
851
|
+
# If the buffer is not compressed, the result will be -1
|
852
|
+
def compressed_size
|
853
|
+
# A number of these are commented out because we just don't care enough to read
|
854
|
+
# that section of the header. If we do care, uncomment and check!
|
855
|
+
proto = @data_buffer.read_int64(0)
|
856
|
+
size = proto & 0xFFFFFFFFFFFF
|
857
|
+
msg_type = (proto >> 48) & 0xFF
|
858
|
+
|
859
|
+
return nil if msg_type != AS_MSG_TYPE_COMPRESSED
|
860
|
+
|
861
|
+
size
|
862
|
+
end
|
863
|
+
|
864
|
+
def mark_compressed(policy)
|
865
|
+
@compress = policy.use_compression
|
866
|
+
end
|
867
|
+
|
813
868
|
end # class
|
814
869
|
|
815
870
|
end # module
|
@@ -29,6 +29,9 @@ module Aerospike
|
|
29
29
|
@valid = true
|
30
30
|
@mutex = Mutex.new
|
31
31
|
|
32
|
+
@compressed_data_buffer = nil
|
33
|
+
@compressed_data_offset = nil
|
34
|
+
|
32
35
|
self
|
33
36
|
end
|
34
37
|
|
@@ -42,12 +45,41 @@ module Aerospike
|
|
42
45
|
status = true
|
43
46
|
|
44
47
|
while status
|
48
|
+
@data_offset = 0
|
49
|
+
@compressed_data_buffer = nil
|
50
|
+
|
45
51
|
# Read header.
|
46
52
|
read_bytes(8)
|
47
53
|
|
48
54
|
size = @data_buffer.read_int64(0)
|
49
55
|
receive_size = size & 0xFFFFFFFFFFFF
|
50
56
|
|
57
|
+
# inflate if compressed
|
58
|
+
compressed_sz = compressed_size
|
59
|
+
if compressed_sz
|
60
|
+
begin
|
61
|
+
# read compressed msg header
|
62
|
+
@conn.read(@data_buffer, 8)
|
63
|
+
|
64
|
+
# read compressed message
|
65
|
+
@conn.read(@data_buffer, compressed_sz - 8)
|
66
|
+
|
67
|
+
# inflate the results
|
68
|
+
# TODO: reuse the current buffer
|
69
|
+
uncompressed = Zlib::inflate(@data_buffer.buf)
|
70
|
+
receive_size = uncompressed.size - 8
|
71
|
+
|
72
|
+
@compressed_data_buffer = Buffer.new(-1, uncompressed)
|
73
|
+
@compressed_data_offset = 0
|
74
|
+
|
75
|
+
# waste the first 8 header bytes
|
76
|
+
@compressed_data_buffer.eat!(8)
|
77
|
+
rescue => e
|
78
|
+
Aerospike.logger.error("parse result error: #{e}")
|
79
|
+
raise e
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
51
83
|
if receive_size > 0
|
52
84
|
status = parse_group(receive_size)
|
53
85
|
else
|
@@ -157,7 +189,13 @@ module Aerospike
|
|
157
189
|
@data_buffer = Buffer.new(length)
|
158
190
|
end
|
159
191
|
|
160
|
-
|
192
|
+
if compressed?
|
193
|
+
@data_buffer.write_binary(@compressed_data_buffer.buf[@compressed_data_offset...@compressed_data_offset+length], 0)
|
194
|
+
@compressed_data_offset += length
|
195
|
+
else
|
196
|
+
@conn.read(@data_buffer, length)
|
197
|
+
end
|
198
|
+
|
161
199
|
@data_offset += length
|
162
200
|
end
|
163
201
|
|
@@ -176,6 +214,11 @@ module Aerospike
|
|
176
214
|
res
|
177
215
|
end
|
178
216
|
|
217
|
+
def compressed?
|
218
|
+
@compressed_data_buffer != nil
|
219
|
+
end
|
220
|
+
|
221
|
+
|
179
222
|
end # class
|
180
223
|
|
181
224
|
end # module
|
@@ -15,6 +15,8 @@
|
|
15
15
|
# License for the specific language governing permissions and limitations under
|
16
16
|
# the License.
|
17
17
|
|
18
|
+
require 'zlib'
|
19
|
+
|
18
20
|
require 'aerospike/record'
|
19
21
|
|
20
22
|
require 'aerospike/command/single_command'
|
@@ -50,12 +52,40 @@ module Aerospike
|
|
50
52
|
def parse_result
|
51
53
|
# Read header.
|
52
54
|
begin
|
53
|
-
@conn.read(@data_buffer,
|
55
|
+
@conn.read(@data_buffer, 8)
|
54
56
|
rescue => e
|
55
57
|
Aerospike.logger.error("parse result error: #{e}")
|
56
58
|
raise e
|
57
59
|
end
|
58
60
|
|
61
|
+
# inflate if compressed
|
62
|
+
compressed_sz = compressed_size
|
63
|
+
if compressed_sz
|
64
|
+
begin
|
65
|
+
# waste 8 size bytes
|
66
|
+
@conn.read(@data_buffer, 8)
|
67
|
+
|
68
|
+
# read compressed message
|
69
|
+
@conn.read(@data_buffer, compressed_sz - 8)
|
70
|
+
|
71
|
+
# inflate the results
|
72
|
+
# TODO: reuse the current buffer
|
73
|
+
uncompressed = Zlib::inflate(@data_buffer.buf)
|
74
|
+
|
75
|
+
@data_buffer = Buffer.new(-1, uncompressed)
|
76
|
+
rescue => e
|
77
|
+
Aerospike.logger.error("parse result error: #{e}")
|
78
|
+
raise e
|
79
|
+
end
|
80
|
+
else
|
81
|
+
begin
|
82
|
+
bytes_read = @conn.read(@data_buffer, MSG_TOTAL_HEADER_SIZE - 8, 8)
|
83
|
+
rescue => e
|
84
|
+
Aerospike.logger.error("parse result error: #{e}")
|
85
|
+
raise e
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
59
89
|
# A number of these are commented out because we just don't care enough to read
|
60
90
|
# that section of the header. If we do care, uncomment and check!
|
61
91
|
sz = @data_buffer.read_int64(0)
|
@@ -68,7 +98,9 @@ module Aerospike
|
|
68
98
|
receive_size = (sz & 0xFFFFFFFFFFFF) - header_length
|
69
99
|
|
70
100
|
# Read remaining message bytes.
|
71
|
-
if
|
101
|
+
if compressed_sz
|
102
|
+
@data_buffer.eat!(MSG_TOTAL_HEADER_SIZE)
|
103
|
+
elsif receive_size > 0
|
72
104
|
size_buffer_sz(receive_size)
|
73
105
|
|
74
106
|
begin
|
@@ -40,7 +40,40 @@ module Aerospike
|
|
40
40
|
|
41
41
|
def parse_result
|
42
42
|
# Read header.
|
43
|
-
|
43
|
+
begin
|
44
|
+
@conn.read(@data_buffer, 8)
|
45
|
+
rescue => e
|
46
|
+
Aerospike.logger.error("parse result error: #{e}")
|
47
|
+
raise e
|
48
|
+
end
|
49
|
+
|
50
|
+
# inflate if compressed
|
51
|
+
compressed_sz = compressed_size
|
52
|
+
if compressed_sz
|
53
|
+
begin
|
54
|
+
#waste 8 size bytes
|
55
|
+
@conn.read(@data_buffer, 8)
|
56
|
+
|
57
|
+
# read compressed message
|
58
|
+
@conn.read(@data_buffer, sz - 8)
|
59
|
+
|
60
|
+
# inflate the results
|
61
|
+
# TODO: reuse the current buffer
|
62
|
+
uncompressed = Zlib::inflate(@data_buffer.buf)
|
63
|
+
|
64
|
+
@data_buffer = Buffer.new(-1, uncompressed)
|
65
|
+
rescue => e
|
66
|
+
Aerospike.logger.error("parse result error: #{e}")
|
67
|
+
raise e
|
68
|
+
end
|
69
|
+
else
|
70
|
+
begin
|
71
|
+
bytes_read = @conn.read(@data_buffer, MSG_TOTAL_HEADER_SIZE - 8, 8)
|
72
|
+
rescue => e
|
73
|
+
Aerospike.logger.error("parse result error: #{e}")
|
74
|
+
raise e
|
75
|
+
end
|
76
|
+
end
|
44
77
|
|
45
78
|
result_code = @data_buffer.read(13).ord & 0xFF
|
46
79
|
|
data/lib/aerospike/features.rb
CHANGED
data/lib/aerospike/node.rb
CHANGED
@@ -22,7 +22,7 @@ require 'aerospike/atomic/atomic'
|
|
22
22
|
module Aerospike
|
23
23
|
class Node
|
24
24
|
|
25
|
-
attr_reader :reference_count, :responded, :name, :features, :cluster_name, :partition_generation, :peers_generation, :failures, :cluster, :peers_count, :host
|
25
|
+
attr_reader :reference_count, :responded, :name, :features, :cluster_name, :partition_generation, :rebalance_generation, :peers_generation, :failures, :cluster, :peers_count, :host
|
26
26
|
|
27
27
|
PARTITIONS = 4096
|
28
28
|
FULL_HEALTH = 100
|
@@ -46,16 +46,29 @@ module Aerospike
|
|
46
46
|
@peers_count = Atomic.new(0)
|
47
47
|
@peers_generation = ::Aerospike::Node::Generation.new
|
48
48
|
@partition_generation = ::Aerospike::Node::Generation.new
|
49
|
+
@rebalance_generation = ::Aerospike::Node::Rebalance.new
|
49
50
|
@reference_count = Atomic.new(0)
|
50
51
|
@responded = Atomic.new(false)
|
51
52
|
@active = Atomic.new(true)
|
52
53
|
@failures = Atomic.new(0)
|
53
54
|
|
54
55
|
@replica_index = Atomic.new(0)
|
56
|
+
@racks = Atomic.new(nil)
|
55
57
|
|
56
58
|
@connections = ::Aerospike::ConnectionPool.new(cluster, host)
|
57
59
|
end
|
58
60
|
|
61
|
+
def update_racks(parser)
|
62
|
+
new_racks = parser.update_racks
|
63
|
+
@racks.value = new_racks if new_racks
|
64
|
+
end
|
65
|
+
|
66
|
+
def has_rack(ns, rack_id)
|
67
|
+
racks = @racks.value
|
68
|
+
return false if !racks
|
69
|
+
racks[ns] == rack_id
|
70
|
+
end
|
71
|
+
|
59
72
|
# Get a connection to the node. If no cached connection is not available,
|
60
73
|
# a new connection will be created
|
61
74
|
def get_connection(timeout)
|
@@ -199,6 +212,10 @@ module Aerospike
|
|
199
212
|
Node::Refresh::Partitions.(self, peers)
|
200
213
|
end
|
201
214
|
|
215
|
+
def refresh_racks()
|
216
|
+
Node::Refresh::Racks.(self)
|
217
|
+
end
|
218
|
+
|
202
219
|
def refresh_peers(peers)
|
203
220
|
Node::Refresh::Peers.(self, peers)
|
204
221
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 Aerospike, Inc.
|
4
|
+
#
|
5
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
6
|
+
# license agreements.
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
9
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
10
|
+
# the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
16
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
17
|
+
# License for the specific language governing permissions and limitations under
|
18
|
+
# the License.
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
class Node
|
22
|
+
# generic class for representing changes in eg. peer and partition generation
|
23
|
+
class Rebalance
|
24
|
+
attr_reader :generation
|
25
|
+
|
26
|
+
def initialize(generation = -1)
|
27
|
+
@generation = ::Aerospike::Atomic.new(generation)
|
28
|
+
@changed = ::Aerospike::Atomic.new(false)
|
29
|
+
end
|
30
|
+
|
31
|
+
def changed?
|
32
|
+
@changed.value == true
|
33
|
+
end
|
34
|
+
|
35
|
+
def eql?(generation)
|
36
|
+
@generation.value == generation
|
37
|
+
end
|
38
|
+
|
39
|
+
def reset_changed!
|
40
|
+
@changed.value = false
|
41
|
+
end
|
42
|
+
|
43
|
+
def update(new_generation)
|
44
|
+
return if @generation.value == new_generation
|
45
|
+
@generation.value = new_generation
|
46
|
+
@changed.value = true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -24,14 +24,17 @@ module Aerospike
|
|
24
24
|
CMDS_BASE = %w[node partition-generation cluster-name].freeze
|
25
25
|
CMDS_PEERS = (CMDS_BASE + ['peers-generation']).freeze
|
26
26
|
CMDS_SERVICES = (CMDS_BASE + ['services']).freeze
|
27
|
+
CMDS_REBALANCE = (CMDS_PEERS + ['rebalance-generation']).freeze
|
27
28
|
|
28
29
|
class << self
|
29
30
|
def call(node, peers)
|
30
31
|
conn = node.tend_connection
|
31
32
|
if peers.use_peers?
|
32
|
-
|
33
|
+
cmds = node.cluster.rack_aware ? CMDS_REBALANCE : CMDS_PEERS
|
34
|
+
info_map = ::Aerospike::Info.request(conn, *cmds)
|
33
35
|
Verify::PeersGeneration.(node, info_map, peers)
|
34
36
|
Verify::PartitionGeneration.(node, info_map)
|
37
|
+
Verify::RebalanceGeneration.(node, info_map) if node.cluster.rack_aware
|
35
38
|
Verify::Name.(node, info_map)
|
36
39
|
Verify::ClusterName.(node, info_map)
|
37
40
|
else
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018-2020 Aerospike, Inc.
|
4
|
+
#
|
5
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
6
|
+
# license agreements.
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
9
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
10
|
+
# the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
16
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
17
|
+
# License for the specific language governing permissions and limitations under
|
18
|
+
# the License.
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
class Node
|
22
|
+
module Refresh
|
23
|
+
module Racks
|
24
|
+
class << self
|
25
|
+
def call(node)
|
26
|
+
return unless should_refresh?(node)
|
27
|
+
|
28
|
+
Aerospike.logger.info("Updating racks for node #{node.name}")
|
29
|
+
conn = node.tend_connection
|
30
|
+
parser = RackParser.new(node, conn)
|
31
|
+
node.update_racks(parser)
|
32
|
+
rescue ::Aerospike::Exceptions::Aerospike => e
|
33
|
+
conn.close
|
34
|
+
Refresh::Failed.(node, e)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Do not refresh racks when node connection has already failed
|
38
|
+
# during this cluster tend iteration.
|
39
|
+
def should_refresh?(node)
|
40
|
+
return false if node.failed? || !node.active?
|
41
|
+
true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 Aerospike, Inc.
|
4
|
+
#
|
5
|
+
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
6
|
+
# license agreements.
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
9
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
10
|
+
# the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
16
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
17
|
+
# License for the specific language governing permissions and limitations under
|
18
|
+
# the License.
|
19
|
+
|
20
|
+
module Aerospike
|
21
|
+
class Node
|
22
|
+
module Verify
|
23
|
+
# Fetch and set rebalance generation. If racks needs to be refreshed
|
24
|
+
# this will be indicated in node.rebalance_changed
|
25
|
+
module RebalanceGeneration
|
26
|
+
class << self
|
27
|
+
def call(node, info_map)
|
28
|
+
gen_string = info_map.fetch('rebalance-generation', nil)
|
29
|
+
|
30
|
+
raise Aerospike::Exceptions::Parse.new('rebalance-generation is empty') if gen_string.to_s.empty?
|
31
|
+
|
32
|
+
generation = gen_string.to_i
|
33
|
+
|
34
|
+
node.rebalance_generation.update(generation)
|
35
|
+
|
36
|
+
return unless node.rebalance_generation.changed?
|
37
|
+
Aerospike.logger.info("Node #{node.name} rebalance generation #{generation} changed")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -27,6 +27,7 @@ module Aerospike
|
|
27
27
|
attr_accessor :cluster_name
|
28
28
|
attr_accessor :tls
|
29
29
|
attr_accessor :policies
|
30
|
+
attr_accessor :rack_aware, :rack_id
|
30
31
|
|
31
32
|
def initialize(opt={})
|
32
33
|
# Initial host connection timeout in seconds. The timeout when opening a connection
|
@@ -56,6 +57,20 @@ module Aerospike
|
|
56
57
|
|
57
58
|
# Default Policies
|
58
59
|
@policies = opt.fetch(:policies) { Hash.new }
|
60
|
+
|
61
|
+
# Track server rack data. This field is useful when directing read commands to the server node
|
62
|
+
# that contains the key and exists on the same rack as the client. This serves to lower cloud
|
63
|
+
# provider costs when nodes are distributed across different racks/data centers.
|
64
|
+
#
|
65
|
+
# ClientPolicy#rack_id, Replica#PREFER_RACK and server rack
|
66
|
+
# configuration must also be set to enable this functionality.
|
67
|
+
@rack_aware = opt[:rack_aware] || false
|
68
|
+
|
69
|
+
# Rack where this client instance resides.
|
70
|
+
#
|
71
|
+
# ClientPolicy#rack_aware, Replica#PREFER_RACK and server rack
|
72
|
+
# configuration must also be set to enable this functionality.
|
73
|
+
@rack_id = opt[:rack_id] || 0
|
59
74
|
end
|
60
75
|
|
61
76
|
def requires_authentication
|
@@ -24,7 +24,7 @@ module Aerospike
|
|
24
24
|
class Policy
|
25
25
|
|
26
26
|
attr_accessor :priority, :timeout, :max_retries, :sleep_between_retries, :consistency_level,
|
27
|
-
:predexp, :fail_on_filtered_out, :replica
|
27
|
+
:predexp, :fail_on_filtered_out, :replica, :use_compression
|
28
28
|
|
29
29
|
def initialize(opt={})
|
30
30
|
# Container object for transaction policy attributes used in all database
|
@@ -89,9 +89,17 @@ module Aerospike
|
|
89
89
|
# to the node containing the key's master partition.
|
90
90
|
#
|
91
91
|
# Default to sending read commands to the node containing the key's master partition.
|
92
|
-
@replica = opt[:replica] || Aerospike::Replica::MASTER
|
92
|
+
@replica = opt[:replica] || Aerospike::Replica::MASTER
|
93
93
|
|
94
|
-
|
94
|
+
# Use zlib compression on write or batch read commands when the command buffer size is greater
|
95
|
+
# than 128 bytes. In addition, tell the server to compress its response on read commands.
|
96
|
+
# The server response compression threshold is also 128 bytes.
|
97
|
+
#
|
98
|
+
# This option will increase cpu and memory usage (for extra compressed buffers), but
|
99
|
+
# decrease the size of data sent over the network.
|
100
|
+
@use_compression = opt[:use_compression] || false
|
101
|
+
|
102
|
+
# Transaction timeout.
|
95
103
|
# This timeout is used to set the socket timeout and is also sent to the
|
96
104
|
# server along with the transaction in the wire protocol.
|
97
105
|
# Default to no timeout (0).
|
@@ -28,6 +28,13 @@ module Aerospike
|
|
28
28
|
# Policy#retryOnTimeout is true, try nodes containing prole partition.
|
29
29
|
SEQUENCE = 2
|
30
30
|
|
31
|
+
# Try node on the same rack as the client first. If there are no nodes on the
|
32
|
+
# same rack, use SEQUENCE instead.
|
33
|
+
#
|
34
|
+
# ClientPolicy#rack_aware}, ClientPolicy#rack_id, and server rack
|
35
|
+
# configuration must also be set to enable this functionality.
|
36
|
+
PREFER_RACK = 3
|
37
|
+
|
31
38
|
# Distribute reads across all nodes in cluster in round-robin fashion.
|
32
39
|
# This option is useful when the replication factor equals the number
|
33
40
|
# of nodes in the cluster and the overhead of requesting proles is not desired.
|
@@ -25,13 +25,14 @@ module Aerospike
|
|
25
25
|
@timeout = nil
|
26
26
|
end
|
27
27
|
|
28
|
-
def read(buffer, length)
|
28
|
+
def read(buffer, length, offset = 0)
|
29
29
|
bytes_read = 0
|
30
30
|
until bytes_read >= length
|
31
31
|
result = read_from_socket(length - bytes_read)
|
32
|
-
buffer.write_binary(result, bytes_read)
|
32
|
+
buffer.write_binary(result, offset + bytes_read)
|
33
33
|
bytes_read += result.bytesize
|
34
34
|
end
|
35
|
+
bytes_read
|
35
36
|
end
|
36
37
|
|
37
38
|
def read_from_socket(length)
|
@@ -42,9 +42,9 @@ module Aerospike
|
|
42
42
|
DEFAULT_BUFFER_SIZE = 16 * 1024
|
43
43
|
MAX_BUFFER_SIZE = 10 * 1024 * 1024
|
44
44
|
|
45
|
-
def initialize(size=DEFAULT_BUFFER_SIZE)
|
46
|
-
@buf = "%0#{size}d" % 0
|
47
|
-
|
45
|
+
def initialize(size=DEFAULT_BUFFER_SIZE, buf = nil)
|
46
|
+
@buf = (buf ? buf : ("%0#{size}d" % 0))
|
47
|
+
@buf.force_encoding('binary')
|
48
48
|
@slice_end = @buf.bytesize
|
49
49
|
end
|
50
50
|
|
@@ -61,6 +61,10 @@ module Aerospike
|
|
61
61
|
end
|
62
62
|
alias_method :length, :size
|
63
63
|
|
64
|
+
def eat!(n)
|
65
|
+
@buf.replace(@buf[n..-1])
|
66
|
+
end
|
67
|
+
|
64
68
|
def resize(length)
|
65
69
|
if @buf.bytesize < length
|
66
70
|
@buf.concat("%0#{length - @buf.bytesize}d" % 0)
|
@@ -156,6 +160,12 @@ module Aerospike
|
|
156
160
|
@buf[0..@slice_end-1]
|
157
161
|
end
|
158
162
|
|
163
|
+
def reset
|
164
|
+
for i in 0..@buf.size-1
|
165
|
+
@buf[i] = ' '
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
159
169
|
def dump(from=nil, to=nil)
|
160
170
|
from ||= 0
|
161
171
|
to ||= @slice_end - 1
|
data/lib/aerospike/version.rb
CHANGED
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: 2.
|
4
|
+
version: 2.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Khosrow Afroozeh
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-
|
12
|
+
date: 2020-08-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: msgpack
|
@@ -74,6 +74,7 @@ files:
|
|
74
74
|
- lib/aerospike/cluster/find_nodes_to_remove.rb
|
75
75
|
- lib/aerospike/cluster/partition.rb
|
76
76
|
- lib/aerospike/cluster/partition_parser.rb
|
77
|
+
- lib/aerospike/cluster/rack_parser.rb
|
77
78
|
- lib/aerospike/command/admin_command.rb
|
78
79
|
- lib/aerospike/command/batch_direct_command.rb
|
79
80
|
- lib/aerospike/command/batch_direct_exists_command.rb
|
@@ -108,16 +109,19 @@ files:
|
|
108
109
|
- lib/aerospike/loggable.rb
|
109
110
|
- lib/aerospike/node.rb
|
110
111
|
- lib/aerospike/node/generation.rb
|
112
|
+
- lib/aerospike/node/rebalance.rb
|
111
113
|
- lib/aerospike/node/refresh/failed.rb
|
112
114
|
- lib/aerospike/node/refresh/friends.rb
|
113
115
|
- lib/aerospike/node/refresh/info.rb
|
114
116
|
- lib/aerospike/node/refresh/partitions.rb
|
115
117
|
- lib/aerospike/node/refresh/peers.rb
|
118
|
+
- lib/aerospike/node/refresh/racks.rb
|
116
119
|
- lib/aerospike/node/refresh/reset.rb
|
117
120
|
- lib/aerospike/node/verify/cluster_name.rb
|
118
121
|
- lib/aerospike/node/verify/name.rb
|
119
122
|
- lib/aerospike/node/verify/partition_generation.rb
|
120
123
|
- lib/aerospike/node/verify/peers_generation.rb
|
124
|
+
- lib/aerospike/node/verify/rebalance_generation.rb
|
121
125
|
- lib/aerospike/node_validator.rb
|
122
126
|
- lib/aerospike/operation.rb
|
123
127
|
- lib/aerospike/peer.rb
|