From e10079c3793da3d0f6d76adaf38422cba63bc427 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Mon, 28 Nov 2011 10:39:15 +0100 Subject: Fix minor faults in documentation of release handling Fix typos or minor faults. Move out code listing of target_system.erl, and use codeinclude statement to include this file from sasl/examples directory. --- system/doc/design_principles/release_handling.xml | 44 +-- system/doc/design_principles/release_structure.xml | 20 +- system/doc/system_principles/create_target.xmlsrc | 295 +++------------------ 3 files changed, 73 insertions(+), 286 deletions(-) (limited to 'system/doc') diff --git a/system/doc/design_principles/release_handling.xml b/system/doc/design_principles/release_handling.xml index 8ed36f3c56..4378b6599c 100644 --- a/system/doc/design_principles/release_handling.xml +++ b/system/doc/design_principles/release_handling.xml @@ -178,13 +178,13 @@ Release Handling Instructions

OTP supports a set of release handling instructions - that is used when creating .appup files. The release + that are used when creating .appup files. The release handler understands a subset of these, the low-level instructions. To make it easier for the user, there are also a number of high-level instructions, which are translated to low-level instructions by systools:make_relup.

Here, some of the most frequently used instructions are - described. The complete list of instructions is found in + described. The complete list of instructions can be found in appup(4).

First, some definitions:

@@ -239,9 +239,10 @@

update with argument supervisor is used when changing the start specification of a supervisor. See Appup Cookbook.

-

The release handler finds the processes using a module - to update by traversing the supervision tree of each running - application and checking all the child specifications:

+

When a module is to be updated, the release handler finds + which processes that are using the module by + traversing the supervision tree of each running application + and checking all the child specifications:

{Id, StartFunc, Restart, Shutdown, Type, Modules}

A process is using a module if the name is listed in @@ -265,8 +266,8 @@

The instruction loads the module and is absolutely necessary when running Erlang in embedded mode. It is not strictly required when running Erlang in interactive (default) mode, - since the code server automatically searches for and loads - unloaded modules.

+ since the code server then automatically searches for and + loads unloaded modules.

The opposite of add_module is delete_module which unloads a module:

@@ -294,7 +295,7 @@ the modules are unloaded using a number of delete_module instructions and then the application specification is unloaded from the application controller.

-

Instruction for removing an application:

+

Instruction for restarting an application:

{restart_application, Application}

Restarting an application means that the application is stopped @@ -331,17 +332,17 @@ of the emulator and the core applications. Then it shuts down the current emulator by calling init:reboot(), see init(3). All processes are terminated gracefully and - the system can then be rebooted by the heart program, using - the temporary boot file. After the reboot, the rest of the - relup instructions are executed. This is done as a part of the - boot script.

+ the system is rebooted by the heart program, using the + temporary boot file. After the reboot, the rest of the relup + instructions are executed. This is done as a part of the + temporary boot script.

An info report is written when the upgrade is completed. To programatically find out if the upgrade is complete, - call release_handler:which_releases/0 and check if the - expected release has status current.

-

The new version must be made permanent when the new emulator - is up and running. Otherwise, the old version will be used in - case of a new system reboot.

+ call release_handler:which_releases(current) and check + if it returns the expected (i.e. the new) release.

+

The new release version must be made permanent when the new + emulator is up and running. Otherwise, the old version will be + used in case of a new system reboot.

On UNIX, the release handler tells the heart program which command to use to reboot the system. Note that the environment variable HEART_COMMAND, normally used by the heart @@ -362,8 +363,8 @@ a relup script, and it shall always be placed at the end. If the relup is generated by systools:make_relup/3,4 this is automatically ensured.

-

When the release handler encounters the instruction, it shuts down - the emulator by calling init:reboot(), see +

When the release handler encounters the instruction, it shuts + down the emulator by calling init:reboot(), see init(3). All processes are terminated gracefully and the system can then be rebooted by the heart program using the new release version. No more upgrade instruction will be @@ -581,8 +582,8 @@ release_handler:remove_release(Vsn) => ok [].

2) Start the system as a simple target system. Note that in reality, it should be started as an embedded system. However, - using erl with the correct boot script and .config - file is enough for illustration purposes:

+ using erl with the correct boot script and config file is + enough for illustration purposes:

 % cd $ROOT
 % bin/erl -boot $ROOT/releases/A/start -config $ROOT/releases/A/sys
@@ -617,6 +618,7 @@ lib/ch_app-2/ebin/ch3.beam
 releases/B/start.boot
 releases/B/relup
 releases/B/sys.config
+releases/B/ch_rel-2.rel
 releases/ch_rel-2.rel
     

4) Copy the release package ch_rel-2.tar.gz to the $ROOT/releases directory.

diff --git a/system/doc/design_principles/release_structure.xml b/system/doc/design_principles/release_structure.xml index 2e1daa611a..8aea0e1a10 100644 --- a/system/doc/design_principles/release_structure.xml +++ b/system/doc/design_principles/release_structure.xml @@ -4,7 +4,7 @@
- 20032009 + 20032011 Ericsson AB. All Rights Reserved. @@ -61,12 +61,14 @@ {ApplicationN, AppVsnN}]}.

The file must be named Rel.rel, where Rel is a unique name.

-

Name, Vsn and Evsn are strings.

+

Name, Vsn and EVsn are strings.

Each Application (atom) and AppVsn (string) is the name and version of an application included in the release. - Note the the minimal release based on Erlang/OTP consists of + Note that the minimal release based on Erlang/OTP consists of the kernel and stdlib applications, so these applications must be included in the list.

+

If the release is to be upgraded, it must also include + the sasl application.

Example: We want to make a release of ch_app from the Applications @@ -173,6 +175,7 @@ lib/ch_app-1/ebin/ch_app.beam lib/ch_app-1/ebin/ch_sup.beam lib/ch_app-1/ebin/ch3.beam releases/A/start.boot +releases/A/ch_rel-1.rel releases/ch_rel-1.rel

Note that a new boot script was generated, without the local option set, before the release package was made. @@ -180,6 +183,17 @@ releases/ch_rel-1.rel under lib. Also, we do not know where the release package will be installed, so we do not want any hardcoded absolute paths in the boot script here.

+

The release resource file mysystem.rel is duplicated in + the tar file. Originally, this file was only stored in + the releases directory in order to make it possible for + the release_handler to extract this file + separately. After unpacking the tar file, release_handler + would automatically copy the file + to releases/FIRST. However, sometimes the tar file is + unpacked without involving the release_handler (e.g. when + unpacking the first target system) and therefore the file is now + instead duplicated in the tar file so no manual copying is + necessary.

If a relup file and/or a system configuration file called sys.config is found, these files are included in the release package as well. See diff --git a/system/doc/system_principles/create_target.xmlsrc b/system/doc/system_principles/create_target.xmlsrc index 1564423e00..bc2a76db47 100644 --- a/system/doc/system_principles/create_target.xmlsrc +++ b/system/doc/system_principles/create_target.xmlsrc @@ -44,9 +44,9 @@ may be irrelevant for the purpose in question. Thus, there is a need to be able to create a new system based on a given Erlang/OTP system, where dispensable applications are removed, - and a set of new applications that are included in the new - system. Documentation and source code is irrelevant and is - therefore not included in the new system.

+ and a set of new applications are included. Documentation and + source code is irrelevant and is therefore not included in the + new system.

This chapter is about creating such a system, which we call a target system.

In the following sections we consider creating target systems with @@ -63,10 +63,11 @@

We only consider the case when Erlang/OTP is running on a UNIX system.

-

There is an example Erlang module target_system.erl that - contains functions for creating and installing a target system. - That module is used in the examples below. The source code of - the module is listed at the end of this chapter.

+

In the sasl application there is an example Erlang + module target_system.erl that contains functions for + creating and installing a target system. This module is used in + the examples below, and the source code of the module is listed + at the end of this chapter.

@@ -117,28 +118,41 @@ os> erl -pa /home/user/target_system/myapps/pea-1.0/ebin erts-5.1/bin/ releases/FIRST/start.boot +releases/FIRST/mysystem.rel releases/mysystem.rel lib/kernel-2.7/ lib/stdlib-1.10/ lib/sasl-1.9.3/ lib/pea-1.0/

The file releases/FIRST/start.boot is a copy of our - mysystem.boot, and a copy of the original - mysystem.rel has been put in the releases - directory.

+ mysystem.boot

+

The release resource file mysystem.rel is duplicated + in the tar file. Originally, this file was only stored in + the releases directory in order to make it possible + for the release_handler to extract this file + separately. After unpacking the tar + file, release_handler would automatically copy the + file to releases/FIRST. However, sometimes the tar + file is unpacked without involving + the release_handler (e.g. when unpacking the first + target system) and therefore the file is now instead + duplicated in the tar file so no manual copying is + necessary.

Creates the temporary directory tmp and extracts the tar file mysystem.tar.gz into that directory. Deletes the erl and start files from - tmp/erts-5.1/bin. XXX Why. + tmp/erts-5.1/bin. These files will be created again from + source when installing the release. Creates the directory tmp/bin. - Copies the previously creates file plain.boot to + Copies the previously created file plain.boot to tmp/bin/start.boot. Copies the files epmd, run_erl, and to_erl from the directory tmp/erts-5.1/bin to the directory tmp/bin. - Creates the file tmp/releases/start_erl.data with the - contents "5.1 FIRST". + Creates the file tmp/releases/start_erl.data with + the contents "5.1 FIRST". This file is to be passed as data + file to the start_erl script. Recreates the file mysystem.tar.gz from the directories in the directory tmp, and removes tmp. @@ -210,7 +224,7 @@ os> /usr/local/erl-target/bin/erl -boot /usr/local/erl-target/releases/FI file of the release version found ("releases/FIRST/start.boot").

start_erl also assumes that there is sys.config in - release version directory ("releases/FIRST/sys.config). That + release version directory ("releases/FIRST/sys.config"). That is the topic of the next section (see below).

The start_erl shell script should normally not be altered by the user.

@@ -222,7 +236,7 @@ os> /usr/local/erl-target/bin/erl -boot /usr/local/erl-target/releases/FI sys.config in the release version directory ("releases/FIRST/sys.config"). If there is no such a file, the system start will fail. Hence such a file has to - added as well.

+ be added as well.

If you have system configuration data that are neither file location dependent nor site dependent, it may be convenient to @@ -245,252 +259,9 @@ os> /usr/local/erl-target/bin/erl -boot /usr/local/erl-target/releases/FI

Listing of target_system.erl - This module can also be found in the examples directory + of the sasl application.

+ -%% Note: RelFileName below is the *stem* without trailing .rel, -%% .script etc. -%% - -%% create(RelFileName) -%% -create(RelFileName) -> - RelFile = RelFileName ++ ".rel", - io:fwrite("Reading file: \"~s\" ...~n", [RelFile]), - {ok, [RelSpec]} = file:consult(RelFile), - io:fwrite("Creating file: \"~s\" from \"~s\" ...~n", - ["plain.rel", RelFile]), - {release, - {RelName, RelVsn}, - {erts, ErtsVsn}, - AppVsns} = RelSpec, - PlainRelSpec = {release, - {RelName, RelVsn}, - {erts, ErtsVsn}, - lists:filter(fun({kernel, _}) -> - true; - ({stdlib, _}) -> - true; - (_) -> - false - end, AppVsns) - }, - {ok, Fd} = file:open("plain.rel", [write]), - io:fwrite(Fd, "~p.~n", [PlainRelSpec]), - file:close(Fd), - - io:fwrite("Making \"plain.script\" and \"plain.boot\" files ...~n"), - make_script("plain"), - - io:fwrite("Making \"~s.script\" and \"~s.boot\" files ...~n", - [RelFileName, RelFileName]), - make_script(RelFileName), - - TarFileName = io_lib:fwrite("~s.tar.gz", [RelFileName]), - io:fwrite("Creating tar file \"~s\" ...~n", [TarFileName]), - make_tar(RelFileName), - - io:fwrite("Creating directory \"tmp\" ...~n"), - file:make_dir("tmp"), - - io:fwrite("Extracting \"~s\" into directory \"tmp\" ...~n", [TarFileName]), - extract_tar(TarFileName, "tmp"), - - TmpBinDir = filename:join(["tmp", "bin"]), - ErtsBinDir = filename:join(["tmp", "erts-" ++ ErtsVsn, "bin"]), - io:fwrite("Deleting \"erl\" and \"start\" in directory \"~s\" ...~n", - [ErtsBinDir]), - file:delete(filename:join([ErtsBinDir, "erl"])), - file:delete(filename:join([ErtsBinDir, "start"])), - - io:fwrite("Creating temporary directory \"~s\" ...~n", [TmpBinDir]), - file:make_dir(TmpBinDir), - - io:fwrite("Copying file \"plain.boot\" to \"~s\" ...~n", - [filename:join([TmpBinDir, "start.boot"])]), - copy_file("plain.boot", filename:join([TmpBinDir, "start.boot"])), - - io:fwrite("Copying files \"epmd\", \"run_erl\" and \"to_erl\" from \n" - "\"~s\" to \"~s\" ...~n", - [ErtsBinDir, TmpBinDir]), - copy_file(filename:join([ErtsBinDir, "epmd"]), - filename:join([TmpBinDir, "epmd"]), [preserve]), - copy_file(filename:join([ErtsBinDir, "run_erl"]), - filename:join([TmpBinDir, "run_erl"]), [preserve]), - copy_file(filename:join([ErtsBinDir, "to_erl"]), - filename:join([TmpBinDir, "to_erl"]), [preserve]), - - StartErlDataFile = filename:join(["tmp", "releases", "start_erl.data"]), - io:fwrite("Creating \"~s\" ...~n", [StartErlDataFile]), - StartErlData = io_lib:fwrite("~s ~s~n", [ErtsVsn, RelVsn]), - write_file(StartErlDataFile, StartErlData), - - io:fwrite("Recreating tar file \"~s\" from contents in directory " - "\"tmp\" ...~n", [TarFileName]), - {ok, Tar} = erl_tar:open(TarFileName, [write, compressed]), - {ok, Cwd} = file:get_cwd(), - file:set_cwd("tmp"), - erl_tar:add(Tar, "bin", []), - erl_tar:add(Tar, "erts-" ++ ErtsVsn, []), - erl_tar:add(Tar, "releases", []), - erl_tar:add(Tar, "lib", []), - erl_tar:close(Tar), - file:set_cwd(Cwd), - io:fwrite("Removing directory \"tmp\" ...~n"), - remove_dir_tree("tmp"), - ok. - - -install(RelFileName, RootDir) -> - TarFile = RelFileName ++ ".tar.gz", - io:fwrite("Extracting ~s ...~n", [TarFile]), - extract_tar(TarFile, RootDir), - StartErlDataFile = filename:join([RootDir, "releases", "start_erl.data"]), - {ok, StartErlData} = read_txt_file(StartErlDataFile), - [ErlVsn, RelVsn| _] = string:tokens(StartErlData, " \n"), - ErtsBinDir = filename:join([RootDir, "erts-" ++ ErlVsn, "bin"]), - BinDir = filename:join([RootDir, "bin"]), - io:fwrite("Substituting in erl.src, start.src and start_erl.src to\n" - "form erl, start and start_erl ...\n"), - subst_src_scripts(["erl", "start", "start_erl"], ErtsBinDir, BinDir, - [{"FINAL_ROOTDIR", RootDir}, {"EMU", "beam"}], - [preserve]), - io:fwrite("Creating the RELEASES file ...\n"), - create_RELEASES(RootDir, - filename:join([RootDir, "releases", RelFileName])). - -%% LOCALS - -%% make_script(RelFileName) -%% -make_script(RelFileName) -> - Opts = [no_module_tests], - systools:make_script(RelFileName, Opts). - -%% make_tar(RelFileName) -%% -make_tar(RelFileName) -> - RootDir = code:root_dir(), - systools:make_tar(RelFileName, [{erts, RootDir}]). - -%% extract_tar(TarFile, DestDir) -%% -extract_tar(TarFile, DestDir) -> - erl_tar:extract(TarFile, [{cwd, DestDir}, compressed]). - -create_RELEASES(DestDir, RelFileName) -> - release_handler:create_RELEASES(DestDir, RelFileName ++ ".rel"). - -subst_src_scripts(Scripts, SrcDir, DestDir, Vars, Opts) -> - lists:foreach(fun(Script) -> - subst_src_script(Script, SrcDir, DestDir, - Vars, Opts) - end, Scripts). - -subst_src_script(Script, SrcDir, DestDir, Vars, Opts) -> - subst_file(filename:join([SrcDir, Script ++ ".src"]), - filename:join([DestDir, Script]), - Vars, Opts). - -subst_file(Src, Dest, Vars, Opts) -> - {ok, Conts} = read_txt_file(Src), - NConts = subst(Conts, Vars), - write_file(Dest, NConts), - case lists:member(preserve, Opts) of - true -> - {ok, FileInfo} = file:read_file_info(Src), - file:write_file_info(Dest, FileInfo); - false -> - ok - end. - -%% subst(Str, Vars) -%% Vars = [{Var, Val}] -%% Var = Val = string() -%% Substitute all occurrences of %Var% for Val in Str, using the list -%% of variables in Vars. -%% -subst(Str, Vars) -> - subst(Str, Vars, []). - -subst([$%, C| Rest], Vars, Result) when $A =< C, C =< $Z -> - subst_var([C| Rest], Vars, Result, []); -subst([$%, C| Rest], Vars, Result) when $a =< C, C =< $z -> - subst_var([C| Rest], Vars, Result, []); -subst([$%, C| Rest], Vars, Result) when C == $_ -> - subst_var([C| Rest], Vars, Result, []); -subst([C| Rest], Vars, Result) -> - subst(Rest, Vars, [C| Result]); -subst([], _Vars, Result) -> - lists:reverse(Result). - -subst_var([$%| Rest], Vars, Result, VarAcc) -> - Key = lists:reverse(VarAcc), - case lists:keysearch(Key, 1, Vars) of - {value, {Key, Value}} -> - subst(Rest, Vars, lists:reverse(Value, Result)); - false -> - subst(Rest, Vars, [$%| VarAcc ++ [$%| Result]]) - end; -subst_var([C| Rest], Vars, Result, VarAcc) -> - subst_var(Rest, Vars, Result, [C| VarAcc]); -subst_var([], Vars, Result, VarAcc) -> - subst([], Vars, [VarAcc ++ [$%| Result]]). - -copy_file(Src, Dest) -> - copy_file(Src, Dest, []). - -copy_file(Src, Dest, Opts) -> - {ok, InFd} = file:open(Src, [raw, binary, read]), - {ok, OutFd} = file:open(Dest, [raw, binary, write]), - do_copy_file(InFd, OutFd), - file:close(InFd), - file:close(OutFd), - case lists:member(preserve, Opts) of - true -> - {ok, FileInfo} = file:read_file_info(Src), - file:write_file_info(Dest, FileInfo); - false -> - ok - end. - -do_copy_file(InFd, OutFd) -> - case file:read(InFd, ?BUFSIZE) of - {ok, Bin} -> - file:write(OutFd, Bin), - do_copy_file(InFd, OutFd); - eof -> - ok - end. - -write_file(FName, Conts) -> - {ok, Fd} = file:open(FName, [write]), - file:write(Fd, Conts), - file:close(Fd). - -read_txt_file(File) -> - {ok, Bin} = file:read_file(File), - {ok, binary_to_list(Bin)}. - -remove_dir_tree(Dir) -> - remove_all_files(".", [Dir]). - -remove_all_files(Dir, Files) -> - lists:foreach(fun(File) -> - FilePath = filename:join([Dir, File]), - {ok, FileInfo} = file:read_file_info(FilePath), - case FileInfo#file_info.type of - directory -> - {ok, DirFiles} = file:list_dir(FilePath), - remove_all_files(FilePath, DirFiles), - file:del_dir(FilePath); - _ -> - file:delete(FilePath) - end - end, Files). - ]]>
-- cgit v1.2.3