Skip to content
flambard edited this page Jul 17, 2011 · 8 revisions

To make sense of CLERIC, one needs to know a bit about the Erlang distribution mechanism.

Query the EPMD to find another node

On every machine that runs at least one Erlang node, EPMD (Erlang Port Mapper Daemon) is running.

A node that wants to connect to another node on another machine begins by asking the EPMD on that machine if there is such a node. If the node exists, EPMD responds with a port number along with some other useful information about the node. With the port number in hand, our node can connect to the other node!

In CLERIC, the EPMD is queried with cleric-epmd:lookup-node like this:

(cleric-epmd:lookup-node "jaheira" "amn")
=> #<COMMON-LISP-ERLANG-INTERFACE:REMOTE-NODE (ERLANG) jaheira@amn [49246]>

Here we query the EPMD on host "amn" about a node called "jaheira". The EPMD responds and we get a remote-node object.

The remote-node object tells us

  1. that the node is a real Erlang node (the "(ERLANG)" part.)
  2. the node name is "jaheira@amn".
  3. it's listening on port 49246.

Connect using the magic cookie

With the node name and the port number we are ready to connect to the other node, but there is one more thing. To be allowed to connect we must know the other node's magic cookie.

Retrieve an Erlang node's magic cookie by calling erlang:get_cookie().

In CLERIC, we connect to a node with cleric:remote-node-connect like this:

(cleric:remote-node-connect node "DIMGQDIGZLSUOVKNRTHG")
FULL-NODE-NAME: jaheira@amn, VERSION: 5, FLAGS: 111111111111100
=> T

where node is a variable holding the remote node object and the string after it is the magic cookie.

We are connected!

Processes send and receive messages

In Erlang, processes send messages to each other. A process is identified with a pid.

That means if we want to send a message to another node using CLERIC, there must exist a remote process to receive it and a local process to send it.

In CLERIC, we create pid objects with cleric:make-pid like this:

(cleric:make-pid)
=> #<COMMON-LISP-ERLANG-INTERFACE:ERLANG-PID lispnode@localhost <1.0>>

Now, let's assume that there is a registered process cleric_listener on node jaheira@amn, and send a message to it using cleric:reg-send:

(cleric:reg-send pid "cleric_listener" "jaheira" "Hello, Erlang world!")
=> NIL

where pid is a variable holding a pid object.

Heartbeats

Nodes send heartbeats to each other every once in a while. If a node does not respond to heartbeats it is considered dead and the connection is closed.

This means that when using CLERIC you have to devise your program to listen for incoming messages and heartbeats continuously to not lose the connection. Fortunately, heartbeats are handled automatically by CLERIC but one still needs to listen continuously for messages to keep the connection alive.

In CLERIC, we listen for messages with cleric:receive-node-messages like this:

(cleric:receive-node-messages)
=> (#<COMMON-LISP-ERLANG-INTERFACE:SEND #x89B4796>)

receive-node-messages returns a list of control messages. Here we received a single "send" control message.

There are different kinds of control messages, here are a couple:

  • SEND is a message from a remote process to a local process.
  • REG-SEND is a message from a remote process to a local process with a registered name.
  • LINK sets up a link between a remote process and a local process.
  • UNLINK removes a link between a remote process and a local process.
  • EXIT is an exit signal from a remote process to a local process.