higgs 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,23 +3,24 @@
3
3
  require 'higgs/lock'
4
4
  require 'higgs/thread'
5
5
  require 'test/unit'
6
- require 'thwait'
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 652 2007-10-22 15:23:50Z toki $'
14
+ CVS_ID = '$Id: test_lock.rb 746 2008-01-20 13:29:24Z toki $'
14
15
 
15
- WORK_COUNT = 100
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}.#{j}")
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
- @lock_manager.transaction{|lock_handler|
72
- lock_handler.lock(:foo)
73
- count += 1
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
- lock_handler.lock(:foo)
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(0, count, "read transaction: #{i}.#{j}")
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
- @lock_manager.transaction{|lock_handler|
108
- lock_handler.lock(:foo)
109
- count += 1
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
- v = 'foo'
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
- lock_handler.lock(:foo)
166
- assert_equal('foo', v, "read transaction: #{i}.#{j}")
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
- @lock_manager.transaction{|lock_handler|
177
- lock_handler.lock(:foo)
178
- assert_equal('foo', v, "write transaction: #{i}.#{j}")
179
- v = 'bar'
180
- v = 'foo'
181
- count += 1
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
- assert_equal('foo', v, "exclusive: #{i}.#{j}")
193
- v = 'baz'
194
- v = 'foo'
195
- count += 1
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('foo', v)
206
- assert_equal(THREAD_COUNT * WORK_COUNT * 2, count)
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 FineGrainLockManagerDeadLockTest < Test::Unit::TestCase
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 652 2007-10-22 15:23:50Z toki $'
309
+ CVS_ID = '$Id: test_lock.rb 746 2008-01-20 13:29:24Z toki $'
346
310
 
347
311
  def setup
348
- @lock_manager = FineGrainLockManager.new(:spin_lock_count => 10,
349
- :try_lock_limit => 0.1,
350
- :try_lock_interval => 0.001)
312
+ @lock_manager = GiantLockManager.new
351
313
  end
352
314
 
353
- def test_transaction_dead_lock
354
- barrier = Barrier.new(3)
355
-
356
- m1 = Mutex.new
357
- end_of_t1 = false
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
- m2 = Mutex.new
360
- end_of_t2 = false
322
+ class OptimisticLockManagerTest < Test::Unit::TestCase
323
+ include Higgs
324
+ include LockManagerTest
361
325
 
362
- t1 = Thread.new{
363
- barrier.wait
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
- t2 = Thread.new{
378
- barrier.wait
379
- begin
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
- barrier.wait
393
- assert_raise(LockManager::TryLockTimeoutError) {
394
- t1.join
395
- t2.join
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
@@ -9,6 +9,8 @@ require 'higgs/tman'
9
9
  require 'logger'
10
10
  require 'test/unit'
11
11
 
12
+ Thread.abort_on_exception = true if $DEBUG
13
+
12
14
  module Higgs::Test
13
15
  module ReplicationTest
14
16
  include Higgs