class RIMS::DB::Meta
Constants
- LOST_FOUND_MBOX_NAME
Attributes
lost_found_mbox_set[R]
lost_found_msg_set[R]
Public Instance Methods
add_mbox(name, mbox_id: nil)
click to toggle source
# File lib/rims/db.rb, line 178 def add_mbox(name, mbox_id: nil) if (@kvs.key? "mbox_name2id-#{name}") then raise "duplicated mailbox name: #{name}." end if (mbox_id) then if (@kvs.key? "mbox_id2name-#{mbox_id}") then raise "duplicated mailbox id: #{mbox_id}" end if (uidvalidity <= mbox_id) then put_num('uidvalidity', mbox_id + 1) end else mbox_id = uidvalidity_succ! end mbox_set = get_num_set('mbox_set') if (mbox_set.include? mbox_id) then raise "internal error: duplicated mailbox id: #{mbox_id}" end mbox_set << mbox_id put_num_set('mbox_set', mbox_set) put_str("mbox_id2name-#{mbox_id}", name) put_num("mbox_name2id-#{name}", mbox_id) mbox_id end
add_msg_mbox_uid(msg_id, mbox_id)
click to toggle source
# File lib/rims/db.rb, line 360 def add_msg_mbox_uid(msg_id, mbox_id) uid = mbox_uid_succ!(mbox_id) mbox_uid_map = msg_mbox_uid_mapping(msg_id) if (mbox_uid_map.key? mbox_id) then msg_uid_set = mbox_uid_map[mbox_id] else msg_uid_set = mbox_uid_map[mbox_id] = [].to_set end if (msg_uid_set.include? uid) then raise "duplicated uid(#{uid}) in mailbox id(#{mbox_id} on message id(#{msg_id}))" end mbox_uid_map[mbox_id] << uid put_obj("msg_id2mbox-#{msg_id}", mbox_uid_map) mbox_msg_num_increment(mbox_id) flag_set = get_str_set("msg_id2flag-#{msg_id}") for name in flag_set mbox_flag_num_increment(mbox_id, name) end uid end
clear_mbox_flag_num(mbox_id, name)
click to toggle source
# File lib/rims/db.rb, line 296 def clear_mbox_flag_num(mbox_id, name) mbox_name(mbox_id) or raise "not found a mailbox for id: #{mbox_id}" if (@kvs.delete("mbox_id2flagnum-#{mbox_id}-#{name}")) then self end end
clear_msg_date(msg_id)
click to toggle source
# File lib/rims/db.rb, line 312 def clear_msg_date(msg_id) if (@kvs.delete("msg_id2date-#{msg_id}")) then self end end
clear_msg_flag(msg_id)
click to toggle source
# File lib/rims/db.rb, line 350 def clear_msg_flag(msg_id) if (@kvs.delete("msg_id2flag-#{msg_id}")) then self end end
clear_msg_mbox_uid_mapping(msg_id)
click to toggle source
# File lib/rims/db.rb, line 402 def clear_msg_mbox_uid_mapping(msg_id) if (@kvs.delete("msg_id2mbox-#{msg_id}")) then self end end
cnum()
click to toggle source
# File lib/rims/db.rb, line 154 def cnum get_num('cnum') end
cnum_succ!()
click to toggle source
# File lib/rims/db.rb, line 158 def cnum_succ! num_succ!('cnum') end
del_mbox(mbox_id)
click to toggle source
# File lib/rims/db.rb, line 207 def del_mbox(mbox_id) mbox_set = get_num_set('mbox_set') if (mbox_set.include? mbox_id) then mbox_set.delete(mbox_id) put_num_set('mbox_set', mbox_set) name = mbox_name(mbox_id) @kvs.delete("mbox_id2name-#{mbox_id}") or raise "not found a mailbox name for id: #{mbox_id}" @kvs.delete("mbox_name2id-#{name}") or raise "not found a mailbox id for name: #{name}" @kvs.delete("mbox_id2uid-#{mbox_id}") @kvs.delete("mbox_id2msgnum-#{mbox_id}") self end end
del_msg_mbox_uid(msg_id, mbox_id, uid)
click to toggle source
# File lib/rims/db.rb, line 383 def del_msg_mbox_uid(msg_id, mbox_id, uid) mbox_uid_map = msg_mbox_uid_mapping(msg_id) if (uid_set = mbox_uid_map[mbox_id]) then if (uid_set.include? uid) then uid_set.delete(uid) mbox_uid_map.delete(mbox_id) if uid_set.empty? put_obj("msg_id2mbox-#{msg_id}", mbox_uid_map) mbox_msg_num_decrement(mbox_id) flag_set = get_str_set("msg_id2flag-#{msg_id}") for name in flag_set mbox_flag_num_decrement(mbox_id, name) end mbox_uid_map end end end
dirty=(dirty_flag)
click to toggle source
# File lib/rims/db.rb, line 143 def dirty=(dirty_flag) if (dirty_flag) then put_str('dirty', '') else @kvs.delete('dirty') end @kvs.sync dirty_flag end
dirty?()
click to toggle source
# File lib/rims/db.rb, line 139 def dirty? @kvs.key? 'dirty' end
each_mbox_id() { |mbox_id| ... }
click to toggle source
# File lib/rims/db.rb, line 235 def each_mbox_id return enum_for(:each_mbox_id) unless block_given? mbox_set = get_num_set('mbox_set') for mbox_id in mbox_set yield(mbox_id) end self end
mbox_flag_num(mbox_id, name)
click to toggle source
# File lib/rims/db.rb, line 279 def mbox_flag_num(mbox_id, name) mbox_name(mbox_id) or raise "not found a mailbox for id: #{mbox_id}" get_num("mbox_id2flagnum-#{mbox_id}-#{name}") end
mbox_flag_num_decrement(mbox_id, name)
click to toggle source
# File lib/rims/db.rb, line 290 def mbox_flag_num_decrement(mbox_id, name) mbox_name(mbox_id) or raise "not found a mailbox for id: #{mbox_id}" num_decrement("mbox_id2flagnum-#{mbox_id}-#{name}") self end
mbox_flag_num_increment(mbox_id, name)
click to toggle source
# File lib/rims/db.rb, line 284 def mbox_flag_num_increment(mbox_id, name) mbox_name(mbox_id) or raise "not found a mailbox for id: #{mbox_id}" num_increment("mbox_id2flagnum-#{mbox_id}-#{name}") self end
mbox_id(name)
click to toggle source
# File lib/rims/db.rb, line 248 def mbox_id(name) get_num("mbox_name2id-#{name}", default_value: nil) end
mbox_msg_num(mbox_id)
click to toggle source
# File lib/rims/db.rb, line 262 def mbox_msg_num(mbox_id) mbox_name(mbox_id) or raise "not found a mailbox for id: #{mbox_id}" get_num("mbox_id2msgnum-#{mbox_id}") end
mbox_msg_num_decrement(mbox_id)
click to toggle source
# File lib/rims/db.rb, line 273 def mbox_msg_num_decrement(mbox_id) mbox_name(mbox_id) or raise "not found a mailbox for id: #{mbox_id}" num_decrement("mbox_id2msgnum-#{mbox_id}") self end
mbox_msg_num_increment(mbox_id)
click to toggle source
# File lib/rims/db.rb, line 267 def mbox_msg_num_increment(mbox_id) mbox_name(mbox_id) or raise "not found a mailbox for id: #{mbox_id}" num_increment("mbox_id2msgnum-#{mbox_id}") self end
mbox_name(mbox_id)
click to toggle source
# File lib/rims/db.rb, line 244 def mbox_name(mbox_id) get_str("mbox_id2name-#{mbox_id}", default_value: nil) end
mbox_uid(mbox_id)
click to toggle source
# File lib/rims/db.rb, line 252 def mbox_uid(mbox_id) mbox_name(mbox_id) or raise "not found a mailbox for id: #{mbox_id}" get_num("mbox_id2uid-#{mbox_id}", default_value: 1) end
mbox_uid_succ!(mbox_id)
click to toggle source
# File lib/rims/db.rb, line 257 def mbox_uid_succ!(mbox_id) mbox_name(mbox_id) or raise "not found a mailbox for id: #{mbox_id}" num_succ!("mbox_id2uid-#{mbox_id}", default_value: 1) end
msg_date(msg_id)
click to toggle source
# File lib/rims/db.rb, line 303 def msg_date(msg_id) get_obj("msg_id2date-#{msg_id}") or raise "not found a message date for internal id: #{msg_id}" end
msg_flag(msg_id, name)
click to toggle source
# File lib/rims/db.rb, line 318 def msg_flag(msg_id, name) flag_set = get_str_set("msg_id2flag-#{msg_id}") flag_set.include? name end
msg_id()
click to toggle source
# File lib/rims/db.rb, line 162 def msg_id get_num('msg_id') end
msg_id_succ!()
click to toggle source
# File lib/rims/db.rb, line 166 def msg_id_succ! num_succ!('msg_id') end
msg_mbox_uid_mapping(msg_id)
click to toggle source
# File lib/rims/db.rb, line 356 def msg_mbox_uid_mapping(msg_id) get_obj("msg_id2mbox-#{msg_id}", default_value: {}) end
recovery_end()
click to toggle source
# File lib/rims/db.rb, line 413 def recovery_end @lost_found_msg_set = nil @lost_found_mbox_set = nil end
recovery_phase1_msg_scan(msg_db, logger: Logger.new(STDOUT))
click to toggle source
# File lib/rims/db.rb, line 430 def recovery_phase1_msg_scan(msg_db, logger: Logger.new(STDOUT)) logger.info('recovery phase 1: start.') max_msg_id = -1 msg_db.each_msg_id do |msg_id| max_msg_id = msg_id if (max_msg_id < msg_id) unless (@kvs.key? "msg_id2mbox-#{msg_id}") then logger.warn("lost+found message: #{msg_id}") @lost_found_msg_set << msg_id end unless (@kvs.key? "msg_id2date-#{msg_id}") then logger.warn("repair internal date: #{msg_id}") set_msg_date(msg_id, Time.now) end end if (msg_id <= max_msg_id) then next_msg_id = max_msg_id + 1 logger.warn("repair msg_id: #{next_msg_id}") put_num('msg_id', next_msg_id) end logger.info('recovery phase 1: end.') self end
recovery_phase2_msg_scan(msg_db, logger: Logger.new(STDOUT))
click to toggle source
# File lib/rims/db.rb, line 457 def recovery_phase2_msg_scan(msg_db, logger: Logger.new(STDOUT)) logger.info('recovery phase 2: start.') lost_msg_set = [].to_set mbox_set = get_num_set('mbox_set') @kvs.each_key do |key| if (msg_id = get_recover_entry(key, 'msg_id2mbox-') {|s| s.to_i }) then if (msg_db.msg_exist? msg_id) then msg_mbox_uid_mapping(msg_id).each_key do |mbox_id| unless (mbox_set.include? mbox_id) then logger.warn("lost+found mailbox: #{mbox_id}") @lost_found_mbox_set << mbox_id end end else lost_msg_set << msg_id end end end for msg_id in lost_msg_set logger.warn("clear lost message: #{msg_id}") clear_msg_date(msg_id) clear_msg_flag(msg_id) clear_msg_mbox_uid_mapping(msg_id) end logger.info('recovery phase 2: end.') self end
recovery_phase3_mbox_scan(logger: Logger.new(STDOUT))
click to toggle source
# File lib/rims/db.rb, line 503 def recovery_phase3_mbox_scan(logger: Logger.new(STDOUT)) logger.info('recovery phase 3: start.') mbox_set = get_num_set('mbox_set') max_mbox_id = 0 for mbox_id in mbox_set max_mbox_id = mbox_id if (mbox_id > max_mbox_id) if (name = mbox_name(mbox_id)) then mbox_id2 = mbox_id(name) unless (mbox_id2 && (mbox_id2 == mbox_id)) then logger.warn("repair mailbox name -> id: #{name.inspect} -> #{mbox_id}") put_num("mbox_name2id-#{name}", mbox_id) end else new_name = make_mbox_repair_name(mbox_id) logger.warn("repair mailbox id name pair: #{mbox_id}, #{new_name.inspect}") put_str("mbox_id2name-#{mbox_id}", new_name) put_num("mbox_name2id-#{new_name}", mbox_id) end end if (uidvalidity <= max_mbox_id) then next_uidvalidity = max_mbox_id + 1 logger.warn("repair uidvalidity: #{next_uidvalidity}") put_num('uidvalidity', next_uidvalidity) end logger.info('recovery phase 3: end.') self end
recovery_phase4_mbox_scan(logger: Logger.new(STDOUT))
click to toggle source
# File lib/rims/db.rb, line 536 def recovery_phase4_mbox_scan(logger: Logger.new(STDOUT)) logger.info('recovery phase 4: start.') mbox_set = get_num_set('mbox_set') del_key_list = [] @kvs.each_key do |key| if (mbox_id = get_recover_entry(key, 'mbox_id2name-') {|s| s.to_i }) then unless (mbox_set.include? mbox_id) then del_key_list << key end elsif (name = get_recover_entry(key, 'mbox_name2id-')) then unless ((mbox_id = mbox_id(name)) && (mbox_set.include? mbox_id) && (mbox_name(mbox_id) == name)) then del_key_list << key end end end for key in del_key_list logger.warn("unlinked mailbox entry: #{key}") @kvs.delete(key) end logger.info('recovery phase 4: end.') self end
recovery_phase5_mbox_repair(logger: Logger.new(STDOUT)) { |mbox_id| ... }
click to toggle source
# File lib/rims/db.rb, line 566 def recovery_phase5_mbox_repair(logger: Logger.new(STDOUT)) logger.info('recovery phase 5: start.') for mbox_id in @lost_found_mbox_set logger.warn("repair lost mailbox: #{mbox_id}") add_mbox(make_mbox_repair_name(mbox_id), mbox_id: mbox_id) yield(mbox_id) end unless (mbox_id(LOST_FOUND_MBOX_NAME)) then logger.warn('create lost+found mailbox.') mbox_id = add_mbox(LOST_FOUND_MBOX_NAME) yield(mbox_id) end logger.info('recovery phase 5: end.') self end
recovery_phase6_msg_scan(mbox_db, logger: Logger.new(STDOUT))
click to toggle source
# File lib/rims/db.rb, line 585 def recovery_phase6_msg_scan(mbox_db, logger: Logger.new(STDOUT)) logger.info('recovery phase 6: start.') @kvs.each_key do |key| if (msg_id = get_recover_entry(key, 'msg_id2mbox-') {|s| s.to_i }) then is_modified = false mbox_uid_map = msg_mbox_uid_mapping(msg_id) mbox_uid_map.each_pair.to_a.each do |mbox_id, uid_set| uid_set.to_a.each do |uid| if (msg_id2 = mbox_db[mbox_id].msg_id(uid)) then if (msg_id != msg_id2) then logger.warn("lost+found message -> mailbox: #{msg_id} -> #{mbox_id},#{uid}") is_modified = true uid_set.delete(uid) mbox_uid_map.delete(mbox_id) if uid_set.empty? @lost_found_msg_set << msg_id end else logger.warn("repair mailbox -> message: #{mbox_id},#{uid} -> #{msg_id}") mbox_db[mbox_id].add_msg(uid, msg_id) end end end if (is_modified) then logger.warn("save repaired message: #{msg_id}") put_obj("msg_id2mbox-#{msg_id}", mbox_uid_map) end end end logger.info('recovery phase 6: end.') self end
recovery_phase7_mbox_msg_scan(mbox_db, flag_name_list, logger: Logger.new(STDOUT))
click to toggle source
# File lib/rims/db.rb, line 621 def recovery_phase7_mbox_msg_scan(mbox_db, flag_name_list, logger: Logger.new(STDOUT)) logger.info('recovery phase 7: start.') mbox_db.each_key do |mbox_id| logger.info("scan mailbox: #{mbox_id}") max_uid = 0 msg_num = 0 flag_num = Hash.new(0) del_uid_list = [] mbox_db[mbox_id].each_msg_uid do |uid| msg_id = mbox_db[mbox_id].msg_id(uid) if ((mbox_uid_map = msg_mbox_uid_mapping(msg_id)) && (uid_set = mbox_uid_map[mbox_id]) && (uid_set.include? uid)) then max_uid = uid if (max_uid < uid) msg_num += 1 for name in flag_name_list if (name == 'deleted') then if (mbox_db[mbox_id].msg_flag_deleted(uid)) then flag_num['deleted'] += 1 end else if (msg_flag(msg_id, name)) then flag_num[name] += 1 end end end else del_uid_list << uid end end for uid in del_uid_list logger.warn("unlinked message uid: #{mbox_id},#{uid}") mbox_db[mbox_id].set_msg_flag_deleted(uid, true) mbox_db[mbox_id].expunge_msg(uid) end if (mbox_uid(mbox_id) <= max_uid) then next_uid = max_uid + 1 logger.warn("repair mailbox uid: #{next_uid}") put_num("mbox_id2uid-#{mbox_id}", next_uid) end if (mbox_msg_num(mbox_id) != msg_num) then logger.warn("repair mailbox message number: #{msg_num}") put_num("mbox_id2msgnum-#{mbox_id}", msg_num) end for name in flag_name_list if (mbox_flag_num(mbox_id, name) != flag_num[name]) then logger.warn("repair mailbox #{name} flag number: #{flag_num[name]}") put_num("mbox_id2flagnum-#{mbox_id}-#{name}", flag_num[name]) end end end logger.info('recovery phase 7: end.') self end
recovery_phase8_lost_found(mbox_db, logger: Logger.new(STDOUT))
click to toggle source
# File lib/rims/db.rb, line 683 def recovery_phase8_lost_found(mbox_db, logger: Logger.new(STDOUT)) logger.info('recovery phase 8: start.') mbox_id = mbox_id(LOST_FOUND_MBOX_NAME) or raise "not found a #{LOST_FOUND_MBOX_NAME} mailbox." for msg_id in @lost_found_msg_set logger.warn("repair lost+found message: #{msg_id}") uid = add_msg_mbox_uid(msg_id, mbox_id) mbox_db[mbox_id].add_msg(uid, msg_id) end logger.info('recovery phase 8: end.') self end
recovery_start()
click to toggle source
# File lib/rims/db.rb, line 408 def recovery_start @lost_found_msg_set = [].to_set @lost_found_mbox_set = [].to_set end
rename_mbox(mbox_id, new_name)
click to toggle source
# File lib/rims/db.rb, line 221 def rename_mbox(mbox_id, new_name) old_name = get_str("mbox_id2name-#{mbox_id}") or raise "not found a mailbox name for id: #{mbox_id}" if (new_name == old_name) then return end if (@kvs.key? "mbox_name2id-#{new_name}") then raise "duplicated mailbox name: #{new_name}" end @kvs.delete("mbox_name2id-#{old_name}") or raise "not found a mailbox old name for id: #{mbox_id}" put_str("mbox_id2name-#{mbox_id}", new_name) put_num("mbox_name2id-#{new_name}", mbox_id) self end
set_msg_date(msg_id, date)
click to toggle source
# File lib/rims/db.rb, line 307 def set_msg_date(msg_id, date) put_obj("msg_id2date-#{msg_id}", date) self end
set_msg_flag(msg_id, name, value)
click to toggle source
# File lib/rims/db.rb, line 323 def set_msg_flag(msg_id, name, value) flag_set = get_str_set("msg_id2flag-#{msg_id}") if (value) then unless (flag_set.include? name) then mbox_uid_map = msg_mbox_uid_mapping(msg_id) for mbox_id, uid_set in mbox_uid_map uid_set.length.times do mbox_flag_num_increment(mbox_id, name) end end end flag_set.add(name) else if (flag_set.include? name) then mbox_uid_map = msg_mbox_uid_mapping(msg_id) for mbox_id, uid_set in mbox_uid_map uid_set.length.times do mbox_flag_num_decrement(mbox_id, name) end end end flag_set.delete(name) end put_str_set("msg_id2flag-#{msg_id}", flag_set) self end
uidvalidity()
click to toggle source
# File lib/rims/db.rb, line 170 def uidvalidity get_num('uidvalidity', default_value: 1) end
uidvalidity_succ!()
click to toggle source
# File lib/rims/db.rb, line 174 def uidvalidity_succ! num_succ!('uidvalidity', default_value: 1) end
Private Instance Methods
get_recover_entry(key, prefix) { |entry_key| ... }
click to toggle source
# File lib/rims/db.rb, line 421 def get_recover_entry(key, prefix) if (key.start_with? prefix) then entry_key = key[(prefix.length)..-1] entry_key = yield(entry_key) if block_given? entry_key end end
make_mbox_repair_name(mbox_id)
click to toggle source
# File lib/rims/db.rb, line 490 def make_mbox_repair_name(mbox_id) new_name = "MAILBOX##{mbox_id}" if (mbox_id(new_name)) then new_name << ' (1)' while (mbox_id(new_name)) new_name.succ! end end new_name end