roma 0.8.2
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.
- data/LICENSE.rdoc +675 -0
- data/README.rdoc +0 -0
- data/Rakefile +70 -0
- data/bin/mkrecent +7 -0
- data/bin/mkroute +7 -0
- data/bin/recoverlost +8 -0
- data/bin/recoverlost_alist +8 -0
- data/bin/romad +7 -0
- data/bin/sample_watcher +8 -0
- data/bin/sample_watcher2 +8 -0
- data/bin/simple_bench +8 -0
- data/bin/ssroute +7 -0
- data/bin/tribunus +7 -0
- data/lib/roma/async_process.rb +696 -0
- data/lib/roma/command/bg_command_receiver.rb +188 -0
- data/lib/roma/command/mh_command_receiver.rb +117 -0
- data/lib/roma/command/receiver.rb +287 -0
- data/lib/roma/command/rt_command_receiver.rb +147 -0
- data/lib/roma/command/st_command_receiver.rb +564 -0
- data/lib/roma/command/util_command_receiver.rb +67 -0
- data/lib/roma/command/vn_command_receiver.rb +143 -0
- data/lib/roma/command_plugin.rb +11 -0
- data/lib/roma/config.rb +64 -0
- data/lib/roma/event/con_pool.rb +140 -0
- data/lib/roma/event/handler.rb +159 -0
- data/lib/roma/plugin/plugin_alist.rb +1572 -0
- data/lib/roma/plugin/plugin_debug.rb +19 -0
- data/lib/roma/plugin/plugin_test.rb +14 -0
- data/lib/roma/romad.rb +582 -0
- data/lib/roma/routing/cb_rttable.rb +326 -0
- data/lib/roma/routing/merkle_tree.rb +54 -0
- data/lib/roma/routing/rttable.rb +148 -0
- data/lib/roma/stats.rb +112 -0
- data/lib/roma/storage/basic_storage.rb +510 -0
- data/lib/roma/storage/dbm_storage.rb +80 -0
- data/lib/roma/storage/dummy_storage.rb +44 -0
- data/lib/roma/storage/rh_storage.rb +35 -0
- data/lib/roma/storage/sqlite3_storage.rb +73 -0
- data/lib/roma/storage/tc_storage.rb +133 -0
- data/lib/roma/tools/mkrecent.rb +138 -0
- data/lib/roma/tools/mkroute.rb +52 -0
- data/lib/roma/tools/recoverlost.rb +9 -0
- data/lib/roma/tools/recoverlost_alist.rb +9 -0
- data/lib/roma/tools/recoverlost_lib.rb +217 -0
- data/lib/roma/tools/sample_watcher.rb +38 -0
- data/lib/roma/tools/sample_watcher2.rb +38 -0
- data/lib/roma/tools/simple_bench.rb +57 -0
- data/lib/roma/tools/ssroute.rb +23 -0
- data/lib/roma/tools/tribunus.rb +299 -0
- data/lib/roma/version.rb +4 -0
- data/lib/roma/write_behind.rb +179 -0
- data/test/rcirb.rb +16 -0
- data/test/roma-test-utils.rb +65 -0
- data/test/run-test.rb +16 -0
- data/test/t_cpdata.rb +277 -0
- data/test/t_listplugin.rb +592 -0
- data/test/t_rclient.rb +318 -0
- data/test/t_routing_data.rb +100 -0
- data/test/t_storage.rb +644 -0
- data/test/t_writebehind.rb +200 -0
- metadata +134 -0
@@ -0,0 +1,1572 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'roma/messaging/con_pool'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Roma
|
6
|
+
module CommandPlugin
|
7
|
+
|
8
|
+
module PluginAshiatoList
|
9
|
+
include ::Roma::CommandPlugin
|
10
|
+
|
11
|
+
# alist_at <key> <index> [forward]\r\n
|
12
|
+
#
|
13
|
+
# (
|
14
|
+
# [VALUE <key> 0 <value length>\r\n
|
15
|
+
# <value>\r\n]
|
16
|
+
# END\r\n
|
17
|
+
# |SERVER_ERROR <error message>\r\n)
|
18
|
+
def ev_alist_at(s)
|
19
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
20
|
+
return forward1(nodes[0], s) if nodes[0] != @nid
|
21
|
+
|
22
|
+
ddata = @storages[hname].get(vn, k, d)
|
23
|
+
@stats.read_count += 1
|
24
|
+
if ddata
|
25
|
+
v = Marshal.load(ddata)[0]
|
26
|
+
return send_data("END\r\n") if v.length <= s[2].to_i
|
27
|
+
ret = v.at(s[2].to_i)
|
28
|
+
return send_data("VALUE #{s[1]} 0 #{ret.length}\r\n#{ret}\r\nEND\r\n")
|
29
|
+
else
|
30
|
+
return send_data("END\r\n")
|
31
|
+
end
|
32
|
+
rescue => e
|
33
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
34
|
+
send_data("#{msg}\r\n")
|
35
|
+
@log.error("#{e} #{$@}")
|
36
|
+
end
|
37
|
+
|
38
|
+
# alist_clear <key> [forward]\r\n
|
39
|
+
#
|
40
|
+
# (CLEARED|NOT_CLEARED|SERVER_ERROR <error message>)\r\n
|
41
|
+
def ev_alist_clear(s)
|
42
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
43
|
+
return forward2(nodes[0], s) if nodes[0] != @nid
|
44
|
+
|
45
|
+
ddata = @storages[hname].get(vn, k, d)
|
46
|
+
return send_data("NOT_FOUND\r\n") unless ddata
|
47
|
+
|
48
|
+
expt = 0x7fffffff
|
49
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump([[],[]]))
|
50
|
+
@stats.delete_count += 1
|
51
|
+
Roma::WriteBehindProcess::push(hname, 3, k, ddata)
|
52
|
+
|
53
|
+
if ret
|
54
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
55
|
+
send_data("CLEARED\r\n")
|
56
|
+
else
|
57
|
+
send_data("NOT_CLEARED\r\n")
|
58
|
+
end
|
59
|
+
rescue => e
|
60
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
61
|
+
send_data("#{msg}\r\n")
|
62
|
+
@log.error("#{e} #{$@}")
|
63
|
+
end
|
64
|
+
|
65
|
+
# alist_delete <key> <bytes> [forward]\r\n
|
66
|
+
# <data block>\r\n
|
67
|
+
#
|
68
|
+
# (DELETED|NOT_DELETED|NOT_FOUND|SERVER_ERROR <error message>)\r\n
|
69
|
+
def ev_alist_delete(s)
|
70
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
71
|
+
data = read_bytes(s[2].to_i)
|
72
|
+
read_bytes(2)
|
73
|
+
return forward2(nodes[0], s, data) if nodes[0] != @nid
|
74
|
+
|
75
|
+
ddata = @storages[hname].get(vn, k, d)
|
76
|
+
return send_data("NOT_FOUND\r\n") unless ddata
|
77
|
+
|
78
|
+
v = Marshal.load(ddata)
|
79
|
+
return send_data("NOT_DELETED\r\n") unless v[0].include?(data)
|
80
|
+
while(idx = v[0].index(data))
|
81
|
+
v[0].delete_at(idx)
|
82
|
+
v[1].delete_at(idx)
|
83
|
+
end
|
84
|
+
|
85
|
+
expt = 0x7fffffff
|
86
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
87
|
+
@stats.delete_count += 1
|
88
|
+
|
89
|
+
Roma::WriteBehindProcess::push(hname, 2, k, data)
|
90
|
+
|
91
|
+
if ret
|
92
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
93
|
+
send_data("DELETED\r\n")
|
94
|
+
else
|
95
|
+
send_data("NOT_DELETED\r\n")
|
96
|
+
end
|
97
|
+
rescue => e
|
98
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
99
|
+
send_data("#{msg}\r\n")
|
100
|
+
@log.error("#{e} #{$@}")
|
101
|
+
end
|
102
|
+
|
103
|
+
# alist_delete_at <key> <index> [forward]\r\n
|
104
|
+
#
|
105
|
+
# (DELETED|NOT_DELETED|NOT_FOUND|SERVER_ERROR <error message>)\r\n
|
106
|
+
def ev_alist_delete_at(s)
|
107
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
108
|
+
return forward2(nodes[0], s) if nodes[0] != @nid
|
109
|
+
|
110
|
+
ddata = @storages[hname].get(vn, k, d)
|
111
|
+
return send_data("NOT_FOUND\r\n") unless ddata
|
112
|
+
|
113
|
+
v = Marshal.load(ddata)
|
114
|
+
dret = v[0].delete_at(s[2].to_i)
|
115
|
+
return send_data("NOT_DELETED\r\n") unless dret
|
116
|
+
v[1].delete_at(s[2].to_i)
|
117
|
+
|
118
|
+
expt = 0x7fffffff
|
119
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
120
|
+
@stats.delete_count += 1
|
121
|
+
|
122
|
+
Roma::WriteBehindProcess::push(hname, 2, k, dret)
|
123
|
+
|
124
|
+
if ret
|
125
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
126
|
+
send_data("DELETED\r\n")
|
127
|
+
else
|
128
|
+
send_data("NOT_DELETED\r\n")
|
129
|
+
end
|
130
|
+
rescue => e
|
131
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
132
|
+
send_data("#{msg}\r\n")
|
133
|
+
@log.error("${e} #{$@}")
|
134
|
+
end
|
135
|
+
|
136
|
+
# alist_empty? <key> [forward]\r\n
|
137
|
+
#
|
138
|
+
# (true|false|NOT_FOUND|SERVER_ERROR <error message>)\r\n
|
139
|
+
def ev_alist_empty?(s)
|
140
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
141
|
+
return forward2(nodes[0], s) if nodes[0] != @nid
|
142
|
+
|
143
|
+
ddata = @storages[hname].get(vn, k, d)
|
144
|
+
@stats.read_count += 1
|
145
|
+
|
146
|
+
return send_data("NOT_FOUND\r\n") unless ddata
|
147
|
+
|
148
|
+
v = Marshal.load(ddata)
|
149
|
+
ret = v[0].empty?
|
150
|
+
|
151
|
+
send_data("#{ret}\r\n")
|
152
|
+
rescue => e
|
153
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
154
|
+
send_data("#{msg}\r\n")
|
155
|
+
@log.error("#{e} #{$@}")
|
156
|
+
end
|
157
|
+
|
158
|
+
# alist_first <key> [forward]\r\n
|
159
|
+
#
|
160
|
+
# (
|
161
|
+
# [VALUE <key> 0 <value length>\r\n
|
162
|
+
# <value>\r\n]
|
163
|
+
# END\r\n
|
164
|
+
# |SERVER_ERROR <error message>\r\n)
|
165
|
+
def ev_alist_first(s)
|
166
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
167
|
+
return forward1(nodes[0], s) if nodes[0] != @nid
|
168
|
+
|
169
|
+
ddata = @storages[hname].get(vn, k, d)
|
170
|
+
@stats.read_count += 1
|
171
|
+
|
172
|
+
if ddata
|
173
|
+
v = Marshal.load(ddata)[0]
|
174
|
+
return send_data("END\r\n") if v.length == 0
|
175
|
+
ret = v.first
|
176
|
+
return send_data("VALUE #{s[1]} 0 #{ret.length}\r\n#{ret}\r\nEND\r\n")
|
177
|
+
else
|
178
|
+
return send_data("END\r\n")
|
179
|
+
end
|
180
|
+
rescue => e
|
181
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
182
|
+
send_data("#{msg}\r\n")
|
183
|
+
@log.error("#{e} #{$@}")
|
184
|
+
end
|
185
|
+
|
186
|
+
# alist_gets <key> [index|range] [forward]\r\n
|
187
|
+
#
|
188
|
+
# (
|
189
|
+
# [VALUE <key> 0 <length of length string>\r\n
|
190
|
+
# <length string>\r\n
|
191
|
+
# (VALUE <key> 0 <value length>\r\n
|
192
|
+
# <value>\r\n)*
|
193
|
+
# ]
|
194
|
+
# END\r\n
|
195
|
+
# |SERVER_ERROR <error message>\r\n)
|
196
|
+
def ev_alist_gets(s)
|
197
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
198
|
+
return forward1(nodes[0], s) if nodes[0] != @nid
|
199
|
+
|
200
|
+
ddata = @storages[hname].get(vn, k, 0)
|
201
|
+
@stats.read_count += 1
|
202
|
+
|
203
|
+
if ddata
|
204
|
+
v = Marshal.load(ddata)[0]
|
205
|
+
if /(?:^(\d+)$|^(\d+)..((?:-)?\d+)$)/ =~ s[2]
|
206
|
+
if $1
|
207
|
+
if v.length <= $1.to_i
|
208
|
+
return send_data("END\r\n")
|
209
|
+
end
|
210
|
+
buf = v[Range.new($1.to_i,$1.to_i)]
|
211
|
+
else
|
212
|
+
buf = v[Range.new($2.to_i,$3.to_i)]
|
213
|
+
end
|
214
|
+
else
|
215
|
+
buf = v
|
216
|
+
end
|
217
|
+
len = v.length
|
218
|
+
send_data("VALUE #{s[1]} 0 #{len.to_s.length}\r\n#{len.to_s}\r\n")
|
219
|
+
buf.each{|val|
|
220
|
+
send_data("VALUE #{s[1]} 0 #{val.length}\r\n#{val}\r\n")
|
221
|
+
}
|
222
|
+
return send_data("END\r\n")
|
223
|
+
else
|
224
|
+
return send_data("END\r\n")
|
225
|
+
end
|
226
|
+
rescue => e
|
227
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
228
|
+
send_data("#{msg}\r\n")
|
229
|
+
@log.error("#{e} #{$@}")
|
230
|
+
end
|
231
|
+
|
232
|
+
# alist_gets_with_time <key> [index|range] [forward]\r\n
|
233
|
+
#
|
234
|
+
# (
|
235
|
+
# [VALUE <key> 0 <length of length string>\r\n
|
236
|
+
# <length string>\r\n
|
237
|
+
# (VALUE <key> 0 <value length>\r\n
|
238
|
+
# <value string>\r\n
|
239
|
+
# VALUE <key> 0 <value length>\r\n
|
240
|
+
# <time string>\r\n)*
|
241
|
+
# ]
|
242
|
+
# END\r\n
|
243
|
+
# |SERVER_ERROR <error message>\r\n)
|
244
|
+
def ev_alist_gets_with_time(s)
|
245
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
246
|
+
return forward1(nodes[0], s) if nodes[0] != @nid
|
247
|
+
|
248
|
+
ddata = @storages[hname].get(vn, k, 0)
|
249
|
+
@stats.read_count += 1
|
250
|
+
|
251
|
+
if ddata
|
252
|
+
v = Marshal.load(ddata)
|
253
|
+
if /(?:^(\d+)$|^(\d+)..((?:-)?\d+)$)/ =~ s[2]
|
254
|
+
if $1
|
255
|
+
if v[0].length <= $1.to_i
|
256
|
+
return send_data("END\r\n")
|
257
|
+
end
|
258
|
+
v_buf = v[0][Range.new($1.to_i,$1.to_i)]
|
259
|
+
t_buf = v[1][Range.new($1.to_i,$1.to_i)]
|
260
|
+
else
|
261
|
+
v_buf = v[0][Range.new($2.to_i,$3.to_i)]
|
262
|
+
t_buf = v[1][Range.new($2.to_i,$3.to_i)]
|
263
|
+
end
|
264
|
+
else
|
265
|
+
v_buf = v[0]
|
266
|
+
t_buf = v[1]
|
267
|
+
end
|
268
|
+
len = v[0].length
|
269
|
+
send_data("VALUE #{s[1]} 0 #{len.to_s.length}\r\n#{len.to_s}\r\n")
|
270
|
+
v_buf.each_with_index{|val,idx|
|
271
|
+
send_data("VALUE #{s[1]} 0 #{val.length}\r\n#{val}\r\n")
|
272
|
+
send_data("VALUE #{s[1]} 0 #{t_buf[idx].to_s.length}\r\n#{t_buf[idx]}\r\n")
|
273
|
+
}
|
274
|
+
return send_data("END\r\n")
|
275
|
+
else
|
276
|
+
return send_data("END\r\n")
|
277
|
+
end
|
278
|
+
rescue => e
|
279
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
280
|
+
send_data("#{msg}\r\n")
|
281
|
+
@log.error("#{e} #{$@}")
|
282
|
+
end
|
283
|
+
|
284
|
+
|
285
|
+
# alist_include? <key> <bytes> [forward]\r\n
|
286
|
+
# <data block>\r\n
|
287
|
+
#
|
288
|
+
# (true|false|NOT_FOUND|SERVER_ERROR <error message>)\r\n
|
289
|
+
def ev_alist_include?(s)
|
290
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
291
|
+
data = read_bytes(s[2].to_i)
|
292
|
+
read_bytes(2)
|
293
|
+
return forward2(nodes[0], s, data) if nodes[0] != @nid
|
294
|
+
|
295
|
+
ddata = @storages[hname].get(vn, k, d)
|
296
|
+
@stats.read_count += 1
|
297
|
+
|
298
|
+
return send_data("NOT_FOUND\r\n") unless ddata
|
299
|
+
|
300
|
+
v = Marshal.load(ddata)[0]
|
301
|
+
ret = v.include?(data)
|
302
|
+
|
303
|
+
send_data("#{ret}\r\n")
|
304
|
+
rescue => e
|
305
|
+
send_data("SERVER_ERROR #{e} #{$@}\r\n")
|
306
|
+
@log.error("#{e} #{$@}")
|
307
|
+
end
|
308
|
+
|
309
|
+
# alist_index <key> <bytes> [forward]\r\n
|
310
|
+
# <data block>\r\n
|
311
|
+
#
|
312
|
+
# (<index>|nil|NOT_FOUND|SERVER_ERROR <error message>)\r\n
|
313
|
+
def ev_alist_index(s)
|
314
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
315
|
+
data = read_bytes(s[2].to_i)
|
316
|
+
read_bytes(2)
|
317
|
+
return forward2(nodes[0], s, data) if nodes[0] != @nid
|
318
|
+
|
319
|
+
ddata = @storages[hname].get(vn, k, d)
|
320
|
+
@stats.read_count += 1
|
321
|
+
|
322
|
+
return send_data("NOT_FOUND\r\n") unless ddata
|
323
|
+
|
324
|
+
v = Marshal.load(ddata)[0]
|
325
|
+
ret = v.index(data)
|
326
|
+
if ret
|
327
|
+
send_data("#{ret}\r\n")
|
328
|
+
else
|
329
|
+
send_data("nil\r\n")
|
330
|
+
end
|
331
|
+
rescue => e
|
332
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
333
|
+
send_data("#{msg}\r\n")
|
334
|
+
@log.error("#{e} #{$@}")
|
335
|
+
end
|
336
|
+
|
337
|
+
# alist_insert <key> <index> <bytes> [forward]\r\n
|
338
|
+
# <data block>\r\n
|
339
|
+
#
|
340
|
+
# (STORED|NOT_STORED|SERVER_ERROR <error message>)\r\n
|
341
|
+
def ev_alist_insert(s)
|
342
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
343
|
+
data = read_bytes(s[3].to_i)
|
344
|
+
read_bytes(2)
|
345
|
+
return forward2(nodes[0], s, data) if nodes[0] != @nid
|
346
|
+
|
347
|
+
ddata = @storages[hname].get(vn, k, d)
|
348
|
+
if ddata
|
349
|
+
v = Marshal.load(ddata)
|
350
|
+
else
|
351
|
+
v = [[],[]]
|
352
|
+
end
|
353
|
+
|
354
|
+
v[0].insert(s[2].to_i,data)
|
355
|
+
v[1].insert(s[2].to_i,Time.now.to_i)
|
356
|
+
expt = 0x7fffffff
|
357
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
358
|
+
@stats.write_count += 1
|
359
|
+
|
360
|
+
if ret
|
361
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
362
|
+
send_data("STORED\r\n")
|
363
|
+
else
|
364
|
+
send_data("NOT_STORED\r\n")
|
365
|
+
end
|
366
|
+
rescue => e
|
367
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
368
|
+
send_data("#{msg}\r\n")
|
369
|
+
@log.error("#{e} #{$@}")
|
370
|
+
end
|
371
|
+
|
372
|
+
def ev_alist_sized_prepend(s); ev_alist_sized_insert(s); end
|
373
|
+
|
374
|
+
# alist_sized_insert <key> <array-size> <bytes> [forward]\r\n
|
375
|
+
# <data block>\r\n
|
376
|
+
#
|
377
|
+
# (STORED|NOT_STORED|SERVER_ERROR <error message>)\r\n
|
378
|
+
def ev_alist_sized_insert(s)
|
379
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
380
|
+
data = read_bytes(s[3].to_i)
|
381
|
+
read_bytes(2)
|
382
|
+
return forward2(nodes[0], s, data) if nodes[0] != @nid
|
383
|
+
|
384
|
+
ddata = @storages[hname].get(vn, k, d)
|
385
|
+
if ddata
|
386
|
+
v = Marshal.load(ddata)
|
387
|
+
else
|
388
|
+
v = [[],[]]
|
389
|
+
end
|
390
|
+
|
391
|
+
v[0].insert(0,data)
|
392
|
+
v[0] = v[0][0..(s[2].to_i - 1)]
|
393
|
+
v[1].insert(0,Time.now.to_i)
|
394
|
+
v[1] = v[1][0..(s[2].to_i - 1)]
|
395
|
+
|
396
|
+
expt = 0x7fffffff
|
397
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
398
|
+
@stats.write_count += 1
|
399
|
+
|
400
|
+
if ret
|
401
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
402
|
+
send_data("STORED\r\n")
|
403
|
+
else
|
404
|
+
send_data("NOT_STORED\r\n")
|
405
|
+
end
|
406
|
+
rescue => e
|
407
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
408
|
+
send_data("#{msg}\r\n")
|
409
|
+
@log.error("#{e} #{$@}")
|
410
|
+
end
|
411
|
+
|
412
|
+
def ev_alist_delete_and_prepend(s); ev_alist_swap_and_insert(s); end
|
413
|
+
|
414
|
+
# alist_swap_and_insert <key> <bytes> [forward]\r\n
|
415
|
+
# <data block>\r\n
|
416
|
+
#
|
417
|
+
# (STORED|NOT_STORED|SERVER_ERROR <error message>)\r\n
|
418
|
+
def ev_alist_swap_and_insert(s)
|
419
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
420
|
+
data = read_bytes(s[2].to_i)
|
421
|
+
read_bytes(2)
|
422
|
+
return forward2(nodes[0], s, data) if nodes[0] != @nid
|
423
|
+
|
424
|
+
ddata = @storages[hname].get(vn, k, d)
|
425
|
+
if ddata
|
426
|
+
v = Marshal.load(ddata)
|
427
|
+
else
|
428
|
+
v = [[],[]]
|
429
|
+
end
|
430
|
+
|
431
|
+
idx = v[0].index(data)
|
432
|
+
if idx
|
433
|
+
v[0].delete_at(idx)
|
434
|
+
v[1].delete_at(idx)
|
435
|
+
end
|
436
|
+
v[0].insert(0,data)
|
437
|
+
v[1].insert(0,Time.now.to_i)
|
438
|
+
|
439
|
+
expt = 0x7fffffff
|
440
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
441
|
+
@stats.write_count += 1
|
442
|
+
|
443
|
+
Roma::WriteBehindProcess::push(hname, 1, k, data)
|
444
|
+
|
445
|
+
if ret
|
446
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
447
|
+
send_data("STORED\r\n")
|
448
|
+
else
|
449
|
+
send_data("NOT_STORED\r\n")
|
450
|
+
end
|
451
|
+
rescue => e
|
452
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
453
|
+
send_data("#{msg}\r\n")
|
454
|
+
@log.error("#{e} #{$@}")
|
455
|
+
end
|
456
|
+
|
457
|
+
def ev_alist_sized_delete_and_prepend(s); ev_alist_swap_and_sized_insert(s); end
|
458
|
+
|
459
|
+
# alist_swap_and_sized_insert <key> <array-size> <bytes> [forward]\r\n
|
460
|
+
# <data block>\r\n
|
461
|
+
#
|
462
|
+
# (STORED|NOT_STORED|SERVER_ERROR <error message>)\r\n
|
463
|
+
def ev_alist_swap_and_sized_insert(s)
|
464
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
465
|
+
data = read_bytes(s[3].to_i)
|
466
|
+
read_bytes(2)
|
467
|
+
return forward2(nodes[0], s, data) if nodes[0] != @nid
|
468
|
+
|
469
|
+
ddata = @storages[hname].get(vn, k, d)
|
470
|
+
if ddata
|
471
|
+
v = Marshal.load(ddata)
|
472
|
+
else
|
473
|
+
v = [[],[]]
|
474
|
+
end
|
475
|
+
|
476
|
+
idx = v[0].index(data)
|
477
|
+
if idx
|
478
|
+
v[0].delete_at(idx)
|
479
|
+
v[1].delete_at(idx)
|
480
|
+
end
|
481
|
+
v[0].insert(0,data)
|
482
|
+
v[1].insert(0,Time.now.to_i)
|
483
|
+
v[0] = v[0][0..(s[2].to_i - 1)]
|
484
|
+
v[1] = v[1][0..(s[2].to_i - 1)]
|
485
|
+
|
486
|
+
expt = 0x7fffffff
|
487
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
488
|
+
@stats.write_count += 1
|
489
|
+
|
490
|
+
Roma::WriteBehindProcess::push(hname, 1, k, data)
|
491
|
+
|
492
|
+
if ret
|
493
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
494
|
+
send_data("STORED\r\n")
|
495
|
+
else
|
496
|
+
send_data("NOT_STORED\r\n")
|
497
|
+
end
|
498
|
+
rescue => e
|
499
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
500
|
+
send_data("#{msg}\r\n")
|
501
|
+
@log.error("#{e} #{$@}")
|
502
|
+
end
|
503
|
+
|
504
|
+
# alist_expired_swap_and_insert <key> <expire-time> <bytes> [forward]\r\n
|
505
|
+
# <data block>\r\n
|
506
|
+
#
|
507
|
+
# the data expire-time's ago will be deleated.
|
508
|
+
# the unit of the expire-time's is a second.
|
509
|
+
# however,as follows when there is a suffix.
|
510
|
+
# 'h' as +expire-time+ suffix is hour.
|
511
|
+
# 'd' as +expire-time+ suffix is day.
|
512
|
+
#
|
513
|
+
# (STORED|NOT_STORED|SERVER_ERROR <error message>)\r\n
|
514
|
+
def ev_alist_expired_swap_and_insert(s)
|
515
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
516
|
+
data = read_bytes(s[3].to_i)
|
517
|
+
read_bytes(2)
|
518
|
+
return forward2(nodes[0], s, data) if nodes[0] != @nid
|
519
|
+
|
520
|
+
et = expired_str_to_i(s[2])
|
521
|
+
return send_data("SERVER_ERROR format error in expire-time.\r\n") unless et
|
522
|
+
|
523
|
+
v = to_alist_value_for_write(hname, vn, k, d)
|
524
|
+
unless v
|
525
|
+
return send_data("SERVER_ERROR data other than alist's format already exist.\r\n")
|
526
|
+
end
|
527
|
+
|
528
|
+
# @log.debug("#{s[2]} et=#{et}")
|
529
|
+
v = expired_swap(v, data, et)
|
530
|
+
|
531
|
+
v[0].insert(0,data)
|
532
|
+
v[1].insert(0,Time.now.to_i)
|
533
|
+
|
534
|
+
expt = 0x7fffffff
|
535
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
536
|
+
@stats.write_count += 1
|
537
|
+
|
538
|
+
Roma::WriteBehindProcess::push(hname, 1, k, data)
|
539
|
+
|
540
|
+
if ret
|
541
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
542
|
+
send_data("STORED\r\n")
|
543
|
+
else
|
544
|
+
send_data("NOT_STORED\r\n")
|
545
|
+
end
|
546
|
+
rescue => e
|
547
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
548
|
+
send_data("#{msg}\r\n")
|
549
|
+
@log.error("#{e} #{$@}")
|
550
|
+
end
|
551
|
+
|
552
|
+
# alist_expired_swap_and_sized_insert <key> <expire-time> <array-size> <bytes> [forward]\r\n
|
553
|
+
# <data block>\r\n
|
554
|
+
#
|
555
|
+
# the data expire-time's ago will be deleated.
|
556
|
+
# the unit of the expire-time's is a second.
|
557
|
+
# however,as follows when there is a suffix.
|
558
|
+
# 'h' as +expire-time+ suffix is hour.
|
559
|
+
# 'd' as +expire-time+ suffix is day.
|
560
|
+
#
|
561
|
+
# (STORED|NOT_STORED|SERVER_ERROR <error message>)\r\n
|
562
|
+
def ev_alist_expired_swap_and_sized_insert(s)
|
563
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
564
|
+
data = read_bytes(s[4].to_i)
|
565
|
+
read_bytes(2)
|
566
|
+
return forward2(nodes[0], s, data) if nodes[0] != @nid
|
567
|
+
|
568
|
+
et = expired_str_to_i(s[2])
|
569
|
+
return send_data("SERVER_ERROR format error in expire-time.\r\n") unless et
|
570
|
+
|
571
|
+
v = to_alist_value_for_write(hname, vn, k, d)
|
572
|
+
unless v
|
573
|
+
return send_data("SERVER_ERROR data other than alist's format already exist.\r\n")
|
574
|
+
end
|
575
|
+
|
576
|
+
# @log.debug("#{s[2]} et=#{et}")
|
577
|
+
v = expired_swap(v, data, et)
|
578
|
+
|
579
|
+
v[0].insert(0,data)
|
580
|
+
v[0] = v[0][0..(s[3].to_i - 1)]
|
581
|
+
v[1].insert(0,Time.now.to_i)
|
582
|
+
v[1] = v[1][0..(s[3].to_i - 1)]
|
583
|
+
|
584
|
+
expt = 0x7fffffff
|
585
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
586
|
+
@stats.write_count += 1
|
587
|
+
|
588
|
+
Roma::WriteBehindProcess::push(hname, 1, k, data)
|
589
|
+
|
590
|
+
if ret
|
591
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
592
|
+
send_data("STORED\r\n")
|
593
|
+
else
|
594
|
+
send_data("NOT_STORED\r\n")
|
595
|
+
end
|
596
|
+
rescue => e
|
597
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
598
|
+
send_data("#{msg}\r\n")
|
599
|
+
@log.error("#{e} #{$@}")
|
600
|
+
end
|
601
|
+
|
602
|
+
|
603
|
+
# alist_join_with_time <key> <bytes> [index|range] [forward]\r\n
|
604
|
+
# <separator block>\r\n
|
605
|
+
#
|
606
|
+
# (
|
607
|
+
# [VALUE <key> 0 <length of length string>\r\n
|
608
|
+
# <length string>\r\n
|
609
|
+
# VALUE <key> 0 <value length>\r\n
|
610
|
+
# <value string>\r\n
|
611
|
+
# VALUE <key> 0 <value length>\r\n
|
612
|
+
# <time string>\r\n]
|
613
|
+
# END\r\n
|
614
|
+
# |SERVER_ERROR <error message>\r\n)
|
615
|
+
def ev_alist_join_with_time(s)
|
616
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
617
|
+
data = read_bytes(s[2].to_i)
|
618
|
+
read_bytes(2)
|
619
|
+
return forward1(nodes[0], s, data) if nodes[0] != @nid
|
620
|
+
|
621
|
+
ddata = @storages[hname].get(vn, k, 0)
|
622
|
+
@stats.read_count += 1
|
623
|
+
if ddata
|
624
|
+
v = Marshal.load(ddata)
|
625
|
+
if /(?:^(\d+)$|^(\d+)..((?:-)?\d+)$)/ =~ s[3]
|
626
|
+
if $1
|
627
|
+
if v[0].length <= $1.to_i
|
628
|
+
return send_data("END\r\n")
|
629
|
+
end
|
630
|
+
v_buf = v[0][Range.new($1.to_i,$1.to_i)]
|
631
|
+
t_buf = v[1][Range.new($1.to_i,$1.to_i)]
|
632
|
+
else
|
633
|
+
v_buf = v[0][Range.new($2.to_i,$3.to_i)]
|
634
|
+
t_buf = v[1][Range.new($2.to_i,$3.to_i)]
|
635
|
+
end
|
636
|
+
else
|
637
|
+
v_buf = v[0]
|
638
|
+
t_buf = v[1]
|
639
|
+
end
|
640
|
+
len = v[0].length
|
641
|
+
v_ret = v_buf.join(data)
|
642
|
+
t_ret = t_buf.join(data)
|
643
|
+
send_data("VALUE #{s[1]} 0 #{len.to_s.length}\r\n#{len.to_s}\r\n")
|
644
|
+
send_data("VALUE #{s[1]} 0 #{v_ret.length}\r\n#{v_ret}\r\n")
|
645
|
+
return send_data("VALUE #{s[1]} 0 #{t_ret.length}\r\n#{t_ret}\r\nEND\r\n")
|
646
|
+
else
|
647
|
+
return send_data("END\r\n")
|
648
|
+
end
|
649
|
+
rescue => e
|
650
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
651
|
+
send_data("#{msg}\r\n")
|
652
|
+
@log.error("#{e} #{$@}")
|
653
|
+
end
|
654
|
+
|
655
|
+
# alist_join <key> <bytes> [index|range] [forward]\r\n
|
656
|
+
# <separator block>\r\n
|
657
|
+
#
|
658
|
+
# (
|
659
|
+
# [VALUE <key> 0 <length of length string>\r\n
|
660
|
+
# <length string>\r\n
|
661
|
+
# VALUE <key> 0 <value length>\r\n
|
662
|
+
# <value>\r\n]
|
663
|
+
# END\r\n
|
664
|
+
# |SERVER_ERROR <error message>\r\n)
|
665
|
+
def ev_alist_join(s)
|
666
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
667
|
+
data = read_bytes(s[2].to_i)
|
668
|
+
read_bytes(2)
|
669
|
+
return forward1(nodes[0], s, data) if nodes[0] != @nid
|
670
|
+
|
671
|
+
ddata = @storages[hname].get(vn, k, 0)
|
672
|
+
@stats.read_count += 1
|
673
|
+
|
674
|
+
if ddata
|
675
|
+
v = Marshal.load(ddata)[0]
|
676
|
+
if /(?:^(\d+)$|^(\d+)..((?:-)?\d+)$)/ =~ s[3]
|
677
|
+
if $1
|
678
|
+
if v.length <= $1.to_i
|
679
|
+
return send_data("END\r\n")
|
680
|
+
end
|
681
|
+
buf = v[Range.new($1.to_i,$1.to_i)]
|
682
|
+
else
|
683
|
+
buf = v[Range.new($2.to_i,$3.to_i)]
|
684
|
+
end
|
685
|
+
else
|
686
|
+
buf = v
|
687
|
+
end
|
688
|
+
len = v.length
|
689
|
+
ret = buf.join(data)
|
690
|
+
send_data("VALUE #{s[1]} 0 #{len.to_s.length}\r\n#{len.to_s}\r\n")
|
691
|
+
return send_data("VALUE #{s[1]} 0 #{ret.length}\r\n#{ret}\r\nEND\r\n")
|
692
|
+
else
|
693
|
+
return send_data("END\r\n")
|
694
|
+
end
|
695
|
+
rescue => e
|
696
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
697
|
+
send_data("#{msg}\r\n")
|
698
|
+
@log.error("#{e} #{$@}")
|
699
|
+
end
|
700
|
+
|
701
|
+
# alist_to_json <key> [index|range] [forward]\r\n
|
702
|
+
#
|
703
|
+
# (
|
704
|
+
# VALUE <key> 0 <length of json string>\r\n
|
705
|
+
# <json string>\r\n
|
706
|
+
# END\r\n
|
707
|
+
# |SERVER_ERROR <error message>\r\n)
|
708
|
+
def ev_alist_to_json(s)
|
709
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
710
|
+
return forward1(nodes[0], s) if nodes[0] != @nid
|
711
|
+
|
712
|
+
ddata = @storages[hname].get(vn, k, 0)
|
713
|
+
@stats.read_count += 1
|
714
|
+
|
715
|
+
if ddata
|
716
|
+
v = Marshal.load(ddata)[0]
|
717
|
+
ret = nil
|
718
|
+
if /(?:^(\d+)$|^(\d+)..((?:-)?\d+)$)/ =~ s[2]
|
719
|
+
if $1
|
720
|
+
if v.length <= $1.to_i
|
721
|
+
return send_data("END\r\n")
|
722
|
+
end
|
723
|
+
ret = JSON.generate(v[Range.new($1.to_i,$1.to_i)])
|
724
|
+
else
|
725
|
+
ret = JSON.generate(v[Range.new($2.to_i,$3.to_i)])
|
726
|
+
end
|
727
|
+
else
|
728
|
+
ret = JSON.generate(v)
|
729
|
+
end
|
730
|
+
return send_data("VALUE #{s[1]} 0 #{ret.length}\r\n#{ret}\r\nEND\r\n")
|
731
|
+
else
|
732
|
+
return send_data("END\r\n")
|
733
|
+
end
|
734
|
+
rescue => e
|
735
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
736
|
+
send_data("#{msg}\r\n")
|
737
|
+
@log.error("#{e} #{$@}")
|
738
|
+
end
|
739
|
+
|
740
|
+
# alist_last <key> [forward]\r\n
|
741
|
+
#
|
742
|
+
# (
|
743
|
+
# [VALUE <key> 0 <value length>\r\n
|
744
|
+
# <value>\r\n]
|
745
|
+
# END\r\n
|
746
|
+
# |SERVER_ERROR <error message>\r\n)
|
747
|
+
def ev_alist_last(s)
|
748
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
749
|
+
return forward1(nodes[0], s) if nodes[0] != @nid
|
750
|
+
|
751
|
+
ddata = @storages[hname].get(vn, k, d)
|
752
|
+
@stats.read_count += 1
|
753
|
+
|
754
|
+
if ddata
|
755
|
+
v = Marshal.load(ddata)[0]
|
756
|
+
return send_data("END\r\n") if v.length == 0
|
757
|
+
ret = v.last
|
758
|
+
return send_data("VALUE #{s[1]} 0 #{ret.length}\r\n#{ret}\r\nEND\r\n")
|
759
|
+
else
|
760
|
+
return send_data("END\r\n")
|
761
|
+
end
|
762
|
+
rescue => e
|
763
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
764
|
+
send_data("#{msg}\r\n")
|
765
|
+
@log.error("#{e} #{$@}")
|
766
|
+
end
|
767
|
+
|
768
|
+
# alist_length <key> [forward]\r\n
|
769
|
+
#
|
770
|
+
# (<length>|NOT_FOUND|SERVER_ERROR <error message>)\r\n
|
771
|
+
def ev_alist_length(s)
|
772
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
773
|
+
return forward2(nodes[0], s) if nodes[0] != @nid
|
774
|
+
ddata = @storages[hname].get(vn, k, d)
|
775
|
+
@stats.read_count += 1
|
776
|
+
|
777
|
+
return send_data("NOT_FOUND\r\n") unless ddata
|
778
|
+
v = Marshal.load(ddata)[0]
|
779
|
+
ret = v.length
|
780
|
+
send_data("#{ret}\r\n")
|
781
|
+
rescue => e
|
782
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
783
|
+
send_data("#{msg}\r\n")
|
784
|
+
@log.error("#{e} #{$@}")
|
785
|
+
end
|
786
|
+
|
787
|
+
# alist_pop <key> [forward]\r\n
|
788
|
+
#
|
789
|
+
# (
|
790
|
+
# [VALUE <key> 0 <value length>\r\n
|
791
|
+
# <value>\r\n]
|
792
|
+
# END
|
793
|
+
# |NOT_STORED|SERVER_ERROR <error message>)\r\n
|
794
|
+
def ev_alist_pop(s)
|
795
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
796
|
+
return forward1(nodes[0], s) if nodes[0] != @nid
|
797
|
+
|
798
|
+
ddata = @storages[hname].get(vn, k, d)
|
799
|
+
if ddata
|
800
|
+
v = Marshal.load(ddata)
|
801
|
+
return send_data("END\r\n") if v[0].length ==0
|
802
|
+
else
|
803
|
+
return send_data("END\r\n")
|
804
|
+
end
|
805
|
+
|
806
|
+
retv = v[0].pop
|
807
|
+
v[1].pop
|
808
|
+
expt = 0x7fffffff
|
809
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
810
|
+
@stats.read_count += 1
|
811
|
+
@stats.write_count += 1
|
812
|
+
|
813
|
+
if ret
|
814
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
815
|
+
send_data("VALUE #{s[1]} 0 #{retv.length}\r\n#{retv}\r\nEND\r\n")
|
816
|
+
else
|
817
|
+
send_data("NOT_STORED\r\n")
|
818
|
+
end
|
819
|
+
rescue => e
|
820
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
821
|
+
send_data("#{msg}\r\n")
|
822
|
+
@log.error("#{e} #{$@}")
|
823
|
+
end
|
824
|
+
|
825
|
+
# alist_push <key> <bytes> [forward]\r\n
|
826
|
+
# <data block>\r\n
|
827
|
+
#
|
828
|
+
# (STORED|NOT_STORED|SERVER_ERROR <error message>)\r\n
|
829
|
+
def ev_alist_push(s)
|
830
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
831
|
+
data = read_bytes(s[2].to_i)
|
832
|
+
read_bytes(2)
|
833
|
+
if nodes[0] != @nid
|
834
|
+
@log.debug("forward to #{nodes[0]}");
|
835
|
+
return forward2(nodes[0], s, data)
|
836
|
+
end
|
837
|
+
|
838
|
+
ddata = @storages[hname].get(vn, k, d)
|
839
|
+
if ddata
|
840
|
+
v = Marshal.load(ddata)
|
841
|
+
else
|
842
|
+
v = [[],[]]
|
843
|
+
end
|
844
|
+
|
845
|
+
v[0].push(data)
|
846
|
+
v[1].push(Time.now.to_i)
|
847
|
+
expt = 0x7fffffff
|
848
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
849
|
+
@stats.write_count += 1
|
850
|
+
|
851
|
+
if ret
|
852
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
853
|
+
send_data("STORED\r\n")
|
854
|
+
else
|
855
|
+
send_data("NOT_STORED\r\n")
|
856
|
+
end
|
857
|
+
rescue => e
|
858
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
859
|
+
send_data("#{msg}\r\n")
|
860
|
+
@log.error("#{e} #{$@}")
|
861
|
+
end
|
862
|
+
|
863
|
+
# alist_sized_push <key> <array-size> <bytes> [forward]\r\n
|
864
|
+
# <data block>\r\n
|
865
|
+
#
|
866
|
+
# (STORED|NOT_PUSHED|NOT_STORED|SERVER_ERROR <error message>)\r\n
|
867
|
+
def ev_alist_sized_push(s)
|
868
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
869
|
+
data = read_bytes(s[3].to_i)
|
870
|
+
read_bytes(2)
|
871
|
+
return forward2(nodes[0], s, data) if nodes[0] != @nid
|
872
|
+
|
873
|
+
ddata = @storages[hname].get(vn, k, d)
|
874
|
+
if ddata
|
875
|
+
v = Marshal.load(ddata)
|
876
|
+
else
|
877
|
+
v = [[],[]]
|
878
|
+
end
|
879
|
+
|
880
|
+
max = s[2].to_i
|
881
|
+
return send_data("NOT_PUSHED\r\n") if v[0].length >= max
|
882
|
+
|
883
|
+
v[0].push(data)
|
884
|
+
v[0] = v[0][0..(max - 1)]
|
885
|
+
v[1].push(Time.now.to_i)
|
886
|
+
v[1] = v[1][0..(max - 1)]
|
887
|
+
|
888
|
+
expt = 0x7fffffff
|
889
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
890
|
+
@stats.write_count += 1
|
891
|
+
|
892
|
+
if ret
|
893
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
894
|
+
send_data("STORED\r\n")
|
895
|
+
else
|
896
|
+
send_data("NOT_STORED\r\n")
|
897
|
+
end
|
898
|
+
rescue => e
|
899
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
900
|
+
send_data("#{msg}\r\n")
|
901
|
+
@log.error("#{e} #{$@}")
|
902
|
+
end
|
903
|
+
|
904
|
+
# alist_swap_and_push <key> <bytes> [forward]\r\n
|
905
|
+
# <data block>\r\n
|
906
|
+
#
|
907
|
+
# (STORED|NOT_STORED|SERVER_ERROR <error message>)\r\n
|
908
|
+
def ev_alist_swap_and_push(s)
|
909
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
910
|
+
data = read_bytes(s[2].to_i)
|
911
|
+
read_bytes(2)
|
912
|
+
return forward2(nodes[0], s, data) if nodes[0] != @nid
|
913
|
+
|
914
|
+
ddata = @storages[hname].get(vn, k, d)
|
915
|
+
if ddata
|
916
|
+
v = Marshal.load(ddata)
|
917
|
+
else
|
918
|
+
v = [[],[]]
|
919
|
+
end
|
920
|
+
|
921
|
+
idx = v[0].index(data)
|
922
|
+
if idx
|
923
|
+
v[0].delete_at(idx)
|
924
|
+
v[1].delete_at(idx)
|
925
|
+
end
|
926
|
+
v[0].push(data)
|
927
|
+
v[1].push(Time.now.to_i)
|
928
|
+
|
929
|
+
expt = 0x7fffffff
|
930
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
931
|
+
@stats.write_count += 1
|
932
|
+
|
933
|
+
if ret
|
934
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
935
|
+
send_data("STORED\r\n")
|
936
|
+
else
|
937
|
+
send_data("NOT_STORED\r\n")
|
938
|
+
end
|
939
|
+
rescue => e
|
940
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
941
|
+
send_data("#{msg}\r\n")
|
942
|
+
@log.error("#{e} #{$@}")
|
943
|
+
end
|
944
|
+
|
945
|
+
# alist_swap_and_sized_push <key> <array-size> <bytes> [forward]\r\n
|
946
|
+
# <data block>\r\n
|
947
|
+
#
|
948
|
+
# (STORED|NOT_PUSHED|NOT_STORED|SERVER_ERROR <error message>)\r\n
|
949
|
+
def ev_alist_swap_and_sized_push(s)
|
950
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
951
|
+
data = read_bytes(s[3].to_i)
|
952
|
+
read_bytes(2)
|
953
|
+
return forward2(nodes[0], s, data) if nodes[0] != @nid
|
954
|
+
|
955
|
+
ddata = @storages[hname].get(vn, k, d)
|
956
|
+
if ddata
|
957
|
+
v = Marshal.load(ddata)
|
958
|
+
else
|
959
|
+
v = [[],[]]
|
960
|
+
end
|
961
|
+
|
962
|
+
max = s[2].to_i
|
963
|
+
|
964
|
+
idx = v[0].index(data)
|
965
|
+
if idx
|
966
|
+
v[0].delete_at(idx)
|
967
|
+
v[1].delete_at(idx)
|
968
|
+
else
|
969
|
+
return send_data("NOT_PUSHED\r\n") if v[0].length >= max
|
970
|
+
end
|
971
|
+
v[0].push(data)
|
972
|
+
v[0] = v[0][0..(max - 1)]
|
973
|
+
v[1].push(Time.now.to_i)
|
974
|
+
v[1] = v[1][0..(max - 1)]
|
975
|
+
|
976
|
+
expt = 0x7fffffff
|
977
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
978
|
+
@stats.write_count += 1
|
979
|
+
|
980
|
+
if ret
|
981
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
982
|
+
send_data("STORED\r\n")
|
983
|
+
else
|
984
|
+
send_data("NOT_STORED\r\n")
|
985
|
+
end
|
986
|
+
rescue => e
|
987
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
988
|
+
send_data("#{msg}\r\n")
|
989
|
+
@log.error("#{e} #{$@}")
|
990
|
+
end
|
991
|
+
|
992
|
+
# alist_expired_swap_and_push <key> <expire-time> <bytes> [forward]\r\n
|
993
|
+
# <data block>\r\n
|
994
|
+
#
|
995
|
+
# the data expire-time's ago will be deleated.
|
996
|
+
# the unit of the expire-time's is a second.
|
997
|
+
# however,as follows when there is a suffix.
|
998
|
+
# 'h' as +expire-time+ suffix is hour.
|
999
|
+
# 'd' as +expire-time+ suffix is day.
|
1000
|
+
#
|
1001
|
+
# (STORED|NOT_STORED|SERVER_ERROR <error message>)\r\n
|
1002
|
+
def ev_alist_expired_swap_and_push(s)
|
1003
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
1004
|
+
data = read_bytes(s[3].to_i)
|
1005
|
+
read_bytes(2)
|
1006
|
+
return forward2(nodes[0], s, data) if nodes[0] != @nid
|
1007
|
+
|
1008
|
+
et = expired_str_to_i(s[2])
|
1009
|
+
return send_data("SERVER_ERROR format error in expire-time.\r\n") unless et
|
1010
|
+
|
1011
|
+
v = to_alist_value_for_write(hname, vn, k, d)
|
1012
|
+
unless v
|
1013
|
+
return send_data("SERVER_ERROR data other than alist's format already exist.\r\n")
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
# @log.debug("#{s[2]} et=#{et}")
|
1017
|
+
v = expired_swap(v, data, et)
|
1018
|
+
|
1019
|
+
v[0].push(data)
|
1020
|
+
v[1].push(Time.now.to_i)
|
1021
|
+
|
1022
|
+
expt = 0x7fffffff
|
1023
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
1024
|
+
@stats.write_count += 1
|
1025
|
+
|
1026
|
+
if ret
|
1027
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
1028
|
+
send_data("STORED\r\n")
|
1029
|
+
else
|
1030
|
+
send_data("NOT_STORED\r\n")
|
1031
|
+
end
|
1032
|
+
rescue => e
|
1033
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
1034
|
+
send_data("#{msg}\r\n")
|
1035
|
+
@log.error("#{e} #{$@}")
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
# alist_expired_swap_and_sized_push <key> <expire-time> <array-size> <bytes> [forward]\r\n
|
1039
|
+
# <data block>\r\n
|
1040
|
+
#
|
1041
|
+
# the data expire-time's ago will be deleated.
|
1042
|
+
# the unit of the expire-time's is a second.
|
1043
|
+
# however,as follows when there is a suffix.
|
1044
|
+
# 'h' as +expire-time+ suffix is hour.
|
1045
|
+
# 'd' as +expire-time+ suffix is day.
|
1046
|
+
#
|
1047
|
+
# (STORED|NOT_STORED|SERVER_ERROR <error message>)\r\n
|
1048
|
+
def ev_alist_expired_swap_and_sized_push(s)
|
1049
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
1050
|
+
data = read_bytes(s[4].to_i)
|
1051
|
+
read_bytes(2)
|
1052
|
+
return forward2(nodes[0], s, data) if nodes[0] != @nid
|
1053
|
+
|
1054
|
+
et = expired_str_to_i(s[2])
|
1055
|
+
return send_data("SERVER_ERROR format error in expire-time.\r\n") unless et
|
1056
|
+
|
1057
|
+
v = to_alist_value_for_write(hname, vn, k, d)
|
1058
|
+
unless v
|
1059
|
+
return send_data("SERVER_ERROR data other than alist's format already exist.\r\n")
|
1060
|
+
end
|
1061
|
+
|
1062
|
+
# @log.debug("#{s[2]} et=#{et}")
|
1063
|
+
v = expired_swap(v, data, et)
|
1064
|
+
|
1065
|
+
max = s[3].to_i
|
1066
|
+
return send_data("NOT_PUSHED\r\n") if v[0].length >= max
|
1067
|
+
|
1068
|
+
v[0].push(data)
|
1069
|
+
v[0] = v[0][0..(max - 1)]
|
1070
|
+
v[1].push(Time.now.to_i)
|
1071
|
+
v[1] = v[1][0..(max - 1)]
|
1072
|
+
|
1073
|
+
expt = 0x7fffffff
|
1074
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
1075
|
+
@stats.write_count += 1
|
1076
|
+
|
1077
|
+
if ret
|
1078
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
1079
|
+
send_data("STORED\r\n")
|
1080
|
+
else
|
1081
|
+
send_data("NOT_STORED\r\n")
|
1082
|
+
end
|
1083
|
+
rescue => e
|
1084
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
1085
|
+
send_data("#{msg}\r\n")
|
1086
|
+
@log.error("#{e} #{$@}")
|
1087
|
+
end
|
1088
|
+
|
1089
|
+
|
1090
|
+
# alist_shift <key> [forward]\r\n
|
1091
|
+
#
|
1092
|
+
# (
|
1093
|
+
# [VALUE <key> 0 <value length>\r\n
|
1094
|
+
# <value>\r\n]
|
1095
|
+
# END
|
1096
|
+
# |NOT_STORED|SERVER_ERROR <error message>)\r\n
|
1097
|
+
def ev_alist_shift(s)
|
1098
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
1099
|
+
return forward1(nodes[0], s) if nodes[0] != @nid
|
1100
|
+
|
1101
|
+
ddata = @storages[hname].get(vn, k, d)
|
1102
|
+
if ddata
|
1103
|
+
v = Marshal.load(ddata)
|
1104
|
+
return send_data("END\r\n") if v[0].length ==0
|
1105
|
+
else
|
1106
|
+
return send_data("END\r\n")
|
1107
|
+
end
|
1108
|
+
|
1109
|
+
retv = v[0].shift
|
1110
|
+
v[1].shift
|
1111
|
+
expt = 0x7fffffff
|
1112
|
+
ret = @storages[hname].set(vn, k, d, expt ,Marshal.dump(v))
|
1113
|
+
@stats.read_count += 1
|
1114
|
+
@stats.write_count += 1
|
1115
|
+
|
1116
|
+
if ret
|
1117
|
+
redundant(nodes[1..-1], hname, k, d, ret[2], expt, ret[4])
|
1118
|
+
send_data("VALUE #{s[1]} 0 #{retv.length}\r\n#{retv}\r\nEND\r\n")
|
1119
|
+
else
|
1120
|
+
send_data("NOT_STORED\r\n")
|
1121
|
+
end
|
1122
|
+
rescue => e
|
1123
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
1124
|
+
send_data("#{msg}\r\n")
|
1125
|
+
@log.error("#{e} #{$@}")
|
1126
|
+
end
|
1127
|
+
|
1128
|
+
# alist_to_s <key> [index|range] [forward]\r\n
|
1129
|
+
#
|
1130
|
+
# (
|
1131
|
+
# [VALUE <key> 0 <length of length string>\r\n
|
1132
|
+
# <length string>\r\n
|
1133
|
+
# VALUE <key> 0 <value length>\r\n
|
1134
|
+
# <value>\r\n]
|
1135
|
+
# END\r\n
|
1136
|
+
# |SERVER_ERROR <error message>\r\n)
|
1137
|
+
def ev_alist_to_s(s)
|
1138
|
+
hname, k, d, vn, nodes = calc_hash(s[1])
|
1139
|
+
return forward1(nodes[0], s) if nodes[0] != @nid
|
1140
|
+
|
1141
|
+
ddata = @storages[hname].get(vn, k, 0)
|
1142
|
+
@stats.read_count += 1
|
1143
|
+
|
1144
|
+
return send_data("END\r\n") unless ddata
|
1145
|
+
v = to_alist_value(ddata)
|
1146
|
+
if v
|
1147
|
+
ret = nil
|
1148
|
+
if /(?:^(\d+)$|^(\d+)..((?:-)?\d+)$)/ =~ s[2]
|
1149
|
+
if $1
|
1150
|
+
ret = v[0][Range.new($1.to_i,$1.to_i)].to_s
|
1151
|
+
else
|
1152
|
+
ret = v[0][Range.new($2.to_i,$3.to_i)].to_s
|
1153
|
+
end
|
1154
|
+
else
|
1155
|
+
ret = v[0].to_s
|
1156
|
+
end
|
1157
|
+
len = v[0].length
|
1158
|
+
send_data("VALUE #{s[1]} 0 #{len.to_s.length}\r\n#{len.to_s}\r\n")
|
1159
|
+
return send_data("VALUE #{s[1]} 0 #{ret.length}\r\n#{ret}\r\nEND\r\n")
|
1160
|
+
else
|
1161
|
+
return send_data("SERVER_ERROR data other than alist's format already exist.\r\n")
|
1162
|
+
end
|
1163
|
+
rescue => e
|
1164
|
+
msg = "SERVER_ERROR #{e} #{$@}".tr("\r\n"," ")
|
1165
|
+
send_data("#{msg}\r\n")
|
1166
|
+
@log.error("#{e} #{$@}")
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
|
1170
|
+
# alist_spushv <hash-name> <vnode-id>
|
1171
|
+
# src dst
|
1172
|
+
# | ['alist_spushv' <hname> <vn>\r\n]->|
|
1173
|
+
# |<-['READY'\r\n] |
|
1174
|
+
# | [<dumpdata>]->|
|
1175
|
+
# | : |
|
1176
|
+
# | : |
|
1177
|
+
# | [<end of dump>]->|
|
1178
|
+
# |<-['STORED'\r\n] |
|
1179
|
+
def ev_alist_spushv(s)
|
1180
|
+
send_data("READY\r\n")
|
1181
|
+
@stats.run_receive_a_vnode = true
|
1182
|
+
count = 0
|
1183
|
+
loop {
|
1184
|
+
context_bin = read_bytes(20, 100)
|
1185
|
+
vn, last, clk, expt, klen = context_bin.unpack('NNNNN')
|
1186
|
+
break if klen == 0 # end of dump ?
|
1187
|
+
k = read_bytes(klen)
|
1188
|
+
vlen_bin = read_bytes(4, 100)
|
1189
|
+
vlen, = vlen_bin.unpack('N')
|
1190
|
+
v = read_bytes(vlen, 100)
|
1191
|
+
val = to_alist_value(v)
|
1192
|
+
if val
|
1193
|
+
# @log.debug("listdata #{vn} #{k} #{val.inspect}")
|
1194
|
+
count += 1 if merge_list(s[1], vn, last, clk, expt, k, v, val)
|
1195
|
+
else
|
1196
|
+
# @log.debug("not listdata #{vn} #{k} #{val}")
|
1197
|
+
count += 1 if @storages[s[1]].load_stream_dump(vn, last, clk, expt, k, v)
|
1198
|
+
end
|
1199
|
+
}
|
1200
|
+
send_data("STORED\r\n")
|
1201
|
+
@log.debug("alist #{count} keys loaded.")
|
1202
|
+
rescue => e
|
1203
|
+
@log.error("#{e}\n#{$@}")
|
1204
|
+
ensure
|
1205
|
+
@stats.run_receive_a_vnode = false
|
1206
|
+
end
|
1207
|
+
|
1208
|
+
private
|
1209
|
+
|
1210
|
+
def expired_swap(v, rcv_val, et)
|
1211
|
+
del = [rcv_val]
|
1212
|
+
expt = Time.now.to_i - et
|
1213
|
+
v[1].each_with_index{|t,i|
|
1214
|
+
# @log.debug("v=#{v[0][i]} expt=#{expt} t=#{t} #{expt >= t}")
|
1215
|
+
del << v[0][i] if expt >= t
|
1216
|
+
}
|
1217
|
+
del.each{|dat|
|
1218
|
+
i = v[0].index(dat)
|
1219
|
+
if i
|
1220
|
+
v[0].delete_at(i)
|
1221
|
+
v[1].delete_at(i)
|
1222
|
+
end
|
1223
|
+
}
|
1224
|
+
v
|
1225
|
+
end
|
1226
|
+
|
1227
|
+
def expired_str_to_i(s)
|
1228
|
+
if s.upcase =~ /(\d+)([H|D])?/
|
1229
|
+
t = $1.to_i
|
1230
|
+
if $2 == 'D'
|
1231
|
+
t *= 86400
|
1232
|
+
elsif $2 == 'H'
|
1233
|
+
t *= 3600
|
1234
|
+
end
|
1235
|
+
t
|
1236
|
+
else
|
1237
|
+
nil
|
1238
|
+
end
|
1239
|
+
end
|
1240
|
+
|
1241
|
+
def to_alist_value_for_write(hname, vn, k, d)
|
1242
|
+
ddata = @storages[hname].get(vn, k, d)
|
1243
|
+
unless ddata
|
1244
|
+
v = [[],[]]
|
1245
|
+
else
|
1246
|
+
v = to_alist_value(ddata)
|
1247
|
+
end
|
1248
|
+
end
|
1249
|
+
|
1250
|
+
def to_alist_value(v)
|
1251
|
+
# Marshal.dump([[],[]])[0..3].unpack("cc a c")
|
1252
|
+
# => [4, 8, "[", 7]
|
1253
|
+
# marshal format version 4.8
|
1254
|
+
# array object "["
|
1255
|
+
# array.length fixednum format 7 (7-5=2)
|
1256
|
+
return nil if v == nil || v[0..3] != "\x04\b[\a"
|
1257
|
+
val = Marshal.load(v)
|
1258
|
+
if val[0].instance_of?(Array) && val[1].instance_of?(Array)
|
1259
|
+
return val
|
1260
|
+
else
|
1261
|
+
return nil
|
1262
|
+
end
|
1263
|
+
rescue
|
1264
|
+
nil
|
1265
|
+
end
|
1266
|
+
|
1267
|
+
def merge_list(hname, vn, last, clk, expt, k, v, val)
|
1268
|
+
ddata = @storages[hname].get(vn, k, 0)
|
1269
|
+
if ddata
|
1270
|
+
lv = Marshal.load(ddata)
|
1271
|
+
lv[0].each{|buf|
|
1272
|
+
idx = val[0].index(buf)
|
1273
|
+
if idx
|
1274
|
+
val[0].delete_at(idx)
|
1275
|
+
val[1].delete_at(idx)
|
1276
|
+
end
|
1277
|
+
}
|
1278
|
+
lv[0] += val[0]
|
1279
|
+
lv[1] += val[1]
|
1280
|
+
@storages[hname].set(vn, k, 0, expt ,Marshal.dump(lv))
|
1281
|
+
else
|
1282
|
+
@storages[hname].load_stream_dump(vn, last, clk, expt, k, v)
|
1283
|
+
end
|
1284
|
+
end
|
1285
|
+
|
1286
|
+
def calc_hash(key)
|
1287
|
+
k,hname = key.split("\e")
|
1288
|
+
hname ||= @defhash
|
1289
|
+
d = Digest::SHA1.hexdigest(k).hex % @rttable.hbits
|
1290
|
+
vn = @rttable.get_vnode_id(d)
|
1291
|
+
nodes = @rttable.search_nodes_for_write(vn)
|
1292
|
+
[hname, k, d, vn, nodes]
|
1293
|
+
end
|
1294
|
+
|
1295
|
+
# for a several lines received command
|
1296
|
+
def forward1(nid, rs, data=nil)
|
1297
|
+
if rs.last == "forward"
|
1298
|
+
return send_data("SERVER_ERROR Routing table is inconsistent.\r\n")
|
1299
|
+
end
|
1300
|
+
|
1301
|
+
buf = ''
|
1302
|
+
rs.each{|ss| buf << "#{ss} " }
|
1303
|
+
buf << "forward\r\n"
|
1304
|
+
if data
|
1305
|
+
buf << data
|
1306
|
+
buf << "\r\n"
|
1307
|
+
end
|
1308
|
+
|
1309
|
+
con = get_connection(nid)
|
1310
|
+
con.send(buf)
|
1311
|
+
|
1312
|
+
res = ''
|
1313
|
+
while (buf = con.gets)!="END\r\n"
|
1314
|
+
res << buf
|
1315
|
+
s = buf.split(/ /)
|
1316
|
+
if s[0] != 'VALUE'
|
1317
|
+
return send_data(buf)
|
1318
|
+
end
|
1319
|
+
res << con.read_bytes(s[3].to_i + 2)
|
1320
|
+
end
|
1321
|
+
res << "END\r\n"
|
1322
|
+
|
1323
|
+
return_connection(nid, con)
|
1324
|
+
@rttable.proc_succeed(nid)
|
1325
|
+
if res
|
1326
|
+
send_data(res)
|
1327
|
+
else
|
1328
|
+
send_data("SERVER_ERROR Message forward failed.\r\n")
|
1329
|
+
end
|
1330
|
+
rescue => e
|
1331
|
+
@rttable.proc_failed(nid)
|
1332
|
+
@log.error("forward get failed:nid=#{nid} rs=#{rs} #{e} #{$@}")
|
1333
|
+
send_data("SERVER_ERROR Message forward failed.\r\n")
|
1334
|
+
end
|
1335
|
+
|
1336
|
+
# for a one line reveived command
|
1337
|
+
def forward2(nid, rs, data=nil)
|
1338
|
+
if rs.last == "forward"
|
1339
|
+
return send_data("SERVER_ERROR Routing table is inconsistent.\r\n")
|
1340
|
+
end
|
1341
|
+
|
1342
|
+
buf = ''
|
1343
|
+
rs.each{|ss| buf << "#{ss} " }
|
1344
|
+
buf << "forward\r\n"
|
1345
|
+
if data
|
1346
|
+
buf << data
|
1347
|
+
buf << "\r\n"
|
1348
|
+
end
|
1349
|
+
|
1350
|
+
res = send_cmd(nid, buf)
|
1351
|
+
return send_data("#{res}\r\n") if res
|
1352
|
+
return send_data("SERVER_ERROR Message forward failed.\r\n")
|
1353
|
+
end
|
1354
|
+
|
1355
|
+
end # PluginAshiatoList
|
1356
|
+
end # CommandPlugin
|
1357
|
+
|
1358
|
+
|
1359
|
+
module ClientPlugin
|
1360
|
+
|
1361
|
+
module PluginAshiatoList
|
1362
|
+
|
1363
|
+
def alist_at(key, index)
|
1364
|
+
ret = sender(:value_list_receiver, key, nil, "alist_at %s #{index}")
|
1365
|
+
return nil if ret.length == 0
|
1366
|
+
ret[0]
|
1367
|
+
end
|
1368
|
+
|
1369
|
+
def alist_clear(key)
|
1370
|
+
sender(:oneline_receiver, key, nil, "alist_clear %s")
|
1371
|
+
end
|
1372
|
+
|
1373
|
+
def alist_delete(key, value)
|
1374
|
+
value_validator(value)
|
1375
|
+
sender(:oneline_receiver, key, value, "alist_delete %s #{value.length}")
|
1376
|
+
end
|
1377
|
+
|
1378
|
+
def alist_delete_at(key, index)
|
1379
|
+
sender(:oneline_receiver, key, nil, "alist_delete_at %s #{index}")
|
1380
|
+
end
|
1381
|
+
|
1382
|
+
def alist_empty?(key)
|
1383
|
+
sender(:oneline_receiver, key, nil, "alist_empty? %s")
|
1384
|
+
end
|
1385
|
+
|
1386
|
+
def alist_first(key)
|
1387
|
+
ret = sender(:value_list_receiver, key, nil, "alist_first %s")
|
1388
|
+
return nil if ret.length == 0
|
1389
|
+
ret[0]
|
1390
|
+
end
|
1391
|
+
|
1392
|
+
def alist_gets(key, range=nil)
|
1393
|
+
if range
|
1394
|
+
ret = sender(:value_list_receiver, key, nil, "alist_gets %s #{range}")
|
1395
|
+
else
|
1396
|
+
ret = sender(:value_list_receiver, key, nil, "alist_gets %s")
|
1397
|
+
end
|
1398
|
+
return nil if ret.length == 0
|
1399
|
+
ret[0] = ret[0].to_i
|
1400
|
+
ret
|
1401
|
+
end
|
1402
|
+
|
1403
|
+
def alist_gets_with_time(key, range=nil)
|
1404
|
+
if range
|
1405
|
+
ret = sender(:value_list_receiver, key, nil, "alist_gets_with_time %s #{range}")
|
1406
|
+
else
|
1407
|
+
ret = sender(:value_list_receiver, key, nil, "alist_gets_with_time %s")
|
1408
|
+
end
|
1409
|
+
return nil if ret.length == 0
|
1410
|
+
ret[0] = ret[0].to_i
|
1411
|
+
ret
|
1412
|
+
end
|
1413
|
+
|
1414
|
+
def alist_include?(key, value)
|
1415
|
+
sender(:oneline_receiver, key, value, "alist_include? %s #{value.length}")
|
1416
|
+
end
|
1417
|
+
|
1418
|
+
def alist_index(key, value)
|
1419
|
+
value_validator(value)
|
1420
|
+
ret = sender(:oneline_receiver, key, value, "alist_index %s #{value.length}")
|
1421
|
+
return ret.to_i if ret =~ /\d+/
|
1422
|
+
return nil if ret=='nil'
|
1423
|
+
ret
|
1424
|
+
end
|
1425
|
+
|
1426
|
+
def alist_insert(key, index, value)
|
1427
|
+
value_validator(value)
|
1428
|
+
sender(:oneline_receiver, key, value, "alist_insert %s #{index} #{value.length}")
|
1429
|
+
end
|
1430
|
+
|
1431
|
+
def alist_sized_insert(key, array_size, value)
|
1432
|
+
sender(:oneline_receiver, key, value, "alist_sized_insert %s #{array_size} #{value.length}")
|
1433
|
+
end
|
1434
|
+
|
1435
|
+
def alist_swap_and_insert(key, value)
|
1436
|
+
sender(:oneline_receiver, key, value, "alist_swap_and_insert %s #{value.length}")
|
1437
|
+
end
|
1438
|
+
|
1439
|
+
def alist_swap_and_sized_insert(key, array_size, value)
|
1440
|
+
value_validator(value)
|
1441
|
+
sender(:oneline_receiver, key, value, "alist_swap_and_sized_insert %s #{array_size} #{value.length}")
|
1442
|
+
end
|
1443
|
+
|
1444
|
+
def alist_expired_swap_and_insert(key, expt, value)
|
1445
|
+
value_validator(value)
|
1446
|
+
sender(:oneline_receiver, key, value,
|
1447
|
+
"alist_expired_swap_and_insert %s #{expt} #{value.length}")
|
1448
|
+
end
|
1449
|
+
|
1450
|
+
def alist_expired_swap_and_sized_insert(key, expt, array_size, value)
|
1451
|
+
value_validator(value)
|
1452
|
+
sender(:oneline_receiver, key, value,
|
1453
|
+
"alist_expired_swap_and_sized_insert %s #{expt} #{array_size} #{value.length}")
|
1454
|
+
end
|
1455
|
+
|
1456
|
+
def alist_join(key, sep, range=nil)
|
1457
|
+
if range
|
1458
|
+
ret = sender(:value_list_receiver, key, sep, "alist_join %s #{sep.length} #{range}")
|
1459
|
+
else
|
1460
|
+
ret = sender(:value_list_receiver, key, sep, "alist_join %s #{sep.length}")
|
1461
|
+
end
|
1462
|
+
return nil if ret.length == 0
|
1463
|
+
ret[0] = ret[0].to_i
|
1464
|
+
ret
|
1465
|
+
end
|
1466
|
+
|
1467
|
+
def alist_join_with_time(key, sep, range=nil)
|
1468
|
+
if range
|
1469
|
+
ret = sender(:value_list_receiver, key, sep,
|
1470
|
+
"alist_join_with_time %s #{sep.length} #{range}")
|
1471
|
+
else
|
1472
|
+
ret = sender(:value_list_receiver, key, sep,
|
1473
|
+
"alist_join_with_time %s #{sep.length}")
|
1474
|
+
end
|
1475
|
+
return nil if ret.length == 0
|
1476
|
+
ret[0] = ret[0].to_i
|
1477
|
+
ret
|
1478
|
+
end
|
1479
|
+
|
1480
|
+
def alist_to_json(key, range=nil)
|
1481
|
+
if range
|
1482
|
+
ret = sender(:value_list_receiver, key, nil, "alist_to_json %s #{range}")
|
1483
|
+
else
|
1484
|
+
ret = sender(:value_list_receiver, key, nil, "alist_to_json %s")
|
1485
|
+
end
|
1486
|
+
return nil if ret.length == 0
|
1487
|
+
ret[0]
|
1488
|
+
end
|
1489
|
+
|
1490
|
+
def alist_last(key)
|
1491
|
+
ret = sender(:value_list_receiver, key, nil, "alist_last %s")
|
1492
|
+
return nil if ret.length == 0
|
1493
|
+
ret[0]
|
1494
|
+
end
|
1495
|
+
|
1496
|
+
def alist_length(key)
|
1497
|
+
ret = sender(:oneline_receiver, key, nil, "alist_length %s")
|
1498
|
+
return ret.to_i if ret =~ /\d+/
|
1499
|
+
ret
|
1500
|
+
end
|
1501
|
+
|
1502
|
+
def alist_pop(key)
|
1503
|
+
ret = sender(:value_list_receiver, key, nil, "alist_pop %s")
|
1504
|
+
return nil if ret.length == 0
|
1505
|
+
ret[0]
|
1506
|
+
end
|
1507
|
+
|
1508
|
+
def alist_push(key, value)
|
1509
|
+
value_validator(value)
|
1510
|
+
sender(:oneline_receiver, key, value, "alist_push %s #{value.length}")
|
1511
|
+
end
|
1512
|
+
|
1513
|
+
def alist_sized_push(key, array_size, value)
|
1514
|
+
value_validator(value)
|
1515
|
+
sender(:oneline_receiver, key, value,
|
1516
|
+
"alist_sized_push %s #{array_size} #{value.length}")
|
1517
|
+
end
|
1518
|
+
|
1519
|
+
def alist_swap_and_push(key, value)
|
1520
|
+
value_validator(value)
|
1521
|
+
sender(:oneline_receiver, key, value, "alist_swap_and_push %s #{value.length}")
|
1522
|
+
end
|
1523
|
+
|
1524
|
+
def alist_swap_and_sized_push(key, array_size, value)
|
1525
|
+
value_validator(value)
|
1526
|
+
sender(:oneline_receiver, key, value,
|
1527
|
+
"alist_swap_and_sized_push %s #{array_size} #{value.length}")
|
1528
|
+
end
|
1529
|
+
|
1530
|
+
def alist_expired_swap_and_push(key, expt, value)
|
1531
|
+
value_validator(value)
|
1532
|
+
sender(:oneline_receiver, key, value,
|
1533
|
+
"alist_expired_swap_and_push %s #{expt} #{value.length}")
|
1534
|
+
end
|
1535
|
+
|
1536
|
+
def alist_expired_swap_and_sized_push(key, expt, array_size, value)
|
1537
|
+
value_validator(value)
|
1538
|
+
sender(:oneline_receiver, key, value,
|
1539
|
+
"alist_expired_swap_and_sized_push %s #{expt} #{array_size} #{value.length}")
|
1540
|
+
end
|
1541
|
+
|
1542
|
+
def alist_shift(key)
|
1543
|
+
ret = sender(:value_list_receiver, key, nil, "alist_shift %s")
|
1544
|
+
return nil if ret.length == 0
|
1545
|
+
ret[0]
|
1546
|
+
end
|
1547
|
+
|
1548
|
+
def alist_to_s(key, range=nil)
|
1549
|
+
if range
|
1550
|
+
ret = sender(:value_list_receiver, key, nil, "alist_to_s %s #{range}")
|
1551
|
+
else
|
1552
|
+
ret = sender(:value_list_receiver, key, nil, "alist_to_s %s")
|
1553
|
+
end
|
1554
|
+
return ret if ret.instance_of?(String)
|
1555
|
+
return nil if ret.length == 0
|
1556
|
+
ret[0] = ret[0].to_i
|
1557
|
+
ret[1] = eval(ret[1])
|
1558
|
+
ret
|
1559
|
+
end
|
1560
|
+
|
1561
|
+
private
|
1562
|
+
|
1563
|
+
def value_validator(value)
|
1564
|
+
if value == nil || !value.instance_of?(String)
|
1565
|
+
raise "value must be a String object."
|
1566
|
+
end
|
1567
|
+
end
|
1568
|
+
|
1569
|
+
end # PluginAshiatoList
|
1570
|
+
end # ClientPlugin
|
1571
|
+
|
1572
|
+
end # Roma
|