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

📄 release_handler.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 5 页
字号:
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %%     $Id$%%-module(release_handler).-behaviour(gen_server).-include_lib("kernel/include/file.hrl").%% External exports-export([start_link/0,	 create_RELEASES/1, create_RELEASES/2, create_RELEASES/4,	 unpack_release/1,	 check_install_release/1, install_release/1, install_release/2,	 remove_release/1, 	 which_releases/0, make_permanent/1, reboot_old_release/1,	 set_unpacked/2, set_removed/1, install_file/2]).-export([upgrade_app/2, downgrade_app/2, downgrade_app/3,	 upgrade_script/2, downgrade_script/3,	 eval_appup_script/4]).%% Internal exports-export([init/1, handle_call/3, handle_info/2, terminate/2,	 handle_cast/2, code_change/3]).%% Internal exports, a client release_handler may call this functions.-export([do_write_release/3, do_copy_file/2, do_copy_files/2,	 do_copy_files/1, do_rename_files/1, do_remove_files/1,	 do_write_file/2, do_ensure_RELEASES/1]).-record(state, {unpurged = [],		root,		rel_dir,		releases,		timer,		start_prg,		masters = false,		client_dir = false,	        static_emulator = false,		pre_sync_nodes = []}).%%-----------------------------------------------------------------%% status      action                next_status%% =============================================%%   -         unpack                unpacked%% unpacked    install               current%%             remove                -%% current     make_permanent        permanent%%             install other         old%%             remove                -%% permanent   make other permanent  old%%             install               permanent%% old         reboot                permanen%%             install               current%%             remove                -%%-----------------------------------------------------------------%% libs = [{Lib, Vsn, Dir}]-record(release, {name, vsn, erts_vsn, libs = [], status}).-define(timeout, 10000).%%-----------------------------------------------------------------%% Assumes the following file structure:%% root --- lib --- Appl-Vsn1 --- <src>%%       |       |             |- ebin%%       |       |             |_ priv%%       |       |_ Appl-Vsn2%%       |%%       |- bin --- start (default; {sasl, start_prg} overrides%%       |       |- run_erl%%       |       |- start_erl (reads start_erl.data)%%       |       |_ <to_erl>%%       |%%       |- erts-EVsn1 --- bin --- <jam44>%%       |                      |- <epmd>%%       |                      |_ erl%%       |- erts-EVsn2%%       |%%       |- clients --- ClientName1 --- bin -- start%%         <clients use same lib and erts as master>%%       |           |               |_ releases --- start_erl.data%%       |           |                           |_ Vsn1 -- start.boot%%       |           |_ ClientName2%%       |%%       |- clients --- Type1 --- lib%%         <clients use own lib and erts>%%       |           |         |- erts-EVsn%%       |           |         |- bin -- start%%       |           |         |_ ClientName1 -- releases -- start_erl.data%%       |           |                                    |_ start.boot (static)%%       |           |                                    |_ Vsn1%%       |           |_ Type2 %%       |%%       |- releases --- RELEASES%%       |            |_ <Vsn1.tar.Z>%%       |            |%%       |            |- start_erl.data (generated by rh)%%       |            |%%       |            |_ Vsn1 --- start.boot%%       |            |        |- <sys.config>%%       |            |        |_ relup%%       |            |_ Vsn2        %%       |%%       |- log --- erlang.log.N (1 .. 5)%%%% where <Name> means 'for example Name', and root is%% init:get_argument(root)%%%% It is configurable where the start file is located, and what it%% is called.%%   The paramater is {sasl, start_prg} = File%% It is also configurable where the releases directory is located.%% Default is $ROOT/releases.  $RELDIR overrids, and%% {sasl, releases_dir} overrides both.%%-----------------------------------------------------------------start_link() ->    gen_server:start_link({local, release_handler}, ?MODULE, [], []).%%-----------------------------------------------------------------%% Args: ReleaseName is the name of the package file%%       (without .tar.Z (.tar on non unix systems))%% Purpose: Copies all files in the release package to their%%          directories.  Checks that all required libs and erts%%          files are present.%% Returns: {ok, Vsn} | {error, Reason}%%          Reason = {existing_release, Vsn} |%%                   {no_such_file, File} |%%                   {bad_rel_file, RelFile} |%%                   {file_missing, FileName} |  (in the tar package)%%                   exit_reason()%%-----------------------------------------------------------------unpack_release(ReleaseName) ->    gen_server:call(release_handler, {unpack_release, ReleaseName}, infinity).    %%-----------------------------------------------------------------%% Purpose: Checks the relup script for the specified version.%%          The release must be unpacked.%% Returns: {ok, FromVsn, Descr} | {error, Reason}%%          Reason = {already_installed, Vsn} |%%                   {bad_relup_file, RelFile} |%%                   {no_such_release, Vsn} |%%                   {no_such_from_vsn, Vsn} |%%                   exit_reason()%%-----------------------------------------------------------------check_install_release(Vsn) ->    gen_server:call(release_handler, {check_install_release, Vsn}, infinity).%%-----------------------------------------------------------------%% Purpose: Executes the relup script for the specified version.%%          The release must be unpacked.%% Returns: {ok, FromVsn, Descr} | {error, Reason}%%          Reason = {already_installed, Vsn} |%%                   {bad_relup_file, RelFile} |%%                   {no_such_release, Vsn} |%%                   {no_such_from_vsn, Vsn} |%%                   {illegal_option, Opt}} |%%                   exit_reason()%%-----------------------------------------------------------------install_release(Vsn) ->    gen_server:call(release_handler, 		    {install_release, Vsn, restart, []}, 		    infinity).install_release(Vsn, Opt) ->    case check_install_options(Opt, restart, []) of	{ok, ErrorAction, InstallOpt} ->	    gen_server:call(release_handler, 			    {install_release, Vsn, ErrorAction, InstallOpt},			    infinity);	Error ->	    Error    end.check_install_options([Opt | Opts], ErrAct, InstOpts) ->    case install_option(Opt) of	{error_action, EAct} ->	    check_install_options(Opts, EAct, InstOpts);	true ->	    check_install_options(Opts, ErrAct, [Opt | InstOpts]);	false ->	    {error, {illegal_option, Opt}}    end;check_install_options([], ErrAct, InstOpts) ->    {ok, ErrAct, InstOpts}.install_option(Opt = {error_action, reboot}) -> Opt;install_option(Opt = {error_action, restart}) -> Opt;install_option({code_change_timeout, TimeOut}) ->    check_timeout(TimeOut);install_option({suspend_timeout, TimeOut}) ->    check_timeout(TimeOut);install_option({update_paths, Bool}) when Bool==true; Bool==false ->    true;install_option(_Opt) -> false.check_timeout(infinity) -> true;check_timeout(Int) when is_integer(Int), Int > 0 -> true;check_timeout(_Else) -> false.%%-----------------------------------------------------------------%% Purpose: Makes the specified release version be the one that is%%          used when the system starts (or restarts).%%          The release must be installed (not unpacked).%% Returns: ok | {error, Reason}%%          Reason = {bad_status, Status} |%%                   {no_such_release, Vsn} |%%                   exit_reason()%%-----------------------------------------------------------------make_permanent(Vsn) ->    gen_server:call(release_handler, {make_permanent, Vsn}, infinity).%%-----------------------------------------------------------------%% Purpose: Reboots the system from an old release.%%-----------------------------------------------------------------reboot_old_release(Vsn) ->    gen_server:call(release_handler, {reboot_old_release, Vsn}, infinity).%%-----------------------------------------------------------------%% Purpose: Deletes all files and directories used by the release%%          version, that are not used by any other release.%%          The release must not be permanent.%% Returns: ok | {error, Reason}%%          Reason = {permanent, Vsn} |%%-----------------------------------------------------------------remove_release(Vsn) ->    gen_server:call(release_handler, {remove_release, Vsn}, infinity).%%-----------------------------------------------------------------%% Args: RelFile = string()%%       Libs = [{Lib, LibVsn, Dir}]%%       Lib = LibVsn = Dir = string()%% Purpose: Tells the release handler that a release has been%%          unpacked, without using the function unpack_release/1.%%          RelFile is an absolute file name including the extension%%          .rel.%%          The release dir will be created.  The necessary files can%%          be installed by calling install_file/2.%%          The release_handler remebers where all libs are located.%%          If remove_release is called later,%%          those libs are removed as well (if no other releases uses%%          them).%% Returns: ok | {error, Reason}%%-----------------------------------------------------------------set_unpacked(RelFile, LibDirs) ->    gen_server:call(release_handler, {set_unpacked, RelFile, LibDirs}).%%-----------------------------------------------------------------%% Args: Vsn = string()%% Purpose: Makes it possible to handle removal of releases%%          outside the release_handler.%%          This function won't delete any files at all.%% Returns: ok | {error, Reason}%%-----------------------------------------------------------------set_removed(Vsn) ->    gen_server:call(release_handler, {set_removed, Vsn}).%%-----------------------------------------------------------------%% Purpose: Makes it possible to install the start.boot,%%          sys.config and relup files if they are not part of a %%          standard release package.  May be used to%%          install files that are generated, before install_release%%          is called.%% Returns: ok | {error, {no_such_release, Vsn}}%%-----------------------------------------------------------------install_file(Vsn, File) when is_list(File) ->    gen_server:call(release_handler, {install_file, File, Vsn}).%%-----------------------------------------------------------------%% Returns: [{Name, Vsn, [LibName], Status}]%%          Status = unpacked | current | permanent | old%%-----------------------------------------------------------------which_releases() ->    gen_server:call(release_handler, which_releases).%%-----------------------------------------------------------------%% check_script(Script, LibDirs) -> ok | {error, Reason}%%-----------------------------------------------------------------check_script(Script, LibDirs) ->    release_handler_1:check_script(Script, LibDirs).%%-----------------------------------------------------------------%% eval_script(Script, Apps, LibDirs, Opts) -> {ok, UnPurged} |%%                                             restart_new_emulator |%%                                             {error, Error}%%                                             {'EXIT', Reason}%% If sync_nodes is present, the calling process must have called%% net_kernel:monitor_nodes(true) before calling this function.%% No!  No other process than the release_handler can ever call this%% function, if sync_nodes is used.%%-----------------------------------------------------------------eval_script(Script, Apps, LibDirs, Opts) ->    catch release_handler_1:eval_script(Script, Apps, LibDirs, Opts).%%-----------------------------------------------------------------%% Func: create_RELEASES(Root, RelFile, LibDirs) -> ok | {error, Reason}%% Types: Root = RelFile = string()%% Purpose: Creates an initial RELEASES file.%%-----------------------------------------------------------------create_RELEASES([Root, RelFile | LibDirs]) ->    create_RELEASES(Root, filename:join(Root, "releases"), RelFile, LibDirs).create_RELEASES(Root, RelFile) ->    create_RELEASES(Root, filename:join(Root, "releases"), RelFile, []).create_RELEASES(Root, RelDir, RelFile, LibDirs) ->    case catch check_rel(Root, RelFile, LibDirs, false) of	{error, Reason } ->	    {error, Reason};	Rel ->	    Rel2 = Rel#release{status = permanent},	    catch write_releases(RelDir, [Rel2], false)    end.%%-----------------------------------------------------------------%% Func: upgrade_app(App, Dir) -> {ok, Unpurged}%%                              | restart_new_emulator%%                              | {error, Error}%% Types:%%   App = atom()%%   Dir = string() assumed to be application directory, the code%%         located under Dir/ebin%% Purpose: Upgrade to the version in Dir according to an appup file%%-----------------------------------------------------------------upgrade_app(App, NewDir) ->    try upgrade_script(App, NewDir) of	{ok, NewVsn, Script} ->	    eval_appup_script(App, NewVsn, NewDir, Script)    catch	throw:Reason ->	    {error, Reason}    end.%%-----------------------------------------------------------------%% Func: downgrade_app(App, Dir)%%       downgrade_app(App, Vsn, Dir) -> {ok, Unpurged}%%                                     | restart_new_emulator%%                                     | {error, Error}%% Types:%%   App = atom()%%   Vsn = string(), may be omitted if Dir == App-Vsn%%   Dir = string() assumed to be application directory, the code%%         located under Dir/ebin%% Purpose: Downgrade from the version in Dir according to an appup file%%          located in the ebin dir of the _current_ version%%-----------------------------------------------------------------downgrade_app(App, OldDir) ->    case string:tokens(filename:basename(OldDir), "-") of	[_AppS, OldVsn] ->	    downgrade_app(App, OldVsn, OldDir);	_ ->	    {error, {unknown_version, App}}    end.downgrade_app(App, OldVsn, OldDir) ->    try downgrade_script(App, OldVsn, OldDir) of	{ok, Script} ->	    eval_appup_script(App, OldVsn, OldDir, Script)    catch	throw:Reason ->	    {error, Reason}    end.upgrade_script(App, NewDir) ->    OldVsn = ensure_running(App),    OldDir = code:lib_dir(App),    {NewVsn, Script} = find_script(App, NewDir, OldVsn, up),    OldAppl = read_app(App, OldVsn, OldDir),    NewAppl = read_app(App, NewVsn, NewDir),    case systools_rc:translate_scripts(up,

⌨️ 快捷键说明

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