roma 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
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