rims 0.2.1

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