RELEASE UPGRADE INSTRUCTIONS
Release upgrade instructions are interpreted by the release
handler when an upgrade or downgrade is made. For more
information about release handling, refer to OTP Design Principles.
A process is said to use a module Mod, if
Mod is listed in the Modules part of the child
specification used to start the process, see supervisor(3).
In the case of gen_event, an event manager process is said to use
Mod if Mod is an installed event handler.
High-level instructions
{update, Mod}
{update, Mod, supervisor}
{update, Mod, Change}
{update, Mod, DepMods}
{update, Mod, Change, DepMods}
{update, Mod, Change, PrePurge, PostPurge, DepMods}
{update, Mod, Timeout, Change, PrePurge, PostPurge, DepMods}
{update, Mod, ModType, Timeout, Change, PrePurge, PostPurge, DepMods}
Mod = atom()
ModType = static | dynamic
Timeout = int()>0 | default | infinity
Change = soft | {advanced,Extra}
Extra = term()
PrePurge = PostPurge = soft_purge | brutal_purge
DepMods = [Mod]
Synchronized code replacement of processes using the module
Mod. All those processes are suspended using
sys:suspend, the new version of the module is loaded and
then the processes are resumed using sys:resume.
Change defaults to soft and defines the type of
code change. If it is set to {advanced,Extra}, processes
implemented using gen_server, gen_fsm or gen_event will transform
their internal state by calling the callback function
code_change. Special processes will call the callback
function system_code_change/4. In both cases, the term
Extra is passed as an argument to the callback function.
PrePurge defaults to brutal_purge and controls
what action to take with processes that are executing old code
before loading the new version of the module. If the value
is brutal_purge, the processes are killed. If the value is
soft_purge, release_handler:install_release/1
returns {error,{old_processes,Mod}}.
PostPurge defaults to brutal_purge and controls
what action to take with processes that are executing old code
when the new version of the module has been loaded. If the value
is brutal_purge, the code is purged when the release is
made permanent and the processes are killed. If the value is
soft_purge, the release handler will purge the old code
when no remaining processes execute the code.
DepMods defaults to [] and defines which other modules
Mod is dependent on. In relup, instructions for
suspending processes using Mod will come before
instructions for suspending processes using modules in
DepMods when upgrading, and vice versa when downgrading.
In case of circular dependencies, the order of the instructions in
the appup script is kept.
Timeout defines the timeout when suspending processes.
If no value or default is given, the default value for
sys:suspend is used.
ModType defaults to dynamic and specifies if
the code is "dynamic", that is if a process using the module does
spontaneously switch to new code, or if it is "static".
When doing an advanced update and upgrading, the new version of a
dynamic module is loaded before the process is asked to change
code. When downgrading, the process is asked to change code before
loading the new version. For static modules, the new version is
loaded before the process is asked to change code, both in
the case of upgrading and downgrading. Callback modules are
dynamic.
update with argument supervisor is used when
changing the start specification of a supervisor.
{load_module, Mod}
{load_module, Mod, DepMods}
{load_module, Mod, PrePurge, PostPurge, DepMods}
Mod = atom()
PrePurge = PostPurge = soft_purge | brutal_purge
DepMods = [Mod]
Simple code replacement of the module Mod.
See update above for a description of PrePurge and
PostPurge.
DepMods defaults to [] and defines which other modules
Mod is dependent on. In relup, instructions for
loading these modules will come before the instruction for loading
Mod when upgrading, and vice versa when downgrading.
{add_module, Mod}
Mod = atom()
Loads a new module Mod.
{delete_module, Mod}
Mod = atom()
Deletes a module Mod using the low-level instructions
remove and purge.
{add_application, Application}
{add_application, Application, Type}
Application = atom()
Type = permanent | transient | temporary | load | none
Adding an application means that the modules defined by
the modules key in the .app file are loaded using
add_module.
Type defaults to permanent and specifies the start type
of the application. If Type = permanent | transient | temporary,
the application will be loaded and started in the corresponding way,
see application(3). If Type = load, the application will
only be loaded. If Type = none, the application will be neither
loaded nor started, although the code for its modules will be loaded.
{remove_application, Application}
Application = atom()
Removing an application means that the application is stopped,
the modules are unloaded using delete_module and then
the application specification is unloaded from the application
controller.
{restart_application, Application}
Application = atom()
Restarting an application means that the application is
stopped and then started again similar to using the instructions
remove_application and add_application in sequence.
Low-level instructions
{load_object_code, {App, Vsn, [Mod]}}
App = Mod = atom()
Vsn = string()
Reads each Mod from the directory App-Vsn/ebin as
a binary. It does not load the modules. The instruction should be
placed first in the script in order to read all new code from file
to make the suspend-load-resume cycle less time consuming. After
this instruction has been executed, the code server with the new
version of App.
point_of_no_return
If a crash occurs after this instruction, the system cannot
recover and is restarted from the old version of the release.
The instruction must only occur once in a script. It should be
placed after all load_object_code instructions.
{load, {Mod, PrePurge, PostPurge}}
Mod = atom()
PrePurge = PostPurge = soft_purge | brutal_purge
Before this instruction occurs, Mod must have been loaded
using load_object_code. This instruction loads the module.
PrePurge is ignored. See the high-level instruction
update for a description of PostPurge.
{remove, {Mod, PrePurge, PostPurge}}
Mod = atom()
PrePurge = PostPurge = soft_purge | brutal_purge
Makes the current version of Mod old.
PrePurge is ignored. See the high-level instruction
update for a description of PostPurge.
{purge, [Mod]}
Mod = atom()
Purges each module Mod, that is removes the old code.
Note that any process executing purged code is killed.
{suspend, [Mod | {Mod, Timeout}]}
Mod = atom()
Timeout = int()>0 | default | infinity
Tries to suspend all processes using a module Mod. If a
process does not respond, it is ignored. This may cause
the process to die, either because it crashes when it
spontaneously switches to new code, or as a result of a purge
operation. If no Timeout is specified or default is
given, the default value for sys:suspend is used.
{resume, [Mod]}
Mod = atom()
Resumes all suspended processes using a module Mod.
{code_change, [{Mod, Extra}]}
{code_change, Mode, [{Mod, Extra}]}
Mod = atom()
Mode = up | down
Extra = term()
Mode defaults to up and specifies if it is an
upgrade or downgrade.
This instruction sends a code_change system message to
all processes using a module Mod by calling the function
sys:change_code, passing the term Extra as argument.
{stop, [Mod]}
Mod = atom()
Stops all processes using a module Mod by calling
supervisor:terminate_child/2. The instruction is useful
when the simplest way to change code is to stop and restart the
processes which run the code.
{start, [Mod]}
Mod = atom()
Starts all stopped processes using a module Mod by calling
supervisor:restart_child/2.
{sync_nodes, Id, [Node]}
{sync_nodes, Id, {M, F, A}}
Id = term()
Node = node()
M = F = atom()
A = [term()]
apply(M, F, A) must return a list of nodes.
The instruction synchronizes the release installation with other
nodes. Each Node must evaluate this command, with the same
Id. The local node waits for all other nodes to evaluate
the instruction before execution continues. In case a node goes
down, it is considered to be an unrecoverable error, and
the local node is restarted from the old release. There is no
timeout for this instruction, which means that it may hang
forever.
{apply, {M, F, A}}
M = F = atom()
A = [term()]
Evaluates apply(M, F, A). If the instruction appears
before the point_of_no_return instruction, a failure is
caught. release_handler:install_release/1 then returns
{error,{'EXIT',Reason}}, unless {error,Error} is
thrown or returned. Then it returns {error,Error}.
If the instruction appears after the point_of_no_return
instruction, and the function call fails, the system is
restarted.
restart_new_emulator
This instruction is used when erts, kernel, stdlib or sasl is
upgraded. It shuts down the current emulator and starts a new
one. All processes are terminated gracefully, and the new
version of erts, kernel, stdlib and sasl are used when the
emulator restarts. Only one restart_new_emulator
instruction is allowed in the relup, and it shall be placed
first. systools:make_relup3,4
will ensure this when the relup is generated. The rest of the
relup script is executed after the restart as a part of the boot
script.
An info report will be written when the upgrade is
completed. To programatically find out if the upgrade is
complete,
call
release_handler:which_releases and check if the
expected release has status current.
The new release must still be made permanent after the upgrade
is completed. Otherwise, the old emulator is started in case of
an emulator restart.
restart_emulator
This instruction is similar to restart_new_emulator,
except it shall be placed at the end of the relup script. It is
not related to an upgrade of the emulator or the core
applications, but can be used by any application when a complete
reboot of the system is reqiured. When generating the
relup, systools:make_relup/3,4
ensures that there is only one restart_emulator
instruction and that it is the last instruction of the
relup.