diff options
author | Björn Gustavsson <[email protected]> | 2015-03-12 15:35:13 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2015-03-12 15:35:13 +0100 |
commit | 42a0387e886ddbf60b0e2cb977758e2ca74954ae (patch) | |
tree | 2dc50aa0b66626e4e162111a046929763394374a /system/doc/design_principles/appup_cookbook.xml | |
parent | d1aeabb317811c203c08194c3dab464a48ec1dd3 (diff) | |
download | otp-42a0387e886ddbf60b0e2cb977758e2ca74954ae.tar.gz otp-42a0387e886ddbf60b0e2cb977758e2ca74954ae.tar.bz2 otp-42a0387e886ddbf60b0e2cb977758e2ca74954ae.zip |
Update Design Principles
Language cleaned up by the technical writers xsipewe and tmanevik
from Combitech. Proofreading and corrections by Björn Gustavsson.
Diffstat (limited to 'system/doc/design_principles/appup_cookbook.xml')
-rw-r--r-- | system/doc/design_principles/appup_cookbook.xml | 368 |
1 files changed, 193 insertions, 175 deletions
diff --git a/system/doc/design_principles/appup_cookbook.xml b/system/doc/design_principles/appup_cookbook.xml index 22c48db855..63adea8a5c 100644 --- a/system/doc/design_principles/appup_cookbook.xml +++ b/system/doc/design_principles/appup_cookbook.xml @@ -28,15 +28,15 @@ <rev></rev> <file>appup_cookbook.xml</file> </header> - <p>This chapter contains examples of <c>.appup</c> files for - typical cases of upgrades/downgrades done in run-time.</p> + <marker id="appup cookbook"></marker> + <p>This section includes examples of <c>.appup</c> files for + typical cases of upgrades/downgrades done in runtime.</p> <section> <title>Changing a Functional Module</title> - <p>When a change has been made to a functional module, for example + <p>When a functional module has been changed, for example, if a new function has been added or a bug has been corrected, - simple code replacement is sufficient.</p> - <p>Example:</p> + simple code replacement is sufficient, for example:</p> <code type="none"> {"2", [{"1", [{load_module, m}]}], @@ -46,29 +46,31 @@ <section> <title>Changing a Residence Module</title> - <p>In a system implemented according to the OTP Design Principles, + <p>In a system implemented according to the OTP design principles, all processes, except system processes and special processes, reside in one of the behaviours <c>supervisor</c>, - <c>gen_server</c>, <c>gen_fsm</c> or <c>gen_event</c>. These + <c>gen_server</c>, <c>gen_fsm</c>, or <c>gen_event</c>. These belong to the STDLIB application and upgrading/downgrading normally requires an emulator restart.</p> - <p>OTP thus provides no support for changing residence modules - except in the case of <seealso marker="#spec">special processes</seealso>.</p> + <p>OTP thus provides no support for changing residence modules except + in the case of <seealso marker="#spec">special processes</seealso>.</p> </section> <section> <title>Changing a Callback Module</title> - <p>A callback module is a functional module, and for code + <p>A callback module is a functional module, and for code extensions simple code replacement is sufficient.</p> - <p>Example: When adding a function to <c>ch3</c> as described in - the example in <seealso marker="release_handling#appup">Release Handling</seealso>, <c>ch_app.appup</c> looks as follows:</p> + <p><em>Example:</em> When adding a function to <c>ch3</c>, + as described in the example in + <seealso marker="release_handling#appup">Release Handling</seealso>, + <c>ch_app.appup</c> looks as follows:</p> <code type="none"> {"2", [{"1", [{load_module, ch3}]}], [{"1", [{load_module, ch3}]}] }.</code> <p>OTP also supports changing the internal state of behaviour - processes, see <seealso marker="#int_state">Changing Internal State</seealso> below.</p> + processes, see <seealso marker="#int_state">Changing Internal State</seealso>.</p> </section> <section> @@ -77,26 +79,28 @@ <p>In this case, simple code replacement is not sufficient. The process must explicitly transform its state using the callback function <c>code_change</c> before switching to the new version - of the callback module. Thus synchronized code replacement is + of the callback module. Thus, synchronized code replacement is used.</p> - <p>Example: Consider the gen_server <c>ch3</c> from the chapter - about the <seealso marker="gen_server_concepts#ex">gen_server behaviour</seealso>. The internal state is a term <c>Chs</c> - representing the available channels. Assume we want add a counter - <c>N</c> which keeps track of the number of <c>alloc</c> requests - so far. This means we need to change the format to + <p><em>Example:</em> Consider <c>gen_server</c> <c>ch3</c> from + <seealso marker="gen_server_concepts#ex">gen_server Behaviour</seealso>. + The internal state is a term <c>Chs</c> + representing the available channels. Assume you want to add a counter + <c>N</c>, which keeps track of the number of <c>alloc</c> requests + so far. This means that the format must be changed to <c>{Chs,N}</c>.</p> - <p>The <c>.appup</c> file could look as follows:</p> + <p>The <c>.appup</c> file can look as follows:</p> <code type="none"> {"2", [{"1", [{update, ch3, {advanced, []}}]}], [{"1", [{update, ch3, {advanced, []}}]}] }.</code> <p>The third element of the <c>update</c> instruction is a tuple - <c>{advanced,Extra}</c> which says that the affected processes - should do a state transformation before loading the new version + <c>{advanced,Extra}</c>, which says that the affected processes + are to do a state transformation before loading the new version of the module. This is done by the processes calling the callback - function <c>code_change</c> (see <c>gen_server(3)</c>). The term - <c>Extra</c>, in this case [], is passed as-is to the function:</p> + function <c>code_change</c> (see the <c>gen_server(3)</c> manual + page in STDLIB). The term <c>Extra</c>, in this case + <c>[]</c>, is passed as is to the function:</p> <marker id="code_change"></marker> <code type="none"> -module(ch3). @@ -107,40 +111,41 @@ code_change({down, _Vsn}, {Chs, N}, _Extra) -> {ok, Chs}; code_change(_Vsn, Chs, _Extra) -> {ok, {Chs, 0}}.</code> - <p>The first argument is <c>{down,Vsn}</c> in case of a downgrade, - or <c>Vsn</c> in case of an upgrade. The term <c>Vsn</c> is - fetched from the 'original' version of the module, i.e. - the version we are upgrading from, or downgrading to.</p> + <p>The first argument is <c>{down,Vsn}</c> if there is a downgrade, + or <c>Vsn</c> if there is a upgrade. The term <c>Vsn</c> is + fetched from the 'original' version of the module, that is, + the version you are upgrading from, or downgrading to.</p> <p>The version is defined by the module attribute <c>vsn</c>, if any. There is no such attribute in <c>ch3</c>, so in this case - the version is the checksum (a huge integer) of the BEAM file, an - uninteresting value which is ignored.</p> - <p>(The other callback functions of <c>ch3</c> need to be modified - as well and perhaps a new interface function added, this is not - shown here).</p> + the version is the checksum (a huge integer) of the beam file, an + uninteresting value, which is ignored.</p> + <p>The other callback functions of <c>ch3</c> must also be modified + and perhaps a new interface function must be added, but this is not + shown here.</p> </section> <section> <title>Module Dependencies</title> - <p>Assume we extend a module by adding a new interface function, as - in the example in <seealso marker="release_handling#appup">Release Handling</seealso>, where a function <c>available/0</c> is - added to <c>ch3</c>.</p> - <p>If we also add a call to this function, say in the module - <c>m1</c>, a run-time error could occur during release upgrade if + <p>Assume that a module is extended by adding an interface function, + as in the example in + <seealso marker="release_handling#appup">Release Handling</seealso>, + where a function <c>available/0</c> is added to <c>ch3</c>.</p> + <p>If a call is added to this function, say in module + <c>m1</c>, a runtime error could can occur during release upgrade if the new version of <c>m1</c> is loaded first and calls <c>ch3:available/0</c> before the new version of <c>ch3</c> is loaded.</p> - <p>Thus, <c>ch3</c> must be loaded before <c>m1</c> is, in - the upgrade case, and vice versa in the downgrade case. We say - that <c>m1</c> <em>is dependent on</em> <c>ch3</c>. In a release - handling instruction, this is expressed by the element - <c>DepMods</c>:</p> + <p>Thus, <c>ch3</c> must be loaded before <c>m1</c>, in + the upgrade case, and conversely in the downgrade case. + <c>m1</c> is said to be <em>dependent on</em> <c>ch3</c>. In a release + handling instruction, this is expressed by the + <c>DepMods</c> element:</p> <code type="none"> {load_module, Module, DepMods} {update, Module, {advanced, Extra}, DepMods}</code> <p><c>DepMods</c> is a list of modules, on which <c>Module</c> is dependent.</p> - <p>Example: The module <c>m1</c> in the application <c>myapp</c> is + <p><em>Example:</em> The module <c>m1</c> in application <c>myapp</c> is dependent on <c>ch3</c> when upgrading from "1" to "2", or downgrading from "2" to "1":</p> <code type="none"> @@ -157,8 +162,8 @@ ch_app.appup: [{"1", [{load_module, ch3}]}], [{"1", [{load_module, ch3}]}] }.</code> - <p>If <c>m1</c> and <c>ch3</c> had belonged to the same application, - the <c>.appup</c> file could have looked like this:</p> + <p>If instead <c>m1</c> and <c>ch3</c> belong to the same application, + the <c>.appup</c> file can look as follows:</p> <code type="none"> {"2", [{"1", @@ -168,48 +173,48 @@ ch_app.appup: [{load_module, ch3}, {load_module, m1, [ch3]}]}] }.</code> - <p>Note that it is <c>m1</c> that is dependent on <c>ch3</c> also + <p><c>m1</c> is dependent on <c>ch3</c> also when downgrading. <c>systools</c> knows the difference between - up- and downgrading and will generate a correct <c>relup</c>, - where <c>ch3</c> is loaded before <c>m1</c> when upgrading but + up- and downgrading and generates a correct <c>relup</c>, + where <c>ch3</c> is loaded before <c>m1</c> when upgrading, but <c>m1</c> is loaded before <c>ch3</c> when downgrading.</p> </section> <section> <marker id="spec"></marker> - <title>Changing Code For a Special Process</title> + <title>Changing Code for a Special Process</title> <p>In this case, simple code replacement is not sufficient. When a new version of a residence module for a special process is loaded, the process must make a fully qualified call to - its loop function to switch to the new code. Thus synchronized + its loop function to switch to the new code. Thus, synchronized code replacement must be used.</p> <note> <p>The name(s) of the user-defined residence module(s) must be listed in the <c>Modules</c> part of the child specification - for the special process, in order for the release handler to + for the special process. Otherwise the release handler cannot find the process.</p> </note> - <p>Example. Consider the example <c>ch4</c> from the chapter about + <p><em>Example:</em> Consider the example <c>ch4</c> in <seealso marker="spec_proc#ex">sys and proc_lib</seealso>. - When started by a supervisor, the child specification could look - like this:</p> + When started by a supervisor, the child specification can look + as follows:</p> <code type="none"> {ch4, {ch4, start_link, []}, permanent, brutal_kill, worker, [ch4]}</code> <p>If <c>ch4</c> is part of the application <c>sp_app</c> and a new - version of the module should be loaded when upgrading from - version "1" to "2" of this application, <c>sp_app.appup</c> could - look like this:</p> + version of the module is to be loaded when upgrading from + version "1" to "2" of this application, <c>sp_app.appup</c> can + look as follows:</p> <code type="none"> {"2", [{"1", [{update, ch4, {advanced, []}}]}], [{"1", [{update, ch4, {advanced, []}}]}] }.</code> <p>The <c>update</c> instruction must contain the tuple - <c>{advanced,Extra}</c>. The instruction will make the special + <c>{advanced,Extra}</c>. The instruction makes the special process call the callback function <c>system_code_change/4</c>, a function the user must implement. The term <c>Extra</c>, in this - case [], is passed as-is to <c>system_code_change/4</c>:</p> + case <c>[]</c>, is passed as is to <c>system_code_change/4</c>:</p> <code type="none"> -module(ch4). ... @@ -218,39 +223,43 @@ ch_app.appup: system_code_change(Chs, _Module, _OldVsn, _Extra) -> {ok, Chs}.</code> - <p>The first argument is the internal state <c>State</c> passed from - the function <c>sys:handle_system_msg(Request, From, Parent, Module, Deb, State)</c>, called by the special process when - a system message is received. In <c>ch4</c>, the internal state is - the set of available channels <c>Chs</c>.</p> - <p>The second argument is the name of the module (<c>ch4</c>).</p> - <p>The third argument is <c>Vsn</c> or <c>{down,Vsn}</c> as - described for - <seealso marker="#code_change">gen_server:code_change/3</seealso>.</p> + <list type="bulleted"> + <item>The first argument is the internal state <c>State</c>, + passed from function + <c>sys:handle_system_msg(Request, From, Parent, Module, Deb, State)</c>, + and called by the special process when a system message is received. + In <c>ch4</c>, the internal state is the set of available channels + <c>Chs</c>.</item> + <item>The second argument is the name of the module + (<c>ch4</c>).</item> + <item>The third argument is <c>Vsn</c> or <c>{down,Vsn}</c>, as + described for <c>gen_server:code_change/3</c> in + <seealso marker="#code_change">Changing Internal State</seealso>.</item> + </list> <p>In this case, all arguments but the first are ignored and the function simply returns the internal state again. This is - enough if the code only has been extended. If we had wanted to - change the internal state (similar to the example in + enough if the code only has been extended. If instead the + internal state is changed (similar to the example in <seealso marker="#int_state">Changing Internal State</seealso>), - it would have been done in this function and - <c>{ok,Chs2}</c> returned.</p> + this is done in this function and <c>{ok,Chs2}</c> returned.</p> </section> <section> <marker id="sup"></marker> <title>Changing a Supervisor</title> <p>The supervisor behaviour supports changing the internal state, - i.e. changing restart strategy and maximum restart intensity - properties, as well as changing existing child specifications.</p> - <p>Adding and deleting child processes are also possible, but not + that is, changing the restart strategy and maximum restart frequency + properties, as well as changing the existing child specifications.</p> + <p>Child processes can be added or deleted, but this is not handled automatically. Instructions must be given by in the <c>.appup</c> file.</p> <section> <title>Changing Properties</title> - <p>Since the supervisor should change its internal state, + <p>Since the supervisor is to change its internal state, synchronized code replacement is required. However, a special <c>update</c> instruction must be used.</p> - <p>The new version of the callback module must be loaded first + <p>First, the new version of the callback module must be loaded, both in the case of upgrade and downgrade. Then the new return value of <c>init/1</c> can be checked and the internal state be changed accordingly.</p> @@ -258,10 +267,11 @@ system_code_change(Chs, _Module, _OldVsn, _Extra) -> supervisors:</p> <code type="none"> {update, Module, supervisor}</code> - <p>Example: Assume we want to change the restart strategy of - <c>ch_sup</c> from the <seealso marker="sup_princ#ex">Supervisor Behaviour</seealso> chapter from one_for_one to one_for_all. - We change the callback function <c>init/1</c> in - <c>ch_sup.erl</c>:</p> + <p><em>Example:</em> To change the restart strategy of + <c>ch_sup</c> (from + <seealso marker="sup_princ#ex">Supervisor Behaviour</seealso>) + from <c>one_for_one</c> to <c>one_for_all</c>, change the callback + function <c>init/1</c> in <c>ch_sup.erl</c>:</p> <code type="none"> -module(ch_sup). ... @@ -280,7 +290,7 @@ init(_Args) -> <title>Changing Child Specifications</title> <p>The instruction, and thus the <c>.appup</c> file, when changing an existing child specification, is the same as when - changing properties as described above:</p> + changing properties as described earlier:</p> <code type="none"> {"2", [{"1", [{update, ch_sup, supervisor}]}], @@ -288,25 +298,25 @@ init(_Args) -> }.</code> <p>The changes do not affect existing child processes. For example, changing the start function only specifies how - the child process should be restarted, if needed later on.</p> - <p>Note that the id of the child specification cannot be changed.</p> - <p>Note also that changing the <c>Modules</c> field of the child - specification may affect the release handling process itself, + the child process is to be restarted, if needed later on.</p> + <p>The id of the child specification cannot be changed.</p> + <p>Changing the <c>Modules</c> field of the child + specification can affect the release handling process itself, as this field is used to identify which processes are affected when doing a synchronized code replacement.</p> </section> <marker id="sup_add"></marker> <section> - <title>Adding And Deleting Child Processes</title> - <p>As stated above, changing child specifications does not affect + <title>Adding and Deleting Child Processes</title> + <p>As stated earlier, changing child specifications does not affect existing child processes. New child specifications are - automatically added, but not deleted. Also, child processes are - not automatically started or terminated. Instead, this must be - done explicitly using <c>apply</c> instructions.</p> - <p>Example: Assume we want to add a new child process <c>m1</c> to - <c>ch_sup</c> when upgrading <c>ch_app</c> from "1" to "2". - This means <c>m1</c> should be deleted when downgrading from + automatically added, but not deleted. Child processes are + not automatically started or terminated, this must be + done using <c>apply</c> instructions.</p> + <p><em>Example:</em> Assume a new child process <c>m1</c> is to be + added to <c>ch_sup</c> when upgrading <c>ch_app</c> from "1" to "2". + This means <c>m1</c> is to be deleted when downgrading from "2" to "1":</p> <code type="none"> {"2", @@ -320,13 +330,13 @@ init(_Args) -> {update, ch_sup, supervisor} ]}] }.</code> - <p>Note that the order of the instructions is important.</p> - <p>Note also that the supervisor must be registered as + <p>The order of the instructions is important.</p> + <p>The supervisor must be registered as <c>ch_sup</c> for the script to work. If the supervisor is not registered, it cannot be accessed directly from the script. Instead a help function that finds the pid of the supervisor - and calls <c>supervisor:restart_child</c> etc. must be written, - and it is this function that should be called from the script + and calls <c>supervisor:restart_child</c>, and so on, must be + written. This function is then to be called from the script using the <c>apply</c> instruction.</p> <p>If the module <c>m1</c> is introduced in version "2" of <c>ch_app</c>, it must also be loaded when upgrading and @@ -345,18 +355,18 @@ init(_Args) -> {delete_module, m1} ]}] }.</code> - <p>Note again that the order of the instructions is important. - When upgrading, <c>m1</c> must be loaded and the supervisor's + <p>As stated earlier, the order of the instructions is important. + When upgrading, <c>m1</c> must be loaded, and the supervisor child specification changed, before the new child process can be started. When downgrading, the child process must be - terminated before child specification is changed and the module + terminated before the child specification is changed and the module is deleted.</p> </section> </section> <section> <title>Adding or Deleting a Module</title> - <p>Example: A new functional module <c>m</c> is added to + <p><em>Example:</em> A new functional module <c>m</c> is added to <c>ch_app</c>:</p> <code type="none"> {"2", @@ -367,15 +377,16 @@ init(_Args) -> <section> <title>Starting or Terminating a Process</title> <p>In a system structured according to the OTP design principles, - any process would be a child process belonging to a supervisor, - see <seealso marker="#sup_add">Adding and Deleting Child Processes</seealso> above.</p> + any process would be a child process belonging to a supervisor, see + <seealso marker="#sup_add">Adding and Deleting Child Processes</seealso> + in Changing a Supervisor.</p> </section> <section> <title>Adding or Removing an Application</title> <p>When adding or removing an application, no <c>.appup</c> file is needed. When generating <c>relup</c>, the <c>.rel</c> files - are compared and <c>add_application</c> and + are compared and the <c>add_application</c> and <c>remove_application</c> instructions are added automatically.</p> </section> @@ -383,11 +394,11 @@ init(_Args) -> <title>Restarting an Application</title> <p>Restarting an application is useful when a change is too complicated to be made without restarting the processes, for - example if the supervisor hierarchy has been restructured.</p> - <p>Example: When adding a new child <c>m1</c> to <c>ch_sup</c>, as - in the <seealso marker="#sup_add">example above</seealso>, an - alternative to updating the supervisor is to restart the entire - application:</p> + example, if the supervisor hierarchy has been restructured.</p> + <p><em>Example:</em> When adding a child <c>m1</c> to <c>ch_sup</c>, as in + <seealso marker="#sup_add">Adding and Deleting Child Processes</seealso> + in Changing a Supervisor, an alternative to updating + the supervisor is to restart the entire application:</p> <code type="none"> {"2", [{"1", [{restart_application, ch_app}]}], @@ -400,7 +411,7 @@ init(_Args) -> <title>Changing an Application Specification</title> <p>When installing a release, the application specifications are automatically updated before evaluating the <c>relup</c> script. - Hence, no instructions are needed in the <c>.appup</c> file:</p> + Thus, no instructions are needed in the <c>.appup</c> file:</p> <pre> {"2", [{"1", []}], @@ -412,28 +423,29 @@ init(_Args) -> <title>Changing Application Configuration</title> <p>Changing an application configuration by updating the <c>env</c> key in the <c>.app</c> file is an instance of changing an - application specification, <seealso marker="#app_spec">see above</seealso>.</p> + application specification, see the previous section.</p> <p>Alternatively, application configuration parameters can be added or updated in <c>sys.config</c>.</p> </section> <section> <title>Changing Included Applications</title> - <p>The release handling instructions for adding, removing and + <p>The release handling instructions for adding, removing, and restarting applications apply to primary applications only. There are no corresponding instructions for included applications. However, since an included application is really a supervision tree with a topmost supervisor, started as a child process to a supervisor in the including application, a <c>relup</c> file can be manually created.</p> - <p>Example: Assume we have a release containing an application - <c>prim_app</c> which have a supervisor <c>prim_sup</c> in its + <p><em>Example:</em> Assume there is a release containing an application + <c>prim_app</c>, which have a supervisor <c>prim_sup</c> in its supervision tree.</p> - <p>In a new version of the release, our example application - <c>ch_app</c> should be included in <c>prim_app</c>. That is, - its topmost supervisor <c>ch_sup</c> should be started as a child + <p>In a new version of the release, the application <c>ch_app</c> + is to be included in <c>prim_app</c>. That is, + its topmost supervisor <c>ch_sup</c> is to be started as a child process to <c>prim_sup</c>.</p> - <p>1) Edit the code for <c>prim_sup</c>:</p> + <p>The workflow is as follows:</p> + <p><em>Step 1)</em> Edit the code for <c>prim_sup</c>:</p> <code type="none"> init(...) -> {ok, {...supervisor flags..., @@ -441,7 +453,7 @@ init(...) -> {ch_sup, {ch_sup,start_link,[]}, permanent,infinity,supervisor,[ch_sup]}, ...]}}.</code> - <p>2) Edit the <c>.app</c> file for <c>prim_app</c>:</p> + <p><em>Step 2)</em> Edit the <c>.app</c> file for <c>prim_app</c>:</p> <code type="none"> {application, prim_app, [..., @@ -450,27 +462,29 @@ init(...) -> {included_applications, [ch_app]}, ... ]}.</code> - <p>3) Create a new <c>.rel</c> file, including <c>ch_app</c>:</p> + <p><em>Step 3)</em> Create a new <c>.rel</c> file, including + <c>ch_app</c>:</p> <code type="none"> {release, ..., [..., {prim_app, "2"}, {ch_app, "1"}]}.</code> + <p>The included application can be started in two ways. + This is described in the next two sections.</p> <section> <title>Application Restart</title> - <p>4a) One way to start the included application is to restart - the entire <c>prim_app</c> application. Normally, we would then - use the <c>restart_application</c> instruction in - the <c>.appup</c> file for <c>prim_app</c>.</p> - <p>However, if we did this and then generated a <c>relup</c> file, - not only would it contain instructions for restarting (i.e. + <p><em>Step 4a)</em> One way to start the included application is to + restart the entire <c>prim_app</c> application. Normally, the + <c>restart_application</c> instruction in the <c>.appup</c> file + for <c>prim_app</c> would be used.</p> + <p>However, if this is done and a <c>relup</c> file is generated, + not only would it contain instructions for restarting (that is, removing and adding) <c>prim_app</c>, it would also contain instructions for starting <c>ch_app</c> (and stopping it, in - the case of downgrade). This is due to the fact that - <c>ch_app</c> is included in the new <c>.rel</c> file, but not - in the old one.</p> + the case of downgrade). This is because <c>ch_app</c> is included + in the new <c>.rel</c> file, but not in the old one.</p> <p>Instead, a correct <c>relup</c> file can be created manually, either from scratch or by editing the generated version. The instructions for starting/stopping <c>ch_app</c> are @@ -512,7 +526,8 @@ init(...) -> <section> <title>Supervisor Change</title> - <p>4b) Another way to start the included application (or stop it + <p><em>Step 4b)</em> Another way to start the included + application (or stop it in the case of downgrade) is by combining instructions for adding and removing child processes to/from <c>prim_sup</c> with instructions for loading/unloading all <c>ch_app</c> code and @@ -521,7 +536,7 @@ init(...) -> scratch or by editing a generated version. Load all code for <c>ch_app</c> first, and also load the application specification, before <c>prim_sup</c> is updated. When - downgrading, <c>prim_sup</c> should be updated first, before + downgrading, <c>prim_sup</c> is to updated first, before the code for <c>ch_app</c> and its application specification are unloaded.</p> <code type="none"> @@ -560,10 +575,10 @@ init(...) -> <section> <title>Changing Non-Erlang Code</title> <p>Changing code for a program written in another programming - language than Erlang, for example a port program, is very - application dependent and OTP provides no special support for it.</p> - <p>Example, changing code for a port program: Assume that - the Erlang process controlling the port is a gen_server + language than Erlang, for example, a port program, is + application-dependent and OTP provides no special support for it.</p> + <p><em>Example:</em> When changing code for a port program, assume that + the Erlang process controlling the port is a <c>gen_server</c> <c>portc</c> and that the port is opened in the callback function <c>init/1</c>:</p> <code type="none"> @@ -573,10 +588,11 @@ init(...) -> Port = open_port({spawn,PortPrg}, [...]), ..., {ok, #state{port=Port, ...}}.</code> - <p>If the port program should be updated, we can extend the code for - the gen_server with a <c>code_change</c> function which closes - the old port and opens a new port. (If necessary, the gen_server - may first request data that needs to be saved from the port + <p>If the port program is to be updated, the code for the + <c>gen_server</c> can be extended with a <c>code_change</c> function, + which closes the old port and opens a new port. + (If necessary, the <c>gen_server</c> can + first request data that must be saved from the port program and pass this data to the new port):</p> <code type="none"> code_change(_OldVsn, State, port) -> @@ -595,8 +611,8 @@ code_change(_OldVsn, State, port) -> [{"1", [{update, portc, {advanced,port}}]}], [{"1", [{update, portc, {advanced,port}}]}] ].</code> - <p>Make sure the <c>priv</c> directory where the C program is - located is included in the new release package:</p> + <p>Ensure that the <c>priv</c> directory, where the C program is + located, is included in the new release package:</p> <pre> 1> <input>systools:make_tar("my_release", [{dirs,[priv]}]).</input> ...</pre> @@ -604,28 +620,29 @@ code_change(_OldVsn, State, port) -> <section> <title>Emulator Restart and Upgrade</title> - <p>There are two upgrade instructions that will restart the emulator:</p> - <taglist> - <tag><c>restart_new_emulator</c></tag> - <item>Intended for when erts, kernel, stdlib or sasl is - upgraded. It is automatically added when the relup file is - generated by <c>systools:make_relup/3,4</c>. It is executed - before all other upgrade instructions. See - <seealso marker="release_handling#restart_new_emulator_instr">Release - Handling</seealso> for more information about this - instruction.</item> - <tag><c>restart_emulator</c></tag> - <item>Used when a restart of the emulator is required after all - other upgrade instructions are executed. See - <seealso marker="release_handling#restart_emulator_instr">Release - Handling</seealso> for more information about this - instruction.</item> - </taglist> - + <p>Two upgrade instructions restart the emulator:</p> + <list type="bulleted"> + <item><p><c>restart_new_emulator</c></p> + <p>Intended when ERTS, Kernel, STDLIB, or + SASL is upgraded. It is automatically added when the + <c>relup</c> file is generated by <c>systools:make_relup/3,4</c>. + It is executed before all other upgrade instructions. + For more information about this instruction, see + restart_new_emulator (Low-Level) in + <seealso marker="release_handling#restart_new_emulator_instr">Release Handling Instructions</seealso>. + </p></item> + <item><p><c>restart_emulator</c></p> + <p>Used when a restart of the emulator is required after all + other upgrade instructions are executed. + For more information about this instruction, see + restart_emulator (Low-Level) in + <seealso marker="release_handling#restart_emulator_instr">Release Handling Instructions</seealso>. + </p></item> + </list> <p>If an emulator restart is necessary and no upgrade instructions - are needed, i.e. if the restart itself is enough for the - upgraded applications to start running the new versions, a very - simple <c>.relup</c> file can be created manually:</p> + are needed, that is, if the restart itself is enough for the + upgraded applications to start running the new versions, a + simple <c>relup</c> file can be created manually:</p> <code type="none"> {"B", [{"A", @@ -637,26 +654,27 @@ code_change(_OldVsn, State, port) -> }.</code> <p>In this case, the release handler framework with automatic packing and unpacking of release packages, automatic path - updates etc. can be used without having to specify <c>.appup</c> - files.</p> + updates, and so on, can be used without having to specify + <c>.appup</c> files.</p> </section> <section> - <title>Emulator Upgrade from pre OTP R15</title> + <title>Emulator Upgrade From Pre OTP R15</title> <p>From OTP R15, an emulator upgrade is performed by restarting the emulator with new versions of the core applications - (<c>kernel</c>, <c>stdlib</c> and <c>sasl</c>) before loading code + (Kernel, STDLIB, and SASL) before loading code and running upgrade instruction for other applications. For this - to work, the release to upgrade from must includes OTP R15 or - later. For the case where the release to upgrade from includes an - earlier emulator version, <c>systools:make_relup</c> will create a + to work, the release to upgrade from must include OTP R15 or + later.</p> + <p>For the case where the release to upgrade from includes an + earlier emulator version, <c>systools:make_relup</c> creates a backwards compatible relup file. This means that all upgrade - instructions will be executed before the emulator is - restarted. The new application code will therefore be loaded into + instructions are executed before the emulator is + restarted. The new application code is therefore loaded into the old emulator. If the new code is compiled with the new - emulator, there might be cases where the beam format has changed - and beam files can not be loaded. To overcome this problem, the - new code should be compiled with the old emulator.</p> + emulator, there can be cases where the beam format has changed + and beam files cannot be loaded. To overcome this problem, compile + the new code with the old emulator.</p> </section> </chapter> |