aerospike 1.0.12 → 2.0.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 +54 -18
- data/README.md +7 -2
- data/lib/aerospike.rb +8 -0
- data/lib/aerospike/cdt/list_operation.rb +199 -0
- data/lib/aerospike/cdt/map_operation.rb +352 -0
- data/lib/aerospike/cdt/map_order.rb +38 -0
- data/lib/aerospike/cdt/map_policy.rb +37 -0
- data/lib/aerospike/cdt/map_return_type.rb +74 -0
- data/lib/aerospike/cdt/map_write_mode.rb +41 -0
- data/lib/aerospike/client.rb +84 -119
- data/lib/aerospike/cluster/cluster.rb +4 -4
- data/lib/aerospike/command/admin_command.rb +325 -325
- data/lib/aerospike/command/command.rb +2 -2
- data/lib/aerospike/command/roles.rb +13 -13
- data/lib/aerospike/key.rb +24 -5
- data/lib/aerospike/operation.rb +2 -0
- data/lib/aerospike/policy/admin_policy.rb +10 -10
- data/lib/aerospike/policy/consistency_level.rb +4 -4
- data/lib/aerospike/query/stream_command.rb +1 -1
- data/lib/aerospike/result_code.rb +1 -1
- data/lib/aerospike/task/execute_task.rb +68 -68
- data/lib/aerospike/task/task.rb +2 -6
- data/lib/aerospike/utils/packer.rb +47 -0
- data/lib/aerospike/utils/unpacker.rb +106 -0
- data/lib/aerospike/value/value.rb +19 -51
- data/lib/aerospike/version.rb +1 -1
- metadata +17 -7
@@ -212,7 +212,7 @@ module Aerospike
|
|
212
212
|
|
213
213
|
def launch_tend_thread
|
214
214
|
@tend_thread = Thread.new do
|
215
|
-
abort_on_exception = false
|
215
|
+
Thread.current.abort_on_exception = false
|
216
216
|
while true
|
217
217
|
begin
|
218
218
|
tend
|
@@ -325,9 +325,9 @@ module Aerospike
|
|
325
325
|
|
326
326
|
def update_cluster_features
|
327
327
|
# Cluster supports features that are supported by all nodes
|
328
|
-
@features.update do
|
329
|
-
|
330
|
-
|
328
|
+
@features.update do
|
329
|
+
node_features = self.nodes.map(&:features)
|
330
|
+
node_features.reduce(&:intersection) || Set.new
|
331
331
|
end
|
332
332
|
end
|
333
333
|
|
@@ -17,330 +17,330 @@
|
|
17
17
|
module Aerospike
|
18
18
|
|
19
19
|
private
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
20
|
+
# Commands
|
21
|
+
AUTHENTICATE = 0
|
22
|
+
CREATE_USER = 1
|
23
|
+
DROP_USER = 2
|
24
|
+
SET_PASSWORD = 3
|
25
|
+
CHANGE_PASSWORD = 4
|
26
|
+
GRANT_ROLES = 5
|
27
|
+
REVOKE_ROLES = 6
|
28
|
+
REPLACE_ROLES = 7
|
29
|
+
#CREATE_ROLE = 8
|
30
|
+
QUERY_USERS = 9
|
31
|
+
#QUERY_ROLES = 10
|
32
|
+
|
33
|
+
# Field IDs
|
34
|
+
USER = 0
|
35
|
+
PASSWORD = 1
|
36
|
+
OLD_PASSWORD = 2
|
37
|
+
CREDENTIAL = 3
|
38
|
+
ROLES = 10
|
39
|
+
#PRIVILEGES = 11
|
40
|
+
|
41
|
+
# Misc
|
42
|
+
MSG_VERSION = 0
|
43
|
+
MSG_TYPE = 2
|
44
|
+
|
45
|
+
HEADER_SIZE = 24
|
46
|
+
HEADER_REMAINING = 16
|
47
|
+
RESULT_CODE = 9
|
48
|
+
QUERY_END = 50
|
49
|
+
|
50
|
+
class AdminCommand #:nodoc:
|
51
|
+
|
52
|
+
def initialize
|
53
|
+
@data_buffer = Buffer.get
|
54
|
+
@data_offset = 8
|
55
|
+
end
|
56
|
+
|
57
|
+
def authenticate(conn, user, password)
|
58
|
+
begin
|
59
|
+
set_authenticate(user, password)
|
60
|
+
conn.write(@data_buffer, @data_offset)
|
61
|
+
conn.read(@data_buffer, HEADER_SIZE)
|
62
|
+
|
63
|
+
result = @data_buffer.read(RESULT_CODE)
|
64
|
+
raise Exceptions::Aerospike.new(result, "Authentication failed") if result != 0
|
65
|
+
ensure
|
66
|
+
Buffer.put(@data_buffer)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def set_authenticate(user, password)
|
71
|
+
write_header(AUTHENTICATE, 2)
|
72
|
+
write_field_str(USER, user)
|
73
|
+
write_field_bytes(CREDENTIAL, password)
|
74
|
+
write_size
|
75
|
+
|
76
|
+
return @data_offset
|
77
|
+
end
|
78
|
+
|
79
|
+
def create_user(cluster, policy, user, password, roles)
|
80
|
+
write_header(CREATE_USER, 3)
|
81
|
+
write_field_str(USER, user)
|
82
|
+
write_field_bytes(PASSWORD, password)
|
83
|
+
write_roles(roles)
|
84
|
+
execute_command(cluster, policy)
|
85
|
+
end
|
86
|
+
|
87
|
+
def drop_user(cluster, policy, user)
|
88
|
+
write_header(DROP_USER, 1)
|
89
|
+
write_field_str(USER, user)
|
90
|
+
execute_command(cluster, policy)
|
91
|
+
end
|
92
|
+
|
93
|
+
def set_password(cluster, policy, user, password)
|
94
|
+
write_header(SET_PASSWORD, 2)
|
95
|
+
write_field_str(USER, user)
|
96
|
+
write_field_bytes(PASSWORD, password)
|
97
|
+
execute_command(cluster, policy)
|
98
|
+
end
|
99
|
+
|
100
|
+
def change_password(cluster, policy, user, password)
|
101
|
+
write_header(CHANGE_PASSWORD, 3)
|
102
|
+
write_field_str(USER, user)
|
103
|
+
write_field_bytes(OLD_PASSWORD, cluster.password)
|
104
|
+
write_field_bytes(PASSWORD, password)
|
105
|
+
execute_command(cluster, policy)
|
106
|
+
end
|
107
|
+
|
108
|
+
def grant_roles(cluster, policy, user, roles)
|
109
|
+
write_header(GRANT_ROLES, 2)
|
110
|
+
write_field_str(USER, user)
|
111
|
+
write_roles(roles)
|
112
|
+
execute_command(cluster, policy)
|
113
|
+
end
|
114
|
+
|
115
|
+
def revoke_roles(cluster, policy, user, roles)
|
116
|
+
write_header(REVOKE_ROLES, 2)
|
117
|
+
write_field_str(USER, user)
|
118
|
+
write_roles(roles)
|
119
|
+
execute_command(cluster, policy)
|
120
|
+
end
|
121
|
+
|
122
|
+
def query_user(cluster, policy, user)
|
123
|
+
# TODO: Remove the workaround in the future
|
124
|
+
sleep(0.010)
|
125
|
+
|
126
|
+
list = []
|
127
|
+
begin
|
128
|
+
write_header(QUERY_USERS, 1)
|
129
|
+
write_field_str(USER, user)
|
130
|
+
list = read_users(cluster, policy)
|
131
|
+
return (list.is_a?(Array) && list.length > 0 ? list.first : nil)
|
132
|
+
ensure
|
133
|
+
Buffer.put(@data_buffer)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def query_users(cluster, policy)
|
138
|
+
# TODO: Remove the workaround in the future
|
139
|
+
sleep(0.010)
|
140
|
+
begin
|
141
|
+
write_header(QUERY_USERS, 0)
|
142
|
+
return read_users(cluster, policy)
|
143
|
+
ensure
|
144
|
+
Buffer.put(@data_buffer)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def write_roles(roles)
|
149
|
+
offset = @data_offset + FIELD_HEADER_SIZE
|
150
|
+
@data_buffer.write_byte(roles.length.ord, offset)
|
151
|
+
offset += 1
|
152
|
+
|
153
|
+
roles.each do |role|
|
154
|
+
len = @data_buffer.write_binary(role, offset+1)
|
155
|
+
@data_buffer.write_byte(len, offset)
|
156
|
+
offset += len + 1
|
157
|
+
end
|
158
|
+
|
159
|
+
size = offset - @data_offset - FIELD_HEADER_SIZE
|
160
|
+
write_field_header(ROLES, size)
|
161
|
+
@data_offset = offset
|
162
|
+
end
|
163
|
+
|
164
|
+
def write_size
|
165
|
+
# Write total size of message which is the current offset.
|
166
|
+
size = Integer(@data_offset-8) | Integer(MSG_VERSION << 56) | Integer(MSG_TYPE << 48)
|
167
|
+
@data_buffer.write_int64(size, 0)
|
168
|
+
end
|
169
|
+
|
170
|
+
def write_header(command, field_count)
|
171
|
+
# Authenticate header is almost all zeros
|
172
|
+
i = @data_offset
|
173
|
+
while i < @data_offset+16
|
174
|
+
@data_buffer.write_byte(0, i)
|
175
|
+
i = i.succ
|
176
|
+
end
|
177
|
+
@data_buffer.write_byte(command, @data_offset+2)
|
178
|
+
@data_buffer.write_byte(field_count, @data_offset+3)
|
179
|
+
@data_offset += 16
|
180
|
+
end
|
181
|
+
|
182
|
+
def write_field_str(id, str)
|
183
|
+
len = @data_buffer.write_binary(str, @data_offset+FIELD_HEADER_SIZE)
|
184
|
+
write_field_header(id, len)
|
185
|
+
@data_offset += len
|
186
|
+
end
|
187
|
+
|
188
|
+
def write_field_bytes(id, bytes)
|
189
|
+
@data_buffer.write_binary(bytes, @data_offset+FIELD_HEADER_SIZE)
|
190
|
+
write_field_header(id, bytes.bytesize)
|
191
|
+
@data_offset += bytes.bytesize
|
192
|
+
end
|
193
|
+
|
194
|
+
def write_field_header(id, size)
|
195
|
+
@data_buffer.write_int32(size+1, @data_offset)
|
196
|
+
@data_offset += 4
|
197
|
+
@data_buffer.write_byte(id, @data_offset)
|
198
|
+
@data_offset += 1
|
199
|
+
end
|
200
|
+
|
201
|
+
def execute_command(cluster, policy)
|
202
|
+
# TODO: Remove the workaround in the future
|
203
|
+
sleep(0.010)
|
204
|
+
|
205
|
+
write_size
|
206
|
+
node = cluster.random_node
|
207
|
+
|
208
|
+
timeout = 1
|
209
|
+
timeout = policy.timeout if policy && policy.timeout > 0
|
210
|
+
|
211
|
+
conn = node.get_connection(timeout)
|
212
|
+
|
213
|
+
begin
|
214
|
+
conn.write(@data_buffer, @data_offset)
|
215
|
+
conn.read(@data_buffer, HEADER_SIZE)
|
216
|
+
node.put_connection(conn)
|
217
|
+
rescue => e
|
218
|
+
conn.close if conn
|
219
|
+
raise e
|
220
|
+
end
|
221
|
+
|
222
|
+
result = @data_buffer.read(RESULT_CODE)
|
223
|
+
raise Exceptions::Aerospike.new(result) if result != 0
|
224
|
+
|
225
|
+
Buffer.put(@data_buffer)
|
226
|
+
end
|
227
|
+
|
228
|
+
def read_users(cluster, policy)
|
229
|
+
write_size
|
230
|
+
node = cluster.random_node
|
231
|
+
|
232
|
+
timeout = 1
|
233
|
+
timeout = policy.timeout if policy != nil && policy.timeout > 0
|
234
|
+
|
235
|
+
status = -1
|
236
|
+
list = []
|
237
|
+
begin
|
238
|
+
conn = node.get_connection(timeout)
|
239
|
+
conn.write(@data_buffer, @data_offset)
|
240
|
+
status, list = read_user_blocks(conn)
|
241
|
+
node.put_connection(conn)
|
242
|
+
rescue => e
|
243
|
+
conn.close if conn
|
244
|
+
raise e
|
245
|
+
end
|
246
|
+
|
247
|
+
raise Exceptions::Aerospike.new(result) if status > 0
|
248
|
+
|
249
|
+
return list
|
250
|
+
end
|
251
|
+
|
252
|
+
def read_user_blocks(conn)
|
253
|
+
rlist = []
|
254
|
+
status = 0
|
255
|
+
begin
|
256
|
+
while status == 0
|
257
|
+
conn.read(@data_buffer, 8)
|
258
|
+
size = @data_buffer.read_int64(0)
|
259
|
+
receive_size = (size & 0xFFFFFFFFFFFF)
|
260
|
+
|
261
|
+
if receive_size > 0
|
262
|
+
@data_buffer.resize(receive_size) if receive_size > @data_buffer.size
|
263
|
+
|
264
|
+
conn.read(@data_buffer, receive_size)
|
265
|
+
status, list = parse_users(receive_size)
|
266
|
+
rlist.concat(list.to_a)
|
267
|
+
else
|
268
|
+
break
|
269
|
+
end
|
270
|
+
end
|
271
|
+
return status, rlist
|
272
|
+
rescue
|
273
|
+
return -1, []
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def parse_users(receive_size)
|
278
|
+
@data_offset = 0
|
279
|
+
list = []
|
280
|
+
|
281
|
+
while @data_offset < receive_size
|
282
|
+
result_code = @data_buffer.read(@data_offset+1)
|
283
|
+
|
284
|
+
if result_code != 0
|
285
|
+
return (result_code == QUERY_END ? -1 : result_code)
|
286
|
+
end
|
287
|
+
|
288
|
+
userRoles = UserRoles.new
|
289
|
+
field_count = @data_buffer.read(@data_offset+3)
|
290
|
+
@data_offset += HEADER_REMAINING
|
291
|
+
|
292
|
+
i = 0
|
293
|
+
while i < field_count
|
294
|
+
len = @data_buffer.read_int32(@data_offset)
|
295
|
+
@data_offset += 4
|
296
|
+
id = @data_buffer.read(@data_offset)
|
297
|
+
@data_offset += 1
|
298
|
+
len -= 1
|
299
|
+
|
300
|
+
case id
|
301
|
+
when USER
|
302
|
+
userRoles.user = @data_buffer.read(@data_offset, len)
|
303
|
+
@data_offset += len
|
304
|
+
when ROLES
|
305
|
+
parse_roles(userRoles)
|
306
|
+
else
|
307
|
+
@data_offset += len
|
308
|
+
end
|
309
|
+
|
310
|
+
i = i.succ
|
311
|
+
end
|
312
|
+
|
313
|
+
next if userRoles.user == "" && userRoles.roles == nil
|
314
|
+
|
315
|
+
userRoles.roles = [] if userRoles.roles == nil
|
316
|
+
list << userRoles
|
317
|
+
end
|
318
|
+
|
319
|
+
return 0, list
|
320
|
+
end
|
321
|
+
|
322
|
+
def parse_roles(userRoles)
|
323
|
+
size = @data_buffer.read(@data_offset)
|
324
|
+
@data_offset += 1
|
325
|
+
userRoles.roles = []
|
326
|
+
|
327
|
+
i = 0
|
328
|
+
while i < size
|
329
|
+
len = @data_buffer.read(@data_offset)
|
330
|
+
@data_offset += 1
|
331
|
+
role = @data_buffer.read(@data_offset, len)
|
332
|
+
@data_offset += len
|
333
|
+
userRoles.roles << role
|
334
|
+
|
335
|
+
i = i.succ
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
SALT = '$2a$10$7EqJtq98hPqEX7fNZaFWoO'
|
340
|
+
def self.hash_password(password)
|
341
|
+
# Hashing the password with the cost of 10, with a static salt
|
342
|
+
return BCrypt::Engine.hash_secret(password, SALT, :cost => 10)
|
343
|
+
end
|
344
|
+
end
|
345
345
|
end
|
346
346
|
|