higgs 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +103 -0
- data/Rakefile +9 -2
- data/bin/higgs_apply_jlog +35 -0
- data/bin/higgs_backup +5 -3
- data/bin/higgs_dump_jlog +25 -9
- data/bin/higgs_ping +46 -0
- data/lib/higgs/block.rb +14 -22
- data/lib/higgs/cache.rb +5 -5
- data/lib/higgs/dbm.rb +8 -24
- data/lib/higgs/index.rb +25 -5
- data/lib/higgs/jlog.rb +4 -8
- data/lib/higgs/lock.rb +33 -11
- data/lib/higgs/services.rb +65 -0
- data/lib/higgs/sman.rb +98 -0
- data/lib/higgs/storage.rb +263 -133
- data/lib/higgs/store.rb +8 -24
- data/lib/higgs/thread.rb +9 -9
- data/lib/higgs/tman.rb +66 -21
- data/lib/higgs/utils/bman.rb +40 -20
- data/lib/higgs/version.rb +4 -4
- data/lib/higgs.rb +4 -4
- data/test/test_block.rb +2 -2
- data/test/test_cache.rb +4 -4
- data/test/test_index.rb +17 -5
- data/test/test_jlog.rb +4 -2
- data/test/test_lock.rb +92 -5
- data/test/test_online_backup.rb +19 -10
- data/test/test_replication.rb +468 -0
- data/test/test_services.rb +125 -0
- data/test/test_storage.rb +338 -16
- data/test/test_storage_conf.rb +1 -9
- data/test/test_storage_init_opts.rb +1 -9
- data/test/test_thread.rb +7 -7
- data/test/test_tman.rb +205 -15
- data/test/test_utils_bman.rb +66 -62
- metadata +10 -2
data/test/test_lock.rb
CHANGED
@@ -10,7 +10,7 @@ module Higgs::Test
|
|
10
10
|
include Higgs
|
11
11
|
|
12
12
|
# for ident(1)
|
13
|
-
CVS_ID = '$Id: test_lock.rb
|
13
|
+
CVS_ID = '$Id: test_lock.rb 652 2007-10-22 15:23:50Z toki $'
|
14
14
|
|
15
15
|
WORK_COUNT = 100
|
16
16
|
THREAD_COUNT = 10
|
@@ -118,6 +118,93 @@ module Higgs::Test
|
|
118
118
|
end
|
119
119
|
assert_equal(THREAD_COUNT * WORK_COUNT, count)
|
120
120
|
end
|
121
|
+
|
122
|
+
def test_exclusive_single_thread
|
123
|
+
v = "foo"
|
124
|
+
WORK_COUNT.times do
|
125
|
+
@lock_manager.exclusive{
|
126
|
+
assert_equal("foo", v)
|
127
|
+
}
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_exclusive_multithread
|
132
|
+
count = 0
|
133
|
+
th_grp = ThreadGroup.new
|
134
|
+
barrier = Barrier.new(THREAD_COUNT + 1)
|
135
|
+
|
136
|
+
THREAD_COUNT.times do
|
137
|
+
th_grp.add Thread.new{
|
138
|
+
barrier.wait
|
139
|
+
WORK_COUNT.times do
|
140
|
+
@lock_manager.exclusive{
|
141
|
+
count += 1
|
142
|
+
}
|
143
|
+
end
|
144
|
+
}
|
145
|
+
end
|
146
|
+
|
147
|
+
barrier.wait
|
148
|
+
for t in th_grp.list
|
149
|
+
t.join
|
150
|
+
end
|
151
|
+
assert_equal(THREAD_COUNT * WORK_COUNT, count)
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_read_write_exclusive_multithread
|
155
|
+
v = 'foo'
|
156
|
+
count = 0
|
157
|
+
th_grp = ThreadGroup.new
|
158
|
+
barrier = Barrier.new(THREAD_COUNT * 3 + 1)
|
159
|
+
|
160
|
+
THREAD_COUNT.times{|i|
|
161
|
+
th_grp.add Thread.new{
|
162
|
+
barrier.wait
|
163
|
+
WORK_COUNT.times do |j|
|
164
|
+
@lock_manager.transaction(true) {|lock_handler|
|
165
|
+
lock_handler.lock(:foo)
|
166
|
+
assert_equal('foo', v, "read transaction: #{i}.#{j}")
|
167
|
+
}
|
168
|
+
end
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
172
|
+
THREAD_COUNT.times{|i|
|
173
|
+
th_grp.add Thread.new{
|
174
|
+
barrier.wait
|
175
|
+
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
|
+
}
|
183
|
+
end
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
THREAD_COUNT.times{|i|
|
188
|
+
th_grp.add Thread.new{
|
189
|
+
barrier.wait
|
190
|
+
WORK_COUNT.times do |j|
|
191
|
+
@lock_manager.exclusive{
|
192
|
+
assert_equal('foo', v, "exclusive: #{i}.#{j}")
|
193
|
+
v = 'baz'
|
194
|
+
v = 'foo'
|
195
|
+
count += 1
|
196
|
+
}
|
197
|
+
end
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
barrier.wait
|
202
|
+
for t in th_grp.list
|
203
|
+
t.join
|
204
|
+
end
|
205
|
+
assert_equal('foo', v)
|
206
|
+
assert_equal(THREAD_COUNT * WORK_COUNT * 2, count)
|
207
|
+
end
|
121
208
|
end
|
122
209
|
|
123
210
|
class GiantLockManagerTest < Test::Unit::TestCase
|
@@ -125,7 +212,7 @@ module Higgs::Test
|
|
125
212
|
include LockManagerTest
|
126
213
|
|
127
214
|
# for ident(1)
|
128
|
-
CVS_ID = '$Id: test_lock.rb
|
215
|
+
CVS_ID = '$Id: test_lock.rb 652 2007-10-22 15:23:50Z toki $'
|
129
216
|
|
130
217
|
def setup
|
131
218
|
@lock_manager = GiantLockManager.new
|
@@ -170,7 +257,7 @@ module Higgs::Test
|
|
170
257
|
include LockManagerTest
|
171
258
|
|
172
259
|
# for ident(1)
|
173
|
-
CVS_ID = '$Id: test_lock.rb
|
260
|
+
CVS_ID = '$Id: test_lock.rb 652 2007-10-22 15:23:50Z toki $'
|
174
261
|
|
175
262
|
def setup
|
176
263
|
@lock_manager = FineGrainLockManager.new
|
@@ -214,7 +301,7 @@ module Higgs::Test
|
|
214
301
|
include Higgs
|
215
302
|
|
216
303
|
# for ident(1)
|
217
|
-
CVS_ID = '$Id: test_lock.rb
|
304
|
+
CVS_ID = '$Id: test_lock.rb 652 2007-10-22 15:23:50Z toki $'
|
218
305
|
|
219
306
|
WORK_COUNT = 1000
|
220
307
|
|
@@ -255,7 +342,7 @@ module Higgs::Test
|
|
255
342
|
include Higgs
|
256
343
|
|
257
344
|
# for ident(1)
|
258
|
-
CVS_ID = '$Id: test_lock.rb
|
345
|
+
CVS_ID = '$Id: test_lock.rb 652 2007-10-22 15:23:50Z toki $'
|
259
346
|
|
260
347
|
def setup
|
261
348
|
@lock_manager = FineGrainLockManager.new(:spin_lock_count => 10,
|
data/test/test_online_backup.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'drb'
|
4
4
|
require 'fileutils'
|
5
5
|
require 'higgs/index'
|
6
|
+
require 'higgs/services'
|
6
7
|
require 'higgs/storage'
|
7
8
|
require 'logger'
|
8
9
|
require 'test/unit'
|
@@ -30,7 +31,7 @@ module Higgs::Test
|
|
30
31
|
include OnlineBackupParams
|
31
32
|
|
32
33
|
# for ident(1)
|
33
|
-
CVS_ID = '$Id: test_online_backup.rb
|
34
|
+
CVS_ID = '$Id: test_online_backup.rb 655 2007-10-23 16:32:59Z toki $'
|
34
35
|
|
35
36
|
def setup
|
36
37
|
srand(0)
|
@@ -45,7 +46,7 @@ module Higgs::Test
|
|
45
46
|
FileUtils.rm_rf(@restore_dir) # for debug
|
46
47
|
FileUtils.mkdir_p(@restore_dir)
|
47
48
|
|
48
|
-
@
|
49
|
+
@remote_services_uri = 'druby://localhost:14142'
|
49
50
|
|
50
51
|
@start_latch = File.join(@backup_dir, '.start')
|
51
52
|
@stop_latch = File.join(@backup_dir, '.stop')
|
@@ -59,18 +60,19 @@ module Higgs::Test
|
|
59
60
|
end
|
60
61
|
|
61
62
|
def run_backup_storage
|
62
|
-
# step 0: storage starts with jlog_rotate_service_uri option
|
63
|
-
# (jlog_rotate_service_uri option is disabled by default)
|
64
63
|
st = Storage.new(@backup_name,
|
65
64
|
:jlog_rotate_max => 0,
|
66
65
|
:jlog_rotate_size => COMMIT_ITEMS * MAX_ITEM_BYTES * LEAST_COMMITS_PER_ROTATION,
|
67
|
-
:jlog_rotate_service_uri => @jlog_rotate_service_uri,
|
68
66
|
:logger => proc{|path|
|
69
67
|
logger = Logger.new(path, 1)
|
70
68
|
logger.level = Logger::DEBUG
|
71
69
|
logger
|
72
70
|
})
|
73
71
|
|
72
|
+
# step 0: storage starts with remote services.
|
73
|
+
sv = RemoteServices.new(:remote_services_uri => @remote_services_uri,
|
74
|
+
:storage => st)
|
75
|
+
|
74
76
|
begin
|
75
77
|
FileUtils.touch(@start_latch)
|
76
78
|
until (File.exist? @stop_latch)
|
@@ -103,17 +105,24 @@ module Higgs::Test
|
|
103
105
|
st.verify
|
104
106
|
ensure
|
105
107
|
st.shutdown
|
108
|
+
sv.shutdown
|
106
109
|
end
|
107
110
|
end
|
108
111
|
private :run_backup_storage
|
109
112
|
|
110
113
|
def test_online_backup
|
111
114
|
pid = fork{ run_backup_storage }
|
115
|
+
DRb.start_service
|
112
116
|
begin
|
113
117
|
until (File.exist? @start_latch)
|
114
118
|
# spin lock
|
115
119
|
end
|
116
|
-
|
120
|
+
sv = DRbObject.new_with_uri(@remote_services_uri)
|
121
|
+
localhost_check_service = sv[:localhost_check_service_v1] or flunk
|
122
|
+
localhost_check_service.call{|check|
|
123
|
+
check.call
|
124
|
+
}
|
125
|
+
jlog_rotate_service = sv[:jlog_rotate_service_v1] or flunk
|
117
126
|
sleep(UPTIME_SECONDS)
|
118
127
|
|
119
128
|
# step 1: backup index
|
@@ -134,7 +143,7 @@ module Higgs::Test
|
|
134
143
|
jlog_rotate_service.call(true)
|
135
144
|
|
136
145
|
# step 4: backup old journal logs
|
137
|
-
for path in Storage.
|
146
|
+
for path in Storage.rotated_entries("#{@backup_name}.jlog")
|
138
147
|
FileUtils.cp(path, File.join(@restore_dir, File.basename(path)))
|
139
148
|
FileUtils.rm(path)
|
140
149
|
end
|
@@ -143,9 +152,9 @@ module Higgs::Test
|
|
143
152
|
Storage.recover(@restore_name)
|
144
153
|
|
145
154
|
# recovered files are same as original files.
|
146
|
-
assert(FileUtils.cmp("#{@backup_name}.tar", "#{@restore_name}.tar"), '
|
147
|
-
|
148
|
-
|
155
|
+
assert(FileUtils.cmp("#{@backup_name}.tar", "#{@restore_name}.tar"), 'DATA should be same.')
|
156
|
+
assert(Index.new.load("#{@backup_name}.idx").to_h ==
|
157
|
+
Index.new.load("#{@restore_name}.idx").to_h, 'INDEX should be same.')
|
149
158
|
ensure
|
150
159
|
FileUtils.touch(@stop_latch)
|
151
160
|
FileUtils.touch(@end_latch)
|
@@ -0,0 +1,468 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'higgs/dbm'
|
5
|
+
require 'higgs/storage'
|
6
|
+
require 'higgs/store'
|
7
|
+
require 'higgs/thread'
|
8
|
+
require 'higgs/tman'
|
9
|
+
require 'logger'
|
10
|
+
require 'test/unit'
|
11
|
+
|
12
|
+
module Higgs::Test
|
13
|
+
module ReplicationTest
|
14
|
+
include Higgs
|
15
|
+
|
16
|
+
# for ident(1)
|
17
|
+
CVS_ID = '$Id: test_tman.rb 662 2007-11-03 16:13:33Z toki $'
|
18
|
+
|
19
|
+
STORAGE_ITEMS = (ENV['STORAGE_ITEMS'] || '100').to_i
|
20
|
+
WARM_START_ITEMS = (ENV['WARM_START_ITEMS'] || '1000').to_i
|
21
|
+
MAX_ITEM_BYTES = (ENV['MAX_ITEM_BYTES'] || '16384').to_i
|
22
|
+
ITEM_CHARS = ('A'..'Z').to_a + ('a'..'z').to_a
|
23
|
+
|
24
|
+
def setup
|
25
|
+
srand(0)
|
26
|
+
|
27
|
+
@name = 'foo'
|
28
|
+
|
29
|
+
@src_dir = 'rep_src'
|
30
|
+
@src_name = File.join(@src_dir, @name)
|
31
|
+
FileUtils.rm_rf(@src_dir)
|
32
|
+
FileUtils.mkdir_p(@src_dir)
|
33
|
+
|
34
|
+
@dst_dir = 'rep_dst'
|
35
|
+
@dst_name = File.join(@dst_dir, @name)
|
36
|
+
FileUtils.rm_rf(@dst_dir)
|
37
|
+
FileUtils.mkdir_p(@dst_dir)
|
38
|
+
|
39
|
+
@jlog_apply_dir = 'rep_jlog'
|
40
|
+
FileUtils.rm_rf(@jlog_apply_dir)
|
41
|
+
FileUtils.mkdir_p(@jlog_apply_dir)
|
42
|
+
|
43
|
+
@logger = proc{|path|
|
44
|
+
logger = Logger.new(path, 1)
|
45
|
+
logger.level = Logger::DEBUG
|
46
|
+
logger
|
47
|
+
}
|
48
|
+
|
49
|
+
setup_storage
|
50
|
+
end
|
51
|
+
|
52
|
+
def teardown
|
53
|
+
shutdown_storage
|
54
|
+
FileUtils.rm_rf(@src_dir) unless $DEBUG
|
55
|
+
FileUtils.rm_rf(@dst_dir) unless $DEBUG
|
56
|
+
FileUtils.rm_rf(@jlog_apply_dir) unless $DEBUG
|
57
|
+
end
|
58
|
+
|
59
|
+
def move_jlog
|
60
|
+
for jlog in Storage.rotated_entries("#{@src_name}.jlog")
|
61
|
+
name = File.basename(jlog)
|
62
|
+
target = File.join(@jlog_apply_dir, name)
|
63
|
+
FileUtils.mv(jlog, target)
|
64
|
+
end
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
private :move_jlog
|
68
|
+
|
69
|
+
def test_replication_basic
|
70
|
+
#### create ####
|
71
|
+
|
72
|
+
@src.transaction{|tx|
|
73
|
+
tx[:foo] = "Hello world.\n"
|
74
|
+
}
|
75
|
+
@dst.transaction{|tx|
|
76
|
+
assert(tx.empty?)
|
77
|
+
}
|
78
|
+
|
79
|
+
src_rotate_journal_log
|
80
|
+
move_jlog
|
81
|
+
@dst.apply_journal_log
|
82
|
+
|
83
|
+
@dst.transaction{|tx|
|
84
|
+
assert(! tx.empty?)
|
85
|
+
assert_equal([ :foo ], tx.keys)
|
86
|
+
assert_equal("Hello world.\n", tx[:foo])
|
87
|
+
}
|
88
|
+
|
89
|
+
#### set property ####
|
90
|
+
|
91
|
+
@src.transaction{|tx|
|
92
|
+
tx.set_property(:foo, 'bar', 'Banana')
|
93
|
+
}
|
94
|
+
@dst.transaction{|tx|
|
95
|
+
assert(! (tx.property? :foo, 'bar'))
|
96
|
+
}
|
97
|
+
|
98
|
+
src_rotate_journal_log
|
99
|
+
move_jlog
|
100
|
+
@dst.apply_journal_log
|
101
|
+
|
102
|
+
@dst.transaction{|tx|
|
103
|
+
assert((tx.property? :foo, 'bar'))
|
104
|
+
assert_equal('Banana', tx.property(:foo, 'bar'))
|
105
|
+
}
|
106
|
+
|
107
|
+
#### update property ####
|
108
|
+
|
109
|
+
@src.transaction{|tx|
|
110
|
+
tx.set_property(:foo, 'bar', 'Orange')
|
111
|
+
}
|
112
|
+
@dst.transaction{|tx|
|
113
|
+
assert((tx.property? :foo, 'bar'))
|
114
|
+
assert_equal('Banana', tx.property(:foo, 'bar'))
|
115
|
+
}
|
116
|
+
|
117
|
+
src_rotate_journal_log
|
118
|
+
move_jlog
|
119
|
+
@dst.apply_journal_log
|
120
|
+
|
121
|
+
@dst.transaction{|tx|
|
122
|
+
assert((tx.property? :foo, 'bar'))
|
123
|
+
assert_equal('Orange', tx.property(:foo, 'bar'))
|
124
|
+
}
|
125
|
+
|
126
|
+
#### delete property ####
|
127
|
+
|
128
|
+
@src.transaction{|tx|
|
129
|
+
tx.delete_property(:foo, 'bar')
|
130
|
+
}
|
131
|
+
@dst.transaction{|tx|
|
132
|
+
assert((tx.property? :foo, 'bar'))
|
133
|
+
assert_equal('Orange', tx.property(:foo, 'bar'))
|
134
|
+
}
|
135
|
+
|
136
|
+
src_rotate_journal_log
|
137
|
+
move_jlog
|
138
|
+
@dst.apply_journal_log
|
139
|
+
|
140
|
+
@dst.transaction{|tx|
|
141
|
+
assert(! (tx.property? :foo, 'bar'))
|
142
|
+
}
|
143
|
+
|
144
|
+
#### update ####
|
145
|
+
|
146
|
+
@src.transaction{|tx|
|
147
|
+
tx[:foo] = 'Apple'
|
148
|
+
}
|
149
|
+
@dst.transaction{|tx|
|
150
|
+
assert(! tx.empty?)
|
151
|
+
assert_equal([ :foo ], tx.keys)
|
152
|
+
assert_equal("Hello world.\n", tx[:foo])
|
153
|
+
}
|
154
|
+
|
155
|
+
src_rotate_journal_log
|
156
|
+
move_jlog
|
157
|
+
@dst.apply_journal_log
|
158
|
+
|
159
|
+
@dst.transaction{|tx|
|
160
|
+
assert(! tx.empty?)
|
161
|
+
assert_equal([ :foo ], tx.keys)
|
162
|
+
assert_equal('Apple', tx[:foo])
|
163
|
+
}
|
164
|
+
|
165
|
+
#### delete ####
|
166
|
+
|
167
|
+
@src.transaction{|tx|
|
168
|
+
tx.delete(:foo)
|
169
|
+
}
|
170
|
+
@dst.transaction{|tx|
|
171
|
+
assert(! tx.empty?)
|
172
|
+
assert_equal([ :foo ], tx.keys)
|
173
|
+
assert_equal('Apple', tx[:foo])
|
174
|
+
}
|
175
|
+
|
176
|
+
src_rotate_journal_log
|
177
|
+
move_jlog
|
178
|
+
@dst.apply_journal_log
|
179
|
+
|
180
|
+
@dst.transaction{|tx|
|
181
|
+
assert(tx.empty?)
|
182
|
+
}
|
183
|
+
|
184
|
+
####
|
185
|
+
|
186
|
+
shutdown_storage
|
187
|
+
|
188
|
+
assert(FileUtils.cmp("#{@src_name}.tar", "#{@dst_name}.tar"), 'DATA should be same.')
|
189
|
+
assert(Index.new.load("#{@src_name}.idx").to_h ==
|
190
|
+
Index.new.load("#{@dst_name}.idx").to_h, 'INDEX should be same.')
|
191
|
+
end
|
192
|
+
|
193
|
+
def update_source_storage(options)
|
194
|
+
count = 0
|
195
|
+
operations = [
|
196
|
+
:write_data,
|
197
|
+
:delete_data,
|
198
|
+
:write_system_properties,
|
199
|
+
:write_custom_properties,
|
200
|
+
:delete_custom_properties
|
201
|
+
]
|
202
|
+
while (options[:spin_lock])
|
203
|
+
count += 1
|
204
|
+
options[:end_of_warm_up].start if (count == WARM_START_ITEMS)
|
205
|
+
|
206
|
+
ope = operations[rand(operations.length)]
|
207
|
+
key = rand(STORAGE_ITEMS)
|
208
|
+
case (ope)
|
209
|
+
when :write_data
|
210
|
+
value = rand(256).chr * rand(MAX_ITEM_BYTES)
|
211
|
+
@src.transaction{|tx|
|
212
|
+
tx[key] = value
|
213
|
+
}
|
214
|
+
when :delete_data
|
215
|
+
@src.transaction{|tx|
|
216
|
+
tx.delete(key)
|
217
|
+
}
|
218
|
+
when :write_system_properties
|
219
|
+
@src.transaction{|tx|
|
220
|
+
if (tx.key? key) then
|
221
|
+
tx.set_property(key, 'string_only', rand(2) > 0)
|
222
|
+
end
|
223
|
+
}
|
224
|
+
when :write_custom_properties
|
225
|
+
@src.transaction{|tx|
|
226
|
+
if (tx.key? key) then
|
227
|
+
value = ITEM_CHARS[rand(ITEM_CHARS.length)] * rand(MAX_ITEM_BYTES)
|
228
|
+
tx.set_property(key, 'foo', value)
|
229
|
+
end
|
230
|
+
}
|
231
|
+
when :delete_custom_properties
|
232
|
+
@src.transaction{|tx|
|
233
|
+
if (tx.key? key) then
|
234
|
+
tx.delete_property(key, 'foo')
|
235
|
+
end
|
236
|
+
}
|
237
|
+
else
|
238
|
+
raise "unknown operation: #{ope}"
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
private :update_source_storage
|
243
|
+
|
244
|
+
def test_update_source_storage
|
245
|
+
options = {
|
246
|
+
:end_of_warm_up => Latch.new,
|
247
|
+
:spin_lock => true
|
248
|
+
}
|
249
|
+
t = Thread.new{ update_source_storage(options) }
|
250
|
+
options[:end_of_warm_up].wait
|
251
|
+
options[:spin_lock] = false
|
252
|
+
t.join
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_replication_with_multithread
|
256
|
+
options = {
|
257
|
+
:end_of_warm_up => Latch.new,
|
258
|
+
:spin_lock => true
|
259
|
+
}
|
260
|
+
t = Thread.new{ update_source_storage(options) }
|
261
|
+
options[:end_of_warm_up].wait
|
262
|
+
|
263
|
+
10.times do
|
264
|
+
sleep(0.01)
|
265
|
+
move_jlog
|
266
|
+
@dst.apply_journal_log
|
267
|
+
end
|
268
|
+
|
269
|
+
options[:spin_lock] = false
|
270
|
+
t.join
|
271
|
+
|
272
|
+
src_rotate_journal_log
|
273
|
+
move_jlog
|
274
|
+
@dst.apply_journal_log
|
275
|
+
|
276
|
+
shutdown_storage
|
277
|
+
|
278
|
+
assert(FileUtils.cmp("#{@src_name}.tar", "#{@dst_name}.tar"), 'DATA should be same.')
|
279
|
+
assert(Index.new.load("#{@src_name}.idx").to_h ==
|
280
|
+
Index.new.load("#{@dst_name}.idx").to_h, 'INDEX should be same.')
|
281
|
+
end
|
282
|
+
|
283
|
+
def test_switch_to_write
|
284
|
+
# check standby mode
|
285
|
+
assert_equal(:standby, @dst.read_only)
|
286
|
+
@dst.transaction{|tx|
|
287
|
+
assert_raise(NoMethodError) { tx[:foo] = "Hello world.\n" }
|
288
|
+
assert_raise(NoMethodError) { tx.set_property(:foo, 'baz', 'orange') }
|
289
|
+
assert_raise(NoMethodError) { tx.delete_property(:foo, 'bar') }
|
290
|
+
assert_raise(NoMethodError) { tx.delete(:foo) }
|
291
|
+
assert_raise(NoMethodError) { tx.delete_if{|key, value| value == 'apple' } }
|
292
|
+
assert_raise(NoMethodError) { tx.clear }
|
293
|
+
assert_raise(NoMethodError) { tx.commit }
|
294
|
+
assert_raise(NoMethodError) { tx.rollback }
|
295
|
+
}
|
296
|
+
assert_raise(Higgs::Storage::NotWritableError) {
|
297
|
+
dst_rotate_journal_log
|
298
|
+
}
|
299
|
+
|
300
|
+
# replication enabled
|
301
|
+
test_update_source_storage
|
302
|
+
src_rotate_journal_log
|
303
|
+
move_jlog
|
304
|
+
@dst.apply_journal_log
|
305
|
+
|
306
|
+
# standby -> read-write
|
307
|
+
@dst.switch_to_write
|
308
|
+
assert_equal(false, @dst.read_only)
|
309
|
+
|
310
|
+
# replication disabled
|
311
|
+
test_update_source_storage
|
312
|
+
src_rotate_journal_log
|
313
|
+
move_jlog
|
314
|
+
assert_raise(RuntimeError) {
|
315
|
+
@dst.apply_journal_log
|
316
|
+
}
|
317
|
+
|
318
|
+
# check read-write
|
319
|
+
@dst.transaction{|tx|
|
320
|
+
tx[:foo] = "Hello world.\n"
|
321
|
+
tx.set_property(:foo, 'baz', 'orange')
|
322
|
+
tx.delete_property(:foo, 'bar')
|
323
|
+
tx.delete(:foo)
|
324
|
+
tx.delete_if{|key, value| value == 'apple' }
|
325
|
+
tx.clear
|
326
|
+
tx.commit
|
327
|
+
tx.rollback
|
328
|
+
}
|
329
|
+
dst_rotate_journal_log
|
330
|
+
end
|
331
|
+
|
332
|
+
def test_switch_to_write_RuntimeError_not_standby_mode
|
333
|
+
assert_equal(false, @src.read_only)
|
334
|
+
assert_raise(RuntimeError) {
|
335
|
+
@src.switch_to_write
|
336
|
+
}
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
class TransactionManagerReplicationTest < Test::Unit::TestCase
|
341
|
+
include Higgs
|
342
|
+
include ReplicationTest
|
343
|
+
|
344
|
+
# for ident(1)
|
345
|
+
CVS_ID = '$Id: test_tman.rb 662 2007-11-03 16:13:33Z toki $'
|
346
|
+
|
347
|
+
def setup_storage
|
348
|
+
@src_st = Storage.new(@src_name,
|
349
|
+
:logger => @logger,
|
350
|
+
:jlog_rotate_max => 0)
|
351
|
+
|
352
|
+
@src_st.rotate_journal_log(true)
|
353
|
+
FileUtils.cp("#{@src_name}.tar", "#{@dst_name}.tar", :preserve => true)
|
354
|
+
FileUtils.cp("#{@src_name}.idx", "#{@dst_name}.idx", :preserve => true)
|
355
|
+
|
356
|
+
@dst_st = Storage.new(@dst_name,
|
357
|
+
:logger => @logger,
|
358
|
+
:read_only => :standby)
|
359
|
+
|
360
|
+
for jlog_path in Storage.rotated_entries("#{@src_name}.jlog")
|
361
|
+
@dst_st.apply_journal_log(jlog_path)
|
362
|
+
end
|
363
|
+
|
364
|
+
@src = TransactionManager.new(@src_st)
|
365
|
+
@dst = TransactionManager.new(@dst_st,
|
366
|
+
:read_only => :standby,
|
367
|
+
:jlog_apply_dir => @jlog_apply_dir)
|
368
|
+
end
|
369
|
+
|
370
|
+
def shutdown_storage
|
371
|
+
@src_st.shutdown if (@src_st && ! @src_st.shutdown?)
|
372
|
+
@dst_st.shutdown if (@dst_st && ! @dst_st.shutdown?)
|
373
|
+
end
|
374
|
+
|
375
|
+
def src_rotate_journal_log
|
376
|
+
@src_st.rotate_journal_log
|
377
|
+
end
|
378
|
+
|
379
|
+
def dst_rotate_journal_log
|
380
|
+
@dst_st.rotate_journal_log
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
class StoreReplicationTest < Test::Unit::TestCase
|
385
|
+
include Higgs
|
386
|
+
include ReplicationTest
|
387
|
+
|
388
|
+
# for ident(1)
|
389
|
+
CVS_ID = '$Id$'
|
390
|
+
|
391
|
+
def setup_storage
|
392
|
+
@src = Store.new(@src_name,
|
393
|
+
:logger => @logger,
|
394
|
+
:jlog_rotate_max => 0)
|
395
|
+
|
396
|
+
@src.rotate_journal_log(true)
|
397
|
+
FileUtils.cp("#{@src_name}.tar", "#{@dst_name}.tar", :preserve => true)
|
398
|
+
FileUtils.cp("#{@src_name}.idx", "#{@dst_name}.idx", :preserve => true)
|
399
|
+
|
400
|
+
@dst = Store.new(@dst_name,
|
401
|
+
:logger => @logger,
|
402
|
+
:read_only => :standby,
|
403
|
+
:jlog_apply_dir => @jlog_apply_dir)
|
404
|
+
|
405
|
+
for jlog_path in Storage.rotated_entries("#{@src_name}.jlog")
|
406
|
+
@dst.apply_journal_log(jlog_path)
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
def shutdown_storage
|
411
|
+
@src.shutdown if (@src && ! @src.shutdown?)
|
412
|
+
@dst.shutdown if (@dst && ! @dst.shutdown?)
|
413
|
+
end
|
414
|
+
|
415
|
+
def src_rotate_journal_log
|
416
|
+
@src.rotate_journal_log
|
417
|
+
end
|
418
|
+
|
419
|
+
def dst_rotate_journal_log
|
420
|
+
@dst.rotate_journal_log
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
class DBMReplicationTest < Test::Unit::TestCase
|
425
|
+
include Higgs
|
426
|
+
include ReplicationTest
|
427
|
+
|
428
|
+
# for ident(1)
|
429
|
+
CVS_ID = '$Id$'
|
430
|
+
|
431
|
+
def setup_storage
|
432
|
+
@src = DBM.new(@src_name,
|
433
|
+
:logger => @logger,
|
434
|
+
:jlog_rotate_max => 0)
|
435
|
+
|
436
|
+
@src.rotate_journal_log(true)
|
437
|
+
FileUtils.cp("#{@src_name}.tar", "#{@dst_name}.tar", :preserve => true)
|
438
|
+
FileUtils.cp("#{@src_name}.idx", "#{@dst_name}.idx", :preserve => true)
|
439
|
+
|
440
|
+
@dst = DBM.new(@dst_name,
|
441
|
+
:logger => @logger,
|
442
|
+
:read_only => :standby,
|
443
|
+
:jlog_apply_dir => @jlog_apply_dir)
|
444
|
+
|
445
|
+
for jlog_path in Storage.rotated_entries("#{@src_name}.jlog")
|
446
|
+
@dst.apply_journal_log(jlog_path)
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
def shutdown_storage
|
451
|
+
@src.shutdown if (@src && ! @src.shutdown?)
|
452
|
+
@dst.shutdown if (@dst && ! @dst.shutdown?)
|
453
|
+
end
|
454
|
+
|
455
|
+
def src_rotate_journal_log
|
456
|
+
@src.rotate_journal_log
|
457
|
+
end
|
458
|
+
|
459
|
+
def dst_rotate_journal_log
|
460
|
+
@dst.rotate_journal_log
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
# Local Variables:
|
466
|
+
# mode: Ruby
|
467
|
+
# indent-tabs-mode: nil
|
468
|
+
# End:
|