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.
Files changed (61) hide show
  1. data/LICENSE.rdoc +675 -0
  2. data/README.rdoc +0 -0
  3. data/Rakefile +70 -0
  4. data/bin/mkrecent +7 -0
  5. data/bin/mkroute +7 -0
  6. data/bin/recoverlost +8 -0
  7. data/bin/recoverlost_alist +8 -0
  8. data/bin/romad +7 -0
  9. data/bin/sample_watcher +8 -0
  10. data/bin/sample_watcher2 +8 -0
  11. data/bin/simple_bench +8 -0
  12. data/bin/ssroute +7 -0
  13. data/bin/tribunus +7 -0
  14. data/lib/roma/async_process.rb +696 -0
  15. data/lib/roma/command/bg_command_receiver.rb +188 -0
  16. data/lib/roma/command/mh_command_receiver.rb +117 -0
  17. data/lib/roma/command/receiver.rb +287 -0
  18. data/lib/roma/command/rt_command_receiver.rb +147 -0
  19. data/lib/roma/command/st_command_receiver.rb +564 -0
  20. data/lib/roma/command/util_command_receiver.rb +67 -0
  21. data/lib/roma/command/vn_command_receiver.rb +143 -0
  22. data/lib/roma/command_plugin.rb +11 -0
  23. data/lib/roma/config.rb +64 -0
  24. data/lib/roma/event/con_pool.rb +140 -0
  25. data/lib/roma/event/handler.rb +159 -0
  26. data/lib/roma/plugin/plugin_alist.rb +1572 -0
  27. data/lib/roma/plugin/plugin_debug.rb +19 -0
  28. data/lib/roma/plugin/plugin_test.rb +14 -0
  29. data/lib/roma/romad.rb +582 -0
  30. data/lib/roma/routing/cb_rttable.rb +326 -0
  31. data/lib/roma/routing/merkle_tree.rb +54 -0
  32. data/lib/roma/routing/rttable.rb +148 -0
  33. data/lib/roma/stats.rb +112 -0
  34. data/lib/roma/storage/basic_storage.rb +510 -0
  35. data/lib/roma/storage/dbm_storage.rb +80 -0
  36. data/lib/roma/storage/dummy_storage.rb +44 -0
  37. data/lib/roma/storage/rh_storage.rb +35 -0
  38. data/lib/roma/storage/sqlite3_storage.rb +73 -0
  39. data/lib/roma/storage/tc_storage.rb +133 -0
  40. data/lib/roma/tools/mkrecent.rb +138 -0
  41. data/lib/roma/tools/mkroute.rb +52 -0
  42. data/lib/roma/tools/recoverlost.rb +9 -0
  43. data/lib/roma/tools/recoverlost_alist.rb +9 -0
  44. data/lib/roma/tools/recoverlost_lib.rb +217 -0
  45. data/lib/roma/tools/sample_watcher.rb +38 -0
  46. data/lib/roma/tools/sample_watcher2.rb +38 -0
  47. data/lib/roma/tools/simple_bench.rb +57 -0
  48. data/lib/roma/tools/ssroute.rb +23 -0
  49. data/lib/roma/tools/tribunus.rb +299 -0
  50. data/lib/roma/version.rb +4 -0
  51. data/lib/roma/write_behind.rb +179 -0
  52. data/test/rcirb.rb +16 -0
  53. data/test/roma-test-utils.rb +65 -0
  54. data/test/run-test.rb +16 -0
  55. data/test/t_cpdata.rb +277 -0
  56. data/test/t_listplugin.rb +592 -0
  57. data/test/t_rclient.rb +318 -0
  58. data/test/t_routing_data.rb +100 -0
  59. data/test/t_storage.rb +644 -0
  60. data/test/t_writebehind.rb +200 -0
  61. metadata +134 -0
data/test/t_storage.rb ADDED
@@ -0,0 +1,644 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require 'roma/storage/tc_storage'
5
+ require 'roma/storage/dbm_storage'
6
+ require 'roma/storage/rh_storage'
7
+ require 'roma/storage/sqlite3_storage'
8
+
9
+ class TCStorageTest < Test::Unit::TestCase
10
+
11
+ def initialize(arg)
12
+ super(arg)
13
+ @ndat=1000
14
+ end
15
+
16
+ def setup
17
+ rmtestdir('storage_test')
18
+ @st=Roma::Storage::TCStorage.new
19
+ @st.vn_list = [0,1,2,3,4,5,6,7,8,9]
20
+ @st.storage_path = 'storage_test'
21
+ @st.opendb
22
+ rescue =>e
23
+ p e
24
+ end
25
+
26
+ def rmtestdir(dirname)
27
+ if File::directory?(dirname)
28
+ File.delete(*Dir["#{dirname}/*"])
29
+ Dir.rmdir(dirname)
30
+ end
31
+ end
32
+
33
+ def teardown
34
+ @st.closedb
35
+ rmtestdir('storage_test')
36
+ end
37
+
38
+ # 普通のset get
39
+ def test_set_get
40
+ assert_equal( 'abc_data',@st.set(0,'abc',0,0xffffffff,'abc_data')[4])
41
+ assert_equal( 'abc_data', @st.get(0,'abc',0) )
42
+ end
43
+
44
+ # 普通のset delete
45
+ def test_set_delete
46
+ @st.set(0,'abc',0,0xffffffff,'abc_data')
47
+ assert_equal( 'abc_data', @st.delete(0,'abc',0)[4]) # 存在するキーの削除は value が返る
48
+ assert_nil( @st.get(0,'abc',0) )
49
+ assert_equal(:deletemark, @st.delete(0,'abc',0)) # 削除済みはマークがあることを返す
50
+ end
51
+
52
+ # 有効期限
53
+ def test_set_exptime
54
+ @st.set(0,'abc',0,Time.now.to_i,'abc_data')
55
+ assert_equal('abc_data', @st.get(0,'abc',0) ) # 期限内
56
+ @st.set(0,'abc',0,Time.now.to_i-1,'abc_data') # 有効期限を1秒前に
57
+ assert_nil( @st.get(0,'abc',0)) # 期限切れ
58
+ end
59
+
60
+ def test_set_get_raw
61
+ n = 100
62
+ n.times{|i|
63
+ assert_equal('abc_data',@st.set(0,'abc',0,0xffffffff,'abc_data')[4])
64
+ vn, t, clk, expt, val = @st.get_raw(0,'abc',0)
65
+ assert_equal(vn,0)
66
+ assert(Time.now.to_i - t <= 1)
67
+ assert_equal(clk,i)
68
+ assert_equal(expt,0xffffffff)
69
+ assert_equal(val,'abc_data')
70
+ }
71
+ end
72
+
73
+ # 期限切れデータの削除
74
+ def test_exp_delete
75
+ assert_nil( @st.delete(0,'abc',0)[4])
76
+ assert_equal('abc_data' , @st.set(0,'abc',0,Time.now.to_i-1,'abc_data')[4]) # 有効期限を1秒前に
77
+ assert_nil( @st.delete(0,'abc',0)[4]) # 期限切れ
78
+ end
79
+
80
+ def test_rset
81
+ # クロックがカウントアップされる
82
+ assert_equal(0, @st.set(0,'abc',0,Time.now.to_i,'abc_data')[2] )
83
+ assert_equal(1, @st.set(0,'abc',0,Time.now.to_i,'abc_data')[2] )
84
+ assert_equal(2, @st.set(0,'abc',0,Time.now.to_i,'abc_data')[2] )
85
+ # 指定したクロックが挿入される
86
+ assert_equal(4, @st.rset(0,'abc',0,4,Time.now.to_i,'new_data')[2] )
87
+ # 古いクロックは拒否される
88
+ assert_nil( @st.rset(0,'abc',0,4,Time.now.to_i,'new_data') )
89
+ assert_nil( @st.rset(0,'abc',0,3,Time.now.to_i,'new_data') )
90
+ end
91
+
92
+ def test_rdelete
93
+ # 指定したクロックで削除マークされる
94
+ assert_equal(2, @st.rdelete(0,'abc',0,2)[2] )
95
+ # 古いクロックの挿入は許されない
96
+ assert_nil( @st.rset(0,'abc',0,1,Time.now.to_i,'new_data'))
97
+ assert_nil( @st.rset(0,'abc',0,2,Time.now.to_i,'new_data'))
98
+ # 古いクロックの削除も拒否される
99
+ assert_nil( @st.rdelete(0,'abc',0,1) )
100
+ assert_nil( @st.rdelete(0,'abc',0,2) )
101
+ # 新しいクロックの削除はマークされる
102
+ assert_equal( 3, @st.rdelete(0,'abc',0,3)[2] )
103
+ end
104
+
105
+ def test_out
106
+ assert( !@st.out(0,'abc',0) )
107
+ @st.set(0,'abc',0,Time.now.to_i,'abc_data')
108
+ assert( @st.out(0,'abc',0) )
109
+ end
110
+
111
+ # 論理クロックの境界をテスト
112
+ def test_clock_count
113
+ assert_equal( 0xfffffffe, @st.rset(0,'set',0,0xfffffffe,Time.now.to_i,'new_data')[2])
114
+ assert_equal(0xffffffff, @st.set(0,'set',0,Time.now.to_i,'abc_data')[2])
115
+ assert_equal(0, @st.set(0,'set',0,Time.now.to_i,'abc_data')[2] )
116
+
117
+ assert_equal(0xffffffff,@st.rdelete(0,'add',0,0xffffffff)[2])
118
+ assert_equal(0, @st.add(0,'add',0,Time.now.to_i,'abc_data')[2] )
119
+
120
+ assert_equal(0xffffffff, @st.rset(0,'replace',0,0xffffffff,Time.now.to_i,'abc_data')[2])
121
+ assert_equal(0, @st.replace(0,'replace',0,Time.now.to_i,'abc_data')[2] )
122
+
123
+ assert_equal(0xffffffff, @st.rset(0,'append',0,0xffffffff,Time.now.to_i,'abc_data')[2])
124
+ assert_equal(0, @st.append(0,'append',0,Time.now.to_i,'abc_data')[2] )
125
+
126
+ assert_equal(0xffffffff, @st.rset(0,'prepend',0,0xffffffff,Time.now.to_i,'abc_data')[2])
127
+ assert_equal(0, @st.prepend(0,'prepend',0,Time.now.to_i,'abc_data')[2] )
128
+
129
+ assert_equal(0xffffffff, @st.rset(0,'incr',0,0xffffffff,Time.now.to_i,'10')[2])
130
+ assert_equal(0, @st.incr(0,'incr',0,10)[2] )
131
+
132
+ assert_equal(0xffffffff, @st.rset(0,'decr',0,0xffffffff,Time.now.to_i,'10')[2])
133
+ assert_equal(0, @st.decr(0,'decr',0,10)[2] )
134
+ end
135
+
136
+ def test_add
137
+ assert_equal('abc_data',@st.add(0,'abc',0,Time.now.to_i+1,'abc_data')[4])
138
+ assert_nil( @st.add(0,'abc',0,Time.now.to_i+1,'abc_data') ) # 上書きは失敗する
139
+ assert_equal( 'abc_data', @st.delete(0,'abc',0)[4])
140
+ assert_equal('abc_data', @st.add(0,'abc',0,Time.now.to_i,'abc_data')[4]) # delete 後の add の成功を確認
141
+ end
142
+
143
+ def test_replace
144
+ assert_nil( @st.replace(0,'abc',0,Time.now.to_i,'abc_data') )
145
+ assert_equal('abc_data', @st.add(0,'abc',0,Time.now.to_i,'abc_data')[4])
146
+ assert_equal('new_data', @st.replace(0,'abc',0,Time.now.to_i,'new_data')[4] )
147
+
148
+ end
149
+
150
+ def test_append
151
+ assert_nil( @st.append(0,'abc',0,Time.now.to_i,'abc_data') )
152
+ assert_equal('abc_data', @st.set(0,'abc',0,Time.now.to_i,'abc_data')[4])
153
+ assert_equal( 'abc_data123',@st.append(0,'abc',0,Time.now.to_i,'123')[4] )
154
+ assert_equal('abc_data123', @st.get(0,'abc',0) )
155
+ end
156
+
157
+ def test_prepend
158
+ assert_nil( @st.prepend(0,'abc',0,Time.now.to_i,'abc_data') )
159
+ assert_equal('abc_data', @st.set(0,'abc',0,Time.now.to_i,'abc_data')[4])
160
+ assert_equal('123abc_data', @st.prepend(0,'abc',0,Time.now.to_i,'123')[4])
161
+ assert_equal('123abc_data', @st.get(0,'abc',0))
162
+ end
163
+
164
+ def test_incr
165
+ assert_nil( @st.incr(0,'abc',0,1) )
166
+ assert_equal('100', @st.set(0,'abc',0,Time.now.to_i,'100')[4] )
167
+ assert_equal('101', @st.incr(0,'abc',0,1)[4])
168
+ assert_equal('106', @st.incr(0,'abc',0,5)[4])
169
+ assert_equal('100', @st.incr(0,'abc',0,-6)[4]) # 106 + (-6) = 100
170
+ assert_equal('0', @st.incr(0,'abc',0,-200)[4] ) # 100 + (-200) = 0
171
+ assert_equal('0', @st.incr(0,'abc',0,-200)[4] ) # 0 + (-200) = 0
172
+ # 最大値をセット
173
+ assert_equal('18446744073709551615', @st.set(0,'abc',0,Time.now.to_i,
174
+ '18446744073709551615')[4])
175
+ assert_equal('1', @st.incr(0,'abc',0,2)[4] ) # max + 2 = 1
176
+ end
177
+
178
+ def test_decr
179
+ assert_nil( @st.decr(0,'abc',0,1) )
180
+ assert_equal('100', @st.set(0,'abc',0,Time.now.to_i,'100')[4] )
181
+ assert_equal('99', @st.decr(0,'abc',0,1)[4])
182
+ assert_equal('94', @st.decr(0,'abc',0,5)[4])
183
+ assert_equal('100', @st.decr(0,'abc',0,-6)[4] ) # 94 - (-6) = 100
184
+ assert_equal('0', @st.decr(0,'abc',0,200)[4] ) # 100 - 200 = 0
185
+ assert_equal('0', @st.decr(0,'abc',0,200)[4] ) # 0 - 200 = 0
186
+ # 最大値をセット
187
+ assert_equal('18446744073709551615', @st.set(0,'abc',0,Time.now.to_i,
188
+ '18446744073709551615')[4])
189
+ assert_equal('2', @st.decr(0,'abc',0,-3)[4]) # max - (-2) = 2
190
+ end
191
+
192
+ def test_dump
193
+ assert_nil( @st.dump(0) ) # 最初は0件
194
+ @st.set(0,'abc',0,0xffffffff,'abc_data')
195
+ assert_equal(1, Marshal.load(@st.dump(0)).length )
196
+ @st.set(0,'def',0,0xffffffff,'def_data')
197
+ assert_equal(2, Marshal.load(@st.dump(0)).length )
198
+ assert_nil( @st.dump(1) ) # 異なるvnodeは0件
199
+
200
+ # 10万件いれてみる
201
+ n=@ndat
202
+ n.times{|i|
203
+ @st.set(2,i.to_s,0,0xffffffff,'abc_data')
204
+ }
205
+ assert_equal(n, Marshal.load(@st.dump(2)).length )
206
+ end
207
+
208
+ # 10万件程度
209
+ def test_volume
210
+ n=@ndat
211
+ n.times{|i|
212
+ @st.set(0,i.to_s,0,0xffffffff,'abc_data')
213
+ }
214
+ n.times{|i|
215
+ assert_equal('abc_data', @st.get(0,i.to_s,0))
216
+ }
217
+ n.times{|i|
218
+ assert_equal('abc_data', @st.delete(0,i.to_s,0)[4])
219
+ }
220
+ # 削除記録も含めた本当のレコード数
221
+ assert_equal(n, @st.true_length )
222
+ end
223
+
224
+ def test_clean_up
225
+ @st.each_clean_up_sleep = 0
226
+ n=@ndat
227
+ n.times{|i|
228
+ @st.set(0,i.to_s,0,0xffffffff,'abc_data')
229
+ }
230
+ # 指定時刻より以前 and 有効期限切れを削除
231
+ # 全てのデータは現在よりも以前だが、有効期限内なので0件
232
+ assert_equal(0, @st.clean_up(Time.now.to_i+100) )
233
+ # 10件を削除(削除は有効期限を0する)
234
+ 10.times{|i|
235
+ assert_equal('abc_data', @st.delete(0,i.to_s,0)[4])
236
+ }
237
+ assert_nil( @st.get(0,'0',0) )
238
+ assert_equal('abc_data', @st.get(0,'19',0) )
239
+ # 削除時刻よりも以前を指定すると、0件
240
+ assert_equal(0, @st.clean_up(Time.now.to_i-100) )
241
+ # 削除時刻よりも進ませると、10件
242
+ assert_equal(10, @st.clean_up(Time.now.to_i+100) )
243
+ # 残は n-10
244
+ assert_equal(n-10, Marshal.load(@st.dump(0)).length )
245
+ end
246
+
247
+ def test_each_clean_up
248
+ n=10
249
+
250
+ vnhash={}
251
+ n.times{|i|
252
+ n.times{|j|
253
+ @st.set(i,"key#{i}-#{j}",0,0xffffffff,"val#{i}-#{j}")
254
+ }
255
+ vnhash[i]=:primary
256
+ }
257
+ # ---------+------+---------------------
258
+ # last < now+100
259
+ # 全てのデータは現在よりも以前だが、有効期限内なので0件
260
+ @st.each_clean_up_sleep = 0
261
+ @st.each_clean_up(Time.now.to_i+100,vnhash){|k,vn|
262
+ puts "k=#{k} vn=#{vn}"
263
+ assert(false)
264
+ }
265
+
266
+ # vn=0 を10件削除
267
+ n.times{|i| @st.delete(0,"key0-#{i}",0) }
268
+ # 削除時刻よりも以前を指定すると、0件
269
+ @st.each_clean_up(Time.now.to_i-100,vnhash){|k,vn|
270
+ assert(false)
271
+ }
272
+
273
+ # 削除時刻よりも進ませると、10件
274
+ cnt=0
275
+ @st.each_clean_up(Time.now.to_i+100,vnhash){|k,vn|
276
+ assert_equal(0, vn)
277
+ assert_match(/key0-/, k )
278
+ cnt += 1
279
+ }
280
+ assert_equal(10,cnt )
281
+
282
+ # vn=1 を10件削除
283
+ n.times{|i| @st.delete(1,"key1-#{i}",0) }
284
+ # vn=1 をセカンダリとする
285
+ vnhash[1]=:secondary
286
+ # セカンダリは削除されないので、0件
287
+ @st.each_clean_up(Time.now.to_i-100,vnhash){|k,vn|
288
+ assert(false)
289
+ }
290
+ # vn=1 をプライマリに戻す
291
+ vnhash[1]=:primary
292
+ # 10件になる
293
+ cnt=0
294
+ @st.each_clean_up(Time.now.to_i+100,vnhash){|k,vn|
295
+ assert_equal(1, vn)
296
+ assert_match(/key1-/, k )
297
+ cnt += 1
298
+ }
299
+ assert_equal(10,cnt)
300
+
301
+ # 消すものが存在しないので、0件
302
+ @st.each_clean_up(Time.now.to_i-100,vnhash){|k,vn|
303
+ assert(false)
304
+ }
305
+
306
+ # vn=2 を担当から外す
307
+ vnhash.delete(2)
308
+ # vn=2 のデータは存在する
309
+ n.times{|i|
310
+ assert_match(/val2-/,@st.get(2,"key2-#{i}",0) )
311
+ }
312
+ # vn=2 の10件が削除される
313
+ cnt=0
314
+ @st.each_clean_up(Time.now.to_i+100,vnhash){|k,vn|
315
+ assert_equal(2, vn)
316
+ assert_match(/key2-/, k )
317
+ cnt += 1
318
+ }
319
+ assert_equal(10,cnt)
320
+ # vn=2 のデータは消えているはず
321
+ n.times{|i|
322
+ assert_nil( @st.get(2,"key2-#{i}",0) )
323
+ }
324
+
325
+ # vn=3 有効期限を 100秒前にする
326
+ n.times{|i|
327
+ @st.set(3,"key3-#{i}",0,Time.now.to_i-100,"val3-#{i}")
328
+ }
329
+ # 期限切れは last に関係なく削除されるので、10件
330
+ cnt=0
331
+ @st.each_clean_up(Time.now.to_i-100,vnhash){|k,vn|
332
+ assert_equal(3, vn)
333
+ assert_match(/key3-/, k )
334
+ cnt += 1
335
+ }
336
+ assert_equal(10,cnt)
337
+ end
338
+
339
+ # 途中で止めるテスト
340
+ def test_each_clean_up2
341
+ n=10
342
+
343
+ # テストデータを100件登録する
344
+ vnhash={}
345
+ n.times{|i|
346
+ n.times{|j|
347
+ @st.set(i,"key#{i}-#{j}",0,0xffffffff,"val#{i}-#{j}")
348
+ @st.delete(i,"key#{i}-#{j}",0)
349
+ }
350
+ vnhash[i]=:primary
351
+ }
352
+
353
+ # 10msec の wait で each する
354
+ cnt = 0
355
+ th = Thread.new{
356
+ @st.each_clean_up_sleep = 0.01
357
+ @st.each_clean_up(Time.now.to_i+100,vnhash){|k,vn|
358
+ cnt += 1
359
+ }
360
+ }
361
+ # 500msec 後に停止を指示
362
+ sleep 0.5
363
+ @st.stop_clean_up
364
+ th.join
365
+ # 途中で停止したので cnt は 100未満
366
+ assert_operator(100, :>, cnt)
367
+ # 残りを削除
368
+ @st.each_clean_up_sleep = 0
369
+ @st.each_clean_up(Time.now.to_i+100,vnhash){|k,vn|
370
+ cnt += 1
371
+ }
372
+ # 全件消えるので cnt は 100
373
+ assert_equal(100, cnt)
374
+ end
375
+
376
+ def test_dump_and_load
377
+ n=10
378
+ n.times{|i|
379
+ @st.set(0,i.to_s,0,0xffffffff,'abc_data')
380
+
381
+ }
382
+ assert_equal(0, @st.load(@st.dump(0)) ) # 同じ論理クロックはコピー件数 0 件
383
+
384
+ # 進んだ論理クロックのデータを n 件作成
385
+ h={}
386
+ n.times{|i|
387
+ h[i.to_s]=[0,Time.now.to_i,1,0xffffffff].pack('NNNN')+'new data'
388
+ }
389
+ dmp=Marshal.dump(h)
390
+
391
+ assert_equal(n, @st.load(dmp) ) # 進んだ論理クロックの n 件のみコピーされる
392
+ assert_equal('new data', @st.get(0,'0',0))
393
+ end
394
+
395
+ def test_dump_and_load2
396
+ n=10
397
+ n.times{|i|
398
+ assert_nil( @st.delete(0,i.to_s,0)[4] ) # データが存在しなくても削除記録を残す
399
+ }
400
+ dmp=@st.dump(0)
401
+ assert_equal(n, Marshal.load(dmp).length ) # 削除記録もダンプされる
402
+ assert_equal(0, @st.load(@st.dump(0)) ) # 同じデータの場合はコピー件数 0 件
403
+
404
+ # 遅れた論理クロックのデータを作成
405
+ h={}
406
+ n.times{|i|
407
+ h[i.to_s]=[0,Time.now.to_i,0xffffffff,0xffffffff].pack('NNNN')+'old data'
408
+ }
409
+ dmp=Marshal.dump(h)
410
+ assert_equal(0, @st.load(dmp) ) # 進んだ論理クロックの削除記録があるのでデータは上書きされない
411
+ assert_nil( @st.get(0,'0',0) )
412
+ end
413
+
414
+ # closedb 後のアクセスは NoMethodError が発生することを確認する
415
+ def test_close
416
+ @st.closedb
417
+
418
+ assert_raise NoMethodError do
419
+ @st.get(0,'abc',0)
420
+ end
421
+
422
+ assert_raise NoMethodError do
423
+ @st.set(0,'abc',0,0xffffffff,'abc_data')
424
+ end
425
+
426
+ assert_raise NoMethodError do
427
+ @st.dump(0)
428
+ end
429
+
430
+ h={}
431
+ 100.times{|i|
432
+ h[i.to_s]=[0,Time.now.to_i,0xffffffff,0xffffffff].pack('NNNN')+'old data'
433
+ }
434
+ dmp=Marshal.dump(h)
435
+
436
+ assert_raise NoMethodError do
437
+ @st.load(dmp)
438
+ end
439
+
440
+ # この場合は 0 件
441
+ assert_equal(0,@st.clean_up(Time.now.to_i+100) )
442
+
443
+ # clean_up 中に closedb をするテスト
444
+ #
445
+ # わざわざユニットテストを行う理由 => レアケースなだけにバグも発見しにくい。
446
+ #
447
+ # バッチによる clean_up 処理中に deletehash を行ったときこの状態になる。
448
+ # NoMethodError を判定した retry を保証するためテストを行う。
449
+ #
450
+ @st.opendb
451
+ h={}
452
+ 10.times{|i|
453
+ h[i.to_s]=[0,Time.now.to_i,0,Time.now.to_i].pack('NNNN')+'old data'
454
+ }
455
+ dmp=Marshal.dump(h)
456
+ @st.load(dmp)
457
+
458
+ # clean_up 中に closedb されると NoMethodError が発生する
459
+ assert_raise NoMethodError do
460
+ @st.clean_up(Time.now.to_i-10,true)
461
+ end
462
+
463
+ # 次のテストのために再度 open
464
+ @st.opendb
465
+ end
466
+
467
+ def test_dump_file
468
+ n=100
469
+ n.times{|i|
470
+ @st.set(0,"key#{i}",0,0x7fffffff,"val#{i}")
471
+ }
472
+ @st.dump_file('storage_test_dump')
473
+
474
+ count = 0
475
+ open("storage_test_dump/#{@st.hdiv[0]}.dump",'rb'){|f|
476
+ until(f.eof?)
477
+ b1 = f.read(5 * 4)
478
+ vn, last, clk, expt, klen = b1.unpack('NNNNN')
479
+ key = f.read(klen)
480
+ b2 = f.read(4)
481
+ vlen = b2.unpack('N')[0]
482
+ val = f.read(vlen)
483
+
484
+ count += 1
485
+ assert_equal('key',key[0..2])
486
+ assert_equal('val',val[0..2])
487
+ assert_equal(val[3..-1],key[3..-1] )
488
+ end
489
+ }
490
+ assert_equal(n,count)
491
+ rmtestdir('storage_test_dump')
492
+
493
+ @st.dump_file('storage_test_dump',{0=>0})
494
+ count = 0
495
+ open("storage_test_dump/#{@st.hdiv[0]}.dump",'rb'){|f|
496
+ until(f.eof?)
497
+ b1 = f.read(5 * 4)
498
+ vn, last, clk, expt, klen = b1.unpack('NNNNN')
499
+ key = f.read(klen)
500
+ b2 = f.read(4)
501
+ vlen = b2.unpack('N')[0]
502
+ val = f.read(vlen)
503
+
504
+ count += 1
505
+ assert_equal('key',key[0..2] )
506
+ assert_equal('val',val[0..2] )
507
+ assert_equal(val[3..-1],key[3..-1] )
508
+ end
509
+ }
510
+ assert_equal(0,count )
511
+ rmtestdir('storage_test_dump')
512
+ end
513
+
514
+ def test_each_vn_dump
515
+ n=100
516
+ n.times{|i|
517
+ @st.set(0,"key#{i}",0,0x7fffffff,"val#{i}")
518
+ }
519
+ (90..99).each{|i|
520
+ @st.delete(0, "key#{i}", 0)
521
+ }
522
+ count = 0
523
+ @st.each_vn_dump(0){|data|
524
+ vn, last, clk, expt, klen = data.slice!(0..19).unpack('NNNNN')
525
+ k = data.slice!(0..(klen-1))
526
+ vlen, = data.slice!(0..3).unpack('N')
527
+ v = data
528
+ count += 1
529
+ # puts "#{vn} #{last} #{clk} #{expt} #{klen} #{k} #{vlen} #{v}"
530
+ assert_equal('key',k[0..2])
531
+ assert_equal('val',v[0..2]) if k[3..-1].to_i < 90
532
+
533
+ assert_nil( @st.load_stream_dump(vn, last, clk, expt, k, v) )
534
+ @st.load_stream_dump(2, last, clk, expt, k, v)
535
+ }
536
+ assert_equal(100,count)
537
+
538
+ count = 0
539
+ @st.each_vn_dump(1){|data| count += 1 }
540
+ assert_equal(0,count )
541
+
542
+ count = 0
543
+ @st.each_vn_dump(2){|data| count += 1 }
544
+ assert_equal(100,count )
545
+ end
546
+
547
+ end
548
+
549
+ class DbmStorageTest < TCStorageTest
550
+ def setup
551
+ rmtestdir('storage_test')
552
+ @st=Roma::Storage::DbmStorage.new
553
+ @st.vn_list = [0]
554
+ @st.storage_path = 'storage_test'
555
+ @st.opendb
556
+ end
557
+
558
+ #undef test_each_clean_up
559
+ #undef test_each_clean_up2
560
+ end
561
+
562
+ class RubyHashStorageTest < TCStorageTest
563
+ def setup
564
+ @st=Roma::Storage::RubyHashStorage.new
565
+ @st.vn_list = [0]
566
+ @st.opendb
567
+ end
568
+
569
+ def teardown
570
+ end
571
+
572
+ def test_cmp_clk
573
+ (0x001E00000..0x002000000).each{|clk|
574
+ assert_equal(0, @st.send(:cmp_clk,clk, clk) )
575
+ }
576
+
577
+ (0x001E00000..0x002000000).each{|clk|
578
+ assert_operator(0,:>, @st.send(:cmp_clk,clk-1, clk) )
579
+ assert_operator(0,:<, @st.send(:cmp_clk,clk, clk-1) )
580
+ }
581
+
582
+ (0x001E00000..0x002000000).each{|clk|
583
+ assert_operator(0,:<, @st.send(:cmp_clk,clk+1, clk) )
584
+ assert_operator(0,:>, @st.send(:cmp_clk,clk, clk+1) )
585
+ }
586
+ # t1=0 t2=0 clk2=0b0000...
587
+ clk1=0x00000010
588
+ clk2=0x00000000
589
+ assert_operator(0,:<, @st.send(:cmp_clk,clk1, clk2) )
590
+ assert_operator(0,:>, @st.send(:cmp_clk,clk2, clk1) )
591
+ # t1=0 t2=1 clk2=0b0010...
592
+ clk2=0x20000000
593
+ assert_operator(0,:>, @st.send(:cmp_clk,clk1, clk2) )
594
+ assert_operator(0,:<, @st.send(:cmp_clk,clk2, clk1) )
595
+ # t1=0 t2=2 clk2=0b0100...
596
+ clk2=0x40000000
597
+ assert_operator(0, :>, @st.send(:cmp_clk,clk1, clk2) )
598
+ assert_operator(0, :<, @st.send(:cmp_clk,clk2, clk1) )
599
+ # t1=0 t2=3 clk2=0b0110...
600
+ clk2=0x60000000
601
+ assert_operator(0,:>, @st.send(:cmp_clk,clk1, clk2) )
602
+ assert_operator(0,:<, @st.send(:cmp_clk,clk2, clk1) )
603
+ # t1=0 t2=4 clk2=0b1000...
604
+ clk2=0x80000000
605
+ assert_operator(0,:>, @st.send(:cmp_clk,clk1, clk2) )
606
+ assert_operator(0,:<, @st.send(:cmp_clk,clk2, clk1) )
607
+
608
+ # t1=0 t2=5 clk2=0b1010...
609
+ clk2=0xa0000000
610
+ assert_operator(0,:<, @st.send(:cmp_clk,clk1, clk2) )
611
+ assert_operator(0,:>, @st.send(:cmp_clk,clk2, clk1) )
612
+ # t1=0 t2=6 clk2=0b1100...
613
+ clk2=0xc0000000
614
+ assert_operator(0,:<, @st.send(:cmp_clk,clk1, clk2))
615
+ assert_operator(0,:>, @st.send(:cmp_clk,clk2, clk1))
616
+ # t1=0 t2=7 clk2=0b1110...
617
+ clk2=0xe0000000
618
+ assert_operator(0,:<, @st.send(:cmp_clk,clk1, clk2) )
619
+ assert_operator(0,:>, @st.send(:cmp_clk,clk2, clk1) )
620
+ end
621
+
622
+ end
623
+
624
+ class SQLite3StorageTest < TCStorageTest
625
+ def setup
626
+ rmtestdir('storage_test')
627
+ @st=Roma::Storage::SQLite3Storage.new
628
+ @st.vn_list = [0]
629
+ @st.storage_path = 'storage_test'
630
+ @st.opendb
631
+ end
632
+
633
+ #undef test_out
634
+ end
635
+
636
+ class TCMemStorageTest < TCStorageTest
637
+ def setup
638
+ rmtestdir('storage_test')
639
+ @st=Roma::Storage::TCMemStorage.new
640
+ @st.vn_list = [0]
641
+ @st.storage_path = 'storage_test'
642
+ @st.opendb
643
+ end
644
+ end