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 + -
显示快捷键?