From be04ed7beceeb4bcf5db7807e86df87e28c9f4b9 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 13 Oct 2011 11:53:51 +0200 Subject: Distinguish restart_new_emulator from restart_emulator in upgrade instructions Earlier, there was only one valid instruction to restart the emulator in an appup/relup script, 'restart_new_emulator'. A new instuction, 'restart_emulator', is now added, and the meaning is as follows: 'restart_new_emulator' is mainly for the core applications (erts, kernel, stdlib and sasl), and it indicates that there is new core functionality in the release and the emulator needs to be restarted before executing the upgrade scripts. If this instruction exists, a temporary release will be created which consists of the new version erts, kernel, stdlib and sasl, and the old versions of all other applications. After restarting the emulator with this temporary release, the rest of the upgrade instructions are executed, including loading of new versions. 'restart_emulator' can be used by any application if a restart of the emulator is needed after the upgrade instructions have been executed. In this case, the emulator will be restarted with the new release (i.e. not a tempoarary one) after all other upgrade instructions for all applications have been excecuted. --- lib/sasl/src/release_handler.erl | 18 ++--- lib/sasl/src/release_handler_1.erl | 10 +-- lib/sasl/src/systools_rc.erl | 45 +++++++---- lib/sasl/src/systools_relup.erl | 13 +-- lib/sasl/test/systools_SUITE.erl | 12 +-- .../d_regexp_appup/lib/fe-3.1/ebin/fe.appup | 2 +- lib/sasl/test/systools_rc_SUITE.erl | 92 +++++++++++++++++++++- 7 files changed, 146 insertions(+), 46 deletions(-) (limited to 'lib') diff --git a/lib/sasl/src/release_handler.erl b/lib/sasl/src/release_handler.erl index 931347bde2..abe6d6bee6 100644 --- a/lib/sasl/src/release_handler.erl +++ b/lib/sasl/src/release_handler.erl @@ -338,7 +338,7 @@ check_script(Script, LibDirs) -> %%----------------------------------------------------------------- %% eval_script(Script, Apps, LibDirs, NewLibs, Opts) -> %% {ok, UnPurged} | -%% restart_new_emulator | +%% restart_emulator | %% {error, Error} %% {'EXIT', Reason} %% If sync_nodes is present, the calling process must have called @@ -375,7 +375,7 @@ create_RELEASES(Root, RelDir, RelFile, LibDirs) -> %%----------------------------------------------------------------- %% Func: upgrade_app(App, Dir) -> {ok, Unpurged} -%% | restart_new_emulator +%% | restart_emulator %% | {error, Error} %% Types: %% App = atom() @@ -395,7 +395,7 @@ upgrade_app(App, NewDir) -> %%----------------------------------------------------------------- %% Func: downgrade_app(App, Dir) %% downgrade_app(App, Vsn, Dir) -> {ok, Unpurged} -%% | restart_new_emulator +%% | restart_emulator %% | {error, Error} %% Types: %% App = atom() @@ -618,11 +618,11 @@ handle_call({install_release, Vsn, ErrorAction, Opts}, From, S) -> {reply, {ok, CurrentVsn, Descr}, NewS}; {error, Reason} -> {reply, {error, Reason}, NS}; - {restart_new_emulator, CurrentVsn, Descr} -> + {restart_emulator, CurrentVsn, Descr} -> gen_server:reply(From, {ok, CurrentVsn, Descr}), init:reboot(), {noreply, NS}; - {restart_new_emulator_then_continue, CurrentVsn, Descr} -> + {restart_new_emulator, CurrentVsn, Descr} -> gen_server:reply(From, {continue_after_restart, CurrentVsn, Descr}), init:reboot(), {noreply, NS}; @@ -991,7 +991,7 @@ do_install_release(#state{start_prg = StartPrg, prepare_restart_new_emulator(StartPrg, RootDir, RelDir, TmpVsn, TmpRelease, NReleases, Masters), - {restart_new_emulator_then_continue, CurrentVsn, Descr}; + {restart_new_emulator, CurrentVsn, Descr}; {ok, {CurrentVsn, Descr, Script}} -> %% In case there has been an emulator upgrade, %% remove the temporary release @@ -1012,14 +1012,14 @@ do_install_release(#state{start_prg = StartPrg, mon_nodes(false), NReleases1 = set_status(Vsn, current, NReleases), {ok, NReleases1, Unpurged, CurrentVsn, Descr}; - restart_new_emulator when Static == true -> + restart_emulator when Static == true -> throw(static_emulator); - restart_new_emulator -> + restart_emulator -> mon_nodes(false), prepare_restart_new_emulator(StartPrg, RootDir, RelDir, Vsn, Release, NReleases, Masters), - {restart_new_emulator, CurrentVsn, Descr}; + {restart_emulator, CurrentVsn, Descr}; Else -> application_controller:config_change(EnvBefore), mon_nodes(false), diff --git a/lib/sasl/src/release_handler_1.erl b/lib/sasl/src/release_handler_1.erl index 4a776fd18b..3a64e10185 100644 --- a/lib/sasl/src/release_handler_1.erl +++ b/lib/sasl/src/release_handler_1.erl @@ -99,8 +99,8 @@ eval_script(Script, Apps, LibDirs, NewLibs, Opts) -> After) of EvalState4 when is_record(EvalState4, eval_state) -> {ok, EvalState4#eval_state.unpurged}; - restart_new_emulator -> - restart_new_emulator; + restart_emulator -> + restart_emulator; Error -> {'EXIT', Error} end; @@ -251,7 +251,7 @@ do_check_old_code(Mod,Procs) -> %% must also exectue the same line. Waits for all these nodes to get %% to this line. %% point_of_no_return -%% restart_new_emulator +%% restart_emulator %% {stop_application, Appl} - Impl with apply %% {unload_application, Appl} - Impl with {remove..} %% {load_application, Appl} - Impl with {load..} @@ -410,8 +410,8 @@ eval({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). +eval(restart_emulator, _EvalState) -> + throw(restart_emulator). get_opt(Tag, EvalState, Default) -> case lists:keysearch(Tag, 1, EvalState#eval_state.opts) of diff --git a/lib/sasl/src/systools_rc.erl b/lib/sasl/src/systools_rc.erl index 6f01901fbc..c16f6aa845 100644 --- a/lib/sasl/src/systools_rc.erl +++ b/lib/sasl/src/systools_rc.erl @@ -54,6 +54,7 @@ %% {sync_nodes, Id, Nodes} %% {apply, {M, F, A}} %% restart_new_emulator +%% restart_emulator %%----------------------------------------------------------------- %% High-level instructions that contain dependencies @@ -145,7 +146,7 @@ translate_merged_script(Mode, Script, Appls, PreAppls) -> Appls), Before3 = merge_load_object_code(Before2), - {Before4,After4} = sort_restart_new_emulator(Mode,Before3,After2), + {Before4,After4} = sort_emulator_restart(Mode,Before3,After2), NewScript = Before4 ++ [point_of_no_return | After4], check_syntax(NewScript), @@ -702,23 +703,37 @@ mlo([{load_object_code, {Lib, LibVsn, Mods}} | T]) -> mlo([]) -> []. %%----------------------------------------------------------------- -%% RESTART DIFF EMULATOR +%% RESTART EMULATOR %% ----------------------------------------------------------------- %% ----------------------------------------------------------------- -%% Check if a diff_vsn_restart_new_emulator instruction exists (i.e. if the -%% emulator version is changed). If so, this must be done first for -%% upgrade and last for downgrade. +%% Check if there are any 'restart_new_emulator' instructions (i.e. if +%% the emulator or core application version is changed). If so, this +%% must be done first for upgrade and last for downgrade. +%% Check if there are any 'restart_emulator' instructions, if so +%% remove all and place one the end. %% ----------------------------------------------------------------- -sort_restart_new_emulator(Mode,Before,After) -> - case lists:delete(diff_vsn_restart_new_emulator,After) of - After -> - {Before,After}; - NewAfter when Mode==up -> - {[restart_new_emulator|Before],NewAfter}; - NewAfter when Mode==dn -> - {Before,NewAfter++[restart_new_emulator]} - end. +sort_emulator_restart(Mode,Before,After) -> + {Before1,After1} = + case filter_out(restart_new_emulator, After) of + After -> + {Before,After}; + A1 when Mode==up -> + {[restart_new_emulator|Before],A1}; + A1 when Mode==dn -> + {Before,A1++[restart_emulator]} + end, + After2 = + case filter_out(restart_emulator, After1) of + After1 -> + After1; + A2 -> + A2++[restart_emulator] + end, + {Before1,After2}. + +filter_out(What,List) -> + lists:filter(fun(X) when X=:=What -> false; (_) -> true end, List). %%----------------------------------------------------------------- %% SYNTAX CHECK @@ -839,7 +854,7 @@ check_op({apply, {M, F, A}}) -> check_func(F), check_args(A); check_op(restart_new_emulator) -> ok; -check_op(diff_vsn_restart_new_emulator) -> ok; +check_op(restart_emulator) -> ok; check_op(X) -> throw({error, {bad_instruction, X}}). check_mod(Mod) when is_atom(Mod) -> ok; diff --git a/lib/sasl/src/systools_relup.erl b/lib/sasl/src/systools_relup.erl index 5cfbc3aadf..b750e86e29 100644 --- a/lib/sasl/src/systools_relup.erl +++ b/lib/sasl/src/systools_relup.erl @@ -263,8 +263,7 @@ foreach_baserel_up(TopRel, TopApps, [BaseRelDc|BaseRelDcs], Path, Opts, {RUs3, Ws3} = create_remove_app_scripts(BaseRel, TopRel, RUs2, Ws2), - {RUs4, Ws4} = - check_for_emulator_restart(TopRel, BaseRel, RUs3, Ws3, Opts), + {RUs4, Ws4} = check_for_emulator_restart(TopRel, BaseRel, RUs3, Ws3, Opts), BaseApps = case systools_make:get_release(BaseRelFile, Path) of @@ -321,8 +320,7 @@ foreach_baserel_dn(TopRel, TopApps, [BaseRelDc|BaseRelDcs], Path, Opts, {RUs4, Ws4} = create_remove_app_scripts(TopRel, BaseRel, RUs3, Ws3), - {RUs5, Ws5} = check_for_emulator_restart(TopRel, BaseRel, - RUs4, Ws4, Opts), + {RUs5, Ws5} = check_for_emulator_restart(TopRel, BaseRel, RUs4, Ws4, Opts), case systools_rc:translate_scripts(dn, RUs5, BaseApps, TopApps) of {ok, RUs} -> @@ -350,7 +348,7 @@ check_for_emulator_restart(#release{erts_vsn = Vsn1, name = N1}, %% We will also allow an extra restart of emulator (specified by %% the restart_emulator option) at the end of the upgrade, for %% application specific purposes. - NewRUs = [[diff_vsn_restart_new_emulator]|RUs], + NewRUs = [[restart_new_emulator]|RUs], NewWs = [{erts_vsn_changed, {N1, N2}} | Ws], check_for_restart_emulator_opt(NewRUs, NewWs, Opts); check_for_emulator_restart(_, _, RUs, Ws, Opts) -> @@ -358,10 +356,13 @@ check_for_emulator_restart(_, _, RUs, Ws, Opts) -> check_for_restart_emulator_opt(RUs, Ws, Opts) -> case get_opt(restart_emulator, Opts) of - true -> {RUs++[[restart_new_emulator]], Ws}; + true -> {RUs++[[restart_emulator]], Ws}; _ -> {RUs, Ws} end. + + + %% collect_appup_scripts(Mode, TopApps, BaseRel, Ws, RUs) -> {NRUs, NWs} %% Mode = up | dn %% TopApps = [#application] diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl index 5b3abad219..4cf6aefea9 100644 --- a/lib/sasl/test/systools_SUITE.erl +++ b/lib/sasl/test/systools_SUITE.erl @@ -1157,7 +1157,7 @@ normal_relup(Config) when is_list(Config) -> ?line ok = file:set_cwd(LatestDir), %% OTP-2561: Check that the option 'restart_emulator' generates a - %% "restart_new_emulator" instruction. + %% "restart_emulator" instruction. ?line {ok, _ , _, []} = systools:make_relup(LatestName, [LatestName1], [LatestName1], [{path, P},restart_emulator,silent]), @@ -1256,19 +1256,19 @@ check_relup_up_only(UpVsnL) -> check_restart_emulator() -> {ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup), - restart_new_emulator = lists:last(Up), - restart_new_emulator = lists:last(Dn), + restart_emulator = lists:last(Up), + restart_emulator = lists:last(Dn), ok. check_restart_emulator_up_only() -> {ok, [{_V1, [{_, _, Up}], []}]} = file:consult(relup), - restart_new_emulator = lists:last(Up), + restart_emulator = lists:last(Up), ok. check_restart_emulator_diff_erts() -> {ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup), [restart_new_emulator|_] = Up, - restart_new_emulator = lists:last(Dn), + restart_emulator = lists:last(Dn), ok. %% make_relup @@ -1444,7 +1444,7 @@ regexp_relup(Config) -> %% Upgrade fe 2.1.1 -> 3.1 %% Shall match the second entry in fe-3.1 appup. Have added a - %% restart_new_emulator instruction there to distinguish it from + %% restart_emulator instruction there to distinguish it from %% the first entry... ?line {ok, _, _, []} = systools:make_relup(LatestName, [LatestName1], [], [{path, P}, silent]), diff --git a/lib/sasl/test/systools_SUITE_data/d_regexp_appup/lib/fe-3.1/ebin/fe.appup b/lib/sasl/test/systools_SUITE_data/d_regexp_appup/lib/fe-3.1/ebin/fe.appup index 53d54735e5..6b99c47e53 100644 --- a/lib/sasl/test/systools_SUITE_data/d_regexp_appup/lib/fe-3.1/ebin/fe.appup +++ b/lib/sasl/test/systools_SUITE_data/d_regexp_appup/lib/fe-3.1/ebin/fe.appup @@ -15,7 +15,7 @@ [{update, fe1, soft, soft_purge, soft_purge, []}, {update, fe2, soft, soft_purge, soft_purge, [fe1]}, {update, fe3, {advanced, extra}, soft_purge, soft_purge,[fe1, fe2]}, - restart_new_emulator]} + restart_emulator]} ], %% Downgrade to: diff --git a/lib/sasl/test/systools_rc_SUITE.erl b/lib/sasl/test/systools_rc_SUITE.erl index bb93f38fa7..2ab9e269f9 100644 --- a/lib/sasl/test/systools_rc_SUITE.erl +++ b/lib/sasl/test/systools_rc_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010. All Rights Reserved. +%% Copyright Ericsson AB 2010-2011. All Rights Reserved. %% %% 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 @@ -21,14 +21,15 @@ -include_lib("test_server/include/test_server.hrl"). -include_lib("sasl/src/systools.hrl"). -export([all/0,groups/0,init_per_group/2,end_per_group/2, - syntax_check/1, translate/1, translate_app/1]). + syntax_check/1, translate/1, translate_app/1, + translate_emulator_restarts/1]). %%----------------------------------------------------------------- %% erl -compile systools_rc_SUITE @i ../src/ @i ../../test_server/include/ %% c(systools_rc_SUITE, [{i, "../src"}, {i, "../../test_server/include"}]). %%----------------------------------------------------------------- all() -> - [syntax_check, translate, translate_app]. + [syntax_check, translate, translate_app, translate_emulator_restarts]. groups() -> []. @@ -87,7 +88,8 @@ syntax_check(Config) when is_list(Config) -> {sync_nodes, id1, {m, f, [a]}}, {sync_nodes, id2, [cp1, cp2]}, {apply, {m,f,[a]}}, - restart_new_emulator + restart_new_emulator, + restart_emulator ], ?line {ok, _} = systools_rc:translate_scripts([S2], Apps, []), S3 = [{apply, {m, f, a}}], @@ -486,3 +488,85 @@ io:format("X2=~p~n", [X2]), {purge,[pelle,kalle]}, {apply,{application,unload,[pelle]}}] = X3, ?line ok. + + +translate_emulator_restarts(_Config) -> + Apps = + [#application{name = test, + description = "TEST", + vsn = "1.0", + modules = [{foo,1},{bar,1},{baz,1}], + regs = [], + mod = {sasl, []}}, + #application{name = test, + description = "TEST2", + vsn = "1.0", + modules = [{x,1},{y,1},{z,1}], + regs = [], + mod = {sasl, []}}], + %% restart_new_emulator + Up1 = [{update, foo, soft, soft_purge, soft_purge, []},restart_new_emulator], + ?line {ok, X1} = systools_rc:translate_scripts([Up1], Apps, []), + ?line [restart_new_emulator, + {load_object_code, {test,"1.0",[foo]}}, + point_of_no_return, + {suspend,[foo]}, + {load,{foo,soft_purge,soft_purge}}, + {resume,[foo]}] = X1, + + %% restart_emulator + Up2 = [{update, foo, soft, soft_purge, soft_purge, []},restart_emulator], + ?line {ok, X2} = systools_rc:translate_scripts([Up2], Apps, []), + ?line [{load_object_code, {test,"1.0",[foo]}}, + point_of_no_return, + {suspend,[foo]}, + {load,{foo,soft_purge,soft_purge}}, + {resume,[foo]}, + restart_emulator] = X2, + + %% restart_emulator + restart_new_emulator + Up3 = [{update, foo, soft, soft_purge, soft_purge, []}, + restart_emulator, + restart_new_emulator], + ?line {ok, X3} = systools_rc:translate_scripts([Up3], Apps, []), + ?line [restart_new_emulator, + {load_object_code, {test,"1.0",[foo]}}, + point_of_no_return, + {suspend,[foo]}, + {load,{foo,soft_purge,soft_purge}}, + {resume,[foo]}, + restart_emulator] = X3, + + %% restart_emulator + restart_new_emulator + Up4a = [{update, foo, soft, soft_purge, soft_purge, []}, + restart_emulator, + restart_new_emulator], + Up4b = [restart_new_emulator, + {update, x, soft, soft_purge, soft_purge, []}, + restart_emulator, + restart_emulator], + ?line {ok, X4} = systools_rc:translate_scripts([Up4a,Up4b], Apps, []), + ?line [restart_new_emulator, + {load_object_code, {test,"1.0",[foo,x]}}, + point_of_no_return, + {suspend,[foo]}, + {load,{foo,soft_purge,soft_purge}}, + {resume,[foo]}, + {suspend,[x]}, + {load,{x,soft_purge,soft_purge}}, + {resume,[x]}, + restart_emulator] = X4, + + %% only restart_new_emulator + Up5 = [restart_new_emulator], + ?line {ok, X5} = systools_rc:translate_scripts([Up5], Apps, []), + ?line [restart_new_emulator, + point_of_no_return] = X5, + + %% only restart_emulator + Up6 = [restart_emulator], + ?line {ok, X6} = systools_rc:translate_scripts([Up6], Apps, []), + ?line [point_of_no_return, + restart_emulator] = X6, + + ok. -- cgit v1.2.3