higgs 0.1.2 → 0.1.3

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/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 559 2007-09-25 15:20:20Z toki $'
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 559 2007-09-25 15:20:20Z toki $'
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 559 2007-09-25 15:20:20Z toki $'
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 559 2007-09-25 15:20:20Z toki $'
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 559 2007-09-25 15:20:20Z toki $'
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,
@@ -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 627 2007-10-12 07:10:13Z toki $'
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
- @jlog_rotate_service_uri = 'druby://localhost:14142'
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
- jlog_rotate_service = DRbObject.new_with_uri(@jlog_rotate_service_uri)
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.rotate_entries("#{@backup_name}.jlog")
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"), 'data')
147
- assert_equal(Index.new.load("#{@backup_name}.idx").to_h,
148
- Index.new.load("#{@restore_name}.idx").to_h, 'index')
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: