mnesia_dumper.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,214 行 · 第 1/3 页
ERL
1,214 行
insert(Tid, Storage, Tab, Key, Tail, Op, InPlace, InitBy);insert(_Tid, _Storage, _Tab, _Key, [], _Op, _InPlace, _InitBy) -> ok; insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy) -> Item = {{Tab, Key}, Val, Op}, case InitBy of startup -> disc_insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy); _ when Storage == ram_copies -> mnesia_tm:do_update_op(Tid, Storage, Item), Snmp = mnesia_tm:prepare_snmp(Tab, Key, [Item]), mnesia_tm:do_snmp(Tid, Snmp); _ when Storage == disc_copies -> disc_insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy), mnesia_tm:do_update_op(Tid, Storage, Item), Snmp = mnesia_tm:prepare_snmp(Tab, Key, [Item]), mnesia_tm:do_snmp(Tid, Snmp); _ when Storage == disc_only_copies -> mnesia_tm:do_update_op(Tid, Storage, Item), Snmp = mnesia_tm:prepare_snmp(Tab, Key, [Item]), mnesia_tm:do_snmp(Tid, Snmp); _ when Storage == unknown -> ignore end.disc_delete_table(Tab, Storage) -> case mnesia_monitor:use_dir() of true -> if Storage == disc_only_copies; Tab == schema -> mnesia_monitor:unsafe_close_dets(Tab), Dat = mnesia_lib:tab2dat(Tab), file:delete(Dat); true -> DclFile = mnesia_lib:tab2dcl(Tab), case get({?MODULE,Tab}) of {opened_dumper, dcl} -> del_opened_tab(Tab), mnesia_log:unsafe_close_log(Tab); _ -> ok end, file:delete(DclFile), DcdFile = mnesia_lib:tab2dcd(Tab), file:delete(DcdFile), ok end, erase({?MODULE, Tab}); false -> ignore end.disc_delete_indecies(_Tab, _Cs, Storage) when Storage /= disc_only_copies -> ignore;disc_delete_indecies(Tab, Cs, disc_only_copies) -> Indecies = Cs#cstruct.index, mnesia_index:del_transient(Tab, Indecies, disc_only_copies).insert_op(Tid, Storage, {{Tab, Key}, Val, Op}, InPlace, InitBy) -> %% Propagate to disc only disc_insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy);%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% NOTE that all operations below will only%% be performed if the dump is initiated by%% startup or fast_schema_update%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%insert_op(_Tid, schema_ops, _OP, _InPlace, Initby) when Initby /= startup, Initby /= fast_schema_update, Initby /= schema_update -> ignore;insert_op(Tid, _, {op, rec, Storage, Item}, InPlace, InitBy) -> {{Tab, Key}, ValList, Op} = Item, insert(Tid, Storage, Tab, Key, ValList, Op, InPlace, InitBy);insert_op(Tid, _, {op, change_table_copy_type, N, FromS, ToS, TabDef}, InPlace, InitBy) -> Cs = mnesia_schema:list2cs(TabDef), Val = mnesia_schema:insert_cstruct(Tid, Cs, true), % Update ram only {schema, Tab, _} = Val, case lists:member(N, val({current, db_nodes})) of true when InitBy /= startup -> mnesia_controller:add_active_replica(Tab, N, Cs); _ -> ignore end, if N == node() -> Dmp = mnesia_lib:tab2dmp(Tab), Dat = mnesia_lib:tab2dat(Tab), Dcd = mnesia_lib:tab2dcd(Tab), Dcl = mnesia_lib:tab2dcl(Tab), case {FromS, ToS} of {ram_copies, disc_copies} when Tab == schema -> ok = ensure_rename(Dmp, Dat); {ram_copies, disc_copies} -> file:delete(Dcl), ok = ensure_rename(Dmp, Dcd); {disc_copies, ram_copies} when Tab == schema -> mnesia_lib:set(use_dir, false), mnesia_monitor:unsafe_close_dets(Tab), file:delete(Dat); {disc_copies, ram_copies} -> file:delete(Dcl), file:delete(Dcd); {ram_copies, disc_only_copies} -> ok = ensure_rename(Dmp, Dat), true = open_files(Tab, disc_only_copies, InPlace, InitBy), %% ram_delete_table must be done before init_indecies, %% it uses info which is reset in init_indecies, %% it doesn't matter, because init_indecies don't use %% the ram replica of the table when creating the disc %% index; Could be improved :) mnesia_schema:ram_delete_table(Tab, FromS), PosList = Cs#cstruct.index, mnesia_index:init_indecies(Tab, disc_only_copies, PosList); {disc_only_copies, ram_copies} -> mnesia_monitor:unsafe_close_dets(Tab), disc_delete_indecies(Tab, Cs, disc_only_copies), case InitBy of startup -> ignore; _ -> mnesia_controller:get_disc_copy(Tab) end, disc_delete_table(Tab, disc_only_copies); {disc_copies, disc_only_copies} -> ok = ensure_rename(Dmp, Dat), true = open_files(Tab, disc_only_copies, InPlace, InitBy), mnesia_schema:ram_delete_table(Tab, FromS), PosList = Cs#cstruct.index, mnesia_index:init_indecies(Tab, disc_only_copies, PosList), file:delete(Dcl), file:delete(Dcd); {disc_only_copies, disc_copies} -> mnesia_monitor:unsafe_close_dets(Tab), disc_delete_indecies(Tab, Cs, disc_only_copies), case InitBy of startup -> ignore; _ -> mnesia_log:ets2dcd(Tab), mnesia_controller:get_disc_copy(Tab), disc_delete_table(Tab, disc_only_copies) end end; true -> ignore end, S = val({schema, storage_type}), disc_insert(Tid, S, schema, Tab, Val, write, InPlace, InitBy);insert_op(Tid, _, {op, transform, _Fun, TabDef}, InPlace, InitBy) -> Cs = mnesia_schema:list2cs(TabDef), case mnesia_lib:cs_to_storage_type(node(), Cs) of disc_copies -> open_dcl(Cs#cstruct.name); _ -> ignore end, insert_cstruct(Tid, Cs, true, InPlace, InitBy);%%% Operations below this are handled without using the logg.insert_op(Tid, _, {op, restore_recreate, TabDef}, InPlace, InitBy) -> Cs = mnesia_schema:list2cs(TabDef), Tab = Cs#cstruct.name, Type = Cs#cstruct.type, Storage = mnesia_lib:cs_to_storage_type(node(), Cs), %% Delete all possibly existing files and tables disc_delete_table(Tab, Storage), disc_delete_indecies(Tab, Cs, Storage), case InitBy of startup -> ignore; _ -> case ?catch_val({Tab, cstruct}) of {'EXIT', _} -> ignore; _ -> mnesia_schema:ram_delete_table(Tab, Storage), mnesia_checkpoint:tm_del_copy(Tab, node()) end end, %% And create new ones.. if (InitBy == startup) or (Storage == unknown) -> ignore; Storage == ram_copies -> Args = [{keypos, 2}, public, named_table, Type], mnesia_monitor:mktab(Tab, Args); Storage == disc_copies -> Args = [{keypos, 2}, public, named_table, Type], mnesia_monitor:mktab(Tab, Args), File = mnesia_lib:tab2dcd(Tab), FArg = [{file, File}, {name, {mnesia,create}}, {repair, false}, {mode, read_write}], {ok, Log} = mnesia_monitor:open_log(FArg), mnesia_monitor:unsafe_close_log(Log); Storage == disc_only_copies -> File = mnesia_lib:tab2dat(Tab), file:delete(File), Args = [{file, mnesia_lib:tab2dat(Tab)}, {type, mnesia_lib:disk_type(Tab, Type)}, {keypos, 2}, {repair, mnesia_monitor:get_env(auto_repair)}], mnesia_monitor:open_dets(Tab, Args) end, insert_op(Tid, ignore, {op, create_table, TabDef}, InPlace, InitBy);insert_op(Tid, _, {op, create_table, TabDef}, InPlace, InitBy) -> Cs = mnesia_schema:list2cs(TabDef), insert_cstruct(Tid, Cs, false, InPlace, InitBy), Tab = Cs#cstruct.name, Storage = mnesia_lib:cs_to_storage_type(node(), Cs), case InitBy of startup -> case Storage of unknown -> ignore; ram_copies -> ignore; disc_copies -> Dcd = mnesia_lib:tab2dcd(Tab), case mnesia_lib:exists(Dcd) of true -> ignore; false -> mnesia_log:open_log(temp, mnesia_log:dcl_log_header(), Dcd, false, false, read_write), mnesia_log:unsafe_close_log(temp) end; _ -> Args = [{file, mnesia_lib:tab2dat(Tab)}, {type, mnesia_lib:disk_type(Tab, Cs#cstruct.type)}, {keypos, 2}, {repair, mnesia_monitor:get_env(auto_repair)}], case mnesia_monitor:open_dets(Tab, Args) of {ok, _} -> mnesia_monitor:unsafe_close_dets(Tab); {error, Error} -> exit({"Failed to create dets table", Error}) end end; _ -> Copies = mnesia_lib:copy_holders(Cs), Active = mnesia_lib:intersect(Copies, val({current, db_nodes})), [mnesia_controller:add_active_replica(Tab, N, Cs) || N <- Active], case Storage of unknown -> mnesia_lib:unset({Tab, create_table}), case Cs#cstruct.local_content of true -> ignore; false -> mnesia_lib:set_remote_where_to_read(Tab) end; _ -> case Cs#cstruct.local_content of true -> mnesia_lib:set_local_content_whereabouts(Tab); false -> mnesia_lib:set({Tab, where_to_read}, node()) end, case Storage of ram_copies -> ignore; _ -> %% Indecies are still created by loader disc_delete_indecies(Tab, Cs, Storage) %% disc_delete_table(Tab, Storage) end, %% Update whereabouts and create table mnesia_controller:create_table(Tab), mnesia_lib:unset({Tab, create_table}) end end;insert_op(_Tid, _, {op, dump_table, Size, TabDef}, _InPlace, _InitBy) -> case Size of unknown -> ignore; _ -> Cs = mnesia_schema:list2cs(TabDef), Tab = Cs#cstruct.name, Dmp = mnesia_lib:tab2dmp(Tab), Dat = mnesia_lib:tab2dcd(Tab), case Size of 0 -> %% Assume that table files already are closed file:delete(Dmp), file:delete(Dat); _ -> ok = ensure_rename(Dmp, Dat) end end;insert_op(Tid, _, {op, delete_table, TabDef}, InPlace, InitBy) -> Cs = mnesia_schema:list2cs(TabDef), Tab = Cs#cstruct.name, case mnesia_lib:cs_to_storage_type(node(), Cs) of unknown -> ignore; Storage -> disc_delete_table(Tab, Storage), disc_delete_indecies(Tab, Cs, Storage), case InitBy of startup -> ignore; _ -> mnesia_schema:ram_delete_table(Tab, Storage), mnesia_checkpoint:tm_del_copy(Tab, node()) end end, delete_cstruct(Tid, Cs, InPlace, InitBy);insert_op(Tid, _, {op, clear_table, TabDef}, InPlace, InitBy) -> Cs = mnesia_schema:list2cs(TabDef), Tab = Cs#cstruct.name, case mnesia_lib:cs_to_storage_type(node(), Cs) of unknown -> ignore; Storage -> Oid = '_', %%val({Tab, wild_pattern}), if Storage == disc_copies -> open_dcl(Cs#cstruct.name); true -> ignore end, %% Need to catch this, it crashes on ram_copies if %% the op comes before table is loaded at startup. catch insert(Tid, Storage, Tab, '_', Oid, clear_table, InPlace, InitBy) end;insert_op(Tid, _, {op, merge_schema, TabDef}, InPlace, InitBy) -> Cs = mnesia_schema:list2cs(TabDef), case Cs#cstruct.name of schema -> %% If we bootstrap an empty (diskless) mnesia from another node %% we might have changed the storage_type of schema. %% I think this is a good place to do it. Update = fun(NS = {Node,Storage}) -> case mnesia_lib:cs_to_storage_type(Node, Cs) of Storage -> NS; disc_copies when Node == node() -> Dir = mnesia_lib:dir(), ok = mnesia_schema:opt_create_dir(true, Dir), mnesia_schema:purge_dir(Dir, []), mnesia_log:purge_all_logs(), mnesia_lib:set(use_dir, true), mnesia_log:init(), Ns = val({current, db_nodes}), F = fun(U) -> mnesia_recover:log_mnesia_up(U) end, lists:foreach(F, Ns), raw_named_dump_table(schema, dat), temp_set_master_nodes(), {Node,disc_copies}; CSstorage -> {Node,CSstorage} end end, W2C0 = val({schema, where_to_commit}), W2C = case W2C0 of {blocked, List} -> {blocked,lists:map(Update,List)}; List -> lists:map(Update,List) end, if W2C == W2C0 -> ignore; true -> mnesia_lib:set({schema, where_to_commit}, W2C) end; _ -> ignore end, insert_cstruct(Tid, Cs, false, InPlace, InitBy);insert_op(Tid, _, {op, del_table_copy, Storage, Node, TabDef}, InPlace, InitBy) -> Cs = mnesia_schema:list2cs(TabDef), Tab = Cs#cstruct.name, if Tab == schema, Storage == ram_copies -> insert_cstruct(Tid, Cs, true, InPlace, InitBy); Tab /= schema -> mnesia_controller:del_active_replica(Tab, Node), mnesia_lib:del({Tab, Storage}, Node), if Node == node() -> case Cs#cstruct.local_content of true -> mnesia_lib:set({Tab, where_to_read}, nowhere); false -> mnesia_lib:set_remote_where_to_read(Tab) end,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?