aboutsummaryrefslogtreecommitdiffstats
path: root/system/doc/design_principles/appup_cookbook.xml
diff options
context:
space:
mode:
Diffstat (limited to 'system/doc/design_principles/appup_cookbook.xml')
-rw-r--r--system/doc/design_principles/appup_cookbook.xml393
1 files changed, 206 insertions, 187 deletions
diff --git a/system/doc/design_principles/appup_cookbook.xml b/system/doc/design_principles/appup_cookbook.xml
index 70c34a5a06..31335197d7 100644
--- a/system/doc/design_principles/appup_cookbook.xml
+++ b/system/doc/design_principles/appup_cookbook.xml
@@ -4,20 +4,21 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2013</year>
+ <year>2003</year><year>2014</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
- 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 online 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.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
</legalnotice>
@@ -28,15 +29,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 +47,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 +80,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 +112,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 +163,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 +174,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 +224,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 frequency
- 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,16 +268,17 @@ 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).
...
init(_Args) ->
- {ok, {{one_for_all, 1, 60}, ...}}.</code>
+ {ok, {#{strategy => one_for_all, ...}, ...}}.</code>
<p>The file <c>ch_app.appup</c>:</p>
<code type="none">
{"2",
@@ -280,7 +291,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 +299,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 +331,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 +356,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 +378,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 +395,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 +412,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 +424,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 +454,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 +463,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 +527,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 +537,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 +576,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 +589,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 +612,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 +621,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 +655,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>