higgs 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/ChangeLog +208 -0
  2. data/LICENSE +26 -0
  3. data/README +2 -0
  4. data/Rakefile +75 -0
  5. data/bin/higgs_backup +67 -0
  6. data/bin/higgs_dump_index +43 -0
  7. data/bin/higgs_dump_jlog +42 -0
  8. data/bin/higgs_verify +37 -0
  9. data/lib/cgi/session/higgs.rb +72 -0
  10. data/lib/higgs/block.rb +192 -0
  11. data/lib/higgs/cache.rb +117 -0
  12. data/lib/higgs/dbm.rb +55 -0
  13. data/lib/higgs/exceptions.rb +31 -0
  14. data/lib/higgs/flock.rb +77 -0
  15. data/lib/higgs/index.rb +164 -0
  16. data/lib/higgs/jlog.rb +159 -0
  17. data/lib/higgs/lock.rb +189 -0
  18. data/lib/higgs/storage.rb +1086 -0
  19. data/lib/higgs/store.rb +228 -0
  20. data/lib/higgs/tar.rb +390 -0
  21. data/lib/higgs/thread.rb +370 -0
  22. data/lib/higgs/tman.rb +513 -0
  23. data/lib/higgs/utils/bman.rb +285 -0
  24. data/lib/higgs/utils.rb +22 -0
  25. data/lib/higgs/version.rb +21 -0
  26. data/lib/higgs.rb +59 -0
  27. data/misc/cache_bench/cache_bench.rb +43 -0
  28. data/misc/dbm_bench/.strc +8 -0
  29. data/misc/dbm_bench/Rakefile +78 -0
  30. data/misc/dbm_bench/dbm_multi_thread.rb +199 -0
  31. data/misc/dbm_bench/dbm_rnd_delete.rb +43 -0
  32. data/misc/dbm_bench/dbm_rnd_read.rb +44 -0
  33. data/misc/dbm_bench/dbm_rnd_update.rb +44 -0
  34. data/misc/dbm_bench/dbm_seq_read.rb +45 -0
  35. data/misc/dbm_bench/dbm_seq_write.rb +44 -0
  36. data/misc/dbm_bench/st_verify.rb +28 -0
  37. data/misc/io_bench/cksum_bench.rb +48 -0
  38. data/misc/io_bench/jlog_bench.rb +71 -0
  39. data/misc/io_bench/write_bench.rb +128 -0
  40. data/misc/thread_bench/lock_bench.rb +132 -0
  41. data/mkrdoc.rb +8 -0
  42. data/rdoc.yml +13 -0
  43. data/sample/count.rb +60 -0
  44. data/sample/dbmtest.rb +38 -0
  45. data/test/Rakefile +45 -0
  46. data/test/run.rb +32 -0
  47. data/test/test_block.rb +163 -0
  48. data/test/test_cache.rb +214 -0
  49. data/test/test_cgi_session.rb +142 -0
  50. data/test/test_flock.rb +162 -0
  51. data/test/test_index.rb +258 -0
  52. data/test/test_jlog.rb +180 -0
  53. data/test/test_lock.rb +320 -0
  54. data/test/test_online_backup.rb +169 -0
  55. data/test/test_storage.rb +439 -0
  56. data/test/test_storage_conf.rb +202 -0
  57. data/test/test_storage_init_opts.rb +89 -0
  58. data/test/test_store.rb +211 -0
  59. data/test/test_tar.rb +432 -0
  60. data/test/test_thread.rb +541 -0
  61. data/test/test_tman.rb +875 -0
  62. data/test/test_tman_init_opts.rb +56 -0
  63. data/test/test_utils_bman.rb +234 -0
  64. metadata +115 -0
data/test/test_tman.rb ADDED
@@ -0,0 +1,875 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ require 'fileutils'
4
+ require 'higgs/storage'
5
+ require 'higgs/thread'
6
+ require 'higgs/tman'
7
+ require 'test/unit'
8
+
9
+ module Higgs::Test
10
+ class TransactionManagerTest < Test::Unit::TestCase
11
+ include Higgs
12
+
13
+ # for ident(1)
14
+ CVS_ID = '$Id: test_tman.rb 559 2007-09-25 15:20:20Z toki $'
15
+
16
+ def setup
17
+ @test_dir = 'st_test'
18
+ FileUtils.rm_rf(@test_dir) # for debug
19
+ FileUtils.mkdir_p(@test_dir)
20
+ @name = File.join(@test_dir, 'foo')
21
+ @st = Storage.new(@name)
22
+ @tman = TransactionManager.new(@st)
23
+ end
24
+
25
+ def teardown
26
+ @st.shutdown unless @st.shutdown?
27
+ FileUtils.rm_rf(@test_dir) unless $DEBUG
28
+ end
29
+
30
+ def test_transaction
31
+ count = 0
32
+ @tman.transaction(false) {|tx|
33
+ assert_instance_of(Higgs::ReadWriteTransactionContext, tx)
34
+ count += 1
35
+ }
36
+ assert_equal(1, count)
37
+
38
+ count = 0
39
+ @tman.transaction(true) {|tx|
40
+ assert_instance_of(Higgs::ReadOnlyTransactionContext, tx)
41
+ count += 1
42
+ }
43
+ assert_equal(1, count)
44
+ end
45
+
46
+ def test_fetch_and_store
47
+ @tman.transaction{|tx|
48
+ assert_equal(nil, tx[:foo])
49
+ assert_equal(nil, tx[:bar])
50
+
51
+ tx[:foo] = 'apple'
52
+
53
+ assert_equal('apple', tx[:foo])
54
+ assert_equal(nil, tx[:bar])
55
+ }
56
+
57
+ assert_equal('apple', @st.fetch(:foo))
58
+
59
+ @tman.transaction{|tx|
60
+ assert_equal('apple', tx[:foo])
61
+ assert_equal(nil, tx[:bar])
62
+ }
63
+ end
64
+
65
+ def test_store_and_key
66
+ @tman.transaction{|tx|
67
+ assert_equal(false, (tx.key? :foo))
68
+ assert_equal(false, (tx.key? :bar))
69
+
70
+ tx[:foo] = 'apple'
71
+
72
+ assert_equal(true, (tx.key? :foo))
73
+ assert_equal(false, (tx.key? :bar))
74
+ }
75
+
76
+ assert_equal(true, (@st.key? :foo))
77
+
78
+ @tman.transaction{|tx|
79
+ assert_equal(true, (tx.key? :foo))
80
+ assert_equal(false, (tx.key? :bar))
81
+ }
82
+ end
83
+
84
+ def test_fetch_and_key
85
+ @tman.transaction{|tx|
86
+ tx[:foo] # load to cache
87
+ tx[:bar] # load to cache
88
+ assert_equal(false, (tx.key? :foo))
89
+ assert_equal(false, (tx.key? :bar))
90
+ }
91
+
92
+ assert_equal(false, (@st.key? :foo))
93
+ assert_equal(false, (@st.key? :bar))
94
+ end
95
+
96
+ def test_store_and_each_key
97
+ @tman.transaction{|tx|
98
+ tx.each_key do |key|
99
+ flunk('not to reach')
100
+ end
101
+
102
+ tx[:foo] = 'apple'
103
+ tx[:bar] = 'banana'
104
+ tx[:baz] = 'orange'
105
+
106
+ expected_keys = [ :foo, :bar, :baz ]
107
+ tx.each_key do |key|
108
+ assert_equal(expected_keys.delete(key), key)
109
+ end
110
+ assert(expected_keys.empty?)
111
+ }
112
+
113
+ expected_keys = [ :foo, :bar, :baz ]
114
+ @st.each_key do |key|
115
+ assert_equal(expected_keys.delete(key), key)
116
+ end
117
+ assert(expected_keys.empty?)
118
+
119
+ @tman.transaction{|tx|
120
+ expected_keys = [ :foo, :bar, :baz ]
121
+ tx.each_key do |key|
122
+ assert_equal(expected_keys.delete(key), key)
123
+ end
124
+ assert(expected_keys.empty?)
125
+ }
126
+ end
127
+
128
+ def test_fetch_and_each_key
129
+ @tman.transaction{|tx|
130
+ tx[:foo] = 'apple'
131
+ tx[:bar] = 'banana'
132
+ tx[:baz] = 'orange'
133
+ }
134
+
135
+ expected_keys = [ :foo, :bar, :baz ]
136
+ @st.each_key do |key|
137
+ assert_equal(expected_keys.delete(key), key)
138
+ end
139
+ assert(expected_keys.empty?)
140
+
141
+ @tman.transaction{|tx|
142
+ tx['alice'] # load to cache
143
+ tx['bob'] # load to cache
144
+
145
+ expected_keys = [ :foo, :bar, :baz ]
146
+ tx.each_key do |key|
147
+ assert_equal(expected_keys.delete(key), key)
148
+ end
149
+ assert(expected_keys.empty?)
150
+ }
151
+ end
152
+
153
+ def test_store_and_each_value
154
+ @tman.transaction{|tx|
155
+ tx.each_value do |value|
156
+ flunk('not to reach')
157
+ end
158
+
159
+ tx[:foo] = 'apple'
160
+ tx[:bar] = 'banana'
161
+ tx[:baz] = 'orange'
162
+
163
+ expected_values = %w[ apple banana orange ]
164
+ tx.each_value do |value|
165
+ assert_equal(expected_values.delete(value), value)
166
+ end
167
+ assert(expected_values.empty?)
168
+ }
169
+
170
+ @tman.transaction{|tx|
171
+ expected_values = %w[ apple banana orange ]
172
+ tx.each_value do |value|
173
+ assert_equal(expected_values.delete(value), value)
174
+ end
175
+ assert(expected_values.empty?)
176
+ }
177
+ end
178
+
179
+ def test_store_and_each_pair
180
+ @tman.transaction{|tx|
181
+ tx.each_pair do |key, value|
182
+ flunk('not to reach')
183
+ end
184
+
185
+ tx[:foo] = 'apple'
186
+ tx[:bar] = 'banana'
187
+ tx[:baz] = 'orange'
188
+
189
+ expected_pairs = [ [ :foo, 'apple' ], [ :bar, 'banana' ], [ :baz, 'orange' ] ]
190
+ tx.each_pair do |key, value|
191
+ assert_equal(expected_pairs.delete([ key, value ]), [ key, value ])
192
+ end
193
+ assert(expected_pairs.empty?)
194
+ }
195
+
196
+ @tman.transaction{|tx|
197
+ expected_pairs = [ [ :foo, 'apple' ], [ :bar, 'banana' ], [ :baz, 'orange' ] ]
198
+ tx.each_pair do |key, value|
199
+ assert_equal(expected_pairs.delete([ key, value ]), [ key, value ])
200
+ end
201
+ assert(expected_pairs.empty?)
202
+ }
203
+ end
204
+
205
+ def test_store_and_keys
206
+ @tman.transaction{|tx|
207
+ assert_equal([], tx.keys)
208
+ tx[:foo] = 'apple'
209
+ tx[:bar] = 'banana'
210
+ tx[:baz] = 'orange'
211
+ assert_equal([ :foo, :bar, :baz ].sort{|a, b| a.to_s <=> b.to_s },
212
+ tx.keys.sort{|a, b| a.to_s <=> b.to_s })
213
+ }
214
+
215
+ @tman.transaction{|tx|
216
+ assert_equal([ :foo, :bar, :baz ].sort{|a, b| a.to_s <=> b.to_s },
217
+ tx.keys.sort{|a, b| a.to_s <=> b.to_s })
218
+ }
219
+ end
220
+
221
+ def test_store_and_values
222
+ @tman.transaction{|tx|
223
+ assert_equal([], tx.values)
224
+ tx[:foo] = 'apple'
225
+ tx[:bar] = 'banana'
226
+ tx[:baz] = 'orange'
227
+ assert_equal(%w[ apple banana orange ].sort, tx.values.sort)
228
+ }
229
+
230
+ @tman.transaction{|tx|
231
+ assert_equal(%w[ apple banana orange ].sort, tx.values.sort)
232
+ }
233
+ end
234
+
235
+ def test_store_and_length
236
+ @tman.transaction{|tx|
237
+ assert_equal(0, tx.length)
238
+ tx[:foo] = 'apple'
239
+ tx[:bar] = 'banana'
240
+ tx[:baz] = 'orange'
241
+ assert_equal(3, tx.length)
242
+ }
243
+
244
+ @tman.transaction{|tx|
245
+ assert_equal(3, tx.length)
246
+ }
247
+ end
248
+
249
+ def test_store_and_empty
250
+ @tman.transaction{|tx|
251
+ assert_equal(true, tx.empty?)
252
+ tx[:foo] = 'apple'
253
+ assert_equal(false, tx.empty?)
254
+ }
255
+
256
+ @tman.transaction{|tx|
257
+ assert_equal(false, tx.empty?)
258
+ }
259
+ end
260
+
261
+ def test_store_and_delete
262
+ @tman.transaction{|tx|
263
+ assert_equal(nil, tx.delete(:foo))
264
+ assert_equal(nil, tx.delete(:bar))
265
+
266
+ tx[:foo] = 'apple'
267
+
268
+ assert_equal('apple', tx.delete(:foo))
269
+ assert_equal(nil, tx.delete(:bar))
270
+
271
+ assert_equal(nil, tx[:foo])
272
+ assert_equal(nil, tx[:bar])
273
+ }
274
+
275
+ assert_equal(nil, @st.fetch(:foo))
276
+ assert_equal(nil, @st.fetch(:bar))
277
+
278
+ @tman.transaction{|tx|
279
+ assert_equal(nil, tx.delete(:foo))
280
+ assert_equal(nil, tx.delete(:bar))
281
+
282
+ assert_equal(nil, tx[:foo])
283
+ assert_equal(nil, tx[:bar])
284
+ }
285
+ end
286
+
287
+ def test_delete_commited_data
288
+ @tman.transaction{|tx|
289
+ tx[:foo] = 'apple'
290
+ tx[:bar] = 'banana'
291
+ }
292
+
293
+ assert_equal('apple', @st.fetch(:foo))
294
+ assert_equal('banana', @st.fetch(:bar))
295
+
296
+ @tman.transaction{|tx|
297
+ assert_equal('apple', tx[:foo])
298
+ assert_equal('banana', tx[:bar])
299
+
300
+ assert_equal('apple', tx.delete(:foo))
301
+
302
+ assert_equal(nil, tx[:foo])
303
+ assert_equal('banana', tx[:bar])
304
+ }
305
+
306
+ assert_equal(nil, @st.fetch(:foo))
307
+ assert_equal('banana', @st.fetch(:bar))
308
+
309
+ @tman.transaction{|tx|
310
+ assert_equal(nil, tx[:foo])
311
+ assert_equal('banana', tx[:bar])
312
+ }
313
+ end
314
+
315
+ def test_store_and_delete_if
316
+ @tman.transaction{|tx|
317
+ tx[:foo] = 'apple'
318
+ tx[:bar] = 'banana'
319
+ tx[:baz] = 'orange'
320
+
321
+ tx.delete_if{|key, value|
322
+ key == :bar || value == 'orange'
323
+ }
324
+
325
+ assert_equal('apple', tx[:foo])
326
+ assert_equal(nil, tx[:bar])
327
+ assert_equal(nil, tx[:baz])
328
+ }
329
+
330
+ assert_equal('apple', @st.fetch(:foo))
331
+ assert_equal(nil, @st.fetch(:bar))
332
+ assert_equal(nil, @st.fetch(:baz))
333
+
334
+ @tman.transaction{|tx|
335
+ assert_equal('apple', tx[:foo])
336
+ assert_equal(nil, tx[:bar])
337
+ assert_equal(nil, tx[:baz])
338
+ }
339
+ end
340
+
341
+ def test_store_and_delete_if_with_keys
342
+ @tman.transaction{|tx|
343
+ tx[:foo] = 'apple'
344
+ tx[:bar] = 'banana'
345
+ tx[:baz] = 'orange'
346
+
347
+ tx.delete_if(:foo, :bar) {|key, value|
348
+ key == :bar || value == 'orange'
349
+ }
350
+
351
+ assert_equal('apple', tx[:foo])
352
+ assert_equal(nil, tx[:bar])
353
+ assert_equal('orange', tx[:baz])
354
+ }
355
+
356
+ assert_equal('apple', @st.fetch(:foo))
357
+ assert_equal(nil, @st.fetch(:bar))
358
+ assert_equal('orange', @st.fetch(:baz))
359
+
360
+ @tman.transaction{|tx|
361
+ assert_equal('apple', tx[:foo])
362
+ assert_equal(nil, tx[:bar])
363
+ assert_equal('orange', tx[:baz])
364
+ }
365
+ end
366
+
367
+ def test_store_and_clear
368
+ @tman.transaction{|tx|
369
+ tx[:foo] = 'apple'
370
+ tx[:bar] = 'banana'
371
+ tx[:baz] = 'orange'
372
+
373
+ tx.clear
374
+
375
+ assert_equal(nil, tx[:foo])
376
+ assert_equal(nil, tx[:bar])
377
+ assert_equal(nil, tx[:baz])
378
+ }
379
+
380
+ assert_equal(nil, @st.fetch(:foo))
381
+ assert_equal(nil, @st.fetch(:bar))
382
+ assert_equal(nil, @st.fetch(:baz))
383
+
384
+ @tman.transaction{|tx|
385
+ assert_equal(nil, tx[:foo])
386
+ assert_equal(nil, tx[:bar])
387
+ assert_equal(nil, tx[:baz])
388
+ }
389
+ end
390
+
391
+ def test_property
392
+ @tman.transaction{|tx|
393
+ tx[:foo] = 'apple'
394
+ tx.set_property(:foo, 'bar', 'banana')
395
+
396
+ assert_equal(nil, tx.property(:foo, :created_time))
397
+ assert_equal(nil, tx.property(:foo, :changed_time))
398
+ assert_equal(nil, tx.property(:foo, :modified_time))
399
+ assert_equal(nil, tx.property(:foo, :hash_type))
400
+ assert_equal(nil, tx.property(:foo, :hash_value))
401
+ assert_equal('banana', tx.property(:foo, 'bar'))
402
+ assert_equal(nil, tx.property(:foo, 'baz'))
403
+
404
+ tx.commit
405
+ assert_instance_of(Time, tx.property(:foo, :created_time))
406
+ assert_instance_of(Time, tx.property(:foo, :changed_time))
407
+ assert_instance_of(Time, tx.property(:foo, :modified_time))
408
+ assert_equal('MD5', tx.property(:foo, :hash_type))
409
+ assert_equal(Digest::MD5.hexdigest('apple'), tx.property(:foo, :hash_value))
410
+ assert_equal('banana', tx.property(:foo, 'bar'))
411
+
412
+ assert_equal(nil, tx.property(:bar, :created_time))
413
+ assert_equal(nil, tx.property(:bar, :changed_time))
414
+ assert_equal(nil, tx.property(:bar, :modified_time))
415
+ assert_equal(nil, tx.property(:bar, :hash_type))
416
+ assert_equal(nil, tx.property(:bar, :hash_value))
417
+ assert_equal(nil, tx.property(:bar, 'baz'))
418
+ }
419
+
420
+ assert_instance_of(Time, @st.fetch_properties(:foo)['system_properties']['created_time'])
421
+ assert_instance_of(Time, @st.fetch_properties(:foo)['system_properties']['changed_time'])
422
+ assert_instance_of(Time, @st.fetch_properties(:foo)['system_properties']['modified_time'])
423
+ assert_equal('MD5', @st.fetch_properties(:foo)['system_properties']['hash_type'])
424
+ assert_equal(Digest::MD5.hexdigest('apple'), @st.fetch_properties(:foo)['system_properties']['hash_value'])
425
+ assert_equal('banana', @st.fetch_properties(:foo)['custom_properties']['bar'])
426
+ assert_nil(@st.fetch_properties(:bar))
427
+
428
+ @tman.transaction{|tx|
429
+ assert_instance_of(Time, tx.property(:foo, :created_time))
430
+ assert_instance_of(Time, tx.property(:foo, :changed_time))
431
+ assert_instance_of(Time, tx.property(:foo, :modified_time))
432
+ assert_equal('MD5', tx.property(:foo, :hash_type))
433
+ assert_equal(Digest::MD5.hexdigest('apple'), tx.property(:foo, :hash_value))
434
+ assert_equal('banana', tx.property(:foo, 'bar'))
435
+
436
+ assert_equal(nil, tx.property(:bar, :created_time))
437
+ assert_equal(nil, tx.property(:bar, :changed_time))
438
+ assert_equal(nil, tx.property(:bar, :modified_time))
439
+ assert_equal(nil, tx.property(:bar, :hash_type))
440
+ assert_equal(nil, tx.property(:bar, :hash_value))
441
+ assert_equal(nil, tx.property(:bar, 'baz'))
442
+ }
443
+ end
444
+
445
+ def test_system_properties
446
+ @tman.transaction{|tx|
447
+ tx[:foo] = 'apple'
448
+ tx.commit
449
+
450
+ cre_time = tx.property(:foo, :created_time)
451
+ chg_time = tx.property(:foo, :changed_time)
452
+ mod_time = tx.property(:foo, :modified_time)
453
+
454
+ sleep(0.001)
455
+ tx[:foo] = 'banana'
456
+ tx.commit
457
+
458
+ assert_equal(cre_time, tx.property(:foo, :created_time))
459
+ assert_equal(chg_time, tx.property(:foo, :changed_time))
460
+ assert(tx.property(:foo, :modified_time) > mod_time)
461
+
462
+ mod_time2 = tx.property(:foo, :modified_time)
463
+ sleep(0.001)
464
+ tx.set_property(:foo, 'bar', 'orange')
465
+ tx.commit
466
+
467
+ assert_equal(cre_time, tx.property(:foo, :created_time))
468
+ assert(tx.property(:foo, :changed_time) > chg_time)
469
+ assert_equal(mod_time2, tx.property(:foo, :modified_time))
470
+ }
471
+ end
472
+
473
+ def test_string_only_property
474
+ @tman.transaction{|tx|
475
+ tx[:foo] = 'apple'
476
+ assert_equal(nil, tx.property(:foo, :string_only))
477
+
478
+ tx.commit
479
+ assert_equal(false, tx.property(:foo, :string_only))
480
+
481
+ tx.set_property(:foo, :string_only, true)
482
+ assert_equal(true, tx.property(:foo, :string_only))
483
+
484
+ tx.commit
485
+ assert_equal(true, tx.property(:foo, :string_only))
486
+ }
487
+
488
+ @tman.transaction{|tx|
489
+ tx[:bar] = 'banana'
490
+ assert_equal(nil, tx.property(:bar, :string_only))
491
+
492
+ tx.set_property(:bar, :string_only, true)
493
+ assert_equal(true, tx.property(:bar, :string_only))
494
+
495
+ tx.commit
496
+ assert_equal(true, tx.property(:bar, :string_only))
497
+ }
498
+ end
499
+
500
+ def test_has_property
501
+ @tman.transaction{|tx|
502
+ tx[:foo] = 'apple'
503
+ tx.set_property(:foo, 'bar', 'banana')
504
+
505
+ assert_equal(false, (tx.property? :foo, :created_time))
506
+ assert_equal(false, (tx.property? :foo, :changed_time))
507
+ assert_equal(false, (tx.property? :foo, :modified_time))
508
+ assert_equal(false, (tx.property? :foo, :hash_type))
509
+ assert_equal(false, (tx.property? :foo, :hash_value))
510
+ assert_equal(true, (tx.property? :foo, 'bar'))
511
+ assert_equal(false, (tx.property? :foo, 'baz'))
512
+
513
+ tx.commit
514
+ assert_equal(true, (tx.property? :foo, :created_time))
515
+ assert_equal(true, (tx.property? :foo, :changed_time))
516
+ assert_equal(true, (tx.property? :foo, :modified_time))
517
+ assert_equal(true, (tx.property? :foo, :hash_type))
518
+ assert_equal(true, (tx.property? :foo, :hash_value))
519
+ assert_equal(true, (tx.property? :foo, 'bar'))
520
+ assert_equal(false, (tx.property? :foo, 'baz'))
521
+
522
+ assert_equal(false, (tx.property? :bar, :created_time))
523
+ assert_equal(false, (tx.property? :bar, :changed_time))
524
+ assert_equal(false, (tx.property? :bar, :modified_time))
525
+ assert_equal(false, (tx.property? :bar, :hash_type))
526
+ assert_equal(false, (tx.property? :bar, :hash_value))
527
+ assert_equal(false, (tx.property? :bar, 'baz'))
528
+ }
529
+
530
+ @tman.transaction{|tx|
531
+ assert_equal(true, (tx.property? :foo, :created_time))
532
+ assert_equal(true, (tx.property? :foo, :changed_time))
533
+ assert_equal(true, (tx.property? :foo, :modified_time))
534
+ assert_equal(true, (tx.property? :foo, :hash_type))
535
+ assert_equal(true, (tx.property? :foo, :hash_value))
536
+ assert_equal(true, (tx.property? :foo, 'bar'))
537
+ assert_equal(false, (tx.property? :foo, 'baz'))
538
+
539
+ assert_equal(false, (tx.property? :bar, :created_time))
540
+ assert_equal(false, (tx.property? :bar, :changed_time))
541
+ assert_equal(false, (tx.property? :bar, :modified_time))
542
+ assert_equal(false, (tx.property? :bar, :hash_type))
543
+ assert_equal(false, (tx.property? :bar, :hash_value))
544
+ assert_equal(false, (tx.property? :bar, 'baz'))
545
+ }
546
+ end
547
+
548
+ def test_delete_property
549
+ @tman.transaction{|tx|
550
+ tx[:foo] = 'apple'
551
+ tx.set_property(:foo, 'bar', 'banana')
552
+ tx.set_property(:foo, 'baz', 'orange')
553
+ }
554
+
555
+ assert_equal('banana', @st.fetch_properties(:foo)['custom_properties']['bar'])
556
+ assert_equal('orange', @st.fetch_properties(:foo)['custom_properties']['baz'])
557
+
558
+ @tman.transaction{|tx|
559
+ assert_equal('banana', tx.property(:foo, 'bar'))
560
+ assert_equal(true, (tx.property? :foo, 'bar'))
561
+ assert_equal('orange', tx.property(:foo, 'baz'))
562
+ assert_equal(true, (tx.property? :foo, 'baz'))
563
+
564
+ assert_equal('banana', tx.delete_property(:foo, 'bar'))
565
+ assert_equal(nil, tx.delete_property(:foo, 'no_property'))
566
+
567
+ assert_equal(nil, tx.property(:foo, 'bar'))
568
+ assert_equal(false, (tx.property? :foo, 'bar'))
569
+ assert_equal('orange', tx.property(:foo, 'baz'))
570
+ assert_equal(true, (tx.property? :foo, 'baz'))
571
+ }
572
+
573
+ assert_equal(false, (@st.fetch_properties(:foo)['custom_properties'].key? 'bar'))
574
+ assert_equal('orange', @st.fetch_properties(:foo)['custom_properties']['baz'])
575
+
576
+ @tman.transaction{|tx|
577
+ assert_equal(nil, tx.property(:foo, 'bar'))
578
+ assert_equal(false, (tx.property? :foo, 'bar'))
579
+ assert_equal('orange', tx.property(:foo, 'baz'))
580
+ assert_equal(true, (tx.property? :foo, 'baz'))
581
+ }
582
+ end
583
+
584
+ def test_each_property
585
+ @tman.transaction{|tx|
586
+ tx[:foo] = 'apple'
587
+
588
+ tx.each_property(:foo) do |name, value|
589
+ flunk('not to reach')
590
+ end
591
+
592
+ tx.set_property(:foo, 'bar', 'banana')
593
+
594
+ assert_alist = [
595
+ [ 'bar', proc{|n, v| assert_equal('banana', v, "name: #{n}") } ]
596
+ ]
597
+ tx.each_property(:foo) do |name, value|
598
+ assert(assert_pair = assert_alist.assoc(name), "name: #{name}")
599
+ assert_pair[1].call(name, value)
600
+ assert_alist.delete(assert_pair)
601
+ end
602
+ assert(assert_alist.empty?)
603
+ }
604
+
605
+ @tman.transaction{|tx|
606
+ assert_alist = [
607
+ [ :created_time, proc{|n, v| assert_instance_of(Time, v, "name: #{n}") } ],
608
+ [ :changed_time, proc{|n, v| assert_instance_of(Time, v, "name: #{n}") } ],
609
+ [ :modified_time, proc{|n, v| assert_instance_of(Time, v, "name: #{n}") } ],
610
+ [ :hash_type, proc{|n, v| assert_equal('MD5', v, "name: #{n}") } ],
611
+ [ :hash_value, proc{|n, v| assert_equal(Digest::MD5.hexdigest('apple'), v, "name: #{n}") } ],
612
+ [ :string_only, proc{|n, v| assert_equal(false, v, "name: #{n}") } ],
613
+ [ 'bar', proc{|n, v| assert_equal('banana', v, "name: #{n}") } ]
614
+ ]
615
+ tx.each_property(:foo) do |name, value|
616
+ assert(assert_pair = assert_alist.assoc(name), "name: #{name}")
617
+ assert_pair[1].call(name, value)
618
+ assert_alist.delete(assert_pair)
619
+ end
620
+ assert(assert_alist.empty?)
621
+ }
622
+ end
623
+
624
+ def test_commit_and_rollback
625
+ @tman.transaction{|tx|
626
+ tx[:foo] = 'apple'
627
+ tx.commit
628
+
629
+ tx.delete(:foo)
630
+ tx[:bar] = 'banana'
631
+ tx[:baz] = 'orange'
632
+ tx.rollback
633
+
634
+ assert_equal('apple', tx[:foo])
635
+ assert_equal(nil, tx[:bar])
636
+ assert_equal(nil, tx[:baz])
637
+ }
638
+
639
+ assert_equal('apple', @st.fetch(:foo))
640
+ assert_equal(nil, @st.fetch(:bar))
641
+ assert_equal(nil, @st.fetch(:baz))
642
+
643
+ @tman.transaction{|tx|
644
+ assert_equal('apple', tx[:foo])
645
+ assert_equal(nil, tx[:bar])
646
+ assert_equal(nil, tx[:baz])
647
+ }
648
+ end
649
+
650
+ def test_read_only_transaction
651
+ @tman.transaction{|tx|
652
+ tx[:foo] = 'apple'
653
+ tx.set_property(:foo, 'bar', 'banana')
654
+ }
655
+
656
+ @tman.transaction(true) {|tx|
657
+ assert_equal('apple', tx[:foo])
658
+ assert_equal(true, (tx.key? :foo))
659
+ assert_equal([ [ :foo, 'apple' ] ], tx.to_a)
660
+ assert_equal([ :foo ], tx.keys)
661
+ assert_equal([ 'apple' ], tx.values)
662
+ assert_equal(1, tx.length)
663
+ assert_equal(false, tx.empty?)
664
+
665
+ assert_instance_of(Time, tx.property(:foo, :created_time))
666
+ assert_instance_of(Time, tx.property(:foo, :changed_time))
667
+ assert_instance_of(Time, tx.property(:foo, :modified_time))
668
+ assert_equal('MD5', tx.property(:foo, :hash_type))
669
+ assert_equal(Digest::MD5.hexdigest('apple'), tx.property(:foo, :hash_value))
670
+ assert_equal('banana', tx.property(:foo, 'bar'))
671
+
672
+ assert_equal(true, (tx.property? :foo, :created_time))
673
+ assert_equal(true, (tx.property? :foo, :changed_time))
674
+ assert_equal(true, (tx.property? :foo, :modified_time))
675
+ assert_equal(true, (tx.property? :foo, :hash_type))
676
+ assert_equal(true, (tx.property? :foo, :hash_value))
677
+ assert_equal(true, (tx.property? :foo, 'bar'))
678
+
679
+ assert_alist = [
680
+ [ :created_time, proc{|n, v| assert_instance_of(Time, v, "name: #{n}") } ],
681
+ [ :changed_time, proc{|n, v| assert_instance_of(Time, v, "name: #{n}") } ],
682
+ [ :modified_time, proc{|n, v| assert_instance_of(Time, v, "name: #{n}") } ],
683
+ [ :hash_type, proc{|n, v| assert_equal('MD5', v, "name: #{n}") } ],
684
+ [ :hash_value, proc{|n, v| assert_equal(Digest::MD5.hexdigest('apple'), v, "name: #{n}") } ],
685
+ [ :string_only, proc{|n, v| assert_equal(false, v, "name: #{n}") } ],
686
+ [ 'bar', proc{|n, v| assert_equal('banana', v, "name: #{n}") } ]
687
+ ]
688
+ tx.each_property(:foo) do |name, value|
689
+ assert(assert_pair = assert_alist.assoc(name), "name: #{name}")
690
+ assert_pair[1].call(name, value)
691
+ assert_alist.delete(assert_pair)
692
+ end
693
+ assert(assert_alist.empty?)
694
+
695
+ assert_raise(NoMethodError) { tx[:foo] = 'melon' }
696
+ assert_raise(NoMethodError) { tx.delete(:foo) }
697
+ assert_raise(NoMethodError) { tx.delete_if{|key, value| value == 'apple' } }
698
+ assert_raise(NoMethodError) { tx.set_property(:foo, 'baz', 'orange') }
699
+ assert_raise(NoMethodError) { tx.delete_property(:foo, 'bar') }
700
+ assert_raise(NoMethodError) { tx.clear }
701
+ assert_raise(NoMethodError) { tx.commit }
702
+ assert_raise(NoMethodError) { tx.rollback }
703
+ }
704
+ end
705
+
706
+ def test_read_only_manager
707
+ @tman.transaction{|tx|
708
+ tx[:foo] = 'apple'
709
+ tx.set_property(:foo, 'bar', 'banana')
710
+ }
711
+ @tman = nil
712
+
713
+ @tman = TransactionManager.new(@st, :read_only => true)
714
+ @tman.transaction{|tx|
715
+ assert_equal('apple', tx[:foo])
716
+ assert_equal(true, (tx.key? :foo))
717
+ assert_equal([ [ :foo, 'apple' ] ], tx.to_a)
718
+ assert_equal([ :foo ], tx.keys)
719
+ assert_equal([ 'apple' ], tx.values)
720
+ assert_equal(1, tx.length)
721
+ assert_equal(false, tx.empty?)
722
+
723
+ assert_instance_of(Time, tx.property(:foo, :created_time))
724
+ assert_instance_of(Time, tx.property(:foo, :changed_time))
725
+ assert_instance_of(Time, tx.property(:foo, :modified_time))
726
+ assert_equal('MD5', tx.property(:foo, :hash_type))
727
+ assert_equal(Digest::MD5.hexdigest('apple'), tx.property(:foo, :hash_value))
728
+ assert_equal('banana', tx.property(:foo, 'bar'))
729
+
730
+ assert_equal(true, (tx.property? :foo, :created_time))
731
+ assert_equal(true, (tx.property? :foo, :changed_time))
732
+ assert_equal(true, (tx.property? :foo, :modified_time))
733
+ assert_equal(true, (tx.property? :foo, :hash_type))
734
+ assert_equal(true, (tx.property? :foo, :hash_value))
735
+ assert_equal(true, (tx.property? :foo, 'bar'))
736
+
737
+ assert_alist = [
738
+ [ :created_time, proc{|n, v| assert_instance_of(Time, v, "name: #{n}") } ],
739
+ [ :changed_time, proc{|n, v| assert_instance_of(Time, v, "name: #{n}") } ],
740
+ [ :modified_time, proc{|n, v| assert_instance_of(Time, v, "name: #{n}") } ],
741
+ [ :hash_type, proc{|n, v| assert_equal('MD5', v, "name: #{n}") } ],
742
+ [ :hash_value, proc{|n, v| assert_equal(Digest::MD5.hexdigest('apple'), v, "name: #{n}") } ],
743
+ [ :string_only, proc{|n, v| assert_equal(false, v, "name: #{n}") } ],
744
+ [ 'bar', proc{|n, v| assert_equal('banana', v, "name: #{n}") } ]
745
+ ]
746
+ tx.each_property(:foo) do |name, value|
747
+ assert(assert_pair = assert_alist.assoc(name), "name: #{name}")
748
+ assert_pair[1].call(name, value)
749
+ assert_alist.delete(assert_pair)
750
+ end
751
+ assert(assert_alist.empty?)
752
+
753
+ assert_raise(NoMethodError) { tx[:foo] = 'melon' }
754
+ assert_raise(NoMethodError) { tx.delete(:foo) }
755
+ assert_raise(NoMethodError) { tx.delete_if{|key, value| value == 'apple' } }
756
+ assert_raise(NoMethodError) { tx.set_property(:foo, 'baz', 'orange') }
757
+ assert_raise(NoMethodError) { tx.delete_property(:foo, 'bar') }
758
+ assert_raise(NoMethodError) { tx.clear }
759
+ assert_raise(NoMethodError) { tx.commit }
760
+ assert_raise(NoMethodError) { tx.rollback }
761
+ }
762
+
763
+ assert_raise(TransactionManager::NotWritableError) {
764
+ @tman.transaction(false) {|tx|
765
+ flunk('not to reach')
766
+ }
767
+ }
768
+ end
769
+
770
+ def test_giant_lock_manager
771
+ @tman = TransactionManager.new(@st, :lock_manager => GiantLockManager.new)
772
+ @tman.transaction{|tx|
773
+ tx[:foo] = '0'
774
+ tx[:bar] = '0'
775
+ tx[:baz] = '0'
776
+ }
777
+
778
+ count = 100
779
+ barrier = Barrier.new(3)
780
+
781
+ a = Thread.new{
782
+ barrier.wait
783
+ count.times do
784
+ @tman.transaction{|tx|
785
+ tx[:foo] = tx[:foo].succ
786
+ tx[:bar] = tx[:bar].succ
787
+ }
788
+ end
789
+ }
790
+
791
+ b = Thread.new{
792
+ barrier.wait
793
+ count.times do
794
+ @tman.transaction{|tx|
795
+ tx[:bar] = tx[:bar].succ
796
+ tx[:baz] = tx[:baz].succ
797
+ }
798
+ end
799
+ }
800
+
801
+ barrier.wait
802
+ a.join
803
+ b.join
804
+
805
+ @tman.transaction(true) {|tx|
806
+ assert_equal(count.to_s, tx[:foo])
807
+ assert_equal((count * 2).to_s, tx[:bar])
808
+ assert_equal(count.to_s, tx[:baz])
809
+ }
810
+ end
811
+
812
+ def test_fine_grain_lock_manager
813
+ @tman = TransactionManager.new(@st, :lock_manager => FineGrainLockManager.new)
814
+ @tman.transaction{|tx|
815
+ tx[:foo] = '0'
816
+ tx[:bar] = '0'
817
+ tx[:baz] = '0'
818
+ }
819
+
820
+ count = 100
821
+ barrier = Barrier.new(3)
822
+
823
+ a = Thread.new{
824
+ barrier.wait
825
+ count.times do
826
+ @tman.transaction{|tx|
827
+ tx[:foo] = tx[:foo].succ
828
+ tx[:bar] = tx[:bar].succ
829
+ }
830
+ end
831
+ }
832
+
833
+ b = Thread.new{
834
+ barrier.wait
835
+ count.times do
836
+ @tman.transaction{|tx|
837
+ tx[:bar] = tx[:bar].succ
838
+ tx[:baz] = tx[:baz].succ
839
+ }
840
+ end
841
+ }
842
+
843
+ barrier.wait
844
+ a.join
845
+ b.join
846
+
847
+ @tman.transaction(true) {|tx|
848
+ assert_equal(count.to_s, tx[:foo])
849
+ assert_equal((count * 2).to_s, tx[:bar])
850
+ assert_equal(count.to_s, tx[:baz])
851
+ }
852
+ end
853
+ end
854
+
855
+ class TransactionManagerTest_with_SecondaryCache < TransactionManagerTest
856
+ # for ident(1)
857
+ CVS_ID = '$Id: test_tman.rb 559 2007-09-25 15:20:20Z toki $'
858
+
859
+ def setup
860
+ super
861
+ @secondary_cache = {}
862
+ @tman = TransactionManager.new(@st, :secondary_cache => @secondary_cache)
863
+ end
864
+
865
+ # def teardown
866
+ # require 'pp'
867
+ # pp @secondary_cache
868
+ # end
869
+ end
870
+ end
871
+
872
+ # Local Variables:
873
+ # mode: Ruby
874
+ # indent-tabs-mode: nil
875
+ # End: