aboutsummaryrefslogblamecommitdiffstats
path: root/system/doc/design_principles/applications.xml
blob: 121c0179c6b26e33d26e321108f530051ce507a1 (plain) (tree)
























































































































































































































































































































































































                                                                                                                                                                         
<?xml version="1.0" encoding="latin1" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">

<chapter>
  <header>
    <copyright>
      <year>1997</year><year>2009</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.
    
    </legalnotice>

    <title>Applications</title>
    <prepared></prepared>
    <docno></docno>
    <date></date>
    <rev></rev>
    <file>applications.xml</file>
  </header>
  <marker id="appl"></marker>
  <p>This chapter should be read in conjunction with <c>app(4)</c> and
    <c>application(3)</c>.</p>

  <section>
    <title>Application Concept</title>
    <p>When we have written code implementing some specific
      functionality, we might want to make the code into an
      <em>application</em>, that is a component that can be started and
      stopped as a unit, and which can be re-used in other systems as
      well.</p>
    <p>To do this, we create an
      <seealso marker="#callback_module">application callback module</seealso>, where we describe how the application should
      be started and stopped.</p>
    <p>Then, an <em>application specification</em> is needed, which is
      put in an <seealso marker="#appl_res_file">application resource file</seealso>. Among other things, we specify which
      modules the application consists of and the name of the callback
      module.</p>
    <p>If we use <c>systools</c>, the Erlang/OTP tools for packaging code
      (see <seealso marker="release_structure">Releases</seealso>),
      the code for each application is placed in a separate directory
      following a pre-defined <seealso marker="#app_dir">directory structure</seealso>.</p>
  </section>

  <section>
    <marker id="callback_module"></marker>
    <title>Application Callback Module</title>
    <p>How to start and stop the code for the application, i.e.
      the supervision tree, is described by two callback functions:</p>
    <code type="none">
start(StartType, StartArgs) -> {ok, Pid} | {ok, Pid, State}
stop(State)</code>
    <p><c>start</c> is called when starting the application and should
      create the supervision tree by starting the top supervisor.
      It is expected to return the pid of the top supervisor and an
      optional term <c>State</c>, which defaults to []. This term is
      passed as-is to <c>stop</c>.</p>
    <p><c>StartType</c> is usually the atom <c>normal</c>. It has other
      values only in the case of a takeover or failover, see
      <seealso marker="distributed_applications">Distributed Applications</seealso>. <c>StartArgs</c> is defined by the key
      <c>mod</c> in the <seealso marker="#appl_res_file">application resource file</seealso> file.</p>
    <p><c>stop/1</c> is called <em>after</em> the application has been
      stopped and should do any necessary cleaning up. Note that
      the actual stopping of the application, that is the shutdown of
      the supervision tree, is handled automatically as described in
      <seealso marker="#stopping">Starting and Stopping Applications</seealso>.</p>
    <marker id="ch_app"></marker>
    <p>Example of an application callback module for packaging
      the supervision tree from
      the <seealso marker="sup_princ#ex">Supervisor</seealso> chapter:</p>
    <code type="none">
-module(ch_app).
-behaviour(application).

-export([start/2, stop/1]).

start(_Type, _Args) ->
    ch_sup:start_link().

stop(_State) ->
    ok.</code>
    <p>A library application, which can not be started or stopped,
      does not need any application callback module.</p>
  </section>

  <section>
    <marker id="appl_res_file"></marker>
    <title>Application Resource File</title>
    <p>To define an application, we create an <em>application specification</em> which is put in an <em>application resource file</em>, or in short <c>.app</c> file:</p>
    <code type="none">
{application, Application, [Opt1,...,OptN]}.</code>
    <p><c>Application</c>, an atom, is the name of the application.
      The file must be named <c>Application.app</c>.</p>
    <p>Each <c>Opt</c> is a tuple <c>{Key, Value}</c> which define a
      certain property of the application. All keys are optional.
      Default values are used for any omitted keys.</p>
    <p>The contents of a minimal <c>.app</c> file for a library
      application <c>libapp</c> looks like this:</p>
    <code type="none">
{application, libapp, []}.</code>
    <p>The contents of a minimal <c>.app</c> file <c>ch_app.app</c> for
      a supervision tree application like <c>ch_app</c> looks like this:</p>
    <code type="none">
{application, ch_app,
 [{mod, {ch_app,[]}}]}.</code>
    <p>The key <c>mod</c> defines the callback module and start
      argument of the application, in this case <c>ch_app</c> and
      [], respectively. This means that</p>
    <code type="none">
ch_app:start(normal, [])</code>
    <p>will be called when the application should be started and</p>
    <code type="none">
ch_app:stop([])</code>
    <p>will be called when the application has been stopped.</p>
    <p>When using <c>systools</c>, the Erlang/OTP tools for packaging
      code (see <seealso marker="release_structure">Releases</seealso>),
      the keys <c>description</c>, <c>vsn</c>, <c>modules</c>,
      <c>registered</c> and <c>applications</c> should also be
      specified:</p>
    <code type="none">
{application, ch_app,
 [{description, "Channel allocator"},
  {vsn, "1"},
  {modules, [ch_app, ch_sup, ch3]},
  {registered, [ch3]},
  {applications, [kernel, stdlib, sasl]},
  {mod, {ch_app,[]}}
 ]}.</code>
    <taglist>
      <tag><c>description</c></tag>
      <item>A short description, a string. Defaults to "".</item>
      <tag><c>vsn</c></tag>
      <item>Version number, a string. Defaults to "".</item>
      <tag><c>modules</c></tag>
      <item>All modules <em>introduced</em> by this application.
      <c>systools</c> uses this list when generating boot scripts and
       tar files. A module must be defined in one and only one
       application. Defaults to [].</item>
      <tag><c>registered</c></tag>
      <item>All names of registered processes in the application.
      <c>systools</c> uses this list to detect name clashes
       between applications. Defaults to [].</item>
      <tag><c>applications</c></tag>
      <item>All applications which must be started before this
       application is started. <c>systools</c> uses this list to
       generate correct boot scripts. Defaults to [], but note that
       all applications have dependencies to at least <c>kernel</c>
       and <c>stdlib</c>.</item>
    </taglist>
    <p>The syntax and contents of of the application resource file
      are described in detail in <c>app(4)</c>.</p>
  </section>

  <section>
    <marker id="app_dir"></marker>
    <title>Directory Structure</title>
    <p>When packaging code using <c>systools</c>, the code for each
      application is placed in a separate directory
      <c>lib/Application-Vsn</c>, where <c>Vsn</c> is the version number.</p>
    <p>This may be useful to know, even if <c>systools</c> is not used,
      since Erlang/OTP itself is packaged according to the OTP principles
      and thus comes with this directory structure. The code server
      (see <c>code(3)</c>) will automatically use code from
      the directory with the highest version number, if there are
      more than one version of an application present.</p>
    <p>The application directory structure can of course be used in
      the development environment as well. The version number may then
      be omitted from the name.</p>
    <p>The application directory have the following sub-directories:</p>
    <list type="bulleted">
      <item><c>src</c></item>
      <item><c>ebin</c></item>
      <item><c>priv</c></item>
      <item><c>include</c></item>
    </list>
    <taglist>
      <tag><c>src</c></tag>
      <item>Contains the Erlang source code.</item>
      <tag><c>ebin</c></tag>
      <item>Contains the Erlang object code, the <c>beam</c> files.
       The <c>.app</c> file is also placed here.</item>
      <tag><c>priv</c></tag>
      <item>Used for application specific files. For example, C
       executables are placed here. The function <c>code:priv_dir/1</c>
       should be used to access this directory.</item>
      <tag><c>include</c></tag>
      <item>Used for include files.</item>
    </taglist>
  </section>

  <section>
    <marker id="application_controller"></marker>
    <title>Application Controller</title>
    <p>When an Erlang runtime system is started, a number of processes
      are started as part of the Kernel application. One of these
      processes is the <em>application controller</em> process,
      registered as <c>application_controller</c>.</p>
    <p>All operations on applications are coordinated by the application
      controller. It is interfaced through the functions in
      the module <c>application</c>, see <c>application(3)</c>.
      In particular, applications can be loaded, unloaded, started and
      stopped.</p>
  </section>

  <section>
    <title>Loading and Unloading Applications</title>
    <p>Before an application can be started, it must be <em>loaded</em>.
      The application controller reads and stores the information from
      the <c>.app</c> file.</p>
    <pre>
1> <input>application:load(ch_app).</input>
ok
2> <input>application:loaded_applications().</input>
[{kernel,"ERTS  CXC 138 10","2.8.1.3"},
 {stdlib,"ERTS  CXC 138 10","1.11.4.3"},
 {ch_app,"Channel allocator","1"}]</pre>
    <p>An application that has been stopped, or has never been started,
      can be unloaded. The information about the application is
      erased from the internal database of the application controller.</p>
    <pre>
3> <input>application:unload(ch_app).</input>
ok
4> <input>application:loaded_applications().</input>
[{kernel,"ERTS  CXC 138 10","2.8.1.3"},
 {stdlib,"ERTS  CXC 138 10","1.11.4.3"}]</pre>
    <note>
      <p>Loading/unloading an application does not load/unload the code
        used by the application. Code loading is done the usual way.</p>
    </note>
  </section>

  <section>
    <marker id="stopping"></marker>
    <title>Starting and Stopping Applications</title>
    <p>An application is started by calling:</p>
    <pre>
5> <input>application:start(ch_app).</input>
ok
6> <input>application:which_applications().</input>
[{kernel,"ERTS  CXC 138 10","2.8.1.3"},
 {stdlib,"ERTS  CXC 138 10","1.11.4.3"},
 {ch_app,"Channel allocator","1"}]</pre>
    <p>If the application is not already loaded, the application
      controller will first load it using <c>application:load/1</c>. It
      will check the value of the <c>applications</c> key, to ensure
      that all applications that should be started before this
      application are running.</p>
    <marker id="application_master"></marker>
    <p>The application controller then creates an <em>application master</em> for the application. The application master is
      the group leader of all the processes in the application.
      The application master starts the application by calling
      the application callback function <c>start/2</c> in the module,
      and with the start argument, defined by the <c>mod</c> key in
      the <c>.app</c> file.</p>
    <p>An application is stopped, but not unloaded, by calling:</p>
    <pre>
7> <input>application:stop(ch_app).</input>
ok</pre>
    <p>The application master stops the application by telling the top
      supervisor to shutdown. The top supervisor tells all its child
      processes to shutdown etc. and the entire tree is terminated in
      reversed start order. The application master then calls
      the application callback function <c>stop/1</c> in the module
      defined by the <c>mod</c> key.</p>
  </section>

  <section>
    <title>Configuring an Application</title>
    <p>An application can be configured using <em>configuration parameters</em>. These are a list of <c>{Par, Val}</c> tuples
      specified by a key <c>env</c> in the <c>.app</c> file.</p>
    <code type="none">
{application, ch_app,
 [{description, "Channel allocator"},
  {vsn, "1"},
  {modules, [ch_app, ch_sup, ch3]},
  {registered, [ch3]},
  {applications, [kernel, stdlib, sasl]},
  {mod, {ch_app,[]}},
  {env, [{file, "/usr/local/log"}]}
 ]}.</code>
    <p><c>Par</c> should be an atom, <c>Val</c> is any term.
      The application can retrieve the value of a configuration
      parameter by calling <c>application:get_env(App, Par)</c> or a
      number of similar functions, see <c>application(3)</c>.</p>
    <p>Example:</p>
    <pre>
% <input>erl</input>
Erlang (BEAM) emulator version 5.2.3.6 [hipe] [threads:0]

Eshell V5.2.3.6  (abort with ^G)
1> <input>application:start(ch_app).</input>
ok
2> <input>application:get_env(ch_app, file).</input>
{ok,"/usr/local/log"}</pre>
    <p>The values in the <c>.app</c> file can be overridden by values
      in a <em>system configuration file</em>. This is a file which
      contains configuration parameters for relevant applications:</p>
    <code type="none">
[{Application1, [{Par11,Val11},...]},
 ...,
 {ApplicationN, [{ParN1,ValN1},...]}].</code>
    <p>The system configuration should be called <c>Name.config</c> and
      Erlang should be started with the command line argument
      <c>-config Name</c>. See <c>config(4)</c> for more information.</p>
    <p>Example: A file <c>test.config</c> is created with the following
      contents:</p>
    <code type="none">
[{ch_app, [{file, "testlog"}]}].</code>
    <p>The value of <c>file</c> will override the value of <c>file</c>
      as defined in the <c>.app</c> file:</p>
    <pre>
% <input>erl -config test</input>
Erlang (BEAM) emulator version 5.2.3.6 [hipe] [threads:0]

Eshell V5.2.3.6  (abort with ^G)
1> <input>application:start(ch_app).</input>
ok
2> <input>application:get_env(ch_app, file).</input>
{ok,"testlog"}</pre>
    <p>If
      <seealso marker="release_handling#sys">release handling</seealso>
      is used, exactly one system configuration file should be used and
      that file should be called <c>sys.config</c></p>
    <p>The values in the <c>.app</c> file, as well as the values in a
      system configuration file, can be overridden directly from
      the command line:</p>
    <pre>
% <input>erl -ApplName Par1 Val1 ... ParN ValN</input></pre>
    <p>Example:</p>
    <pre>
% <input>erl -ch_app file '"testlog"'</input>
Erlang (BEAM) emulator version 5.2.3.6 [hipe] [threads:0]

Eshell V5.2.3.6  (abort with ^G)
1> <input>application:start(ch_app).</input>
ok
2> <input>application:get_env(ch_app, file).</input>
{ok,"testlog"}</pre>
  </section>

  <section>
    <title>Application Start Types</title>
    <p>A <em>start type</em> is defined when starting the application:</p>
    <code type="none">
application:start(Application, Type)</code>
    <p><c>application:start(Application)</c> is the same as calling
      <c>application:start(Application, temporary)</c>. The type can
      also be <c>permanent</c> or <c>transient</c>:</p>
    <list type="bulleted">
      <item>If a permanent application terminates, all other
       applications and the runtime system are also terminated.</item>
      <item>If a transient application terminates with reason
      <c>normal</c>, this is reported but no other applications are
       terminated. If a transient application terminates abnormally,
       that is with any other reason than <c>normal</c>, all other
       applications and the runtime system are also terminated.</item>
      <item>If a temporary application terminates, this is reported but
       no other applications are terminated.</item>
    </list>
    <p>It is always possible to stop an application explicitly by
      calling <c>application:stop/1</c>. Regardless of the mode, no
      other applications will be affected.</p>
    <p>Note that transient mode is of little practical use, since when
      a supervision tree terminates, the reason is set to
      <c>shutdown</c>, not <c>normal</c>.</p>
  </section>
</chapter>