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

📄 release_handler.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 5 页
字号:
%% Check that file exists at all masters.check_file_masters(FileName, Type, [Master|Masters]) ->    do_check_file(Master, FileName, Type),    check_file_masters(FileName, Type, Masters);check_file_masters(_FileName, _Type, []) ->    ok.%% Type == regular | directorydo_check_file(FileName, Type) ->    case file:read_file_info(FileName) of	{ok, Info} when Info#file_info.type==Type -> ok;	{error, _Reason} -> throw({error, {no_such_file, FileName}})    end.do_check_file(Master, FileName, Type) ->    case rpc:call(Master, file, file_info, [FileName]) of	{ok,{_,Type,_,_,_,_,_}} -> ok;	_ -> throw({error, {no_such_file, {Master, FileName}}})    end.%%-----------------------------------------------------------------%% If Rel doesn't exists in tar it could have been created%% by the user in another way, i.e. ignore this here.%%-----------------------------------------------------------------extract_rel_file(Rel, Tar, Root) ->    erl_tar:extract(Tar, [{files, [Rel]}, {cwd, Root}, compressed]).extract_tar(Root, Tar) ->    case erl_tar:extract(Tar, [keep_old_files, {cwd, Root}, compressed]) of	ok ->	    ok;	{error, Reason, Name} ->		% Old erl_tar.	    throw({error, {cannot_extract_file, Name, Reason}});	{error, {Name, Reason}} ->		% New erl_tar (R3A).	    throw({error, {cannot_extract_file, Name, Reason}})    end.write_releases(Dir, NewReleases, false) ->    case do_write_release(Dir, "RELEASES", NewReleases) of	ok    -> ok;	Error -> throw(Error)    end;write_releases(Dir, NewReleases, Masters) ->    all_masters(Masters),    write_releases_m(Dir, NewReleases, Masters).do_write_release(Dir, RELEASES, NewReleases) ->    case file:open(filename:join(Dir, RELEASES), write) of	{ok, Fd} ->	    ok = io:format(Fd, "~p.~n", [NewReleases]),	    file:close(Fd),	    ok;	{error, Reason} ->	    {error, Reason}    end.%%-----------------------------------------------------------------%% Write the "RELEASES" file at all master nodes.%%   1. Save "RELEASES.backup" at all nodes.%%   2. Save "RELEASES.change" at all nodes.%%   3. Update the "RELEASES.change" file at all nodes.%%   4. Move "RELEASES.change" to "RELEASES".%%   5. Remove "RELEASES.backup" at all nodes.%%%% If one of the steps above fails, all steps is recovered from%% (as long as possible), except for 5 which is allowed to fail.%%-----------------------------------------------------------------write_releases_m(Dir, NewReleases, Masters) ->    RelFile = filename:join(Dir, "RELEASES"),    Backup = filename:join(Dir, "RELEASES.backup"),    Change = filename:join(Dir, "RELEASES.change"),    ensure_RELEASES_exists(Masters, RelFile),    case at_all_masters(Masters, ?MODULE, do_copy_files,			[RelFile, [Backup, Change]]) of	ok ->	    case at_all_masters(Masters, ?MODULE, do_write_release,				[Dir, "RELEASES.change", NewReleases]) of		ok ->		    case at_all_masters(Masters, file, rename,					[Change, RelFile]) of			ok ->			    remove_files(all, [Backup, Change], Masters),			    ok;			{error, {Master, R}} ->			    takewhile(Master, Masters, file, rename,				      [Backup, RelFile]),			    remove_files(all, [Backup, Change], Masters),			    throw({error, {Master, R, move_releases}})		    end;		{error, {Master, R}} ->		    remove_files(all, [Backup, Change], Masters),		    throw({error, {Master, R, update_releases}})	    end;	{error, {Master, R}} ->	    remove_files(Master, [Backup, Change], Masters),	    throw({error, {Master, R, backup_releases}})    end.ensure_RELEASES_exists(Masters, RelFile) ->    case at_all_masters(Masters, ?MODULE, do_ensure_RELEASES, [RelFile]) of	ok ->	    ok;	{error, {Master, R}} ->	    throw({error, {Master, R, ensure_RELEASES_exists}})    end.copy_file(File, Dir, false) ->    case do_copy_file(File, Dir) of	ok    -> ok;	Error -> throw(Error)    end;copy_file(File, Dir, Masters) ->    all_masters(Masters),    copy_file_m(File, Dir, Masters).%%-----------------------------------------------------------------%% copy File to Dir at every master node.%% If an error occurs at a node, the total copy failed.%% We do not have to cleanup in case of failure as this%% copy_file is harmless.%%-----------------------------------------------------------------copy_file_m(File, Dir, [Master|Masters]) ->    case rpc:call(Master, ?MODULE, do_copy_file, [File, Dir]) of	ok                   -> copy_file_m(File, Dir, Masters);	{error, {Reason, F}} -> throw({error, {Master, Reason, F}});	Other                -> throw({error, {Master, Other, File}})    end;copy_file_m(_File, _Dir, []) ->    ok.do_copy_file(File, Dir) ->    File2 = filename:join(Dir, filename:basename(File)),    do_copy_file1(File, File2).do_copy_file1(File, File2) ->    case file:read_file(File) of	{ok, Bin} ->	    case file:write_file(File2, Bin) of		ok -> ok;		{error, Reason} ->		    {error, {Reason, File2}}	    end;	{error, Reason} ->	    {error, {Reason, File}}    end.%%-----------------------------------------------------------------%% Copy File to a list of files.%%-----------------------------------------------------------------do_copy_files(File, [ToFile|ToFiles]) ->    case do_copy_file1(File, ToFile) of	ok    -> do_copy_files(File, ToFiles);	Error -> Error    end;do_copy_files(_, []) ->    ok.%%-----------------------------------------------------------------%% Copy each Src file to Dest file in the list of files.%%-----------------------------------------------------------------do_copy_files([{Src, Dest}|Files]) ->    case do_copy_file1(Src, Dest) of	ok    -> do_copy_files(Files);	Error -> Error    end;do_copy_files([]) ->    ok.%%-----------------------------------------------------------------%% Rename each Src file to Dest file in the list of files.%%-----------------------------------------------------------------do_rename_files([{Src, Dest}|Files]) ->    case file:rename(Src, Dest) of	ok    -> do_rename_files(Files);	Error -> Error    end;do_rename_files([]) ->    ok.%%-----------------------------------------------------------------%% Remove a list of files. Ignore failure.%%-----------------------------------------------------------------do_remove_files([File|Files]) ->    file:delete(File),    do_remove_files(Files);do_remove_files([]) ->    ok.%%-----------------------------------------------------------------%% Ensure that the RELEASES file exists.%% If not create an empty RELEASES file.%%-----------------------------------------------------------------do_ensure_RELEASES(RelFile) ->    case file:read_file_info(RelFile) of	{ok, _} -> ok;	_       -> do_write_file(RelFile, "[]. ")     end.%%-----------------------------------------------------------------%% Make a directory, ignore failures (captured later).%%-----------------------------------------------------------------make_dir(Dir, false) ->    file:make_dir(Dir);make_dir(Dir, Masters) ->    lists:foreach(fun(Master) -> rpc:call(Master, file, make_dir, [Dir]) end,		  Masters).%%-----------------------------------------------------------------%% Check that all masters are alive.%%-----------------------------------------------------------------all_masters(Masters) ->    case rpc:multicall(Masters, erlang, info, [version]) of	{_, []}       -> ok;	{_, BadNodes} -> throw({error, {bad_masters, BadNodes}})    end.%%-----------------------------------------------------------------%% Evaluate {M,F,A} at all masters.%% {M,F,A} is supposed to return ok. Otherwise at_all_masters%% returns {error, {Master, Other}}.%%-----------------------------------------------------------------at_all_masters([Master|Masters], M, F, A) ->    case rpc:call(Master, M, F, A) of	ok    -> at_all_masters(Masters, M, F, A);	Error -> {error, {Master, Error}}    end;at_all_masters([], _, _, _) ->    ok.%%-----------------------------------------------------------------%% Evaluate {M,F,A} at all masters until Master is found.%% Ignore {M,F,A} return value.%%-----------------------------------------------------------------takewhile(Master, Masters, M, F, A) ->    lists:takewhile(fun(Ma) when Ma == Master ->			    false;		       (Ma) ->			    rpc:call(Ma, M, F, A),			    true		    end, Masters),    ok.consult(File, false)   -> file:consult(File);consult(File, Masters) -> consult_master(Masters, File).%%-----------------------------------------------------------------%% consult the File at any master node.%% If the file does not exist at one node it should%% not exist at any other node either.%%-----------------------------------------------------------------consult_master([Master|Ms], File) ->    case rpc:call(Master, file, consult, [File]) of	{badrpc, _} -> consult_master(Ms, File);	Res         -> Res    end;consult_master([], _File) ->    {error, no_master}.read_file(File, false) ->    file:read_file(File);read_file(File, Masters) ->    read_master(Masters, File).%% Ignore status of each delete !remove_files(Master, Files, Masters) ->    takewhile(Master, Masters, ?MODULE, do_remove_files, [Files]).%%-----------------------------------------------------------------%% read the File at any master node.%% If the file does not exist at one node it should%% not exist at any other node either.%%-----------------------------------------------------------------read_master([Master|Ms], File) ->    case rpc:call(Master, file, read_file, [File]) of	{badrpc, _} -> read_master(Ms, File);	Res         -> Res    end;read_master([], _File) ->    {error, no_master}.%%-----------------------------------------------------------------%% Write start_erl.data.%%-----------------------------------------------------------------write_start(File, Data, false) ->    case do_write_file(File, Data) of	ok    -> ok;	Error -> throw(Error)    end;write_start(File, Data, Masters) ->    all_masters(Masters),    write_start_m(File, Data, Masters).%%-----------------------------------------------------------------%% Write the "start_erl.data" file at all master nodes.%%   1. Save "start_erl.backup" at all nodes.%%   2. Write the "start_erl.change" file at all nodes.%%   3. Move "start_erl.change" to "start_erl.data".%%   4. Remove "start_erl.backup" at all nodes.%%%% If one of the steps above fails, all steps is recovered from%% (as long as possible), except for 4 which is allowed to fail.%%-----------------------------------------------------------------write_start_m(File, Data, Masters) ->    Dir = filename:dirname(File),    Backup = filename:join(Dir, "start_erl.backup"),    Change = filename:join(Dir, "start_erl.change"),    case at_all_masters(Masters, ?MODULE, do_copy_files,			[File, [Backup]]) of	ok ->	    case at_all_masters(Masters, ?MODULE, do_write_file,				[Change, Data]) of		ok ->		    case at_all_masters(Masters, file, rename,					[Change, File]) of			ok ->			    remove_files(all, [Backup, Change], Masters),			    ok;			{error, {Master, R}} ->			    takewhile(Master, Masters, file, rename,				      [Backup, File]),			    remove_files(all, [Backup, Change], Masters),			    throw({error, {Master, R, move_start_erl}})		    end;		{error, {Master, R}} ->		    remove_files(all, [Backup, Change], Masters),		    throw({error, {Master, R, write_start_erl}})	    end;	{error, {Master, R}} ->	    remove_files(Master, [Backup], Masters),	    throw({error, {Master, R, backup_start_erl}})    end.%%-----------------------------------------------------------------%% Copy the "start.boot" and "sys.config" from SrcDir to DestDir at all%% master nodes.%%   1. Save DestDir/"start.backup" and DestDir/"sys.backup" at all nodes.%%   2. Copy files at all nodes.%%   3. Remove backup files at all nodes.%%%% If one of the steps above fails, all steps is recovered from%% (as long as possible), except for 3 which is allowed to fail.%%-----------------------------------------------------------------set_static_files(SrcDir, DestDir, Masters) ->    all_masters(Masters),    Boot = "start.boot",    Config = "sys.config",    SrcBoot = filename:join(SrcDir, Boot),    DestBoot = filename:join(DestDir, Boot),    BackupBoot = filename:join(DestDir, "start.backup"),    SrcConf = filename:join(SrcDir, Config),    DestConf = filename:join(DestDir, Config),    BackupConf = filename:join(DestDir, "sys.backup"),    case at_all_masters(Masters, ?MODULE, do_copy_files,			[[{DestBoot, BackupBoot},			  {DestConf, BackupConf}]]) of	ok ->	    case at_all_masters(Masters, ?MODULE, do_copy_files,				[[{SrcBoot, DestBoot},				  {SrcConf, DestConf}]]) of		ok ->		    remove_files(all, [BackupBoot, BackupConf], Masters),		    ok;		{error, {Master, R}} ->		    takewhile(Master, Masters, ?MODULE, do_rename_files,			      [{BackupBoot, DestBoot},			       {BackupConf, DestConf}]),		    remove_files(all, [BackupBoot, BackupConf], Masters),		    throw({error, {Master, R, copy_start_config}})	    end;	{error, {Master, R}} ->	    remove_files(Master, [BackupBoot, BackupConf], Masters),	    throw({error, {Master, R, backup_start_config}})    end.

⌨️ 快捷键说明

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