.TH appup 5 "sasl 4.1.1" "Ericsson AB" "Files" .SH NAME appup \- Application upgrade file .SH DESCRIPTION .LP The \fIapplication upgrade file\fR\& defines how an application is upgraded or downgraded in a running system\&. .LP This file is used by the functions in \fIsystools\fR\& when generating a release upgrade file \fIrelup\fR\&\&. .SH "FILE SYNTAX" .LP The application upgrade file is to be called \fIApplication\&.appup\fR\&, where \fIApplication\fR\& is the application name\&. The file is to be located in the \fIebin\fR\& directory for the application\&. .LP The \fI\&.appup\fR\& file contains one single Erlang term, which defines the instructions used to upgrade or downgrade the application\&. The file has the following syntax: .LP .nf {Vsn, [{UpFromVsn, Instructions}, ...], [{DownToVsn, Instructions}, ...]}. .fi .RS 2 .TP 2 .B \fIVsn = string()\fR\&: Current application version\&. .TP 2 .B \fIUpFromVsn = string() | binary()\fR\&: An earlier application version to upgrade from\&. If it is a string, it is interpreted as a specific version number\&. If it is a binary, it is interpreted as a regular expression that can match multiple version numbers\&. .TP 2 .B \fIDownToVsn = string() | binary()\fR\&: An earlier application version to downgrade to\&. If it is a string, it is interpreted as a specific version number\&. If it is a binary, it is interpreted as a regular expression that can match multiple version numbers\&. .TP 2 .B \fIInstructions\fR\&: A list of \fIrelease upgrade instructions\fR\&, see Release Upgrade Instructions\&. It is recommended to use high-level instructions only\&. These are automatically translated to low-level instructions by \fIsystools\fR\& when creating the \fIrelup\fR\& file\&. .RE .LP To avoid duplication of upgrade instructions, it is allowed to use regular expressions to specify \fIUpFromVsn\fR\& and \fIDownToVsn\fR\&\&. To be considered a regular expression, the version identifier must be specified as a binary\&. For example, the following match all versions \fI2\&.1\&.x\fR\&, where \fIx\fR\& is any number: .LP .nf <<"2\\\\.1\\\\.[0-9]+">> .fi .LP Notice that the regular expression must match the complete version string, so this example works for, for example, \fI2\&.1\&.1\fR\&, but not for \fI2\&.1\&.1\&.1\fR\&\&. .SH "RELEASE UPGRADE INSTRUCTIONS" .LP Release upgrade instructions are interpreted by the release handler when an upgrade or downgrade is made\&. For more information about release handling, see OTP Design Principles in \fISystem Documentation\fR\&\&. .LP A process is said to \fIuse\fR\& a module \fIMod\fR\& if \fIMod\fR\& is listed in the \fIModules\fR\& part of the child specification used to start the process, see \fIsupervisor(3)\fR\&\&. In the case of \fIgen_event\fR\&, an event manager process is said to use \fIMod\fR\& if \fIMod\fR\& is an installed event handler\&. .SS "High-Level Instructions" .LP .nf {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] .fi .LP Synchronized code replacement of processes using module \fIMod\fR\&\&. .LP All those processes are suspended using \fIsys:suspend\fR\&, the new module version is loaded, and then the processes are resumed using \fIsys:resume\fR\&\&. .RS 2 .TP 2 .B \fIChange\fR\&: Defaults to \fIsoft\fR\& and defines the type of code change\&. If it is set to \fI{advanced,Extra}\fR\&, implemented processes using \fIgen_server\fR\&, \fIgen_fsm\fR\&, \fIgen_statem\fR\&, or \fIgen_event\fR\& transform their internal state by calling the callback function \fIcode_change\fR\&\&. Special processes call the callback function \fIsystem_code_change/4\fR\&\&. In both cases, the term \fIExtra\fR\& is passed as an argument to the callback function\&. .TP 2 .B \fIPrePurge\fR\&: Defaults to \fIbrutal_purge\fR\&\&. It controls what action to take with processes executing old code before loading the new module version\&. If the value is \fIbrutal_purge\fR\&, the processes are killed\&. If the value is \fIsoft_purge\fR\&, \fIrelease_handler:install_release/1\fR\& returns \fI{error,{old_processes,Mod}}\fR\&\&. .TP 2 .B \fIPostPurge\fR\&: Defaults to \fIbrutal_purge\fR\&\&. It controls what action to take with processes that are executing old code when the new module version has been loaded\&. If the value is \fIbrutal_purge\fR\&, the code is purged when the release is made permanent and the processes are killed\&. If the value is \fIsoft_purge\fR\&, the release handler purges the old code when no remaining processes execute the code\&. .TP 2 .B \fIDepMods\fR\&: Defaults to \fI[]\fR\& and defines other modules that \fIMod\fR\& is dependent on\&. In the \fIrelup\fR\& file, instructions for suspending processes using \fIMod\fR\& come before instructions for suspending processes using modules in \fIDepMods\fR\& when upgrading, and conversely when downgrading\&. In case of circular dependencies, the order of the instructions in the \fIappup\fR\& file is kept\&. .TP 2 .B \fITimeout\fR\&: Defines the time-out when suspending processes\&. If no value or \fIdefault\fR\& is specified, the default value for \fIsys:suspend\fR\& is used\&. .TP 2 .B \fIModType\fR\&: Defaults to \fIdynamic\fR\&\&. It specifies if the code is "dynamic", that is, if a process using the module spontaneously switches to new code, or if it is "static"\&. When doing an advanced update and upgrade, 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\&. .RE .LP \fIupdate\fR\& with argument \fIsupervisor\fR\& is used when changing the start specification of a supervisor\&. .LP .nf {load_module, Mod} {load_module, Mod, DepMods} {load_module, Mod, PrePurge, PostPurge, DepMods} Mod = atom() PrePurge = PostPurge = soft_purge | brutal_purge DepMods = [Mod] .fi .LP Simple code replacement of the module \fIMod\fR\&\&. .LP For a description of \fIPrePurge\fR\& and \fIPostPurge\fR\&, see \fIupdate\fR\& above\&. .LP \fIDepMods\fR\& defaults to \fI[]\fR\& and defines which other modules \fIMod\fR\& is dependent on\&. In the \fIrelup\fR\& file, instructions for loading these modules come before the instruction for loading \fIMod\fR\& when upgrading, and conversely when downgrading\&. .LP .nf {add_module, Mod} {add_module, Mod, DepMods} Mod = atom() DepMods = [Mod] .fi .LP Loads a new module \fIMod\fR\&\&. .LP \fIDepMods\fR\& defaults to \fI[]\fR\& and defines which other modules \fIMod\fR\& is dependent on\&. In the \fIrelup\fR\& file, instructions related to these modules come before the instruction for loading \fIMod\fR\& when upgrading, and conversely when downgrading\&. .LP .nf {delete_module, Mod} {delete_module, Mod, DepMods} Mod = atom() .fi .LP Deletes a module \fIMod\fR\& using the low-level instructions \fIremove\fR\& and \fIpurge\fR\&\&. .LP \fIDepMods\fR\& defaults to \fI[]\fR\& and defines which other modules \fIMod\fR\& is dependent on\&. In the \fIrelup\fR\& file, instructions related to these modules come before the instruction for removing \fIMod\fR\& when upgrading, and conversely when downgrading\&. .LP .nf {add_application, Application} {add_application, Application, Type} Application = atom() Type = permanent | transient | temporary | load | none .fi .LP Adding an application means that the modules defined by the \fImodules\fR\& key in the \fI\&.app\fR\& file are loaded using \fIadd_module\fR\&\&. .LP \fIType\fR\& defaults to \fIpermanent\fR\& and specifies the start type of the application\&. If \fIType = permanent | transient | temporary\fR\&, the application is loaded and started in the corresponding way, see \fIapplication(3)\fR\&\&. If \fIType = load\fR\&, the application is only loaded\&. If \fIType = none\fR\&, the application is not loaded and not started, although the code for its modules is loaded\&. .LP .nf {remove_application, Application} Application = atom() .fi .LP Removing an application means that the application is stopped, the modules are unloaded using \fIdelete_module\fR\&, and then the application specification is unloaded from the application controller\&. .LP .nf {restart_application, Application} Application = atom() .fi .LP Restarting an application means that the application is stopped and then started again, similar to using the instructions \fIremove_application\fR\& and \fIadd_application\fR\& in sequence\&. Note that, even if the application has been started before the release upgrade is performed, \fIrestart_application\fR\& may only \fIload\fR\& it rather than \fIstart\fR\& it, depending on the application\&'s \fIstart type\fR\&: If \fIType = load\fR\&, the application is only loaded\&. If \fIType = none\fR\&, the application is not loaded and not started, although the code for its modules is loaded\&. .SS "Low-Level Instructions" .LP .nf {load_object_code, {App, Vsn, [Mod]}} App = Mod = atom() Vsn = string() .fi .LP Reads each \fIMod\fR\& from directory \fIApp-Vsn/ebin\fR\& as a binary\&. It does not load the modules\&. The instruction is to be placed first in the script to read all new code from the file to make the suspend-load-resume cycle less time-consuming\&. .LP .nf point_of_no_return .fi .LP If a crash occurs after this instruction, the system cannot recover and is restarted from the old release version\&. The instruction must only occur once in a script\&. It is to be placed after all \fIload_object_code\fR\& instructions\&. .LP .nf {load, {Mod, PrePurge, PostPurge}} Mod = atom() PrePurge = PostPurge = soft_purge | brutal_purge .fi .LP Before this instruction occurs, \fIMod\fR\& must have been loaded using \fIload_object_code\fR\&\&. This instruction loads the module\&. \fIPrePurge\fR\& is ignored\&. For a description of \fIPostPurge\fR\&, see the high-level instruction \fIupdate\fR\& earlier\&. .LP .nf {remove, {Mod, PrePurge, PostPurge}} Mod = atom() PrePurge = PostPurge = soft_purge | brutal_purge .fi .LP Makes the current version of \fIMod\fR\& old\&. \fIPrePurge\fR\& is ignored\&. For a description of \fIPostPurge\fR\&, see the high-level instruction \fIupdate\fR\& earlier\&. .LP .nf {purge, [Mod]} Mod = atom() .fi .LP Purges each module \fIMod\fR\&, that is, removes the old code\&. Notice that any process executing purged code is killed\&. .LP .nf {suspend, [Mod | {Mod, Timeout}]} Mod = atom() Timeout = int()>0 | default | infinity .fi .LP Tries to suspend all processes using a module \fIMod\fR\&\&. If a process does not respond, it is ignored\&. This can 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 \fITimeout\fR\& is specified or \fIdefault\fR\& is specified, the default value for \fIsys:suspend\fR\& is used\&. .LP .nf {resume, [Mod]} Mod = atom() .fi .LP Resumes all suspended processes using a module \fIMod\fR\&\&. .LP .nf {code_change, [{Mod, Extra}]} {code_change, Mode, [{Mod, Extra}]} Mod = atom() Mode = up | down Extra = term() .fi .LP \fIMode\fR\& defaults to \fIup\fR\& and specifies if it is an upgrade or downgrade\&. This instruction sends a \fIcode_change\fR\& system message to all processes using a module \fIMod\fR\& by calling function \fIsys:change_code\fR\&, passing term \fIExtra\fR\& as argument\&. .LP .nf {stop, [Mod]} Mod = atom() .fi .LP Stops all processes using a module \fIMod\fR\& by calling \fIsupervisor:terminate_child/2\fR\&\&. This instruction is useful when the simplest way to change code is to stop and restart the processes that run the code\&. .LP .nf {start, [Mod]} Mod = atom() .fi .LP Starts all stopped processes using a module \fIMod\fR\& by calling \fIsupervisor:restart_child/2\fR\&\&. .LP .nf {sync_nodes, Id, [Node]} {sync_nodes, Id, {M, F, A}} Id = term() Node = node() M = F = atom() A = [term()] .fi .LP \fIapply(M, F, A)\fR\& must return a list of nodes\&. .LP This instruction synchronizes the release installation with other nodes\&. Each \fINode\fR\& must evaluate this command with the same \fIId\fR\&\&. The local node waits for all other nodes to evaluate the instruction before execution continues\&. If 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 time-out for this instruction, which means that it can hang forever\&. .LP .nf {apply, {M, F, A}} M = F = atom() A = [term()] .fi .LP Evaluates \fIapply(M, F, A)\fR\&\&. .LP If the instruction appears before instruction \fIpoint_of_no_return\fR\&, a failure is caught\&. \fIrelease_handler:install_release/1\fR\& then returns \fI{error,{\&'EXIT\&',Reason}}\fR\&, unless \fI{error,Error}\fR\& is thrown or returned\&. Then it returns \fI{error,Error}\fR\&\&. .LP If the instruction appears after instruction \fIpoint_of_no_return\fR\& and the function call fails, the system is restarted\&. .LP .nf restart_new_emulator .fi .LP This instruction is used when the application 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 \fIrestart_new_emulator\fR\& instruction is allowed in the \fIrelup\fR\& file, and it must be placed first\&. \fIsystools:make_relup/3,4\fR\& ensures this when the \fIrelup\fR\& file is generated\&. The rest of the instructions in the \fIrelup\fR\& file is executed after the restart as a part of the boot script\&. .LP An info report is written when the upgrade is completed\&. To programmatically determine if the upgrade is complete, call \fIrelease_handler:which_releases/0,1\fR\& and check if the expected release has status \fIcurrent\fR\&\&. .LP The new release must still be made permanent after the upgrade is completed, otherwise the old emulator is started if there is an emulator restart\&. .LP .RS -4 .B Warning: .RE As stated earlier, instruction \fIrestart_new_emulator\fR\& causes the emulator to be restarted with new versions of ERTS>, Kernel, STDLIB, and SASL\&. However, all other applications do at startup run their old versions in this new emulator\&. This is usually no problem, but every now and then incompatible changes occur to the core applications, which can cause trouble in this setting\&. Such incompatible changes (when functions are removed) are normally preceded by a deprecation over two major releases\&. To ensure that your application is not crashed by an incompatible change, always remove any call to deprecated functions as soon as possible\&. .LP .nf restart_emulator .fi .LP This instruction is similar to \fIrestart_new_emulator\fR\&, except it must be placed at the end of the \fIrelup\fR\& file\&. 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 required\&. .LP When generating the \fIrelup\fR\& file, \fIsystools:make_relup/3,4\fR\& ensures that there is only one \fIrestart_emulator\fR\& instruction and that it is the last instruction in the \fIrelup\fR\& file\&. .SH "SEE ALSO" .LP \fIrelease_handler(3)\fR\&, \fIrelup(4)\fR\&, \fIsupervisor(3)\fR\&, \fIsystools(3)\fR\&