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

📄 release_handler_1.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 2 页
字号:
eval({code_change, Mode, Modules}, EvalState) ->    Suspended = EvalState#eval_state.suspended,    Vsns = EvalState#eval_state.vsns,    Timeout = get_opt(code_change_timeout, EvalState, default),    lists:foreach(fun({Mod, Extra}) ->			  Vsn =			      case lists:keysearch(Mod, 1, Vsns) of				  {value, {Mod, OldVsn, _NewVsn}}				    when Mode == up -> OldVsn;				  {value, {Mod, _OldVsn, NewVsn}}				    when Mode == down -> {down, NewVsn};				  _ when Mode == up -> undefined;				  _ -> {down, undefined}			      end,			  case lists:keysearch(Mod, 1, Suspended) of			      {value, {_Mod, Pids}} ->				  change_code(Pids, Mod, Vsn, Extra, Timeout);			      _ -> ok			  end		  end,		  Modules),    EvalState;eval({stop, Modules}, EvalState) ->    Procs = get_supervised_procs(),    NewStopped =	lists:foldl(fun(Mod, Stopped) ->			    Procs2 = stop(Mod, Procs),			    [{Mod, Procs2} | Stopped]		    end,		    EvalState#eval_state.stopped,		    Modules),    EvalState#eval_state{stopped = NewStopped};eval({start, Modules}, EvalState) ->    NewStopped =	lists:foldl(fun(Mod, Stopped) ->			    lists:filter(fun({Mod2, Procs}) when Mod2 == Mod ->						 start(Procs),						 false;					    (_) ->						 true					 end,					 Stopped)		    end,		    EvalState#eval_state.stopped,		    Modules),    EvalState#eval_state{stopped = NewStopped};eval({sync_nodes, Id, {M, F, A}}, EvalState) ->    sync_nodes(Id, apply(M, F, A)),    EvalState;eval({sync_nodes, Id, Nodes}, EvalState) ->    sync_nodes(Id, Nodes),    EvalState;eval({apply, {M, F, A}}, EvalState) ->    apply(M, F, A),    EvalState;eval(restart_new_emulator, _EvalState) ->    throw(restart_new_emulator).get_opt(Tag, EvalState, Default) ->    case lists:keysearch(Tag, 1, EvalState#eval_state.opts) of	{value,  {_Tag, Value}} -> Value;	false                   -> Default    end.%%-----------------------------------------------------------------%% This is a first approximation.  Unfortunately, we might end up%% with the situation that after this suspendation, some new%% processes start *before* we have loaded the new code, and these%% will execute the old code.  These processes could be terminated%% later on (if the prev current version is purged).  The same%% goes for processes that didn't respond to the suspend message.%%-----------------------------------------------------------------suspend(Mod, Procs, Timeout) ->    lists:zf(fun({_Sup, _Name, Pid, Mods}) -> 		     case lists:member(Mod, Mods) of			 true ->			     case catch sys_suspend(Pid, Timeout) of				 ok -> {true, Pid};				 _ -> 				     % If the proc hangs, make sure to				     % resume it when it gets suspended!				     catch sys:resume(Pid),				     false			     end;			 false ->			     false		     end	     end,	     Procs).sys_suspend(Pid, default) ->    sys:suspend(Pid);sys_suspend(Pid, Timeout) ->    sys:suspend(Pid, Timeout).resume(Pids) ->    lists:foreach(fun(Pid) -> catch sys:resume(Pid) end, Pids).change_code(Pids, Mod, Vsn, Extra, Timeout) ->    Fun = fun(Pid) -> 		  case Timeout of		      default ->			  ok = sys:change_code(Pid, Mod, Vsn, Extra);		      _Else ->			  ok = sys:change_code(Pid, Mod, Vsn, Extra, Timeout)		  end	  end,    lists:foreach(Fun, Pids).stop(Mod, Procs) ->    lists:zf(fun({undefined, _Name, _Pid, _Mods}) ->		     false;		({Sup, Name, _Pid, Mods}) -> 		     case lists:member(Mod, Mods) of			 true ->			     case catch supervisor:terminate_child(					  Sup, Name) of				 ok -> {true, {Sup, Name}};				 _ -> false			     end;			 false -> false		     end	     end,	     Procs).start(Procs) ->    lists:foreach(fun({Sup, Name}) -> 			  catch supervisor:restart_child(Sup, Name)		  end,		  Procs).%%-----------------------------------------------------------------%% Func: get_supervised_procs/0%% Purpose: This is the magic function.  It finds all process in%%          the system and which modules they execute as a call_back or%%          process module.%%          This is achieved by asking the main supervisor for the%%          applications for all children and their modules%%          (recursively).%% NOTE: If a supervisor is suspended, it isn't possible to call%%       which_children.  Code change on a supervisor should be%%       done in another way; the only code in a supervisor is%%       code for starting children.  Therefore, to change a%%       supervisor module, we should load the new version, and then%%       delete the old.  Then we should perform the start changes%%       manually, by adding/deleting children.%% Returns: [{SuperPid, ChildName, ChildPid, Mods}]%%-----------------------------------------------------------------%% OTP-3452. For each application the first item contains the pid%% of the top supervisor, and the name of the supervisor call-back module.  %%-----------------------------------------------------------------get_supervised_procs() ->    lists:foldl(      fun(Application, Procs) ->	      case application_controller:get_master(Application) of		  Pid when is_pid(Pid) ->		      {Root, _AppMod} = application_master:get_child(Pid),		      case get_supervisor_module(Root) of			  {ok, SupMod} ->			      get_procs(supervisor:which_children(Root), 					Root) ++				  [{undefined, undefined, Root, [SupMod]} | 				   Procs];			  {error, _} ->			      error_logger:error_msg("release_handler: "						     "cannot find top "						     "supervisor for "						    "application ~w~n", 						    [Application]),			      get_procs(supervisor:which_children(Root), 					Root) ++ Procs		      end;		  _ -> Procs	      end      end,      [],      lists:map(fun({Application, _Name, _Vsn}) ->			Application		end,		application:which_applications())).get_procs([{Name, Pid, worker, dynamic} | T], Sup) when is_pid(Pid) ->    Mods = get_dynamic_mods(Name),    [{Sup, Name, Pid, Mods} | get_procs(T, Sup)];get_procs([{Name, Pid, worker, Mods} | T], Sup) when is_pid(Pid), is_list(Mods) ->    [{Sup, Name, Pid, Mods} | get_procs(T, Sup)];get_procs([{Name, Pid, supervisor, Mods} | T], Sup) when is_pid(Pid) ->    [{Sup, Name, Pid, Mods} | get_procs(T, Sup)] ++ 	get_procs(supervisor:which_children(Pid), Pid);get_procs([_H | T], Sup) ->    get_procs(T, Sup);get_procs(_, _Sup) ->    [].get_dynamic_mods(Pid) ->    {ok,Res} = gen:call(Pid, self(), get_modules),    Res.%% XXXX%% Note: The following is a terrible hack done in order to resolve the%% problem stated in ticket OTP-3452.%% XXXX NOTE WELL: This record is from supervisor.erl. Also the record%% name is really `state'. -record(supervisor_state, {name,                strategy,                children = [],                dynamics = [],                intensity,                period,                restarts = [],                module,                args}).%% Return the name of the call-back module that implements the%% (top) supervisor SupPid.%% Returns: {ok, Module} | {error,undefined}%%get_supervisor_module(SupPid) ->    case catch get_supervisor_module1(SupPid) of	{ok, Module} when is_atom(Module) ->	    {ok, Module};	_Other ->	    io:format("~w: reason: ~w~n", [SupPid, _Other]),	    {error, undefined}    end.get_supervisor_module1(SupPid) ->    {status, _Pid, {module, _Mod},      [_PDict, _SysState, _Parent, _Dbg, Misc]} = sys:get_status(SupPid),    [_Name, State, _Type, _Time] = Misc,    %% Cannot use #supervisor_state{module = Module} = State.    {ok, element(#supervisor_state.module, State)}.%%-----------------------------------------------------------------%% Func: do_soft_purge/3%% Args: Mod = atom()%%       PostPurgeMethod = soft_purge | brutal_purge%%       Unpurged = [{Mod, PostPurgeMethod}]%% Purpose: Check if there are any processes left running this code.%%          If so, make sure Mod is a member in the returned list.%%          Otherwise, make sure Mod isn't a member in the returned%%          list.%% Returns: An updated list of unpurged modules.%%-----------------------------------------------------------------do_soft_purge(Mod, PostPurgeMethod, Unpurged) ->    IsNoOldProcsLeft = code:soft_purge(Mod),    case lists:keymember(Mod, 1, Unpurged) of	true when IsNoOldProcsLeft == true -> lists:keydelete(Mod, 1, Unpurged);	true -> Unpurged;	false when IsNoOldProcsLeft == true -> Unpurged;	false -> [{Mod, PostPurgeMethod} | Unpurged]    end.%%-----------------------------------------------------------------%% Func: sync_nodes/2%% Args: Id = term()%%       Nodes = [atom()]%% Purpose: Synchronizes with all nodes.%%-----------------------------------------------------------------sync_nodes(Id, Nodes) ->    NNodes = lists:delete(node(), Nodes),    lists:foreach(fun(Node) ->			  {release_handler, Node} ! {sync_nodes, Id, node()}		  end,		  NNodes),    lists:foreach(fun(Node) ->			  receive			      {sync_nodes, Id, Node} ->				  ok;			      {nodedown, Node} ->				  throw({sync_error, {nodedown, Node}})			  end		  end,		  NNodes).add_old_vsn(Mod, Vsns) ->    case lists:keysearch(Mod, 1, Vsns) of	{value, {Mod, undefined, NewVsn}} ->	    OldVsn = get_vsn(code:which(Mod)),	    lists:keyreplace(Mod, 1, Vsns, {Mod, OldVsn, NewVsn});	{value, {Mod, _OldVsn, _NewVsn}} ->	    Vsns;	false ->	    OldVsn = get_vsn(code:which(Mod)),	    [{Mod, OldVsn, undefined} | Vsns]    end.add_new_vsn(Mod, File, Vsns) ->    NewVsn = get_vsn(File),    case lists:keysearch(Mod, 1, Vsns) of	{value, {Mod, OldVsn, undefined}} ->	    lists:keyreplace(Mod, 1, Vsns, {Mod, OldVsn, NewVsn});	false ->	    [{Mod, undefined, NewVsn} | Vsns]    end.%%-----------------------------------------------------------------%% Func: get_vsn/1%% Args: File = string()%% Purpose: Finds the version attribute of a module.%% Returns: Vsn%%          Vsn = term()%%-----------------------------------------------------------------get_vsn(File) ->    {ok, {_Mod, Vsn}} = beam_lib:version(File),    case misc_supp:is_string(Vsn) of	true ->	    Vsn;	false ->	    %% If -vsn(Vsn) defines a term which is not a	    %% string, the value is returned here as [Vsn].	    case Vsn of		[VsnTerm] ->		    VsnTerm;		_ ->		    Vsn	    end    end.

⌨️ 快捷键说明

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