higgs 0.1.5 → 0.1.6
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/ChangeLog +67 -0
- data/bin/higgs_apply_jlog +1 -1
- data/bin/higgs_backup +1 -1
- data/bin/higgs_dump_index +1 -1
- data/bin/higgs_dump_jlog +1 -1
- data/bin/higgs_ping +1 -1
- data/bin/higgs_verify +1 -1
- data/lib/cgi/session/higgs.rb +3 -3
- data/lib/higgs/block.rb +3 -3
- data/lib/higgs/cache.rb +17 -13
- data/lib/higgs/dbm.rb +3 -3
- data/lib/higgs/exceptions.rb +3 -3
- data/lib/higgs/flock.rb +3 -3
- data/lib/higgs/index.rb +35 -17
- data/lib/higgs/jlog.rb +3 -3
- data/lib/higgs/lock.rb +5 -5
- data/lib/higgs/services.rb +3 -3
- data/lib/higgs/sman.rb +7 -3
- data/lib/higgs/storage.rb +14 -3
- data/lib/higgs/store.rb +3 -3
- data/lib/higgs/tar.rb +3 -3
- data/lib/higgs/thread.rb +130 -8
- data/lib/higgs/tman.rb +15 -13
- data/lib/higgs/utils/bman.rb +3 -3
- data/lib/higgs/utils.rb +3 -3
- data/lib/higgs/version.rb +4 -4
- data/lib/higgs.rb +2 -2
- data/misc/cache_bench/cache_bench.rb +2 -2
- data/misc/dbm_bench/.strc +1 -1
- data/misc/dbm_bench/Rakefile +1 -1
- data/misc/dbm_bench/dbm_multi_thread.rb +2 -2
- data/misc/dbm_bench/dbm_rnd_delete.rb +2 -2
- data/misc/dbm_bench/dbm_rnd_read.rb +2 -2
- data/misc/dbm_bench/dbm_rnd_update.rb +2 -2
- data/misc/dbm_bench/dbm_seq_read.rb +2 -2
- data/misc/dbm_bench/dbm_seq_write.rb +2 -2
- data/misc/dbm_bench/run.rb +52 -0
- data/misc/dbm_bench/st_verify.rb +2 -2
- data/misc/io_bench/cksum_bench.rb +1 -1
- data/misc/io_bench/jlog_bench.rb +2 -2
- data/misc/io_bench/write_bench.rb +1 -1
- data/misc/thread_bench/lock_bench.rb +2 -2
- data/test/Rakefile +1 -1
- data/test/run.rb +3 -3
- data/test/test_block.rb +1 -1
- data/test/test_cache.rb +9 -9
- data/test/test_cache_mvcc.rb +403 -168
- data/test/test_cgi_session.rb +3 -3
- data/test/test_dbm.rb +14 -5
- data/test/test_flock.rb +1 -1
- data/test/test_index.rb +5 -7
- data/test/test_jlog.rb +1 -1
- data/test/test_lock.rb +21 -21
- data/test/test_online_backup.rb +1 -1
- data/test/test_services.rb +1 -1
- data/test/test_storage.rb +4 -4
- data/test/test_storage_conf.rb +1 -1
- data/test/test_storage_init_opts.rb +1 -1
- data/test/test_store.rb +2 -2
- data/test/test_tar.rb +19 -19
- data/test/test_thread.rb +46 -46
- data/test/test_tman.rb +2 -2
- data/test/test_tman_init_opts.rb +1 -1
- data/test/test_tman_mvcc.rb +11 -11
- data/test/test_utils_bman.rb +4 -2
- metadata +10 -18
- data/Rakefile +0 -81
- data/mkrdoc.rb +0 -11
- data/rdoc.yml +0 -13
data/test/test_cache_mvcc.rb
CHANGED
@@ -14,29 +14,28 @@ module Higgs::Test
|
|
14
14
|
include Higgs
|
15
15
|
|
16
16
|
# for ident(1)
|
17
|
-
CVS_ID = '$Id: test_cache_mvcc.rb
|
17
|
+
CVS_ID = '$Id: test_cache_mvcc.rb 781 2008-07-28 15:13:27Z toki $'
|
18
18
|
|
19
19
|
NUM_OF_THREADS = 10
|
20
|
-
WORK_COUNT =
|
20
|
+
WORK_COUNT = 1000
|
21
21
|
|
22
22
|
def setup
|
23
|
-
srand(0)
|
23
|
+
srand(0) # prset for rand
|
24
24
|
@cache = MVCCCache.new
|
25
25
|
end
|
26
26
|
|
27
27
|
def test_many_transaction
|
28
28
|
assert(@cache.empty?)
|
29
29
|
|
30
|
-
|
30
|
+
cnum_func = proc{ rand(100) }
|
31
31
|
barrier = Higgs::Barrier.new(NUM_OF_THREADS + 1)
|
32
|
-
|
32
|
+
th_list = []
|
33
33
|
|
34
34
|
NUM_OF_THREADS.times{|i|
|
35
|
-
|
35
|
+
th_list << Thread.new{
|
36
36
|
barrier.wait
|
37
37
|
WORK_COUNT.times do
|
38
|
-
|
39
|
-
@cache.transaction(cnum) {
|
38
|
+
@cache.transaction(cnum_func) {
|
40
39
|
assert(! @cache.empty?, "#thread: {i}th")
|
41
40
|
}
|
42
41
|
end
|
@@ -44,7 +43,7 @@ module Higgs::Test
|
|
44
43
|
}
|
45
44
|
|
46
45
|
barrier.wait
|
47
|
-
for t in
|
46
|
+
for t in th_list
|
48
47
|
t.join
|
49
48
|
end
|
50
49
|
|
@@ -55,20 +54,20 @@ module Higgs::Test
|
|
55
54
|
|
56
55
|
class RunFlag
|
57
56
|
def initialize(running)
|
58
|
-
|
57
|
+
@lock = Mutex.new
|
59
58
|
@running = running
|
60
59
|
end
|
61
60
|
|
62
61
|
def running=(running)
|
63
|
-
|
64
|
-
|
65
|
-
|
62
|
+
@lock.synchronize{
|
63
|
+
@running = running
|
64
|
+
}
|
66
65
|
end
|
67
66
|
|
68
67
|
def running?
|
69
|
-
|
70
|
-
|
71
|
-
|
68
|
+
@lock.synchronize{
|
69
|
+
@running
|
70
|
+
}
|
72
71
|
end
|
73
72
|
end
|
74
73
|
|
@@ -91,11 +90,18 @@ module Higgs::Test
|
|
91
90
|
store = {}
|
92
91
|
do_read = RunFlag.new(true)
|
93
92
|
|
93
|
+
cnum = 0
|
94
|
+
cnum_func = proc{
|
95
|
+
last_cnum = cnum
|
96
|
+
cnum += 1
|
97
|
+
last_cnum
|
98
|
+
}
|
99
|
+
|
94
100
|
# change number: 0
|
95
101
|
init_read_latch = Latch.new
|
96
102
|
init_read_count = Count.new
|
97
103
|
init_read_thread = Thread.new{
|
98
|
-
@cache.transaction(
|
104
|
+
@cache.transaction(cnum_func) {|snapshot|
|
99
105
|
while (do_read.running?)
|
100
106
|
p [ 0, snapshot ] if $DEBUG
|
101
107
|
assert_equal([], snapshot.keys(store))
|
@@ -116,7 +122,7 @@ module Higgs::Test
|
|
116
122
|
insert_read_latch = Latch.new
|
117
123
|
insert_read_count = Count.new
|
118
124
|
insert_read_thread = Thread.new{
|
119
|
-
@cache.transaction(
|
125
|
+
@cache.transaction(cnum_func) {|snapshot|
|
120
126
|
while (do_read.running?)
|
121
127
|
p [ 1, snapshot ] if $DEBUG
|
122
128
|
assert_equal([ :foo ], snapshot.keys(store))
|
@@ -137,7 +143,7 @@ module Higgs::Test
|
|
137
143
|
update_read_latch = Latch.new
|
138
144
|
update_read_count = Count.new
|
139
145
|
update_read_thread = Thread.new{
|
140
|
-
@cache.transaction(
|
146
|
+
@cache.transaction(cnum_func) {|snapshot|
|
141
147
|
while (do_read.running?)
|
142
148
|
p [ 2, snapshot ] if $DEBUG
|
143
149
|
assert_equal([ :foo ], snapshot.keys(store))
|
@@ -158,7 +164,7 @@ module Higgs::Test
|
|
158
164
|
delete_read_latch = Latch.new
|
159
165
|
delete_read_count = Count.new
|
160
166
|
delete_read_thread = Thread.new{
|
161
|
-
@cache.transaction(
|
167
|
+
@cache.transaction(cnum_func) {|snapshot|
|
162
168
|
while (do_read.running?)
|
163
169
|
p [ 3, snapshot ] if $DEBUG
|
164
170
|
assert_equal([], snapshot.keys(store))
|
@@ -197,13 +203,236 @@ module Higgs::Test
|
|
197
203
|
end
|
198
204
|
end
|
199
205
|
|
206
|
+
class MVCCCacheWithHashTest < Test::Unit::TestCase
|
207
|
+
include Higgs
|
208
|
+
|
209
|
+
# for ident(1)
|
210
|
+
CVS_ID = '$Id: test_cache_mvcc.rb 781 2008-07-28 15:13:27Z toki $'
|
211
|
+
|
212
|
+
def setup
|
213
|
+
srand(0) # preset for rand
|
214
|
+
@cache = MVCCCache.new
|
215
|
+
|
216
|
+
@st = {}
|
217
|
+
class << @st
|
218
|
+
include Higgs::Synchronized
|
219
|
+
synchronized :[], :[]=, :delete
|
220
|
+
synchronized :key?, :keys, :each_key
|
221
|
+
end
|
222
|
+
@st.__lock__ = Mutex.new
|
223
|
+
|
224
|
+
@cnum = 0
|
225
|
+
@cn_lock = Mutex.new
|
226
|
+
@cnum_func = proc{
|
227
|
+
@cn_lock.synchronize{ @cnum }
|
228
|
+
}
|
229
|
+
end
|
230
|
+
|
231
|
+
def update_cnum
|
232
|
+
@cn_lock.synchronize{
|
233
|
+
@cnum += 1
|
234
|
+
}
|
235
|
+
end
|
236
|
+
private :update_cnum
|
237
|
+
|
238
|
+
class RunFlag
|
239
|
+
def initialize(running)
|
240
|
+
@lock = Mutex.new
|
241
|
+
@running = running
|
242
|
+
end
|
243
|
+
|
244
|
+
def running=(running)
|
245
|
+
@lock.synchronize{
|
246
|
+
@running = running
|
247
|
+
}
|
248
|
+
end
|
249
|
+
|
250
|
+
def running?
|
251
|
+
@lock.synchronize{
|
252
|
+
@running
|
253
|
+
}
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
NUM_OF_READ_THREADS = 10
|
258
|
+
NUM_OF_DATA_CHUNK = 100
|
259
|
+
HEAT_RUN_TIME = 60
|
260
|
+
STORAGE_ITEMS = 1000
|
261
|
+
MAX_ITEM_BYTES = 1024*5
|
262
|
+
ITEM_CHARS = ('A'..'Z').to_a + ('a'..'z').to_a
|
263
|
+
|
264
|
+
def update_storage
|
265
|
+
NUM_OF_DATA_CHUNK.times do
|
266
|
+
write_list = []
|
267
|
+
ope = [ :write, :delete ][rand(2)]
|
268
|
+
key = rand(STORAGE_ITEMS)
|
269
|
+
case (ope)
|
270
|
+
when :write
|
271
|
+
value = rand(256).chr * rand(MAX_ITEM_BYTES)
|
272
|
+
write_list << [ ope, key, value ]
|
273
|
+
when :delete
|
274
|
+
next unless (@st.key? key)
|
275
|
+
write_list << [ ope, key ]
|
276
|
+
else
|
277
|
+
raise "unknown operation: #{ope}"
|
278
|
+
end
|
279
|
+
|
280
|
+
if (block_given?) then
|
281
|
+
old_values = []
|
282
|
+
for ope, key, value in write_list
|
283
|
+
case (ope)
|
284
|
+
when :write
|
285
|
+
if (@st.key? key) then
|
286
|
+
old_values << [ :value, key, :data, @st[key] ]
|
287
|
+
else
|
288
|
+
old_values << [ :none, key ]
|
289
|
+
end
|
290
|
+
when :delete
|
291
|
+
if (@st.key? key) then
|
292
|
+
old_values << [ :value, key, :data, @st[key] ]
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
yield(old_values)
|
297
|
+
end
|
298
|
+
|
299
|
+
for ope, key, value in write_list
|
300
|
+
case (ope)
|
301
|
+
when :write
|
302
|
+
@st[key] = value
|
303
|
+
when :delete
|
304
|
+
@st.delete(key)
|
305
|
+
else
|
306
|
+
raise "unknown operation: #{ope}"
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
private :update_storage
|
312
|
+
|
313
|
+
def test_mvcc_random_write
|
314
|
+
do_read = RunFlag.new(true)
|
315
|
+
update_storage{ @cnum_func.call }
|
316
|
+
|
317
|
+
init_cnum = @cnum_func.call
|
318
|
+
init_cnum_func = proc{ init_cnum }
|
319
|
+
init_keys = @st.keys.sort
|
320
|
+
init_values = {}
|
321
|
+
for key in init_keys
|
322
|
+
init_values[key] = @st[key]
|
323
|
+
end
|
324
|
+
|
325
|
+
th_read_list = []
|
326
|
+
read_start_latch = CountDownLatch.new(NUM_OF_READ_THREADS)
|
327
|
+
NUM_OF_READ_THREADS.times{|i| # `i' should be local scope of thread block
|
328
|
+
th_read_list << Thread.new{
|
329
|
+
@cache.transaction(init_cnum_func) {|snapshot|
|
330
|
+
read_start_latch.count_down
|
331
|
+
|
332
|
+
while (do_read.running?)
|
333
|
+
assert_equal(init_keys, snapshot.keys(@st).sort, "keys at thread:#{i}")
|
334
|
+
STORAGE_ITEMS.times do |k|
|
335
|
+
assert_equal((init_values.key? k),
|
336
|
+
(snapshot.key? @st, k), "thread: #{i}, key: #{k}")
|
337
|
+
assert_equal(init_values[k],
|
338
|
+
snapshot.fetch(k, :data) { @st[k] }, "thread: #{i}, key: #{k}")
|
339
|
+
end
|
340
|
+
end
|
341
|
+
}
|
342
|
+
}
|
343
|
+
}
|
344
|
+
read_start_latch.wait
|
345
|
+
|
346
|
+
t0 = Time.now
|
347
|
+
while (Time.now - t0 < HEAT_RUN_TIME)
|
348
|
+
update_storage{|write_list|
|
349
|
+
update_cnum
|
350
|
+
@cache.write_old_values(@cnum_func.call, write_list)
|
351
|
+
}
|
352
|
+
end
|
353
|
+
|
354
|
+
sleep(HEAT_RUN_TIME)
|
355
|
+
do_read.running = false
|
356
|
+
for t in th_read_list
|
357
|
+
t.join
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
WORK_COUNT = 100
|
362
|
+
NUM_OF_READ_WRITE_THREADS = 10
|
363
|
+
|
364
|
+
def test_mvcc_frequency_update
|
365
|
+
do_read = RunFlag.new(true)
|
366
|
+
write_lock = Mutex.new
|
367
|
+
|
368
|
+
th_read_list = []
|
369
|
+
read_start_latch = CountDownLatch.new(NUM_OF_READ_WRITE_THREADS)
|
370
|
+
NUM_OF_READ_WRITE_THREADS.times{|i| # `i' should be local scope of thread block
|
371
|
+
th_read_list << Thread.new{
|
372
|
+
read_start_latch.count_down
|
373
|
+
|
374
|
+
while (do_read.running?)
|
375
|
+
@cache.transaction(@cnum_func) {|snapshot|
|
376
|
+
if (snapshot.change_number > 0) then
|
377
|
+
assert_equal(snapshot.change_number.to_s,
|
378
|
+
snapshot.fetch(:foo, :data) { @st[:foo] }, "thread: #{i}")
|
379
|
+
else
|
380
|
+
assert_nil(snapshot.fetch(:foo, :data) { @st[:foo] }, "thread: #{i}")
|
381
|
+
end
|
382
|
+
}
|
383
|
+
end
|
384
|
+
}
|
385
|
+
}
|
386
|
+
read_start_latch.wait
|
387
|
+
|
388
|
+
th_write_list = []
|
389
|
+
write_start_latch = CountDownLatch.new(NUM_OF_READ_WRITE_THREADS)
|
390
|
+
NUM_OF_READ_WRITE_THREADS.times{|i| # `i' should be local scope of thread block
|
391
|
+
th_write_list << Thread.new{
|
392
|
+
write_start_latch.count_down
|
393
|
+
|
394
|
+
WORK_COUNT.times do |j|
|
395
|
+
write_lock.synchronize{
|
396
|
+
@cache.transaction(@cnum_func) {|snapshot|
|
397
|
+
value = snapshot.fetch(:foo, :data) { @st[:foo] }
|
398
|
+
if (snapshot.change_number > 0) then
|
399
|
+
assert_equal(snapshot.change_number.to_s, value, "thread: #{i}-#{j}")
|
400
|
+
else
|
401
|
+
assert_nil(value, "thread: #{i}-#{j}")
|
402
|
+
end
|
403
|
+
|
404
|
+
next_value = (value || '0').succ
|
405
|
+
|
406
|
+
snapshot.write_old_values([ [ :value, :foo, :data, value ] ])
|
407
|
+
@st[:foo] = next_value
|
408
|
+
update_cnum
|
409
|
+
}
|
410
|
+
}
|
411
|
+
end
|
412
|
+
}
|
413
|
+
}
|
414
|
+
write_start_latch.wait
|
415
|
+
|
416
|
+
for t in th_write_list
|
417
|
+
t.join
|
418
|
+
end
|
419
|
+
|
420
|
+
do_read.running = false
|
421
|
+
for t in th_read_list
|
422
|
+
t.join
|
423
|
+
end
|
424
|
+
|
425
|
+
assert_equal((NUM_OF_READ_WRITE_THREADS * WORK_COUNT).to_s, @st[:foo])
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
200
429
|
class MVCCCacheWithStorageTest < Test::Unit::TestCase
|
201
430
|
include Higgs
|
202
431
|
|
203
432
|
# for ident(1)
|
204
|
-
CVS_ID = '$Id: test_cache_mvcc.rb
|
433
|
+
CVS_ID = '$Id: test_cache_mvcc.rb 781 2008-07-28 15:13:27Z toki $'
|
205
434
|
|
206
|
-
def setup
|
435
|
+
def setup # preset for rand
|
207
436
|
srand(0)
|
208
437
|
@cache = MVCCCache.new
|
209
438
|
|
@@ -212,9 +441,9 @@ module Higgs::Test
|
|
212
441
|
FileUtils.mkdir_p(@test_dir)
|
213
442
|
@name = File.join(@test_dir, 'foo')
|
214
443
|
@logger = proc{|path|
|
215
|
-
|
216
|
-
|
217
|
-
|
444
|
+
logger = Logger.new(path, 1)
|
445
|
+
logger.level = Logger::DEBUG
|
446
|
+
logger
|
218
447
|
}
|
219
448
|
@st = Storage.new(@name, :logger => @logger)
|
220
449
|
end
|
@@ -226,20 +455,20 @@ module Higgs::Test
|
|
226
455
|
|
227
456
|
class RunFlag
|
228
457
|
def initialize(running)
|
229
|
-
|
458
|
+
@lock = Mutex.new
|
230
459
|
@running = running
|
231
460
|
end
|
232
461
|
|
233
462
|
def running=(running)
|
234
|
-
|
235
|
-
|
236
|
-
|
463
|
+
@lock.synchronize{
|
464
|
+
@running = running
|
465
|
+
}
|
237
466
|
end
|
238
467
|
|
239
468
|
def running?
|
240
|
-
|
241
|
-
|
242
|
-
|
469
|
+
@lock.synchronize{
|
470
|
+
@running
|
471
|
+
}
|
243
472
|
end
|
244
473
|
end
|
245
474
|
|
@@ -252,65 +481,65 @@ module Higgs::Test
|
|
252
481
|
|
253
482
|
def update_storage
|
254
483
|
NUM_OF_DATA_CHUNK.times do
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
484
|
+
write_list = []
|
485
|
+
ope = [ :write, :system_properties, :custom_properties, :delete ][rand(4)]
|
486
|
+
key = rand(STORAGE_ITEMS)
|
487
|
+
case (ope)
|
488
|
+
when :write
|
489
|
+
value = rand(256).chr * rand(MAX_ITEM_BYTES)
|
490
|
+
write_list << [ ope, key, value ]
|
491
|
+
when :system_properties
|
492
|
+
next unless (@st.key? key)
|
493
|
+
write_list << [ ope, key, { 'string_only' => [ true, false ][rand(2)] } ]
|
494
|
+
when :custom_properties
|
495
|
+
next unless (@st.key? key)
|
496
|
+
value = ITEM_CHARS[rand(ITEM_CHARS.length)] * rand(MAX_ITEM_BYTES)
|
497
|
+
write_list << [ ope, key, { 'foo' => value } ]
|
498
|
+
when :delete
|
499
|
+
next unless (@st.key? key)
|
500
|
+
write_list << [ ope, key ]
|
501
|
+
else
|
502
|
+
raise "unknown operation: #{ope}"
|
503
|
+
end
|
504
|
+
|
505
|
+
if (block_given?) then
|
506
|
+
old_values = []
|
507
|
+
for ope, key, value in write_list
|
508
|
+
case (ope)
|
509
|
+
when :write
|
510
|
+
if (@st.key? key) then
|
511
|
+
properties = Marshal.load(Marshal.dump(@st.fetch_properties(key)))
|
512
|
+
old_values << [ :value, key, :data, @st.fetch(key) ]
|
513
|
+
old_values << [ :value, key, :properties, properties ]
|
514
|
+
old_values << [ :value, key, :data_change_number, @st.data_change_number(key) ]
|
515
|
+
old_values << [ :value, key, :properties_change_number, @st.properties_change_number(key) ]
|
516
|
+
old_values << [ :value, key, :unique_data_id, @st.unique_data_id(key) ]
|
517
|
+
else
|
518
|
+
old_values << [ :none, key ]
|
519
|
+
end
|
520
|
+
when :system_properties, :custom_properties
|
521
|
+
if (@st.key? key) then
|
522
|
+
properties = Marshal.load(Marshal.dump(@st.fetch_properties(key)))
|
523
|
+
old_values << [ :value, key, :properties, properties ]
|
524
|
+
old_values << [ :value, key, :properties_change_number, @st.properties_change_number(key) ]
|
525
|
+
else
|
526
|
+
old_values << [ :none, key ]
|
527
|
+
end
|
528
|
+
when :delete
|
529
|
+
if (@st.key? key) then
|
530
|
+
properties = Marshal.load(Marshal.dump(@st.fetch_properties(key)))
|
531
|
+
old_values << [ :value, key, :data, @st.fetch(key) ]
|
532
|
+
old_values << [ :value, key, :properties, properties ]
|
533
|
+
old_values << [ :value, key, :data_change_number, @st.data_change_number(key) ]
|
534
|
+
old_values << [ :value, key, :properties_change_number, @st.properties_change_number(key) ]
|
535
|
+
old_values << [ :value, key, :unique_data_id, @st.unique_data_id(key) ]
|
536
|
+
end
|
537
|
+
end
|
538
|
+
end
|
539
|
+
yield(@st.change_number, old_values)
|
540
|
+
end
|
541
|
+
|
542
|
+
@st.write_and_commit(write_list)
|
314
543
|
end
|
315
544
|
end
|
316
545
|
private :update_storage
|
@@ -320,58 +549,59 @@ module Higgs::Test
|
|
320
549
|
update_storage
|
321
550
|
|
322
551
|
init_cnum = @st.change_number
|
552
|
+
init_cnum_func = proc{ init_cnum }
|
323
553
|
init_keys = @st.keys.sort
|
324
554
|
init_values = {}
|
325
555
|
for key in init_keys
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
556
|
+
init_values[key] = {
|
557
|
+
:data => @st.fetch(key),
|
558
|
+
:properties => Marshal.load(Marshal.dump(@st.fetch_properties(key))),
|
559
|
+
:data_change_number => @st.data_change_number(key),
|
560
|
+
:properties_change_number => @st.properties_change_number(key),
|
561
|
+
:unique_data_id => @st.unique_data_id(key)
|
562
|
+
}
|
333
563
|
end
|
334
564
|
|
335
|
-
|
565
|
+
th_read_list = []
|
336
566
|
read_start_latch = CountDownLatch.new(NUM_OF_READ_THREADS)
|
337
567
|
NUM_OF_READ_THREADS.times{|i| # `i' should be local scope of thread block
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
568
|
+
th_read_list << Thread.new{
|
569
|
+
@cache.transaction(init_cnum_func) {|snapshot|
|
570
|
+
read_start_latch.count_down
|
571
|
+
|
572
|
+
while (do_read.running?)
|
573
|
+
assert_equal(init_keys, snapshot.keys(@st).sort, "keys at thread:#{i}")
|
574
|
+
STORAGE_ITEMS.times do |k|
|
575
|
+
assert_equal((init_values.key? k),
|
576
|
+
(snapshot.key? @st, k), "thread: #{i}, key: #{k}")
|
577
|
+
assert_equal(init_values[k] && init_values[k][:data],
|
578
|
+
snapshot.fetch(k, :data) { @st.fetch(k) }, "thread: #{i}, key: #{k}")
|
579
|
+
assert_equal(init_values[k] && init_values[k][:properties],
|
580
|
+
snapshot.fetch(k, :properties) { @st.fetch_properties(k) }, "thread: #{i}, key: #{k}")
|
581
|
+
assert_equal(init_values[k] && init_values[k][:data_change_number],
|
582
|
+
snapshot.fetch(k, :data_change_number) { @st.data_change_number(k) }, "thread: #{i}, key: #{k}")
|
583
|
+
assert_equal(init_values[k] && init_values[k][:properties_change_number],
|
584
|
+
snapshot.fetch(k, :properties_change_number) { @st.properties_change_number(k) }, "thread: #{i}, key: #{k}")
|
585
|
+
assert_equal(init_values[k] && init_values[k][:unique_data_id],
|
586
|
+
snapshot.fetch(k, :unique_data_id) { @st.unique_data_id(k) }, "thread: #{i}, key: #{k}")
|
587
|
+
end
|
588
|
+
end
|
589
|
+
}
|
590
|
+
}
|
361
591
|
}
|
362
592
|
read_start_latch.wait
|
363
593
|
|
364
594
|
t0 = Time.now
|
365
595
|
while (Time.now - t0 < HEAT_RUN_TIME)
|
366
|
-
|
367
|
-
|
368
|
-
|
596
|
+
update_storage{|cnum, write_list|
|
597
|
+
@cache.write_old_values(cnum, write_list)
|
598
|
+
}
|
369
599
|
end
|
370
600
|
|
371
601
|
sleep(HEAT_RUN_TIME)
|
372
602
|
do_read.running = false
|
373
|
-
for t in
|
374
|
-
|
603
|
+
for t in th_read_list
|
604
|
+
t.join
|
375
605
|
end
|
376
606
|
end
|
377
607
|
|
@@ -382,63 +612,68 @@ module Higgs::Test
|
|
382
612
|
do_read = RunFlag.new(true)
|
383
613
|
write_lock = Mutex.new
|
384
614
|
|
385
|
-
|
615
|
+
th_read_list = []
|
386
616
|
read_start_latch = CountDownLatch.new(NUM_OF_READ_WRITE_THREADS)
|
387
617
|
NUM_OF_READ_WRITE_THREADS.times{|i| # `i' should be local scope of thread block
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
618
|
+
th_read_list << Thread.new{
|
619
|
+
read_start_latch.count_down
|
620
|
+
|
621
|
+
while (do_read.running?)
|
622
|
+
@cache.transaction(@st.method(:change_number)) {|snapshot|
|
623
|
+
if (snapshot.change_number > 0) then
|
624
|
+
assert_equal(snapshot.change_number.to_s,
|
625
|
+
snapshot.fetch(:foo, :data) { @st.fetch(:foo) }, "thread: #{i}")
|
626
|
+
else
|
627
|
+
assert_nil(snapshot.fetch(:foo, :data) { @st.fetch(:foo) }, "thread: #{i}")
|
628
|
+
end
|
629
|
+
}
|
630
|
+
end
|
631
|
+
}
|
402
632
|
}
|
403
633
|
read_start_latch.wait
|
404
634
|
|
405
|
-
|
635
|
+
th_write_list = []
|
406
636
|
write_start_latch = CountDownLatch.new(NUM_OF_READ_WRITE_THREADS)
|
407
637
|
NUM_OF_READ_WRITE_THREADS.times{|i| # `i' should be local scope of thread block
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
638
|
+
th_write_list << Thread.new{
|
639
|
+
write_start_latch.count_down
|
640
|
+
|
641
|
+
WORK_COUNT.times do |j|
|
642
|
+
write_lock.synchronize{
|
643
|
+
@cache.transaction(@st.method(:change_number)) {|snapshot|
|
644
|
+
value = snapshot.fetch(:foo, :data) { @st.fetch(:foo) }
|
645
|
+
if (snapshot.change_number > 0) then
|
646
|
+
assert_equal(snapshot.change_number.to_s, value, "thread: #{i}-#{j}")
|
647
|
+
else
|
648
|
+
assert_nil(value, "thread: #{i}-#{j}")
|
649
|
+
end
|
650
|
+
|
651
|
+
next_value = (value || '0').succ
|
652
|
+
|
653
|
+
snapshot.write_old_values([ [ :value, :foo, :data, value ] ])
|
654
|
+
@st.write_and_commit([ [ :write, :foo, next_value ] ])
|
655
|
+
}
|
656
|
+
}
|
657
|
+
end
|
658
|
+
}
|
429
659
|
}
|
430
660
|
write_start_latch.wait
|
431
661
|
|
432
|
-
for t in
|
433
|
-
|
662
|
+
for t in th_write_list
|
663
|
+
t.join
|
434
664
|
end
|
435
665
|
|
436
666
|
do_read.running = false
|
437
|
-
for t in
|
438
|
-
|
667
|
+
for t in th_read_list
|
668
|
+
t.join
|
439
669
|
end
|
440
670
|
|
441
671
|
assert_equal((NUM_OF_READ_WRITE_THREADS * WORK_COUNT).to_s, @st.fetch(:foo))
|
442
672
|
end
|
443
673
|
end
|
444
674
|
end
|
675
|
+
|
676
|
+
# Local Variables:
|
677
|
+
# mode: Ruby
|
678
|
+
# indent-tabs-mode: nil
|
679
|
+
# End:
|