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

📄 release_handler.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 5 页
字号:
    Tar = filename:join(RelDir, ReleaseName ++ ".tar.gz"),    do_check_file(Tar, regular),    Rel = ReleaseName ++ ".rel",    extract_rel_file(filename:join("releases", Rel), Tar, Root),    RelFile = filename:join(RelDir, Rel),    Release = check_rel(Root, RelFile, false),    #release{vsn = Vsn} = Release,    case lists:keysearch(Vsn, #release.vsn, Releases) of	{value, _} -> throw({error, {existing_release, Vsn}});	_          -> ok    end,    extract_tar(Root, Tar),    NewReleases = [Release#release{status = unpacked} | Releases],    write_releases(RelDir, NewReleases, false),    Dir = filename:join([RelDir, Vsn]),    copy_file(RelFile, Dir, false),    {ok, NewReleases, Vsn}.%% Note that this function is not executed by a client%% release_handler.clean_release(RelDir, ReleaseName) ->    Tar = filename:join(RelDir, ReleaseName ++ ".tar.gz"),    Rel = filename:join(RelDir, ReleaseName ++ ".rel"),    file:delete(Tar),    file:delete(Rel).   check_rel(Root, RelFile, Masters) ->    check_rel(Root, RelFile, [], Masters).check_rel(Root, RelFile, LibDirs, Masters) ->    case consult(RelFile, Masters) of	{ok, [RelData]} ->	    check_rel_data(RelData, Root, LibDirs);	{ok, _} ->	    throw({error, {bad_rel_file, RelFile}});	{error, Reason} when is_tuple(Reason) ->	    throw({error, {bad_rel_file, RelFile}});	{error, FileError} -> % FileError is posix atom | no_master	    throw({error, {FileError, RelFile}})    end.check_rel_data({release, {Name, Vsn}, {erts, EVsn}, Libs}, Root, LibDirs) ->    Libs2 =	lists:map(fun(LibSpec) ->			  Lib = element(1, LibSpec),			  LibVsn = element(2, LibSpec),			  LibName = lists:concat([Lib, "-", LibVsn]),			  LibDir = 			      case lists:keysearch(Lib, 1, LibDirs) of				  {value, {_Lib, _Vsn, Dir}} ->				      Path = filename:join(Dir,LibName),				      check_path(Path),				      Path;				  _ ->				      filename:join([Root, "lib", LibName])			      end,			  {Lib, LibVsn, LibDir}		  end,		  Libs),    #release{name = Name, vsn = Vsn, erts_vsn = EVsn,	     libs = Libs2, status = unpacking};check_rel_data(RelData, _Root, _LibDirs) ->    throw({error, {bad_rel_data, RelData}}).check_path(Path) ->    case file:read_file_info(Path) of	{ok, Info} when Info#file_info.type==directory ->	    ok;	{ok, _Info} ->	    throw({error, {not_a_directory, Path}});	{error, _Reason} ->	    throw({error, {no_such_directory, Path}})    end.    do_check_install_release(RelDir, Vsn, Releases, Masters) ->    case lists:keysearch(Vsn, #release.vsn, Releases) of	{value, #release{status = current}} ->	    {error, {already_installed, Vsn}};	{value, Release} ->	    LatestRelease = get_latest_release(Releases),	    VsnDir = filename:join([RelDir, Vsn]),	    check_file(filename:join(VsnDir, "start.boot"), regular, Masters),	    IsRelup = check_opt_file(filename:join(VsnDir, "relup"), regular, Masters),	    check_opt_file(filename:join(VsnDir, "sys.config"), regular, Masters),	    %% Check that all required libs are present	    Libs = Release#release.libs,	    lists:foreach(fun({_Lib, _LibVsn, LibDir}) ->				  check_file(LibDir, directory, Masters),				  Ebin = filename:join(LibDir, "ebin"),				  check_file(Ebin, directory, Masters)			  end,			  Libs),	    if		IsRelup ->		    case get_rh_script(LatestRelease, Release, RelDir, Masters) of			{ok, {CurrentVsn, Descr, Script}} ->			    case catch check_script(Script, Libs) of				ok ->				    {ok, CurrentVsn, Descr};				Else ->				    Else			    end;			Error ->			    Error		    end;		true ->		    {ok, Vsn, ""}	    end;	_ ->	    {error, {no_such_release, Vsn}}    end.	    do_install_release(#state{start_prg = StartPrg,			  rel_dir = RelDir, releases = Releases,			  masters = Masters,			  static_emulator = Static},		   Vsn, Opts) ->    case lists:keysearch(Vsn, #release.vsn, Releases) of	{value, #release{status = current}} ->	    {error, {already_installed, Vsn}};	{value, Release} ->	    LatestRelease = get_latest_release(Releases),	    case get_rh_script(LatestRelease, Release, RelDir, Masters) of		{ok, {CurrentVsn, Descr, Script}} ->		    mon_nodes(true),		    EnvBefore = application_controller:prep_config_change(),		    Apps = change_appl_data(RelDir, Release, Masters),		    LibDirs = Release#release.libs,		    case eval_script(Script, Apps, LibDirs, Opts) of			{ok, []} ->			    application_controller:config_change(EnvBefore),			    mon_nodes(false),			    NewReleases = set_status(Vsn, current, Releases),			    {ok, NewReleases, CurrentVsn, Descr};			{ok, Unpurged} ->			    application_controller:config_change(EnvBefore),			    mon_nodes(false),			    NewReleases = set_status(Vsn, current, Releases),			    {ok, NewReleases, Unpurged, CurrentVsn, Descr};			restart_new_emulator when Static == true ->			    throw(static_emulator);			restart_new_emulator ->			    mon_nodes(false),			    {value, PermanentRelease} = 				lists:keysearch(permanent, #release.status,						Releases), 			    NReleases = set_status(Vsn, current, Releases),			    NReleases2 = set_status(Vsn,tmp_current,NReleases),			    write_releases(RelDir, NReleases2, Masters),			    prepare_restart_new_emulator(StartPrg, RelDir,							 Release, 							 PermanentRelease, 							 Masters),			    {restart_new_emulator, CurrentVsn, Descr};			Else ->			    application_controller:config_change(EnvBefore),			    mon_nodes(false),			    Else		    end;		Error ->		    Error	    end;	_ ->	    {error, {no_such_release, Vsn}}    end.%%% This code chunk updates the services in one of two ways,%%% Either the emulator is restarted, in which case the old service%%% is to be removed and the new enabled, or the emulator is NOT restarted%%% in which case we try to rename the old service to the new name and try%%% to update heart's view of what service we are really running.do_make_services_permanent(PermanentVsn,Vsn, PermanentEVsn, EVsn) ->    PermName = hd(string:tokens(atom_to_list(node()),"@")) 	++ "_" ++ PermanentVsn,    Name = hd(string:tokens(atom_to_list(node()),"@")) 	++ "_" ++ Vsn,    case erlsrv:get_service(EVsn,Name) of	{error, _Error} ->	    %% We probably do not need to replace services, just 	    %% rename.	    case os:getenv("ERLSRV_SERVICE_NAME") == PermName of		true ->		    case erlsrv:rename_service(EVsn,PermName,Name) of			{ok,_} ->			    case erlsrv:get_service(EVsn,Name) of				{error,Error2} ->				    throw({error,Error2});				_Data2 ->				    %% The interfaces for doing this are				    %% NOT published and may be subject to				    %% change. Do NOT do this anywhere else!				    os:putenv("ERLSRV_SERVICE_NAME", Name),				    %% Restart heart port program, this 				    %% function is only to be used here.				    heart:cycle(),				    ok			    end;			Error3 ->			    throw({error,{service_rename_failed, Error3}})		    end;		false ->		    throw({error,service_name_missmatch})	    end;	Data ->	    UpdData = erlsrv:new_service(Name, Data, []),	    case erlsrv:store_service(EVsn,UpdData) of		ok ->		    erlsrv:disable_service(PermanentEVsn, PermName),		    erlsrv:enable_service(EVsn, Name),		    erlsrv:remove_service(PermName),		    %%% Read comments about these above...		    os:putenv("ERLSRV_SERVICE_NAME", Name),		    heart:cycle(),		    ok;		Error4 ->		    throw(Error4)	    end    end.	    do_make_permanent(#state{releases = Releases,			 rel_dir = RelDir, unpurged = Unpurged,			 masters = Masters,			 static_emulator = Static},		  Vsn) ->    case lists:keysearch(Vsn, #release.vsn, Releases) of	{value, #release{erts_vsn = EVsn, status = Status}}	  when Status /= unpacked, Status /= old, Status /= permanent ->	    Dir = filename:join([RelDir, Vsn]),	    Sys =		case catch check_file(filename:join(Dir, "sys.config"),				      regular, Masters) of		    ok ->     filename:join(Dir, "sys");		    _ -> false		end,	    Boot = filename:join(Dir, "start.boot"),	    check_file(Boot, regular, Masters),	    set_permanent_files(RelDir, EVsn, Vsn, Masters, Static),	    NewReleases = set_status(Vsn, permanent, Releases),	    write_releases(RelDir, NewReleases, Masters),	    case os:type() of		{win32, nt} ->		    {value, PermanentRelease} = 				lists:keysearch(permanent, #release.status,						Releases),		    PermanentVsn = PermanentRelease#release.vsn,		    PermanentEVsn = PermanentRelease#release.erts_vsn,		    case catch do_make_services_permanent(PermanentVsn, 							  Vsn, 							  PermanentEVsn,							  EVsn)  of			{error,Reason} ->			    {error,{service_update_failed, Reason}};			_ ->			    ok		    end;		_ ->		    ok	    end,	    init:make_permanent(filename:join(Dir, "start"), Sys),	    {ok, NewReleases, brutal_purge(Unpurged)};	{value, #release{status = permanent}} ->	    {ok, Releases, Unpurged};	{value, #release{status = Status}} ->	    {error, {bad_status, Status}};	false ->	    {error, {no_such_release, Vsn}}    end.do_back_service(OldVersion, CurrentVersion,OldEVsn,CurrentEVsn) ->    NN = hd(string:tokens(atom_to_list(node()),"@")),    OldName = NN ++ "_" ++ OldVersion,    CurrentName = NN ++ "_" ++ CurrentVersion,    UpdData = case erlsrv:get_service(CurrentEVsn,CurrentName) of		  {error, Error} ->		      throw({error,Error});		  Data ->		      erlsrv:new_service(OldName, Data, [])	      end,    case erlsrv:store_service(OldEVsn,UpdData) of	ok ->	    erlsrv:disable_service(CurrentEVsn,CurrentName),	    erlsrv:enable_service(OldEVsn,OldName);	Error2 ->	    throw(Error2)    end,    OldErlSrv = filename:nativename(erlsrv:erlsrv(OldEVsn)),    CurrentErlSrv = filename:nativename(erlsrv:erlsrv(CurrentEVsn)),    case heart:set_cmd(CurrentErlSrv ++ " remove " ++ CurrentName ++ 		       " & " ++ OldErlSrv ++ " start " ++ OldName) of	ok ->	    ok;	Error3 ->	    throw({error, {'heart:set_cmd() error', Error3}})    end.do_reboot_old_release(#state{releases = Releases,			     rel_dir = RelDir, masters = Masters,			     static_emulator = Static},		      Vsn) ->    case lists:keysearch(Vsn, #release.vsn, Releases) of	{value, #release{erts_vsn = EVsn, status = old}} ->	    CurrentRunning = case os:type() of				 {win32,nt} ->				     %% Get the current release on NT				     case lists:keysearch(permanent, 							  #release.status,							  Releases) of					 false ->					     lists:keysearch(current,							     #release.status,							     Releases);					 {value,CR} ->					     CR				     end;				 _ ->				     false			     end,	    set_permanent_files(RelDir, EVsn, Vsn, Masters, Static),	    NewReleases = set_status(Vsn, permanent, Releases),	    write_releases(RelDir, NewReleases, Masters),	    case os:type() of		{win32,nt} ->		    %% Edit up the services and set a reasonable heart 		    %% command		    do_back_service(Vsn,CurrentRunning#release.vsn,EVsn,				   CurrentRunning#release.erts_vsn);		_ ->		    ok	    end,	    ok;	{value, #release{status = Status}} ->	    {error, {bad_status, Status}};	false ->	    {error, {no_such_release, Vsn}}    end.%%-----------------------------------------------------------------%% Depending of if the release_handler is running in normal, client or%% client with static emulator the new system version is made permanent%% in different ways.%%-----------------------------------------------------------------set_permanent_files(RelDir, EVsn, Vsn, false, _) ->    write_start(filename:join([RelDir, "start_erl.data"]),		EVsn ++ " " ++ Vsn,		false);set_permanent_files(RelDir, EVsn, Vsn, Masters, false) ->    write_start(filename:join([RelDir, "start_erl.data"]),		EVsn ++ " " ++ Vsn,		Masters);set_permanent_files(RelDir, _EVsn, Vsn, Masters, _Static) ->    VsnDir = filename:join([RelDir, Vsn]),    set_static_files(VsnDir, RelDir, Masters).do_remove_service(Vsn) ->    %%% Very unconditionally remove the service.    ServiceName = hd(string:tokens(atom_to_list(node()),"@")) 	++ "_" ++ Vsn,    erlsrv:remove_service(ServiceName).do_remove_release(Root, RelDir, Vsn, Releases) ->    % Decide which libs should be removed    case lists:keysearch(Vsn, #release.vsn, Releases) of	{value, #release{status = permanent}} ->	    {error, {permanent, Vsn}};	{value, #release{libs = RemoveLibs, vsn = Vsn, erts_vsn = EVsn}} ->	    case os:type() of		{win32, nt} ->		    do_remove_service(Vsn);		_ ->		    ok	    end,	    NewReleases = lists:keydelete(Vsn, #release.vsn, Releases),	    RemoveThese =		lists:foldl(fun(#release{libs = Libs}, Remove) ->				    diff_dir(Remove, Libs)			    end, RemoveLibs, NewReleases),

⌨️ 快捷键说明

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