higgs 0.1.4 → 0.1.5
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 +82 -0
- data/README +3 -0
- data/lib/higgs/cache.rb +161 -4
- data/lib/higgs/lock.rb +72 -129
- data/lib/higgs/storage.rb +20 -19
- data/lib/higgs/thread.rb +14 -17
- data/lib/higgs/tman.rb +111 -55
- data/lib/higgs/version.rb +4 -4
- data/test/test_cache.rb +5 -3
- data/test/test_cache_mvcc.rb +444 -0
- data/test/test_lock.rb +126 -187
- data/test/test_replication.rb +2 -0
- data/test/test_storage.rb +4 -11
- data/test/test_tman.rb +22 -38
- data/test/test_tman_mvcc.rb +265 -0
- data/test/test_utils_bman.rb +3 -1
- metadata +4 -2
data/test/test_lock.rb
CHANGED
@@ -3,23 +3,24 @@
|
|
3
3
|
require 'higgs/lock'
|
4
4
|
require 'higgs/thread'
|
5
5
|
require 'test/unit'
|
6
|
-
|
6
|
+
|
7
|
+
Thread.abort_on_exception = true if $DEBUG
|
7
8
|
|
8
9
|
module Higgs::Test
|
9
10
|
module LockManagerTest
|
10
11
|
include Higgs
|
11
12
|
|
12
13
|
# for ident(1)
|
13
|
-
CVS_ID = '$Id: test_lock.rb
|
14
|
+
CVS_ID = '$Id: test_lock.rb 746 2008-01-20 13:29:24Z toki $'
|
14
15
|
|
15
|
-
WORK_COUNT =
|
16
|
+
WORK_COUNT = 1000
|
16
17
|
THREAD_COUNT = 10
|
17
18
|
|
18
19
|
def test_read_transaction_single_thread
|
19
20
|
v = "foo"
|
20
21
|
WORK_COUNT.times do
|
21
22
|
@lock_manager.transaction(true) {|lock_handler|
|
22
|
-
lock_handler.lock(:foo)
|
23
|
+
lock_handler.lock(:foo, :data, 0)
|
23
24
|
assert_equal("foo", v)
|
24
25
|
}
|
25
26
|
end
|
@@ -29,7 +30,8 @@ module Higgs::Test
|
|
29
30
|
count = 0
|
30
31
|
WORK_COUNT.times do
|
31
32
|
@lock_manager.transaction{|lock_handler|
|
32
|
-
lock_handler.lock(:foo)
|
33
|
+
lock_handler.lock(:foo, :data, 0)
|
34
|
+
check_collision(lock_handler, [ :foo, :data ] => 0)
|
33
35
|
count += 1
|
34
36
|
}
|
35
37
|
end
|
@@ -44,10 +46,10 @@ module Higgs::Test
|
|
44
46
|
THREAD_COUNT.times{|i|
|
45
47
|
th_grp.add Thread.new{
|
46
48
|
@lock_manager.transaction(true) {|lock_handler|
|
47
|
-
lock_handler.lock(:foo)
|
49
|
+
lock_handler.lock(:foo, :data, 0)
|
48
50
|
barrier.wait
|
49
51
|
WORK_COUNT.times do |j|
|
50
|
-
assert_equal("foo", v, "read transaction: #{i}
|
52
|
+
assert_equal("foo", v, "read transaction: #{i}-#{j}")
|
51
53
|
end
|
52
54
|
}
|
53
55
|
}
|
@@ -61,6 +63,9 @@ module Higgs::Test
|
|
61
63
|
|
62
64
|
def test_write_transaction_multithread
|
63
65
|
count = 0
|
66
|
+
mvcc_last_cnum = 0
|
67
|
+
mvcc_old_values = {}
|
68
|
+
mvcc_lock = Mutex.new
|
64
69
|
th_grp = ThreadGroup.new
|
65
70
|
barrier = Barrier.new(THREAD_COUNT + 1)
|
66
71
|
|
@@ -68,10 +73,24 @@ module Higgs::Test
|
|
68
73
|
th_grp.add Thread.new{
|
69
74
|
barrier.wait
|
70
75
|
WORK_COUNT.times do
|
71
|
-
|
72
|
-
lock_handler
|
73
|
-
|
74
|
-
|
76
|
+
begin
|
77
|
+
@lock_manager.transaction{|lock_handler|
|
78
|
+
curr_cnum = mvcc_last_cnum # save at first
|
79
|
+
lock_handler.lock(:foo, :data, curr_cnum)
|
80
|
+
next_count = mvcc_lock.synchronize{ mvcc_old_values[curr_cnum] || count }
|
81
|
+
next_count += 1
|
82
|
+
lock_handler.critical{
|
83
|
+
check_collision(lock_handler, [ :foo, :data ] => mvcc_last_cnum)
|
84
|
+
mvcc_lock.synchronize{
|
85
|
+
mvcc_old_values[mvcc_last_cnum] = count
|
86
|
+
}
|
87
|
+
count = next_count
|
88
|
+
mvcc_last_cnum += 1 # increment at last
|
89
|
+
}
|
90
|
+
}
|
91
|
+
rescue LockManager::CollisionError
|
92
|
+
retry
|
93
|
+
end
|
75
94
|
end
|
76
95
|
}
|
77
96
|
end
|
@@ -85,16 +104,22 @@ module Higgs::Test
|
|
85
104
|
|
86
105
|
def test_read_write_transaction_multithread
|
87
106
|
count = 0
|
107
|
+
mvcc_last_cnum = 0
|
108
|
+
mvcc_old_values = {}
|
109
|
+
mvcc_lock = Mutex.new
|
88
110
|
th_grp = ThreadGroup.new
|
89
111
|
barrier = Barrier.new(THREAD_COUNT * 2 + 1)
|
90
112
|
|
91
113
|
THREAD_COUNT.times{|i|
|
92
114
|
th_grp.add Thread.new{
|
93
115
|
@lock_manager.transaction(true) {|lock_handler|
|
94
|
-
|
116
|
+
curr_cnum = mvcc_last_cnum # save at first
|
117
|
+
lock_handler.lock(:foo, :data, curr_cnum)
|
95
118
|
barrier.wait
|
96
119
|
WORK_COUNT.times do |j|
|
97
|
-
assert_equal(
|
120
|
+
assert_equal(curr_cnum,
|
121
|
+
mvcc_lock.synchronize { mvcc_old_values[curr_cnum] || count },
|
122
|
+
"read transaction: #{i}-#{j}")
|
98
123
|
end
|
99
124
|
}
|
100
125
|
}
|
@@ -104,10 +129,26 @@ module Higgs::Test
|
|
104
129
|
th_grp.add Thread.new{
|
105
130
|
barrier.wait
|
106
131
|
WORK_COUNT.times do
|
107
|
-
|
108
|
-
lock_handler
|
109
|
-
|
110
|
-
|
132
|
+
begin
|
133
|
+
@lock_manager.transaction{|lock_handler|
|
134
|
+
curr_cnum = mvcc_last_cnum # save at first
|
135
|
+
lock_handler.lock(:foo, :data, curr_cnum)
|
136
|
+
next_count = mvcc_lock.synchronize{
|
137
|
+
mvcc_old_values[curr_cnum] || count
|
138
|
+
}
|
139
|
+
next_count += 1
|
140
|
+
lock_handler.critical{
|
141
|
+
check_collision(lock_handler, [ :foo, :data ] => mvcc_last_cnum)
|
142
|
+
mvcc_lock.synchronize{
|
143
|
+
mvcc_old_values[mvcc_last_cnum] = count
|
144
|
+
}
|
145
|
+
count = next_count
|
146
|
+
mvcc_last_cnum += 1 # increment at last
|
147
|
+
}
|
148
|
+
}
|
149
|
+
rescue LockManager::CollisionError
|
150
|
+
retry
|
151
|
+
end
|
111
152
|
end
|
112
153
|
}
|
113
154
|
end
|
@@ -152,8 +193,12 @@ module Higgs::Test
|
|
152
193
|
end
|
153
194
|
|
154
195
|
def test_read_write_exclusive_multithread
|
155
|
-
|
196
|
+
state = :transaction
|
156
197
|
count = 0
|
198
|
+
ex_count = 0
|
199
|
+
mvcc_last_cnum = 0
|
200
|
+
mvcc_old_values = {}
|
201
|
+
mvcc_lock = Mutex.new
|
157
202
|
th_grp = ThreadGroup.new
|
158
203
|
barrier = Barrier.new(THREAD_COUNT * 3 + 1)
|
159
204
|
|
@@ -162,8 +207,13 @@ module Higgs::Test
|
|
162
207
|
barrier.wait
|
163
208
|
WORK_COUNT.times do |j|
|
164
209
|
@lock_manager.transaction(true) {|lock_handler|
|
165
|
-
|
166
|
-
|
210
|
+
assert_equal(:transaction, state)
|
211
|
+
curr_cnum = mvcc_last_cnum # save at first
|
212
|
+
lock_handler.lock(:foo, :data, curr_cnum)
|
213
|
+
assert_equal(curr_cnum,
|
214
|
+
mvcc_lock.synchronize{ mvcc_old_values[curr_cnum] || count },
|
215
|
+
"read transaction: #{i}-#{j}")
|
216
|
+
assert_equal(:transaction, state)
|
167
217
|
}
|
168
218
|
end
|
169
219
|
}
|
@@ -173,13 +223,27 @@ module Higgs::Test
|
|
173
223
|
th_grp.add Thread.new{
|
174
224
|
barrier.wait
|
175
225
|
WORK_COUNT.times do |j|
|
176
|
-
|
177
|
-
lock_handler
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
226
|
+
begin
|
227
|
+
@lock_manager.transaction{|lock_handler|
|
228
|
+
assert_equal(:transaction, state)
|
229
|
+
curr_cnum = mvcc_last_cnum # save at first
|
230
|
+
lock_handler.lock(:foo, :data, curr_cnum)
|
231
|
+
next_count = mvcc_lock.synchronize{ mvcc_old_values[curr_cnum] || count }
|
232
|
+
next_count += 1
|
233
|
+
lock_handler.critical{
|
234
|
+
check_collision(lock_handler, [ :foo, :data ] => mvcc_last_cnum)
|
235
|
+
mvcc_lock.synchronize{
|
236
|
+
mvcc_old_values[mvcc_last_cnum] = count
|
237
|
+
}
|
238
|
+
count = next_count
|
239
|
+
ex_count += 1
|
240
|
+
mvcc_last_cnum += 1 # increment at last
|
241
|
+
}
|
242
|
+
assert_equal(:transaction, state)
|
243
|
+
}
|
244
|
+
rescue LockManager::CollisionError
|
245
|
+
retry
|
246
|
+
end
|
183
247
|
end
|
184
248
|
}
|
185
249
|
}
|
@@ -189,10 +253,10 @@ module Higgs::Test
|
|
189
253
|
barrier.wait
|
190
254
|
WORK_COUNT.times do |j|
|
191
255
|
@lock_manager.exclusive{
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
256
|
+
save_state = state
|
257
|
+
state = :exclusive
|
258
|
+
ex_count += 1
|
259
|
+
state = save_state
|
196
260
|
}
|
197
261
|
end
|
198
262
|
}
|
@@ -202,111 +266,8 @@ module Higgs::Test
|
|
202
266
|
for t in th_grp.list
|
203
267
|
t.join
|
204
268
|
end
|
205
|
-
assert_equal(
|
206
|
-
assert_equal(THREAD_COUNT * WORK_COUNT * 2,
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
class GiantLockManagerTest < Test::Unit::TestCase
|
211
|
-
include Higgs
|
212
|
-
include LockManagerTest
|
213
|
-
|
214
|
-
# for ident(1)
|
215
|
-
CVS_ID = '$Id: test_lock.rb 652 2007-10-22 15:23:50Z toki $'
|
216
|
-
|
217
|
-
def setup
|
218
|
-
@lock_manager = GiantLockManager.new
|
219
|
-
end
|
220
|
-
|
221
|
-
def test_write_read_transaction_multithread
|
222
|
-
count = 0
|
223
|
-
th_grp = ThreadGroup.new
|
224
|
-
barrier = Barrier.new(THREAD_COUNT + 2)
|
225
|
-
|
226
|
-
th_grp.add Thread.new{
|
227
|
-
@lock_manager.transaction{|lock_handler|
|
228
|
-
lock_handler.lock(:foo)
|
229
|
-
barrier.wait
|
230
|
-
THREAD_COUNT.times do
|
231
|
-
WORK_COUNT.times do
|
232
|
-
count += 1
|
233
|
-
end
|
234
|
-
end
|
235
|
-
}
|
236
|
-
}
|
237
|
-
|
238
|
-
THREAD_COUNT.times{|i|
|
239
|
-
th_grp.add Thread.new{
|
240
|
-
barrier.wait # different point from FineGrainLockManager
|
241
|
-
@lock_manager.transaction(true) {|lock_handler|
|
242
|
-
lock_handler.lock(:foo)
|
243
|
-
assert_equal(THREAD_COUNT * WORK_COUNT, count, "read transaction: #{i}")
|
244
|
-
}
|
245
|
-
}
|
246
|
-
}
|
247
|
-
|
248
|
-
barrier.wait
|
249
|
-
for t in th_grp.list
|
250
|
-
t.join
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
class FineGrainLockManagerTest < Test::Unit::TestCase
|
256
|
-
include Higgs
|
257
|
-
include LockManagerTest
|
258
|
-
|
259
|
-
# for ident(1)
|
260
|
-
CVS_ID = '$Id: test_lock.rb 652 2007-10-22 15:23:50Z toki $'
|
261
|
-
|
262
|
-
def setup
|
263
|
-
@lock_manager = FineGrainLockManager.new
|
264
|
-
end
|
265
|
-
|
266
|
-
def test_write_read_transaction_multithread
|
267
|
-
count = 0
|
268
|
-
th_grp = ThreadGroup.new
|
269
|
-
barrier = Barrier.new(THREAD_COUNT + 2)
|
270
|
-
|
271
|
-
th_grp.add Thread.new{
|
272
|
-
@lock_manager.transaction{|lock_handler|
|
273
|
-
lock_handler.lock(:foo)
|
274
|
-
barrier.wait
|
275
|
-
THREAD_COUNT.times do
|
276
|
-
WORK_COUNT.times do
|
277
|
-
count += 1
|
278
|
-
end
|
279
|
-
end
|
280
|
-
}
|
281
|
-
}
|
282
|
-
|
283
|
-
THREAD_COUNT.times{|i|
|
284
|
-
th_grp.add Thread.new{
|
285
|
-
@lock_manager.transaction(true) {|lock_handler|
|
286
|
-
barrier.wait # different point from GiantLockManager
|
287
|
-
lock_handler.lock(:foo)
|
288
|
-
assert_equal(THREAD_COUNT * WORK_COUNT, count, "read transaction: #{i}")
|
289
|
-
}
|
290
|
-
}
|
291
|
-
}
|
292
|
-
|
293
|
-
barrier.wait
|
294
|
-
for t in th_grp.list
|
295
|
-
t.join
|
296
|
-
end
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
class GiantLockManagerNoDeadLockTest < Test::Unit::TestCase
|
301
|
-
include Higgs
|
302
|
-
|
303
|
-
# for ident(1)
|
304
|
-
CVS_ID = '$Id: test_lock.rb 652 2007-10-22 15:23:50Z toki $'
|
305
|
-
|
306
|
-
WORK_COUNT = 1000
|
307
|
-
|
308
|
-
def setup
|
309
|
-
@lock_manager = GiantLockManager.new
|
269
|
+
assert_equal(THREAD_COUNT * WORK_COUNT, count)
|
270
|
+
assert_equal(THREAD_COUNT * WORK_COUNT * 2, ex_count)
|
310
271
|
end
|
311
272
|
|
312
273
|
def test_transaction_no_dead_lock
|
@@ -316,8 +277,9 @@ module Higgs::Test
|
|
316
277
|
barrier.wait
|
317
278
|
WORK_COUNT.times do
|
318
279
|
@lock_manager.transaction{|lock_handler|
|
319
|
-
lock_handler.lock(:foo)
|
320
|
-
lock_handler.lock(:bar)
|
280
|
+
lock_handler.lock(:foo, :data, 0)
|
281
|
+
lock_handler.lock(:bar, :data, 0)
|
282
|
+
check_collision(lock_handler, [ :foo, :data ] => 0, [ :bar, :data ] => 0)
|
321
283
|
}
|
322
284
|
end
|
323
285
|
}
|
@@ -326,8 +288,9 @@ module Higgs::Test
|
|
326
288
|
barrier.wait
|
327
289
|
WORK_COUNT.times do
|
328
290
|
@lock_manager.transaction{|lock_handler|
|
329
|
-
lock_handler.lock(:bar)
|
330
|
-
lock_handler.lock(:foo)
|
291
|
+
lock_handler.lock(:bar, :data, 1)
|
292
|
+
lock_handler.lock(:foo, :data, 1)
|
293
|
+
check_collision(lock_handler, [ :foo, :data ] => 1, [ :bar, :data ] => 1)
|
331
294
|
}
|
332
295
|
end
|
333
296
|
}
|
@@ -338,65 +301,41 @@ module Higgs::Test
|
|
338
301
|
end
|
339
302
|
end
|
340
303
|
|
341
|
-
class
|
304
|
+
class GiantLockManagerTest < Test::Unit::TestCase
|
342
305
|
include Higgs
|
306
|
+
include LockManagerTest
|
343
307
|
|
344
308
|
# for ident(1)
|
345
|
-
CVS_ID = '$Id: test_lock.rb
|
309
|
+
CVS_ID = '$Id: test_lock.rb 746 2008-01-20 13:29:24Z toki $'
|
346
310
|
|
347
311
|
def setup
|
348
|
-
@lock_manager =
|
349
|
-
:try_lock_limit => 0.1,
|
350
|
-
:try_lock_interval => 0.001)
|
312
|
+
@lock_manager = GiantLockManager.new
|
351
313
|
end
|
352
314
|
|
353
|
-
def
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
315
|
+
def check_collision(lock_handler, expected_cnum)
|
316
|
+
lock_handler.check_collision{|key, type|
|
317
|
+
flunk("not to reach.")
|
318
|
+
}
|
319
|
+
end
|
320
|
+
end
|
358
321
|
|
359
|
-
|
360
|
-
|
322
|
+
class OptimisticLockManagerTest < Test::Unit::TestCase
|
323
|
+
include Higgs
|
324
|
+
include LockManagerTest
|
361
325
|
|
362
|
-
|
363
|
-
|
364
|
-
begin
|
365
|
-
until (m2.synchronize{ end_of_t2 })
|
366
|
-
@lock_manager.transaction{|lock_handler|
|
367
|
-
lock_handler.lock(:foo)
|
368
|
-
sleep(0.03)
|
369
|
-
lock_handler.lock(:bar)
|
370
|
-
}
|
371
|
-
end
|
372
|
-
ensure
|
373
|
-
m1.synchronize{ end_of_t1 = true }
|
374
|
-
end
|
375
|
-
}
|
326
|
+
# for ident(1)
|
327
|
+
CVS_ID = '$Id: test_lock.rb 746 2008-01-20 13:29:24Z toki $'
|
376
328
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
until (m1.synchronize{ end_of_t1 })
|
381
|
-
@lock_manager.transaction{|lock_handler|
|
382
|
-
lock_handler.lock(:bar)
|
383
|
-
sleep(0.07)
|
384
|
-
lock_handler.lock(:foo)
|
385
|
-
}
|
386
|
-
end
|
387
|
-
ensure
|
388
|
-
m2.synchronize{ end_of_t2 = true }
|
389
|
-
end
|
390
|
-
}
|
329
|
+
def setup
|
330
|
+
@lock_manager = OptimisticLockManager.new
|
331
|
+
end
|
391
332
|
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
333
|
+
def check_collision(lock_handler, expected_cnum)
|
334
|
+
lock_handler.check_collision{|key, type|
|
335
|
+
key_pair = [ key, type ]
|
336
|
+
expected_cnum.delete(key_pair) or flunk("not defined key: `#{key}(#{type})'")
|
396
337
|
}
|
397
|
-
|
398
|
-
# join threads without exception
|
399
|
-
ThreadsWait.all_waits(t1, t2)
|
338
|
+
assert_equal({}, expected_cnum)
|
400
339
|
end
|
401
340
|
end
|
402
341
|
end
|