4 Distributed Erlang Programs
Erlang applications are often designed to run on distributed networks of processors. We use the term node to mean a complete self-contained Erlang system. In a distributed network one or more Erlang nodes may run on a signal computer.
In designing the language we were careful to avoid any primitives which would not map naturally onto a distributed model of computation. The only way of exchanging data between process is by message passing. All the primitives involving processes work transparently on a network of Erlang nodes.
Inter-processor communication makes use of a sophisticated caching technique [WIK94] which makes data transfer highly efficient. Indeed a cross-processor remote procedure call in Erlang is often more efficient than in a language such as C.
Recall that the primitive spawn creates a new parallel process. The new process is always creates on the current node. To create a parallel process on a different node the primitive Pid=spawn(N,Mod....) is used.
This creates a new parallel process on the Erlang node. This allows an Erlang process running on one Erlang node to create a parallel process on another node in the system. All operations on the new process behave in exactly the same way as if the process had beed created on the local node.
Recall that that register primitive created a global alias for a process identifier, the scope of this alias is the node on which the process was registered, so this name is not visible outside the node.
To send a message to a registered process on a different node the syntax {}! Msg is used. This sends Msg to the process named Atom on node.
To turn the bank client-server model from a single processor solution to a fully distributed program we made a single line change to the code in the bank_cilent module, changing the line.
where Host@Domain is the name of the node where the bank server is running.
Note that no data transfer languages are needed to describe the structure of the message which are sent between the different system. The set of messages to be sent does not need to be known in advance but is encoded at run-time. Problems of confusion between different byte orderings on different machines and different representations of data structures in memory are eliminated.
5. Error Handling in Erlang
Erlang has three different mechanism for trapping run-time errors, these can be used to:
-Monitor the evaluation of an expression
-monitor the behavior of a process
-raise an exception when an undefined function is called.
Suppose we evaluate N/M where M is equal to zero, this will cause a run-time error and the process in which this evaluation is performed will die.
We can detect this error in one of two ways. The first method makes use of the primitives catch and throw which are used for monitoring the evaluation of an expression.
The expression x=catch N/M evaluates to the tuple {} where what is an error descriptor in this case term:
catch can be though of as a meta-function which changes the normal evaluation model by converting errors into term which can be manipulated by the program.
If no error occurs then the result of evaluating catch Expr is the same as that of evaluating Expr.
The primitive throw (Expr) evaluates Expr which then becomes the return value of any enclosing catch.
Using catch and throw programs can be written to monitor and correct local errors within a process.
The second error handling mechanisms determines what happens when a process dies. Suppose some code evaluating in a process generates an error and that this error is not handled using the catch mechanism described above.
If the process Pid1 evaluates the expression link(Pid2) then a link is established between these two processes.
When any process dies it broadcasts a message containing information about why it died to all processes in the system to which it is linked. Thus if Pid1 dies, a message containing the reason for death is sent to the process Pid2. link is symmetric, so if Pid2 dies an error message will be sent to Pid1.
As an example, the function monitor( ) creates tow parallel processors. One of these processes evaluates the expression M:F(Args) the other monitors the process performing the evaluation dies, a new process is created by the monitoring process.
**
The primitive process_flag(trap_exist, true) allows the evaluating process to trap exit messages. spawn_link creates a new parallel process and links to it an atomic action.
The third error handling mechanism is used to trap errors occurring when undefined functions are called. If an attempt is made to evaluate M:F(Arge) and no code for the module M has been loaded into the system then the function undefined_function(M,F,Args) in the module error_handler is called
**
The point to note here is not this particular code but rather the fact that the user can program exactly what happens when a program tries to execute code that has not been loaded into the system.
Different types of system, for example, embedded systems, or, development systems need different types of code loading strategy. This above mechanism allows code loading strategies to be programmed by the user in Erlang itself.