⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cover.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 4 页
字号:
    after 0 ->	    {?SERVER,Node} ! Request,	    Return = 		receive 		    {'DOWN', Ref, _Type, _Object, _Info} -> 			{error,node_dead};		    {?SERVER,Reply} -> 			Reply		end,	    erlang:demonitor(Ref),	    Return    end.    remote_reply(MainNode,Reply) ->    {?SERVER,MainNode} ! {?SERVER,Reply}.%%%----------------------------------------------------------------------%%% cover_server on main node%%%----------------------------------------------------------------------init_main(Starter) ->    register(?SERVER,self()),    ets:new(?COVER_TABLE, [set, public, named_table]),    ets:new(?BINARY_TABLE, [set, named_table]),    ets:new(?COLLECTION_TABLE, [set, public, named_table]),    process_flag(trap_exit,true),    Starter ! {?SERVER,started},    main_process_loop(#main_state{}).main_process_loop(State) ->    receive	{From, {start_nodes,Nodes}} ->	    ThisNode = node(),	    StartedNodes = 		lists:foldl(		  fun(Node,Acc) ->			  case rpc:call(Node,cover,remote_start,[ThisNode]) of			      {ok,RPid} ->				  link(RPid),				  [Node|Acc];			      Error ->				  io:format("Could not start cover on ~w: ~p\n",					    [Node,Error]),				  Acc			  end		  end,		  [],		  Nodes),	    %% In case some of the compiled modules have been unloaded they 	    %% should not be loaded on the new node.	    {_LoadedModules,Compiled} = 		get_compiled_still_loaded(State#main_state.nodes,					  State#main_state.compiled),	    remote_load_compiled(StartedNodes,Compiled),	    	    State1 = 		State#main_state{nodes = State#main_state.nodes ++ StartedNodes,				 compiled = Compiled},	    reply(From, {ok,StartedNodes}),	    main_process_loop(State1);	{From, {compile, File, Options}} ->	    case do_compile(File, Options) of		{ok, Module} ->		    remote_load_compiled(State#main_state.nodes,[{Module,File}]),		    reply(From, {ok, Module}),		    Compiled = add_compiled(Module, File,					    State#main_state.compiled),		    Imported = remove_imported(Module,State#main_state.imported),		    main_process_loop(State#main_state{compiled = Compiled,						       imported = Imported});		error ->		    reply(From, {error, File}),		    main_process_loop(State)	    end;	{From, {compile_beam, Module, BeamFile0}} ->	    Compiled0 = State#main_state.compiled,	    case get_beam_file(Module,BeamFile0,Compiled0) of		{ok,BeamFile} ->		    {Reply,Compiled} = 			case do_compile_beam(Module,BeamFile) of			    {ok, Module} ->				remote_load_compiled(State#main_state.nodes,						     [{Module,BeamFile}]),				C = add_compiled(Module,BeamFile,Compiled0),				{{ok,Module},C};			    error ->				{{error, BeamFile}, Compiled0};			    {error,Reason} -> % no abstract code				{{error, {Reason, BeamFile}}, Compiled0}			end,		    reply(From,Reply),		    Imported = remove_imported(Module,State#main_state.imported),		    main_process_loop(State#main_state{compiled = Compiled,						       imported = Imported});		{error,no_beam} ->		    %% The module has first been compiled from .erl, and now		    %% someone tries to compile it from .beam		    reply(From, 			  {error,{already_cover_compiled,no_beam_found,Module}}),		    main_process_loop(State)	    end;	{From, {export,OutFile,Module}} ->	    case file:open(OutFile,[write,binary,raw]) of		{ok,Fd} ->		    Reply = 			case Module of			    '_' ->				export_info(State#main_state.imported),				collect(State#main_state.nodes),				do_export_table(State#main_state.compiled,						State#main_state.imported,						Fd);			    _ ->				export_info(Module,State#main_state.imported),				case is_loaded(Module, State) of				    {loaded, File} ->					[{Module,Clauses}] = 					    ets:lookup(?COVER_TABLE,Module),					collect(Module, Clauses,						State#main_state.nodes),					do_export_table([{Module,File}],[],Fd);				    {imported, File, ImportFiles} ->					%% don't know if I should allow this - 					%% export a module which is only imported					Imported = [{Module,File,ImportFiles}],					do_export_table([],Imported,Fd);				    _NotLoaded ->					{error,{not_cover_compiled,Module}}				end			end,		    file:close(Fd),		    reply(From, Reply);		{error,Reason} ->		    reply(From, {error, {cant_open_file,OutFile,Reason}})	    	    end,	    main_process_loop(State);		{From, {import,File}} ->	    case file:open(File,[read,binary,raw]) of		{ok,Fd} ->		    Imported = do_import_to_table(Fd,File,						  State#main_state.imported),		    reply(From, ok),		    main_process_loop(State#main_state{imported=Imported});		{error,Reason} ->		    reply(From, {error, {cant_open_file,File,Reason}}),		    main_process_loop(State)	    end;	{From, modules} ->	    %% Get all compiled modules which are still loaded	    {LoadedModules,Compiled} = 		get_compiled_still_loaded(State#main_state.nodes,					  State#main_state.compiled),	    	    reply(From, LoadedModules),	    main_process_loop(State#main_state{compiled=Compiled});	{From, imported_modules} ->	    %% Get all modules with imported data	    ImportedModules = lists:map(fun({Mod,_File,_ImportFile}) -> Mod end,					State#main_state.imported),	    reply(From, ImportedModules),	    main_process_loop(State);	{From, imported} ->	    %% List all imported files	    reply(From, get_all_importfiles(State#main_state.imported,[])),	    main_process_loop(State);	{From, which_nodes} ->	    %% List all imported files	    reply(From, State#main_state.nodes),	    main_process_loop(State);	{From, reset} ->	    lists:foreach(	      fun({Module,_File}) -> 		      do_reset_main_node(Module,State#main_state.nodes)	      end, 	      State#main_state.compiled),	    reply(From, ok),	    main_process_loop(State#main_state{imported=[]});	{From, {stop,Nodes}} ->	    remote_collect('_',Nodes,true),	    reply(From, ok),	    State1 = State#main_state{nodes=State#main_state.nodes--Nodes},	    main_process_loop(State1);	{From, stop} ->	    lists:foreach(	      fun(Node) -> 		      remote_call(Node,{remote,stop})	      end,	      State#main_state.nodes),	    reload_originals(State#main_state.compiled),	    reply(From, ok);	{From, {Request, Module}} ->	    case is_loaded(Module, State) of		{loaded, File} ->		    {Reply,State1} = 			case Request of			    {analyse, Analysis, Level} ->				analyse_info(Module,State#main_state.imported),				[{Module,Clauses}] = 				    ets:lookup(?COVER_TABLE,Module),				collect(Module,Clauses,State#main_state.nodes),				R = do_analyse(Module, Analysis, Level, Clauses),				{R,State};			    			    {analyse_to_file, OutFile, Opts} ->				R = case find_source(File) of					{beam,_BeamFile} ->					    {error,no_source_code_found};					ErlFile ->					    Imported = State#main_state.imported,					    analyse_info(Module,Imported),					    [{Module,Clauses}] = 						ets:lookup(?COVER_TABLE,Module),					    collect(Module, Clauses,						    State#main_state.nodes),					    HTML = lists:member(html,Opts),					    do_analyse_to_file(Module,OutFile,							       ErlFile,HTML)				    end,				{R,State};			    			    is_compiled ->				{{file, File},State};			    			    reset ->				R = do_reset_main_node(Module,						       State#main_state.nodes),				Imported = 				    remove_imported(Module,						    State#main_state.imported),				{R,State#main_state{imported=Imported}}			end,		    reply(From, Reply),		    main_process_loop(State1);				{imported,File,_ImportFiles} ->		    {Reply,State1} = 			case Request of			    {analyse, Analysis, Level} ->				analyse_info(Module,State#main_state.imported),				[{Module,Clauses}] = 				    ets:lookup(?COLLECTION_TABLE,Module),				R = do_analyse(Module, Analysis, Level, Clauses),				{R,State};			    			    {analyse_to_file, OutFile, Opts} ->				R = case find_source(File) of					{beam,_BeamFile} ->					    {error,no_source_code_found};					ErlFile ->					    Imported = State#main_state.imported,					    analyse_info(Module,Imported),					    HTML = lists:member(html,Opts),					    do_analyse_to_file(Module,OutFile,							   ErlFile,HTML)				    end,				{R,State};			    			    is_compiled ->				{false,State};			    			    reset ->				R = do_reset_collection_table(Module),				Imported = 				    remove_imported(Module,						    State#main_state.imported),				{R,State#main_state{imported=Imported}}			end,		    reply(From, Reply),		    main_process_loop(State1);		    				NotLoaded ->		    Reply = 			case Request of			    is_compiled ->				false;			    _ ->				{error, {not_cover_compiled,Module}}			end,		    Compiled = 			case NotLoaded of			    unloaded ->				do_clear(Module),				remote_unload(State#main_state.nodes,[Module]),				update_compiled([Module],						State#main_state.compiled);			    false ->				State#main_state.compiled			end,		    reply(From, Reply),		    main_process_loop(State#main_state{compiled=Compiled})	    end;		{'EXIT',Pid,_Reason} ->	    %% Exit is trapped on the main node only, so this will only happen 	    %% there. I assume that I'm only linked to cover_servers on remote 	    %% nodes, so this must be one of them crashing. 	    %% Remove node from list!	    State1 = State#main_state{nodes=State#main_state.nodes--[node(Pid)]},	    main_process_loop(State1);		get_status ->	    io:format("~p~n",[State]),	    main_process_loop(State)    end.%%%----------------------------------------------------------------------%%% cover_server on remote node%%%----------------------------------------------------------------------init_remote(Starter,MainNode) ->    register(?SERVER,self()),    ets:new(?COVER_TABLE, [set, public, named_table]),    Starter ! {self(),started},    remote_process_loop(#remote_state{main_node=MainNode}).remote_process_loop(State) ->    receive 	{remote,load_compiled,Compiled} ->	    Compiled1 = load_compiled(Compiled,State#remote_state.compiled),	    remote_reply(State#remote_state.main_node, ok),	    remote_process_loop(State#remote_state{compiled=Compiled1});	{remote,unload,UnloadedModules} ->	    unload(UnloadedModules),	    Compiled = 		update_compiled(UnloadedModules, State#remote_state.compiled),	    remote_reply(State#remote_state.main_node, ok),	    remote_process_loop(State#remote_state{compiled=Compiled});	{remote,reset,Module} ->	    do_reset(Module),	    remote_reply(State#remote_state.main_node, ok),	    remote_process_loop(State);	{remote,collect,Module,CollectorPid} ->	    MS = 		case Module of		    '_' -> ets:fun2ms(fun({M,C}) when is_atom(M) -> C end);		    _ -> ets:fun2ms(fun({M,C}) when M=:=Module -> C end)		end,	    AllClauses = lists:flatten(ets:select(?COVER_TABLE,MS)),	    	    %% Sending clause by clause in order to avoid large lists	    lists:foreach(	      fun({M,F,A,C,_L}) ->		      Pattern = 			  {#bump{module=M, function=F, arity=A, clause=C}, '_'},		      Bumps = ets:match_object(?COVER_TABLE, Pattern),		      %% Reset		      lists:foreach(fun({Bump,_N}) ->					    ets:insert(?COVER_TABLE, {Bump,0})				    end,				    Bumps),		      CollectorPid ! {chunk,Bumps}	      end,	      AllClauses),	    CollectorPid ! done,	    remote_reply(State#remote_state.main_node, ok),	    remote_process_loop(State);	{remote,stop} ->	    reload_originals(State#remote_state.compiled),	    remote_reply(State#remote_state.main_node, ok);	get_status ->	    io:format("~p~n",[State]),	    remote_process_loop(State);	M ->	    io:format("WARNING: remote cover_server received\n~p\n",[M]),	    case M of		{From,_} ->		    case is_from(From) of			true ->			    reply(From,{error,not_main_node});		        false ->			    ok		    end;		_ ->		    ok	    end,	    remote_process_loop(State)	        end.reload_originals([{Module,_File}|Compiled]) ->    do_reload_original(Module),    reload_originals(Compiled);reload_originals([]) ->    ok.do_reload_original(Module) ->    case code:which(Module) of	?TAG ->	    code:purge(Module),     % remove code marked as 'old'	    code:delete(Module),    % mark cover compiled code as 'old'	    %% Note: original beam code must be loaded before the cover	    %% compiled code is purged, in order to for references to	    %% 'fun M:F/A' and %% 'fun F/A' funs to be correct (they	    %% refer to (M:)F/A in the *latest* version  of the module)	    code:load_file(Module), % load original code	    code:purge(Module);     % remove cover compiled code	_ ->	    ignore    end.load_compiled([{Module,File,Binary,InitialTable}|Compiled],Acc) ->    NewAcc = 	case code:load_binary(Module, ?TAG, Binary) of	    {module,Module} ->		insert_initial_data(InitialTable),		add_compiled(Module, File, Acc);	    _  ->		Acc	end,    load_compiled(Compiled,NewAcc);load_compiled([],Acc) ->    Acc.insert_initial_data([Item|Items]) ->    ets:insert(?COVER_TABLE, Item),    insert_initial_data(Items);insert_initial_data([]) ->    ok.    unload([Module|Modules]) ->    do_clear(Module),    do_reload_original(Module),    unload(Modules);unload([]) ->    ok.%%%----------------------------------------------------------------------%%% Internal functions%%%----------------------------------------------------------------------%%%--Handling of remote nodes--------------------------------------------%% start the cover_server on a remote noderemote_start(MainNode) ->    case whereis(?SERVER) of	undefined ->	    Starter = self(),	    Pid = spawn(fun() -> init_remote(Starter,MainNode) end),	    Ref = erlang:monitor(process,Pid),	    Return = 		receive 		    {Pid,started} -> 			{ok,Pid};		    {'DOWN', Ref, _Type, _Object, Info} -> 			{error,Info}		end,	    erlang:demonitor(Ref),	    Return;	Pid ->	    {error,{already_started,Pid}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -