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/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:
|