rims 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/ChangeLog +379 -0
  4. data/Gemfile +11 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +566 -0
  7. data/Rakefile +29 -0
  8. data/bin/rims +11 -0
  9. data/lib/rims.rb +45 -0
  10. data/lib/rims/auth.rb +133 -0
  11. data/lib/rims/cksum_kvs.rb +68 -0
  12. data/lib/rims/cmd.rb +809 -0
  13. data/lib/rims/daemon.rb +338 -0
  14. data/lib/rims/db.rb +793 -0
  15. data/lib/rims/error.rb +23 -0
  16. data/lib/rims/gdbm_kvs.rb +76 -0
  17. data/lib/rims/hash_kvs.rb +66 -0
  18. data/lib/rims/kvs.rb +101 -0
  19. data/lib/rims/lock.rb +151 -0
  20. data/lib/rims/mail_store.rb +663 -0
  21. data/lib/rims/passwd.rb +251 -0
  22. data/lib/rims/pool.rb +88 -0
  23. data/lib/rims/protocol.rb +71 -0
  24. data/lib/rims/protocol/decoder.rb +1469 -0
  25. data/lib/rims/protocol/parser.rb +1114 -0
  26. data/lib/rims/rfc822.rb +456 -0
  27. data/lib/rims/server.rb +567 -0
  28. data/lib/rims/test.rb +391 -0
  29. data/lib/rims/version.rb +11 -0
  30. data/load_test/Rakefile +93 -0
  31. data/rims.gemspec +38 -0
  32. data/test/test_auth.rb +174 -0
  33. data/test/test_cksum_kvs.rb +121 -0
  34. data/test/test_config.rb +533 -0
  35. data/test/test_daemon_status_file.rb +169 -0
  36. data/test/test_daemon_waitpid.rb +72 -0
  37. data/test/test_db.rb +602 -0
  38. data/test/test_db_recovery.rb +732 -0
  39. data/test/test_error.rb +97 -0
  40. data/test/test_gdbm_kvs.rb +32 -0
  41. data/test/test_hash_kvs.rb +116 -0
  42. data/test/test_lock.rb +161 -0
  43. data/test/test_mail_store.rb +750 -0
  44. data/test/test_passwd.rb +203 -0
  45. data/test/test_protocol.rb +91 -0
  46. data/test/test_protocol_auth.rb +121 -0
  47. data/test/test_protocol_decoder.rb +6490 -0
  48. data/test/test_protocol_fetch.rb +994 -0
  49. data/test/test_protocol_request.rb +332 -0
  50. data/test/test_protocol_search.rb +974 -0
  51. data/test/test_rfc822.rb +696 -0
  52. metadata +174 -0
@@ -0,0 +1,732 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'logger'
4
+ require 'pp' if $DEBUG
5
+ require 'rims'
6
+ require 'test/unit'
7
+
8
+ module RIMS::Test
9
+ class DBRecoveryTest < Test::Unit::TestCase
10
+ def setup
11
+ @logger = Logger.new(STDOUT)
12
+ @logger.level = ($DEBUG) ? Logger::DEBUG : Logger::FATAL
13
+
14
+ @kvs = {}
15
+ @kvs_open = proc{|name| RIMS::Hash_KeyValueStore.new(@kvs[name] = {}) }
16
+
17
+ @meta_db = RIMS::DB::Meta.new(@kvs_open.call('meta'))
18
+ @msg_db = RIMS::DB::Message.new(@kvs_open.call('msg'))
19
+ @mbox_db = {}
20
+
21
+ @mail_store = RIMS::MailStore.new(@meta_db, @msg_db) {|mbox_id|
22
+ @mbox_db[mbox_id] = RIMS::DB::Mailbox.new(@kvs_open.call("mbox_#{mbox_id}"))
23
+ }
24
+
25
+ @inbox_id = @mail_store.add_mbox('INBOX')
26
+ @meta_db.recovery_start
27
+ end
28
+
29
+ def teardown
30
+ @meta_db.recovery_end
31
+ pp @kvs if $DEBUG
32
+ end
33
+
34
+ def deep_copy(obj)
35
+ Marshal.load(Marshal.dump(obj))
36
+ end
37
+ private :deep_copy
38
+
39
+ def test_recovery_phase1_msg_scan_empty
40
+ prev_kvs = deep_copy(@kvs)
41
+ @meta_db.recovery_phase1_msg_scan(@msg_db, logger: @logger)
42
+ assert_equal(prev_kvs, @kvs)
43
+ end
44
+
45
+ def test_recovery_phase1_msg_scan_some_msgs
46
+ @mail_store.add_msg(@inbox_id, 'foo')
47
+ @mail_store.add_msg(@inbox_id, 'bar')
48
+ @mail_store.add_msg(@inbox_id, 'baz')
49
+ prev_kvs = deep_copy(@kvs)
50
+
51
+ @meta_db.recovery_phase1_msg_scan(@msg_db, logger: @logger)
52
+ assert_equal(prev_kvs, @kvs)
53
+ end
54
+
55
+ def test_recovery_phase1_msg_scan_max_msg_id
56
+ @mail_store.add_msg(@inbox_id, 'foo')
57
+ @mail_store.add_msg(@inbox_id, 'bar')
58
+ @mail_store.add_msg(@inbox_id, 'baz')
59
+ prev_kvs = deep_copy(@kvs)
60
+
61
+ @kvs['meta']['msg_id'] = '2'
62
+ assert_equal(2, @meta_db.msg_id)
63
+
64
+ @meta_db.recovery_phase1_msg_scan(@msg_db, logger: @logger)
65
+ assert_equal(3, @meta_db.msg_id)
66
+ assert_equal(prev_kvs, @kvs)
67
+ end
68
+
69
+ def test_recovery_phase1_msg_scan_repair_msg_date
70
+ @mail_store.add_msg(@inbox_id, 'foo')
71
+ @mail_store.add_msg(@inbox_id, 'bar')
72
+ @mail_store.add_msg(@inbox_id, 'baz')
73
+
74
+ @kvs['meta'].delete('msg_id2date-1')
75
+ assert_instance_of(Time, @meta_db.msg_date(0))
76
+ assert_raise(RuntimeError) { @meta_db.msg_date(1) }
77
+ assert_instance_of(Time, @meta_db.msg_date(2))
78
+
79
+ @meta_db.recovery_phase1_msg_scan(@msg_db, logger: @logger)
80
+ assert_instance_of(Time, @meta_db.msg_date(0))
81
+ assert_instance_of(Time, @meta_db.msg_date(1))
82
+ assert_instance_of(Time, @meta_db.msg_date(2))
83
+ end
84
+
85
+ def test_recovery_phase1_msg_scan_msg_collect_lost_found_msg
86
+ @mail_store.add_msg(@inbox_id, 'foo')
87
+ @mail_store.add_msg(@inbox_id, 'bar')
88
+ @mail_store.add_msg(@inbox_id, 'baz')
89
+
90
+ @meta_db.del_msg_mbox_uid(1, @inbox_id, 2)
91
+ @meta_db.clear_msg_mbox_uid_mapping(1)
92
+
93
+ @meta_db.recovery_phase1_msg_scan(@msg_db, logger: @logger)
94
+ assert_equal([ 1 ].to_set, @meta_db.lost_found_msg_set)
95
+ end
96
+
97
+ def test_recovery_phase2_msg_scan_empty
98
+ prev_kvs = deep_copy(@kvs)
99
+ @meta_db.recovery_phase2_msg_scan(@msg_db, logger: @logger)
100
+ assert_equal(prev_kvs, @kvs)
101
+ end
102
+
103
+ def test_recovery_phase2_msg_scan_some_msgs
104
+ @mail_store.add_msg(@inbox_id, 'foo')
105
+ @mail_store.add_msg(@inbox_id, 'bar')
106
+ @mail_store.add_msg(@inbox_id, 'baz')
107
+ prev_kvs = deep_copy(@kvs)
108
+
109
+ @meta_db.recovery_phase2_msg_scan(@msg_db, logger: @logger)
110
+ assert_equal(prev_kvs, @kvs)
111
+ end
112
+
113
+ def test_recovery_phase2_msg_scan_clear_lost_msg
114
+ @mail_store.add_msg(@inbox_id, 'foo')
115
+ @mail_store.add_msg(@inbox_id, 'bar')
116
+ @mail_store.add_msg(@inbox_id, 'baz')
117
+
118
+ @msg_db.del_msg(1)
119
+ assert_equal(false, (@msg_db.msg_exist? 1))
120
+ assert_equal(true, @meta_db.msg_flag(1, 'recent'))
121
+ assert_equal(false, @meta_db.msg_mbox_uid_mapping(1).empty?)
122
+
123
+ @meta_db.recovery_phase2_msg_scan(@msg_db, logger: @logger)
124
+ assert_equal(false, (@msg_db.msg_exist? 1))
125
+ assert_equal(false, @meta_db.msg_flag(1, 'recent'))
126
+ assert_equal(true, @meta_db.msg_mbox_uid_mapping(1).empty?)
127
+ end
128
+
129
+ def test_recovery_phase2_msg_scan_collect_lost_found_mbox
130
+ @mail_store.add_msg(@inbox_id, 'foo')
131
+ @mail_store.add_msg(@inbox_id, 'bar')
132
+ @mail_store.add_msg(@inbox_id, 'baz')
133
+
134
+ mbox_uid_map = Marshal.load(@kvs['meta']['msg_id2mbox-1'])
135
+ uid_set = mbox_uid_map.delete(@inbox_id)
136
+ mbox_uid_map[@inbox_id + 1] = uid_set
137
+ @kvs['meta']['msg_id2mbox-1'] = Marshal.dump(mbox_uid_map)
138
+
139
+ @meta_db.recovery_phase2_msg_scan(@msg_db, logger: @logger)
140
+ assert_equal([ @inbox_id + 1 ].to_set, @meta_db.lost_found_mbox_set)
141
+ end
142
+
143
+ def test_recovery_phase3_msg_scan_empty
144
+ prev_kvs = deep_copy(@kvs)
145
+ @meta_db.recovery_phase3_mbox_scan(logger: @logger)
146
+ assert_equal(prev_kvs, @kvs)
147
+ end
148
+
149
+ def test_recovery_phase3_msg_scan_some_mboxes
150
+ @mail_store.add_mbox('foo')
151
+ @mail_store.add_mbox('bar')
152
+ prev_kvs = deep_copy(@kvs)
153
+
154
+ @meta_db.recovery_phase3_mbox_scan(logger: @logger)
155
+ assert_equal(prev_kvs, @kvs)
156
+ end
157
+
158
+ def test_recovery_phase3_msg_scan_repair_uidvalidity
159
+ @mail_store.add_mbox('foo')
160
+ @mail_store.add_mbox('bar')
161
+ prev_kvs = deep_copy(@kvs)
162
+
163
+ @kvs['meta']['uidvalidity'] = '3'
164
+ assert_equal(3, @meta_db.uidvalidity)
165
+
166
+ @meta_db.recovery_phase3_mbox_scan(logger: @logger)
167
+ assert_equal(4, @meta_db.uidvalidity)
168
+ assert_equal(prev_kvs, @kvs)
169
+ end
170
+
171
+ def test_recovery_phase3_msg_scan_repair_lost_mbox_name2id
172
+ @mail_store.add_mbox('foo')
173
+ @mail_store.add_mbox('bar')
174
+ prev_kvs = deep_copy(@kvs)
175
+
176
+ @kvs['meta'].delete('mbox_name2id-foo')
177
+ assert_equal(1, @meta_db.mbox_id('INBOX'))
178
+ assert_nil(@meta_db.mbox_id('foo'))
179
+ assert_equal(3, @meta_db.mbox_id('bar'))
180
+
181
+ @meta_db.recovery_phase3_mbox_scan(logger: @logger)
182
+ assert_equal(1, @meta_db.mbox_id('INBOX'))
183
+ assert_equal(2, @meta_db.mbox_id('foo'))
184
+ assert_equal(3, @meta_db.mbox_id('bar'))
185
+ assert_equal(prev_kvs, @kvs)
186
+ end
187
+
188
+ def test_recovery_phase3_msg_scan_reapir_dup_mbox_name2id
189
+ @mail_store.add_mbox('foo')
190
+ @mail_store.add_mbox('bar')
191
+ prev_kvs = deep_copy(@kvs)
192
+
193
+ @kvs['meta']['mbox_name2id-foo'] = '1'
194
+ assert_equal(1, @meta_db.mbox_id('INBOX'))
195
+ assert_equal(1, @meta_db.mbox_id('foo'))
196
+ assert_equal(3, @meta_db.mbox_id('bar'))
197
+
198
+ @meta_db.recovery_phase3_mbox_scan(logger: @logger)
199
+ assert_equal(1, @meta_db.mbox_id('INBOX'))
200
+ assert_equal(2, @meta_db.mbox_id('foo'))
201
+ assert_equal(3, @meta_db.mbox_id('bar'))
202
+ assert_equal(prev_kvs, @kvs)
203
+ end
204
+
205
+ def test_recovery_phase3_msg_scan_repair_lost_mbox_id_name_pair
206
+ @mail_store.add_mbox('foo')
207
+ @mail_store.add_mbox('bar')
208
+
209
+ @kvs['meta'].delete('mbox_id2name-2')
210
+ assert_nil(@meta_db.mbox_name(2))
211
+ assert_equal(2, @meta_db.mbox_id('foo'))
212
+
213
+ @meta_db.recovery_phase3_mbox_scan(logger: @logger)
214
+ assert_equal('MAILBOX#2', @meta_db.mbox_name(2))
215
+ assert_equal(2, @meta_db.mbox_id('MAILBOX#2'))
216
+ assert_equal(2, @meta_db.mbox_id('foo')) # recovered at phase 4.
217
+ end
218
+
219
+ def test_recovery_phase3_msg_scan_repair_lost_mbox_id_name_pair2
220
+ @mail_store.add_mbox('foo')
221
+ @mail_store.add_mbox('MAILBOX#2')
222
+ @mail_store.add_mbox('MAILBOX#2 (1)')
223
+ @mail_store.add_mbox('MAILBOX#2 (2)')
224
+
225
+ @kvs['meta'].delete('mbox_id2name-2')
226
+ assert_nil(@meta_db.mbox_name(2))
227
+ assert_equal(2, @meta_db.mbox_id('foo'))
228
+
229
+ @meta_db.recovery_phase3_mbox_scan(logger: @logger)
230
+ assert_equal('MAILBOX#2 (3)', @meta_db.mbox_name(2))
231
+ assert_equal(2, @meta_db.mbox_id('MAILBOX#2 (3)'))
232
+ assert_equal(2, @meta_db.mbox_id('foo')) # recovered at phase 4.
233
+ end
234
+
235
+ def test_recovery_phase4_mbox_scan_empty
236
+ prev_kvs = deep_copy(@kvs)
237
+ @meta_db.recovery_phase4_mbox_scan(logger: @logger)
238
+ assert_equal(prev_kvs, @kvs)
239
+ end
240
+
241
+ def test_recovery_phase4_mbox_scan_some_mboxes
242
+ @mail_store.add_mbox('foo')
243
+ @mail_store.add_mbox('bar')
244
+ prev_kvs = deep_copy(@kvs)
245
+
246
+ @meta_db.recovery_phase4_mbox_scan(logger: @logger)
247
+ assert_equal(prev_kvs, @kvs)
248
+ end
249
+
250
+ def test_recovery_phase4_mbox_scan_excess_key_mbox_id
251
+ @mail_store.add_mbox('foo')
252
+ @mail_store.add_mbox('bar')
253
+ prev_kvs = deep_copy(@kvs)
254
+
255
+ @kvs['meta']['mbox_id2name-4'] = 'foo'
256
+ assert_equal('INBOX', @meta_db.mbox_name(1))
257
+ assert_equal('foo', @meta_db.mbox_name(2))
258
+ assert_equal('bar', @meta_db.mbox_name(3))
259
+ assert_equal('foo', @meta_db.mbox_name(4))
260
+
261
+ @meta_db.recovery_phase4_mbox_scan(logger: @logger)
262
+ assert_equal('INBOX', @meta_db.mbox_name(1))
263
+ assert_equal('foo', @meta_db.mbox_name(2))
264
+ assert_equal('bar', @meta_db.mbox_name(3))
265
+ assert_nil(@meta_db.mbox_name(4))
266
+ assert_equal(prev_kvs, @kvs)
267
+ end
268
+
269
+ def test_recovery_phase4_mbox_scan_reapir_dup_mbox_name
270
+ @mail_store.add_mbox('foo')
271
+ @mail_store.add_mbox('bar')
272
+ prev_kvs = deep_copy(@kvs)
273
+
274
+ @kvs['meta']['mbox_name2id-x'] = '2'
275
+ assert_equal(1, @meta_db.mbox_id('INBOX'))
276
+ assert_equal(2, @meta_db.mbox_id('foo'))
277
+ assert_equal(3, @meta_db.mbox_id('bar'))
278
+ assert_equal(2, @meta_db.mbox_id('x'))
279
+
280
+ @meta_db.recovery_phase4_mbox_scan(logger: @logger)
281
+ assert_equal(1, @meta_db.mbox_id('INBOX'))
282
+ assert_equal(2, @meta_db.mbox_id('foo'))
283
+ assert_equal(3, @meta_db.mbox_id('bar'))
284
+ assert_nil(@meta_db.mbox_id('x'))
285
+ assert_equal(prev_kvs, @kvs)
286
+ end
287
+
288
+ def test_recovery_phase4_mbox_scan_repair_orphaned_mbox_id_mbox_name
289
+ @mail_store.add_mbox('foo')
290
+ @mail_store.add_mbox('bar')
291
+ prev_kvs = deep_copy(@kvs)
292
+
293
+ @kvs['meta']['mbox_name2id-x'] = '4'
294
+ @kvs['meta']['mbox_id2name-4'] = 'x'
295
+ assert_equal(4, @meta_db.mbox_id('x'))
296
+ assert_equal('x', @meta_db.mbox_name(4))
297
+
298
+ @meta_db.recovery_phase4_mbox_scan(logger: @logger)
299
+ assert_nil(@meta_db.mbox_id('x'))
300
+ assert_nil(@meta_db.mbox_name(4))
301
+ assert_equal(prev_kvs, @kvs)
302
+ end
303
+
304
+ def test_recovery_phase5_mbox_repair_make_lost_found_mbox
305
+ @meta_db.recovery_phase5_mbox_repair(logger: @logger) {|mbox_id|
306
+ @mbox_db[mbox_id] = RIMS::DB::Mailbox.new(@kvs_open.call("mbox_#{mbox_id}"))
307
+ }
308
+ assert_equal(3, @meta_db.uidvalidity)
309
+ assert_equal([ 1, 2 ], @meta_db.each_mbox_id.to_a)
310
+ assert_equal('INBOX', @meta_db.mbox_name(1))
311
+ assert_equal(RIMS::DB::Meta::LOST_FOUND_MBOX_NAME, @meta_db.mbox_name(2))
312
+ assert_instance_of(RIMS::DB::Mailbox, @mbox_db[2])
313
+ end
314
+
315
+ def test_recovery_phase5_mbox_repair_lost_found_mbox_exists
316
+ @meta_db.add_mbox(RIMS::DB::Meta::LOST_FOUND_MBOX_NAME)
317
+ prev_kvs = deep_copy(@kvs)
318
+
319
+ @meta_db.recovery_phase5_mbox_repair(logger: @logger) {|mbox_id|
320
+ @mbox_db[mbox_id] = RIMS::DB::Mailbox.new(@kvs_open.call("mbox_#{mbox_id}"))
321
+ }
322
+ assert_equal(prev_kvs, @kvs)
323
+ end
324
+
325
+ def test_recovery_phase5_mbox_repair_make_losted_mbox
326
+ @meta_db.lost_found_mbox_set << 2
327
+ @meta_db.lost_found_mbox_set << 5
328
+
329
+ @meta_db.recovery_phase5_mbox_repair(logger: @logger) {|mbox_id|
330
+ @mbox_db[mbox_id] = RIMS::DB::Mailbox.new(@kvs_open.call("mbox_#{mbox_id}"))
331
+ }
332
+ assert_equal(7, @meta_db.uidvalidity)
333
+ assert_equal([ 1, 2, 5, 6 ], @meta_db.each_mbox_id.to_a)
334
+ assert_equal('INBOX', @meta_db.mbox_name(1))
335
+ assert_equal('MAILBOX#2', @meta_db.mbox_name(2))
336
+ assert_equal('MAILBOX#5', @meta_db.mbox_name(5))
337
+ assert_equal(RIMS::DB::Meta::LOST_FOUND_MBOX_NAME, @meta_db.mbox_name(6))
338
+ assert_instance_of(RIMS::DB::Mailbox, @mbox_db[2])
339
+ assert_instance_of(RIMS::DB::Mailbox, @mbox_db[5])
340
+ assert_instance_of(RIMS::DB::Mailbox, @mbox_db[6])
341
+ end
342
+
343
+ def test_recovery_phase6_msg_scan_empty
344
+ prev_kvs = deep_copy(@kvs)
345
+ @meta_db.recovery_phase6_msg_scan(@mbox_db, logger: @logger)
346
+ assert_equal(prev_kvs, @kvs)
347
+ end
348
+
349
+ def test_recovery_phase6_msg_scan_some_msgs
350
+ @mail_store.add_msg(@inbox_id, 'foo')
351
+ @mail_store.add_msg(@inbox_id, 'bar')
352
+ @mail_store.add_msg(@inbox_id, 'baz')
353
+ prev_kvs = deep_copy(@kvs)
354
+
355
+ @meta_db.recovery_phase6_msg_scan(@mbox_db, logger: @logger)
356
+ assert_equal(prev_kvs, @kvs)
357
+ end
358
+
359
+ def test_recovery_phase6_msg_scan_repair_lost_found_msg
360
+ @mail_store.add_msg(@inbox_id, 'foo')
361
+ @mail_store.add_msg(@inbox_id, 'bar')
362
+ @mail_store.add_msg(@inbox_id, 'baz')
363
+ prev_kvs = deep_copy(@kvs)
364
+
365
+ @kvs['mbox_1'].delete('2')
366
+ assert_equal({ @inbox_id => [ 1 ].to_set }, @meta_db.msg_mbox_uid_mapping(0))
367
+ assert_equal({ @inbox_id => [ 2 ].to_set }, @meta_db.msg_mbox_uid_mapping(1))
368
+ assert_equal({ @inbox_id => [ 3 ].to_set }, @meta_db.msg_mbox_uid_mapping(2))
369
+ assert_equal(0, @mbox_db[@inbox_id].msg_id(1))
370
+ assert_nil(@mbox_db[@inbox_id].msg_id(2))
371
+ assert_equal(2, @mbox_db[@inbox_id].msg_id(3))
372
+
373
+ @meta_db.recovery_phase6_msg_scan(@mbox_db, logger: @logger)
374
+ assert_equal({ @inbox_id => [ 1 ].to_set }, @meta_db.msg_mbox_uid_mapping(0))
375
+ assert_equal({ @inbox_id => [ 2 ].to_set }, @meta_db.msg_mbox_uid_mapping(1))
376
+ assert_equal({ @inbox_id => [ 3 ].to_set }, @meta_db.msg_mbox_uid_mapping(2))
377
+ assert_equal(0, @mbox_db[@inbox_id].msg_id(1))
378
+ assert_equal(1, @mbox_db[@inbox_id].msg_id(2))
379
+ assert_equal(2, @mbox_db[@inbox_id].msg_id(3))
380
+ assert_equal(prev_kvs, @kvs)
381
+ end
382
+
383
+ def test_recovery_phase6_msg_scan_collect_lost_found_msg
384
+ @mail_store.add_msg(@inbox_id, 'foo')
385
+ @mail_store.add_msg(@inbox_id, 'bar')
386
+ @mail_store.add_msg(@inbox_id, 'baz')
387
+
388
+ @kvs['meta']['msg_id2mbox-2'] = Marshal.dump({ @inbox_id => [ 1 ].to_set })
389
+ @kvs['mbox_1'].delete('3')
390
+ assert_equal({ @inbox_id => [ 1 ].to_set }, @meta_db.msg_mbox_uid_mapping(0))
391
+ assert_equal({ @inbox_id => [ 2 ].to_set }, @meta_db.msg_mbox_uid_mapping(1))
392
+ assert_equal({ @inbox_id => [ 1 ].to_set }, @meta_db.msg_mbox_uid_mapping(2))
393
+ assert_equal(0, @mbox_db[@inbox_id].msg_id(1))
394
+ assert_equal(1, @mbox_db[@inbox_id].msg_id(2))
395
+ assert_nil(@mbox_db[@inbox_id].msg_id(3))
396
+
397
+ @meta_db.recovery_phase6_msg_scan(@mbox_db, logger: @logger)
398
+ assert_equal({ @inbox_id => [ 1 ].to_set }, @meta_db.msg_mbox_uid_mapping(0))
399
+ assert_equal({ @inbox_id => [ 2 ].to_set }, @meta_db.msg_mbox_uid_mapping(1))
400
+ assert_equal({}, @meta_db.msg_mbox_uid_mapping(2))
401
+ assert_equal(0, @mbox_db[@inbox_id].msg_id(1))
402
+ assert_equal(1, @mbox_db[@inbox_id].msg_id(2))
403
+ assert_nil(@mbox_db[@inbox_id].msg_id(3))
404
+ assert_equal([ 2 ].to_set, @meta_db.lost_found_msg_set)
405
+ end
406
+
407
+ def test_recovery_phase7_mbox_msg_scan_empty
408
+ prev_kvs = deep_copy(@kvs)
409
+ @meta_db.recovery_phase7_mbox_msg_scan(@mbox_db, RIMS::MailStore::MSG_FLAG_NAMES, logger: @logger)
410
+ assert_equal(prev_kvs, @kvs)
411
+ end
412
+
413
+ def test_recovery_phase7_mbox_msg_scan_some_msgs
414
+ @mail_store.add_msg(@inbox_id, 'foo')
415
+ @mail_store.add_msg(@inbox_id, 'bar')
416
+ @mail_store.add_msg(@inbox_id, 'baz')
417
+ prev_kvs = deep_copy(@kvs)
418
+
419
+ @meta_db.recovery_phase7_mbox_msg_scan(@mbox_db, RIMS::MailStore::MSG_FLAG_NAMES, logger: @logger)
420
+ assert_equal(prev_kvs, @kvs)
421
+ end
422
+
423
+ def test_recovery_phase7_mbox_msg_scan_repiar_mbox_uid
424
+ @mail_store.add_msg(@inbox_id, 'foo')
425
+ @mail_store.add_msg(@inbox_id, 'bar')
426
+ @mail_store.add_msg(@inbox_id, 'baz')
427
+ prev_kvs = deep_copy(@kvs)
428
+
429
+ @kvs['meta']["mbox_id2uid-#{@inbox_id}"] = '3'
430
+ assert_equal(3, @meta_db.mbox_uid(@inbox_id))
431
+
432
+ @meta_db.recovery_phase7_mbox_msg_scan(@mbox_db, RIMS::MailStore::MSG_FLAG_NAMES, logger: @logger)
433
+ assert_equal(4, @meta_db.mbox_uid(@inbox_id))
434
+ assert_equal(prev_kvs, @kvs)
435
+ end
436
+
437
+ def test_recovery_phase7_mbox_msg_scan_repair_mbox_msg
438
+ @mail_store.add_msg(@inbox_id, 'foo')
439
+ @mail_store.add_msg(@inbox_id, 'bar')
440
+ @mail_store.add_msg(@inbox_id, 'baz')
441
+ prev_kvs = deep_copy(@kvs)
442
+
443
+ @mbox_db[@inbox_id].add_msg(4, 0)
444
+ assert_equal(0, @mbox_db[@inbox_id].msg_id(1))
445
+ assert_equal(1, @mbox_db[@inbox_id].msg_id(2))
446
+ assert_equal(2, @mbox_db[@inbox_id].msg_id(3))
447
+ assert_equal(0, @mbox_db[@inbox_id].msg_id(4))
448
+
449
+ @meta_db.recovery_phase7_mbox_msg_scan(@mbox_db, RIMS::MailStore::MSG_FLAG_NAMES, logger: @logger)
450
+ assert_equal(0, @mbox_db[@inbox_id].msg_id(1))
451
+ assert_equal(1, @mbox_db[@inbox_id].msg_id(2))
452
+ assert_equal(2, @mbox_db[@inbox_id].msg_id(3))
453
+ assert_nil(@mbox_db[@inbox_id].msg_id(4))
454
+ assert_equal(prev_kvs, @kvs)
455
+ end
456
+
457
+ def test_recovery_phase7_mbox_msg_scan_repair_msg_num
458
+ @mail_store.add_msg(@inbox_id, 'foo')
459
+ @mail_store.add_msg(@inbox_id, 'bar')
460
+ @mail_store.add_msg(@inbox_id, 'baz')
461
+ prev_kvs = deep_copy(@kvs)
462
+
463
+ @kvs['meta']["mbox_id2msgnum-#{@inbox_id}"] = '0'
464
+ assert_equal(0, @meta_db.mbox_msg_num(@inbox_id))
465
+
466
+ @meta_db.recovery_phase7_mbox_msg_scan(@mbox_db, RIMS::MailStore::MSG_FLAG_NAMES, logger: @logger)
467
+ assert_equal(3, @meta_db.mbox_msg_num(@inbox_id))
468
+ assert_equal(prev_kvs, @kvs)
469
+ end
470
+
471
+ def test_recovery_phase7_mbox_msg_scan_repair_flag_num
472
+ @mail_store.add_msg(@inbox_id, 'foo')
473
+ @mail_store.add_msg(@inbox_id, 'bar')
474
+ @mail_store.add_msg(@inbox_id, 'baz')
475
+ @mail_store.set_msg_flag(@inbox_id, 1, 'seen', true)
476
+ @mail_store.set_msg_flag(@inbox_id, 2, 'seen', true)
477
+ @mail_store.set_msg_flag(@inbox_id, 1, 'deleted', true)
478
+ prev_kvs = deep_copy(@kvs)
479
+
480
+ @kvs['meta']["mbox_id2flagnum-#{@inbox_id}-recent"] = '0'
481
+ @kvs['meta']["mbox_id2flagnum-#{@inbox_id}-seen"] = '0'
482
+ @kvs['meta']["mbox_id2flagnum-#{@inbox_id}-deleted"] = '0'
483
+ assert_equal(0, @meta_db.mbox_flag_num(@inbox_id, 'recent'))
484
+ assert_equal(0, @meta_db.mbox_flag_num(@inbox_id, 'seen'))
485
+ assert_equal(0, @meta_db.mbox_flag_num(@inbox_id, 'deleted'))
486
+
487
+ @meta_db.recovery_phase7_mbox_msg_scan(@mbox_db, RIMS::MailStore::MSG_FLAG_NAMES, logger: @logger)
488
+ assert_equal(3, @meta_db.mbox_flag_num(@inbox_id, 'recent'))
489
+ assert_equal(2, @meta_db.mbox_flag_num(@inbox_id, 'seen'))
490
+ assert_equal(1, @meta_db.mbox_flag_num(@inbox_id, 'deleted'))
491
+ assert_equal(prev_kvs, @kvs)
492
+ end
493
+
494
+ def test_recovery_phase8_lost_found_empty
495
+ _lost_found_id = @mail_store.add_mbox(RIMS::DB::Meta::LOST_FOUND_MBOX_NAME)
496
+ @mail_store.expunge_mbox(_lost_found_id) # explicit open a mailbox database
497
+ prev_kvs = deep_copy(@kvs)
498
+ @meta_db.recovery_phase8_lost_found(@mbox_db, logger: @logger)
499
+ assert_equal(prev_kvs, @kvs)
500
+ end
501
+
502
+ def test_recovery_phase8_lost_found_some_msgs
503
+ _lost_found_id = @mail_store.add_mbox(RIMS::DB::Meta::LOST_FOUND_MBOX_NAME)
504
+ @mail_store.expunge_mbox(_lost_found_id) # explicit open a mailbox database
505
+ @mail_store.add_msg(@inbox_id, 'foo')
506
+ @mail_store.add_msg(@inbox_id, 'bar')
507
+ @mail_store.add_msg(@inbox_id, 'baz')
508
+ prev_kvs = deep_copy(@kvs)
509
+
510
+ @meta_db.recovery_phase8_lost_found(@mbox_db, logger: @logger)
511
+ assert_equal(prev_kvs, @kvs)
512
+ end
513
+
514
+
515
+ def test_recovery_phase8_lost_found_repair_msgs
516
+ lost_found_id = @mail_store.add_mbox(RIMS::DB::Meta::LOST_FOUND_MBOX_NAME)
517
+ @mail_store.expunge_mbox(lost_found_id) # explicit open a mailbox database
518
+ @mail_store.add_msg(@inbox_id, 'foo')
519
+ @mail_store.add_msg(@inbox_id, 'bar')
520
+ @mail_store.add_msg(@inbox_id, 'baz')
521
+
522
+ @meta_db.lost_found_msg_set << 0 << 1
523
+ assert_nil(@meta_db.msg_mbox_uid_mapping(0)[lost_found_id])
524
+ assert_nil(@meta_db.msg_mbox_uid_mapping(1)[lost_found_id])
525
+ assert_nil(@meta_db.msg_mbox_uid_mapping(2)[lost_found_id])
526
+ assert_equal([], @mbox_db[lost_found_id].each_msg_uid.to_a)
527
+
528
+ @meta_db.recovery_phase8_lost_found(@mbox_db, logger: @logger)
529
+ assert_equal([ 1 ].to_set, @meta_db.msg_mbox_uid_mapping(0)[lost_found_id])
530
+ assert_equal([ 2 ].to_set, @meta_db.msg_mbox_uid_mapping(1)[lost_found_id])
531
+ assert_nil(@meta_db.msg_mbox_uid_mapping(2)[lost_found_id])
532
+ assert_equal([ 1, 2 ], @mbox_db[lost_found_id].each_msg_uid.to_a)
533
+ assert_equal(0, @mbox_db[lost_found_id].msg_id(1))
534
+ assert_equal(1, @mbox_db[lost_found_id].msg_id(2))
535
+ end
536
+
537
+ def test_recovery_scenario_empty
538
+ @mail_store.add_mbox(RIMS::DB::Meta::LOST_FOUND_MBOX_NAME)
539
+ prev_kvs = deep_copy(@kvs)
540
+
541
+ @meta_db.recovery_phase1_msg_scan(@msg_db, logger: @logger)
542
+ @meta_db.recovery_phase2_msg_scan(@msg_db, logger: @logger)
543
+ @meta_db.recovery_phase3_mbox_scan(logger: @logger)
544
+ @meta_db.recovery_phase4_mbox_scan(logger: @logger)
545
+ @meta_db.recovery_phase5_mbox_repair(logger: @logger) {|mbox_id|
546
+ @mbox_db[mbox_id] = RIMS::DB::Mailbox.new(@kvs_open.call("mbox_#{mbox_id}"))
547
+ }
548
+ @meta_db.recovery_phase6_msg_scan(@mbox_db, logger: @logger)
549
+ @meta_db.recovery_phase7_mbox_msg_scan(@mbox_db, RIMS::MailStore::MSG_FLAG_NAMES, logger: @logger)
550
+ @meta_db.recovery_phase8_lost_found(@mbox_db, logger: @logger)
551
+
552
+ assert_equal(prev_kvs, @kvs)
553
+ end
554
+
555
+ def test_recovery_scenario_some_msgs_mboxes
556
+ @mail_store.add_msg(@inbox_id, 'foo')
557
+ @mail_store.add_msg(@inbox_id, 'bar')
558
+ @mail_store.add_msg(@inbox_id, 'baz')
559
+ @mail_store.add_mbox('foo')
560
+ @mail_store.add_mbox('bar')
561
+ @mail_store.add_mbox(RIMS::DB::Meta::LOST_FOUND_MBOX_NAME)
562
+ prev_kvs = deep_copy(@kvs)
563
+
564
+ @meta_db.recovery_phase1_msg_scan(@msg_db, logger: @logger)
565
+ @meta_db.recovery_phase2_msg_scan(@msg_db, logger: @logger)
566
+ @meta_db.recovery_phase3_mbox_scan(logger: @logger)
567
+ @meta_db.recovery_phase4_mbox_scan(logger: @logger)
568
+ @meta_db.recovery_phase5_mbox_repair(logger: @logger) {|mbox_id|
569
+ @mbox_db[mbox_id] = RIMS::DB::Mailbox.new(@kvs_open.call("mbox_#{mbox_id}"))
570
+ }
571
+ @meta_db.recovery_phase6_msg_scan(@mbox_db, logger: @logger)
572
+ @meta_db.recovery_phase7_mbox_msg_scan(@mbox_db, RIMS::MailStore::MSG_FLAG_NAMES, logger: @logger)
573
+ @meta_db.recovery_phase8_lost_found(@mbox_db, logger: @logger)
574
+
575
+ assert_equal(prev_kvs, @kvs)
576
+ end
577
+
578
+ def test_recovery_scenario_repair_data
579
+ @mail_store.add_msg(@inbox_id, 'foo'); @mail_store.set_msg_flag(@inbox_id, 1, 'deleted', true)
580
+ @mail_store.add_msg(@inbox_id, 'bar')
581
+ @mail_store.add_msg(@inbox_id, 'baz')
582
+ @mail_store.add_mbox('foo')
583
+ @mail_store.add_mbox('bar')
584
+ @mail_store.add_mbox(RIMS::DB::Meta::LOST_FOUND_MBOX_NAME)
585
+ prev_kvs = deep_copy(@kvs)
586
+
587
+ # recovery phase 1
588
+ @kvs['meta']['msg_id'] = '0'
589
+ assert_equal(0, @meta_db.msg_id)
590
+
591
+ # recovery phase 2
592
+ @kvs['meta']['msg_id2mbox-3'] = Marshal.dump({ 10 => [ 100 ].to_set })
593
+ @kvs['meta']['msg_id2date-3'] = Marshal.dump(Time.now)
594
+ assert_equal({ 10 => [ 100 ].to_set }, @meta_db.msg_mbox_uid_mapping(3))
595
+ assert_instance_of(Time, @meta_db.msg_date(3))
596
+
597
+ # recovery phase 3
598
+ @kvs['meta']['uidvalidity'] = '1'
599
+ @kvs['meta']['mbox_name2id-foo'] = @inbox_id.to_s
600
+ assert_equal(1, @meta_db.uidvalidity)
601
+ assert_equal(@inbox_id, @meta_db.mbox_id('foo'))
602
+
603
+ # recovery phase 4
604
+ @kvs['meta']['mbox_name2id-NoBox'] = '1'
605
+ assert_equal(1, @meta_db.mbox_id('INBOX'))
606
+ assert_equal(1, @meta_db.mbox_id('NoBox'))
607
+
608
+ # recovery phase 6
609
+ @kvs['mbox_1'].delete('2')
610
+ @kvs['mbox_1'].delete('3')
611
+ assert_equal([ 1 ], @mbox_db[@inbox_id].each_msg_uid.to_a)
612
+ assert_equal(0, @mbox_db[@inbox_id].msg_id(1))
613
+
614
+ # recovery phase 7
615
+ @kvs['meta']['mbox_id2msgnum-1'] = '0'
616
+ @kvs['meta']['mbox_id2flagnum-1-recent'] = '0'
617
+ @kvs['meta']['mbox_id2flagnum-1-deleted'] = '0'
618
+ assert_equal(0, @meta_db.mbox_msg_num(@inbox_id))
619
+ assert_equal(0, @meta_db.mbox_flag_num(@inbox_id, 'recent'))
620
+ assert_equal(0, @meta_db.mbox_flag_num(@inbox_id, 'deleted'))
621
+
622
+ @meta_db.recovery_phase1_msg_scan(@msg_db, logger: @logger)
623
+ @meta_db.recovery_phase2_msg_scan(@msg_db, logger: @logger)
624
+ @meta_db.recovery_phase3_mbox_scan(logger: @logger)
625
+ @meta_db.recovery_phase4_mbox_scan(logger: @logger)
626
+ @meta_db.recovery_phase5_mbox_repair(logger: @logger) {|mbox_id|
627
+ @mbox_db[mbox_id] = RIMS::DB::Mailbox.new(@kvs_open.call("mbox_#{mbox_id}"))
628
+ }
629
+ @meta_db.recovery_phase6_msg_scan(@mbox_db, logger: @logger)
630
+ @meta_db.recovery_phase7_mbox_msg_scan(@mbox_db, RIMS::MailStore::MSG_FLAG_NAMES, logger: @logger)
631
+ @meta_db.recovery_phase8_lost_found(@mbox_db, logger: @logger)
632
+
633
+ # recovery phase 1
634
+ assert_equal(3, @meta_db.msg_id)
635
+
636
+ # recovery phase 2
637
+ assert_equal({}, @meta_db.msg_mbox_uid_mapping(3))
638
+ assert_raise(RuntimeError) { @meta_db.msg_date(3) }
639
+
640
+ # recovery phase 3
641
+ assert_equal(5, @meta_db.uidvalidity)
642
+ assert_equal(2, @meta_db.mbox_id('foo'))
643
+
644
+ # recovery phase 4
645
+ assert_equal(1, @meta_db.mbox_id('INBOX'))
646
+ assert_nil(@meta_db.mbox_id('NoBox'))
647
+
648
+ # recovery phase 6
649
+ assert_equal([ 1, 2, 3 ], @mbox_db[@inbox_id].each_msg_uid.to_a)
650
+ assert_equal(0, @mbox_db[@inbox_id].msg_id(1))
651
+ assert_equal(1, @mbox_db[@inbox_id].msg_id(2))
652
+ assert_equal(2, @mbox_db[@inbox_id].msg_id(3))
653
+
654
+ # recovery phase 7
655
+ assert_equal(3, @meta_db.mbox_msg_num(@inbox_id))
656
+ assert_equal(3, @meta_db.mbox_flag_num(@inbox_id, 'recent'))
657
+ assert_equal(1, @meta_db.mbox_flag_num(@inbox_id, 'deleted'))
658
+
659
+ assert_equal(prev_kvs, @kvs)
660
+ end
661
+
662
+ def test_recovery_scenario_lost_found
663
+ @mail_store.add_msg(@inbox_id, 'foo')
664
+ @mail_store.add_msg(@inbox_id, 'bar')
665
+ @mail_store.add_msg(@inbox_id, 'baz')
666
+ @mail_store.add_mbox('foo')
667
+ @mail_store.add_mbox('bar')
668
+
669
+ # recovery phase 5
670
+ assert_nil(@mail_store.mbox_id(RIMS::DB::Meta::LOST_FOUND_MBOX_NAME))
671
+
672
+ # recovery phase 1,8
673
+ @msg_db.add_msg(3, 'apple')
674
+ assert_equal({}, @meta_db.msg_mbox_uid_mapping(3))
675
+ assert_raise(RuntimeError) { @meta_db.msg_date(3) }
676
+
677
+ # recovery phase 2,5,8
678
+ mbox_uid_map = Marshal.load(@kvs['meta']['msg_id2mbox-0'])
679
+ mbox_uid_map[10] = [ 1 ].to_set
680
+ @kvs['meta']['msg_id2mbox-0'] = Marshal.dump(mbox_uid_map)
681
+ assert_equal({ @inbox_id => [ 1 ].to_set, 10 => [ 1 ].to_set }, @meta_db.msg_mbox_uid_mapping(0))
682
+ assert_nil(@meta_db.mbox_name(10))
683
+ assert_nil(@mbox_db[10])
684
+
685
+ # recovery phase 6,8
686
+ mbox_uid_map = Marshal.load(@kvs['meta']['msg_id2mbox-1'])
687
+ mbox_uid_map[@inbox_id] << 1
688
+ @kvs['meta']['msg_id2mbox-1'] = Marshal.dump(mbox_uid_map)
689
+ assert_equal({ @inbox_id => [ 1, 2 ].to_set }, @meta_db.msg_mbox_uid_mapping(1))
690
+
691
+ @meta_db.recovery_phase1_msg_scan(@msg_db, logger: @logger)
692
+ @meta_db.recovery_phase2_msg_scan(@msg_db, logger: @logger)
693
+ @meta_db.recovery_phase3_mbox_scan(logger: @logger)
694
+ @meta_db.recovery_phase4_mbox_scan(logger: @logger)
695
+ @meta_db.recovery_phase5_mbox_repair(logger: @logger) {|mbox_id|
696
+ @mbox_db[mbox_id] = RIMS::DB::Mailbox.new(@kvs_open.call("mbox_#{mbox_id}"))
697
+ }
698
+ @meta_db.recovery_phase6_msg_scan(@mbox_db, logger: @logger)
699
+ @meta_db.recovery_phase7_mbox_msg_scan(@mbox_db, RIMS::MailStore::MSG_FLAG_NAMES, logger: @logger)
700
+ @meta_db.recovery_phase8_lost_found(@mbox_db, logger: @logger)
701
+
702
+ # recovery phase 5
703
+ assert_not_nil(lost_found_id = @mail_store.mbox_id(RIMS::DB::Meta::LOST_FOUND_MBOX_NAME))
704
+ assert_instance_of(RIMS::DB::Mailbox, @mbox_db[lost_found_id])
705
+
706
+ # recovery phase 1,8
707
+ assert_equal({ lost_found_id => [ 1 ].to_set }, @meta_db.msg_mbox_uid_mapping(3))
708
+ assert_instance_of(Time, @meta_db.msg_date(3))
709
+ assert_equal(3, @mbox_db[lost_found_id].msg_id(1))
710
+
711
+ # recovery phase 2,5,8
712
+ assert_equal({ @inbox_id => [ 1 ].to_set, 10 => [ 1 ].to_set }, @meta_db.msg_mbox_uid_mapping(0))
713
+ assert_equal('MAILBOX#10', @meta_db.mbox_name(10))
714
+ assert_equal(10, @meta_db.mbox_id('MAILBOX#10'))
715
+ assert_instance_of(RIMS::DB::Mailbox, @mbox_db[10])
716
+ assert_equal([ 1 ], @mbox_db[10].each_msg_uid.to_a)
717
+ assert_equal(0, @mbox_db[10].msg_id(1))
718
+
719
+ # recovery phase 6,8
720
+ assert_equal({ @inbox_id => [ 2 ].to_set, lost_found_id => [ 2 ].to_set }, @meta_db.msg_mbox_uid_mapping(1))
721
+ assert_equal(1, @mbox_db[lost_found_id].msg_id(2))
722
+
723
+ # recovery phase 8
724
+ assert_equal([ 1, 2 ], @mbox_db[lost_found_id].each_msg_uid.to_a)
725
+ end
726
+ end
727
+ end
728
+
729
+ # Local Variables:
730
+ # mode: Ruby
731
+ # indent-tabs-mode: nil
732
+ # End: