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.
@@ -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