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_storage.rb
CHANGED
@@ -11,7 +11,7 @@ module Higgs::Test
|
|
11
11
|
include Higgs
|
12
12
|
|
13
13
|
# for ident(1)
|
14
|
-
CVS_ID = '$Id: test_storage.rb
|
14
|
+
CVS_ID = '$Id: test_storage.rb 742 2008-01-13 15:55:53Z toki $'
|
15
15
|
|
16
16
|
def setup
|
17
17
|
srand(0) # preset for rand
|
@@ -37,7 +37,7 @@ module Higgs::Test
|
|
37
37
|
include StorageTestCase
|
38
38
|
|
39
39
|
# for ident(1)
|
40
|
-
CVS_ID = '$Id: test_storage.rb
|
40
|
+
CVS_ID = '$Id: test_storage.rb 742 2008-01-13 15:55:53Z toki $'
|
41
41
|
|
42
42
|
def new_storage
|
43
43
|
Storage.new(@name, :logger => @logger)
|
@@ -80,7 +80,6 @@ module Higgs::Test
|
|
80
80
|
assert_equal(Digest::MD5.hexdigest("Hello world.\n"), properties['system_properties']['hash_value'])
|
81
81
|
assert_equal(false, properties['system_properties']['string_only'])
|
82
82
|
assert_equal({}, properties['custom_properties'])
|
83
|
-
assert_equal(false, @st.string_only('foo'))
|
84
83
|
|
85
84
|
# update properties
|
86
85
|
@st.write_and_commit([ [ :system_properties, 'foo', { 'string_only' => true } ] ])
|
@@ -91,7 +90,6 @@ module Higgs::Test
|
|
91
90
|
assert_equal(Digest::MD5.hexdigest("Hello world.\n"), properties['system_properties']['hash_value'])
|
92
91
|
assert_equal(true, properties['system_properties']['string_only'])
|
93
92
|
assert_equal({ :comment => 'test' }, properties['custom_properties'])
|
94
|
-
assert_equal(true, @st.string_only('foo'))
|
95
93
|
|
96
94
|
# update
|
97
95
|
@st.write_and_commit([ [ :write, 'foo', "Good bye.\n" ] ])
|
@@ -101,7 +99,6 @@ module Higgs::Test
|
|
101
99
|
assert_equal(Digest::MD5.hexdigest("Good bye.\n"), properties['system_properties']['hash_value'])
|
102
100
|
assert_equal(true, properties['system_properties']['string_only'])
|
103
101
|
assert_equal({ :comment => 'test' }, properties['custom_properties'])
|
104
|
-
assert_equal(true, @st.string_only('foo'))
|
105
102
|
|
106
103
|
# delete
|
107
104
|
@st.write_and_commit([ [ :delete, 'foo' ] ])
|
@@ -229,10 +226,6 @@ module Higgs::Test
|
|
229
226
|
assert_equal(mod_time2, @st.fetch_properties(:foo)['system_properties']['modified_time'])
|
230
227
|
end
|
231
228
|
|
232
|
-
def test_string_only_IndexError_not_exist_properties
|
233
|
-
assert_raise(IndexError) { @st.string_only('foo') }
|
234
|
-
end
|
235
|
-
|
236
229
|
def test_change_number_and_unique_data_id
|
237
230
|
assert_equal(nil, @st.data_change_number(:foo))
|
238
231
|
assert_equal(nil, @st.properties_change_number(:foo))
|
@@ -476,7 +469,7 @@ module Higgs::Test
|
|
476
469
|
include StorageTestCase
|
477
470
|
|
478
471
|
# for ident(1)
|
479
|
-
CVS_ID = '$Id: test_storage.rb
|
472
|
+
CVS_ID = '$Id: test_storage.rb 742 2008-01-13 15:55:53Z toki $'
|
480
473
|
|
481
474
|
def new_storage
|
482
475
|
Storage.new(@name,
|
@@ -798,7 +791,7 @@ module Higgs::Test
|
|
798
791
|
include Higgs
|
799
792
|
|
800
793
|
# for ident(1)
|
801
|
-
CVS_ID = '$Id: test_storage.rb
|
794
|
+
CVS_ID = '$Id: test_storage.rb 742 2008-01-13 15:55:53Z toki $'
|
802
795
|
|
803
796
|
def setup
|
804
797
|
@test_dir = 'st_test'
|
data/test/test_tman.rb
CHANGED
@@ -8,12 +8,14 @@ require 'higgs/tman'
|
|
8
8
|
require 'logger'
|
9
9
|
require 'test/unit'
|
10
10
|
|
11
|
+
Thread.abort_on_exception = true if $DEBUG
|
12
|
+
|
11
13
|
module Higgs::Test
|
12
14
|
class TransactionManagerTest < Test::Unit::TestCase
|
13
15
|
include Higgs
|
14
16
|
|
15
17
|
# for ident(1)
|
16
|
-
CVS_ID = '$Id: test_tman.rb
|
18
|
+
CVS_ID = '$Id: test_tman.rb 745 2008-01-20 13:28:02Z toki $'
|
17
19
|
|
18
20
|
def setup
|
19
21
|
@test_dir = 'st_test'
|
@@ -50,32 +52,6 @@ module Higgs::Test
|
|
50
52
|
assert_equal(1, count)
|
51
53
|
end
|
52
54
|
|
53
|
-
def test_transaction_RuntimeError_nested_transaction_forbidden
|
54
|
-
@tman.transaction(true) {|tx|
|
55
|
-
assert_raise(RuntimeError) {
|
56
|
-
@tman.transaction(true) {|tx2|
|
57
|
-
flunk('not to reach.')
|
58
|
-
}
|
59
|
-
}
|
60
|
-
}
|
61
|
-
end
|
62
|
-
|
63
|
-
def test_in_transaction?
|
64
|
-
assert_equal(false, TransactionManager.in_transaction?)
|
65
|
-
@tman.transaction{|tx|
|
66
|
-
assert_equal(true, TransactionManager.in_transaction?)
|
67
|
-
}
|
68
|
-
assert_equal(false, TransactionManager.in_transaction?)
|
69
|
-
end
|
70
|
-
|
71
|
-
def test_current_transaction
|
72
|
-
assert_equal(nil, TransactionManager.current_transaction)
|
73
|
-
@tman.transaction{|tx|
|
74
|
-
assert_equal(tx, TransactionManager.current_transaction)
|
75
|
-
}
|
76
|
-
assert_equal(nil, TransactionManager.current_transaction)
|
77
|
-
end
|
78
|
-
|
79
55
|
def test_fetch_and_store
|
80
56
|
@tman.transaction{|tx|
|
81
57
|
assert_equal(nil, tx[:foo])
|
@@ -1059,8 +1035,8 @@ module Higgs::Test
|
|
1059
1035
|
}
|
1060
1036
|
end
|
1061
1037
|
|
1062
|
-
def
|
1063
|
-
@tman = TransactionManager.new(@st, :lock_manager =>
|
1038
|
+
def test_optimistic_lock_manager
|
1039
|
+
@tman = TransactionManager.new(@st, :lock_manager => OptimisticLockManager.new)
|
1064
1040
|
@tman.transaction{|tx|
|
1065
1041
|
tx[:foo] = '0'
|
1066
1042
|
tx[:bar] = '0'
|
@@ -1073,20 +1049,28 @@ module Higgs::Test
|
|
1073
1049
|
a = Thread.new{
|
1074
1050
|
barrier.wait
|
1075
1051
|
count.times do
|
1076
|
-
|
1077
|
-
tx
|
1078
|
-
|
1079
|
-
|
1052
|
+
begin
|
1053
|
+
@tman.transaction{|tx|
|
1054
|
+
tx[:foo] = tx[:foo].succ
|
1055
|
+
tx[:bar] = tx[:bar].succ
|
1056
|
+
}
|
1057
|
+
rescue LockManager::CollisionError
|
1058
|
+
retry
|
1059
|
+
end
|
1080
1060
|
end
|
1081
1061
|
}
|
1082
1062
|
|
1083
1063
|
b = Thread.new{
|
1084
1064
|
barrier.wait
|
1085
1065
|
count.times do
|
1086
|
-
|
1087
|
-
tx
|
1088
|
-
|
1089
|
-
|
1066
|
+
begin
|
1067
|
+
@tman.transaction{|tx|
|
1068
|
+
tx[:bar] = tx[:bar].succ
|
1069
|
+
tx[:baz] = tx[:baz].succ
|
1070
|
+
}
|
1071
|
+
rescue LockManager::CollisionError
|
1072
|
+
retry
|
1073
|
+
end
|
1090
1074
|
end
|
1091
1075
|
}
|
1092
1076
|
|
@@ -1104,7 +1088,7 @@ module Higgs::Test
|
|
1104
1088
|
|
1105
1089
|
class TransactionManagerTest_with_SecondaryCache < TransactionManagerTest
|
1106
1090
|
# for ident(1)
|
1107
|
-
CVS_ID = '$Id: test_tman.rb
|
1091
|
+
CVS_ID = '$Id: test_tman.rb 745 2008-01-20 13:28:02Z toki $'
|
1108
1092
|
|
1109
1093
|
def setup
|
1110
1094
|
super
|
@@ -0,0 +1,265 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'higgs/storage'
|
5
|
+
require 'higgs/thread'
|
6
|
+
require 'higgs/tman'
|
7
|
+
require 'logger'
|
8
|
+
require 'test/unit'
|
9
|
+
require 'timeout'
|
10
|
+
|
11
|
+
Thread.abort_on_exception = true if $DEBUG
|
12
|
+
|
13
|
+
module Higgs::Test
|
14
|
+
class TransactionManagerMVCCTest < Test::Unit::TestCase
|
15
|
+
include Higgs
|
16
|
+
include Timeout
|
17
|
+
|
18
|
+
# for ident(1)
|
19
|
+
CVS_ID = '$Id$'
|
20
|
+
|
21
|
+
def create_lock_manager
|
22
|
+
GiantLockManager.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def setup
|
26
|
+
@test_dir = 'st_test'
|
27
|
+
FileUtils.rm_rf(@test_dir) # for debug
|
28
|
+
FileUtils.mkdir_p(@test_dir)
|
29
|
+
@name = File.join(@test_dir, 'foo')
|
30
|
+
@logger = proc{|path|
|
31
|
+
logger = Logger.new(path, 1)
|
32
|
+
logger.level = Logger::DEBUG
|
33
|
+
logger
|
34
|
+
}
|
35
|
+
@st = Storage.new(@name, :logger => @logger)
|
36
|
+
@tman = TransactionManager.new(@st, :lock_manager => create_lock_manager)
|
37
|
+
end
|
38
|
+
|
39
|
+
def teardown
|
40
|
+
@st.shutdown unless @st.shutdown?
|
41
|
+
FileUtils.rm_rf(@test_dir) unless $DEBUG
|
42
|
+
end
|
43
|
+
|
44
|
+
MVCC_WARMUP_COUNT = 10
|
45
|
+
WRITE_TIMEOUT = 10
|
46
|
+
|
47
|
+
class RunFlag
|
48
|
+
def initialize(running)
|
49
|
+
#@lock = Mutex.new
|
50
|
+
@running = running
|
51
|
+
end
|
52
|
+
|
53
|
+
def running=(running)
|
54
|
+
#@lock.synchronize{
|
55
|
+
@running = running
|
56
|
+
#}
|
57
|
+
end
|
58
|
+
|
59
|
+
def running?
|
60
|
+
#@lock.synchronize{
|
61
|
+
@running
|
62
|
+
#}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Count
|
67
|
+
def initialize
|
68
|
+
@value = 0
|
69
|
+
@lock = Mutex.new
|
70
|
+
end
|
71
|
+
|
72
|
+
def succ!
|
73
|
+
@lock.synchronize{ @value += 1 }
|
74
|
+
end
|
75
|
+
|
76
|
+
def value
|
77
|
+
@lock.synchronize{ @value }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_mvcc
|
82
|
+
do_read = RunFlag.new(true)
|
83
|
+
|
84
|
+
init_read_latch = Latch.new
|
85
|
+
init_read_count = Count.new
|
86
|
+
init_read_thread = Thread.new{
|
87
|
+
@tman.transaction(true) {|tx|
|
88
|
+
while (do_read.running?)
|
89
|
+
assert_equal([], tx.keys)
|
90
|
+
assert_nil(tx[:foo])
|
91
|
+
init_read_count.succ!
|
92
|
+
init_read_latch.start if (init_read_count.value == MVCC_WARMUP_COUNT)
|
93
|
+
end
|
94
|
+
}
|
95
|
+
}
|
96
|
+
init_read_latch.wait
|
97
|
+
|
98
|
+
# insert
|
99
|
+
p [ self.class, :test_mvcc, :insert ] if $DEBUG
|
100
|
+
timeout(WRITE_TIMEOUT) {
|
101
|
+
@tman.transaction{|tx|
|
102
|
+
tx[:foo] = 'Hello world.'
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
insert_read_latch = Latch.new
|
107
|
+
insert_read_count = Count.new
|
108
|
+
insert_read_thread = Thread.new{
|
109
|
+
@tman.transaction(true) {|tx|
|
110
|
+
while (do_read.running?)
|
111
|
+
assert_equal([ :foo ], tx.keys)
|
112
|
+
assert_equal('Hello world.', tx[:foo])
|
113
|
+
insert_read_count.succ!
|
114
|
+
insert_read_latch.start if (insert_read_count.value == MVCC_WARMUP_COUNT)
|
115
|
+
end
|
116
|
+
}
|
117
|
+
}
|
118
|
+
insert_read_latch.wait
|
119
|
+
|
120
|
+
# update
|
121
|
+
p [ self.class, :test_mvcc, :update ] if $DEBUG
|
122
|
+
timeout(WRITE_TIMEOUT) {
|
123
|
+
@tman.transaction{|tx|
|
124
|
+
tx[:foo] = 'I like ruby.'
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
update_read_latch = Latch.new
|
129
|
+
update_read_count = Count.new
|
130
|
+
update_read_thread = Thread.new{
|
131
|
+
@tman.transaction(true) {|tx|
|
132
|
+
while (do_read.running?)
|
133
|
+
assert_equal([ :foo ], tx.keys)
|
134
|
+
assert_equal('I like ruby.', tx[:foo])
|
135
|
+
update_read_count.succ!
|
136
|
+
update_read_latch.start if (update_read_count.value == MVCC_WARMUP_COUNT)
|
137
|
+
end
|
138
|
+
}
|
139
|
+
}
|
140
|
+
update_read_latch.wait
|
141
|
+
|
142
|
+
# delete
|
143
|
+
p [ self.class, :test_mvcc, :delete ] if $DEBUG
|
144
|
+
timeout(WRITE_TIMEOUT) {
|
145
|
+
@tman.transaction{|tx|
|
146
|
+
tx.delete(:foo)
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
delete_read_latch = Latch.new
|
151
|
+
delete_read_count = Count.new
|
152
|
+
delete_read_thread = Thread.new{
|
153
|
+
@tman.transaction(true) {|tx|
|
154
|
+
count = 0
|
155
|
+
while (do_read.running?)
|
156
|
+
assert_equal([], tx.keys)
|
157
|
+
assert_nil(tx[:foo])
|
158
|
+
delete_read_count.succ!
|
159
|
+
delete_read_latch.start if (delete_read_count.value == MVCC_WARMUP_COUNT)
|
160
|
+
end
|
161
|
+
}
|
162
|
+
}
|
163
|
+
delete_read_latch.wait
|
164
|
+
|
165
|
+
# insert
|
166
|
+
p [ self.class, :test_mvcc, :insert2 ] if $DEBUG
|
167
|
+
timeout(WRITE_TIMEOUT) {
|
168
|
+
@tman.transaction{|tx|
|
169
|
+
tx[:foo] = 'Hello world.'
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
173
|
+
[ init_read_count,
|
174
|
+
insert_read_count,
|
175
|
+
update_read_count,
|
176
|
+
delete_read_count
|
177
|
+
].each do |count|
|
178
|
+
c = count.value
|
179
|
+
until (count.value > c)
|
180
|
+
# nothing to do.
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
do_read.running = false
|
185
|
+
[ init_read_thread,
|
186
|
+
update_read_thread,
|
187
|
+
update_read_thread,
|
188
|
+
delete_read_thread
|
189
|
+
].each do |thread|
|
190
|
+
thread.join
|
191
|
+
end
|
192
|
+
|
193
|
+
@tman.transaction(true) {|tx|
|
194
|
+
assert_equal([ :foo ], tx.keys)
|
195
|
+
assert_equal('Hello world.', tx[:foo])
|
196
|
+
}
|
197
|
+
end
|
198
|
+
|
199
|
+
WORK_COUNT = 100
|
200
|
+
READ_THREAD_COUNT = 10
|
201
|
+
WRITE_THREAD_COUNT = 2
|
202
|
+
|
203
|
+
def test_read_write_multithread_mvcc
|
204
|
+
do_read = RunFlag.new(true)
|
205
|
+
read_th_grp = ThreadGroup.new
|
206
|
+
write_th_grp = ThreadGroup.new
|
207
|
+
barrier = Barrier.new((READ_THREAD_COUNT + WRITE_THREAD_COUNT) + 1)
|
208
|
+
|
209
|
+
READ_THREAD_COUNT.times{|i|
|
210
|
+
read_th_grp.add Thread.new{
|
211
|
+
barrier.wait
|
212
|
+
while (do_read.running?)
|
213
|
+
@tman.transaction(true) {|tx|
|
214
|
+
if (tx.key? :foo) then
|
215
|
+
assert_equal(tx.change_number.to_s, tx[:foo], "thread: #{i}")
|
216
|
+
end
|
217
|
+
}
|
218
|
+
end
|
219
|
+
}
|
220
|
+
}
|
221
|
+
|
222
|
+
WRITE_THREAD_COUNT.times{|i|
|
223
|
+
write_th_grp.add Thread.new{
|
224
|
+
barrier.wait
|
225
|
+
WORK_COUNT.times do |j|
|
226
|
+
begin
|
227
|
+
@tman.transaction{|tx|
|
228
|
+
value = tx[:foo] || '0'
|
229
|
+
assert_equal(tx.change_number.to_s, value, "thread-count: #{i}-#{j}")
|
230
|
+
tx[:foo] = value.succ
|
231
|
+
}
|
232
|
+
rescue LockManager::CollisionError
|
233
|
+
retry
|
234
|
+
end
|
235
|
+
end
|
236
|
+
}
|
237
|
+
}
|
238
|
+
|
239
|
+
barrier.wait
|
240
|
+
for t in write_th_grp.list
|
241
|
+
t.join
|
242
|
+
end
|
243
|
+
|
244
|
+
do_read.running = false
|
245
|
+
for t in read_th_grp.list
|
246
|
+
t.join
|
247
|
+
end
|
248
|
+
|
249
|
+
@tman.transaction(true) {|tx|
|
250
|
+
assert_equal((WRITE_THREAD_COUNT * WORK_COUNT).to_s, tx[:foo])
|
251
|
+
}
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
class TransactionManagerMVCCTest_with_OptimisticLockManager < TransactionManagerMVCCTest
|
256
|
+
def create_lock_manager
|
257
|
+
OptimisticLockManager.new
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# Local Variables:
|
263
|
+
# mode: Ruby
|
264
|
+
# indent-tabs-mode: nil
|
265
|
+
# End:
|
data/test/test_utils_bman.rb
CHANGED
@@ -8,12 +8,14 @@ require 'higgs/utils/bman'
|
|
8
8
|
require 'logger'
|
9
9
|
require 'test/unit'
|
10
10
|
|
11
|
+
Thread.abort_on_exception = true if $DEBUG
|
12
|
+
|
11
13
|
module Higgs::Test
|
12
14
|
class UtilsBackupManagerTest < Test::Unit::TestCase
|
13
15
|
include Higgs
|
14
16
|
|
15
17
|
# for ident(1)
|
16
|
-
CVS_ID = '$Id: test_utils_bman.rb
|
18
|
+
CVS_ID = '$Id: test_utils_bman.rb 742 2008-01-13 15:55:53Z toki $'
|
17
19
|
|
18
20
|
STORAGE_ITEMS = (ENV['STORAGE_ITEMS'] || '100').to_i
|
19
21
|
WARM_START_ITEMS = (ENV['WARM_START_ITEMS'] || '1000').to_i
|