% (C) Copyright International Business Machines Corporation 23 January 
% 1990.  All Rights Reserved. 
%  
% See the file USERAGREEMENT distributed with this software for full 
% terms and conditions of use. 
\section{Distributed Hermes} 
\label{distributed}

Distributed Hermes programs are constructed by establishing connections
between Hermes interpreters (running {\tt hermi} commands) on
different machines.
Currently any interpreters that can communicate via SUN rpc can
participate in a distributed Hermes system.
Both network communication {\em and} machine type (currently SUN 3,
SUN 4, Sparcstation or IBM PC RT)
are {\em completely invisible} to a distributed application
Once a Hermes connection between interpreters has been established
all communication over the connection ({\tt send}, {\tt call} and {\tt 
receive}) are invoked with 
{\em exactly} the same syntax and provide 
{\em exactly} the same semantics and 
as connections
between ports in two processes running together in a single interpreter.
A distributed 
connection is simply an outport owned by a process
running in one interpreter connected to an inport owned by a process running
in a different interpreter.


Below we discuss (1) establishing connections between processes
running in different interpreters and (2) additional high-level support for
Distributed Hermes, and (3) running an application demonstration, the
`appointment scheduler', distributively.


\subsubsection{Connecting Independent Hermes Interpreters}


Each interpreter is uniquely identified by the pair <{\em hostName},
{\em invocation id}> where {\em hostName} is
the name of its machine and {\em invocation id} is a positive
integer that must be unique for each interpreter running on a single host.

Assume that two Hermes interpreters (call them A and B) are running,
and a Hermes process in A wants to communicate with a process in B.
To set up connections between processes running on different interpreters
use the C-Hermes services {\tt start\_network}, {\tt set\_linking\_port}, 
and {\tt get\_link}.
Essentially, {\tt start\_network} initializes an interpreter's
network communications.
A process that wants to provide services to processes
in other interpreters makes itself available with {\tt set\_linking\_port}, 
and a process that wants to use the service calls {\tt get\_link}.

Interfaces for these services
are defined in definition module {\tt distributed.d}:
\begin{verbatim}
  -- "start network"
  startNetwork: callmessage (
    interpNo: integer		-- id for this interpreter on this machine
  )
  constant (interpNo)
  exit {full}
  exception failed {full};
  startNetworkQ: inport of startNetwork {full};
  startNetworkFn: outport of startNetworkQ;

  -- "set linking port"
  setLinkingPort: callmessage (
    outport: genericFn		-- generic outport
  )
  exit {}
  exception notDistributed {full}-- network not yet started
  exception alreadySet {full};	-- linking port may not be reset
  setLinkingPortQ: inport of setLinkingPort {full};
  setLinkingPortFn: outport of setLinkingPortQ;
  
  -- "get link"
  getLink: callmessage (
    hostName: charString,	-- name of target machine
    interpNo: integer,		-- id of target interpreter on that machine
    outport: genericFn		-- binding to remote node
  )
  constant (hostName, interpNo)
  exit {full}
  exception notDistributed {init(hostName), init(interpNo)};
  getLinkQ: inport of getLink {init(hostName), init(interpNo)};
  getLinkFn: outport of getLinkQ;

\end{verbatim}

You obtain capabilities for these C-Hermes services from the
CLoader (provided in the main interface, and by the rmain filter
program), under the names given below.\footnote{The names are exactly
as shown,including spaces.  So for example, a program invoked with the
{\tt main} interface might have something like the following:
$$\hbox{\tt startNetwork <- args.cloader("start network");}$$} 

The services are:

\begin{itemize}

\item {\tt start\_network(invocation\_id)} initializes an interpreter's
distributed
services.  It may be called at most once per interpreter; additional
calls return either a {\tt Disconnected} or a {\tt Discarded} exception.
Any Hermes process running in the interpreter may
invoke the call. {\tt start\_network} provides the invocation id that
identifies this interpreter.  Its cloader name is {\tt "start network"}.

\item {\tt set\_linking\_port( output\_port )} gives the interpreter running
the process that calls it an
output port which can later be passed to processes in other interpreters.
{\tt set\_linking\_port( output\_port )} expects {\tt output\_port} to have
type {\tt Distributed!GenericFn}.

Suppose you want process P in interpreter I to provide a service to
processes in other interpreters.
P simply {\tt connect}s output port OP to the inport IP that provides this
service, wraps OP as a {\tt Distributed!GenericFn} polymorph,
and then calls {\tt set\_linking\_port( OP )}.
{\tt set\_linking\_port( OP )} stores OP in interpreter I's 
{\em linking port} so that processes
in other interpreters can request a copy of OP with the call
{\tt get\_link()}.

{\tt set\_linking\_port}'s cloader name is {\tt "set linking port"}.

\item {\tt get\_link(hostName, invocation id, outport} returns a capability to a
service in the identified interpreter.

The {\tt hostName, invocation id} pair should identify a running interpreter.
If {\tt set\_linking\_port} has been invoked on that interpreter then
{\tt get\_link} returns a copy of the interpreter's linking port in 
{\tt outport}.
\end{itemize}

The result of these calls are illustrated in figure \ref{DistributedHermes}.
A process in interpreter A running on host foo has invoked
{\tt start\_network(3)} and a process
in interpreter B running on host bar has invoked
{\tt start\_network(2)}.
Process P in interpreter B then called {\tt set\_linking\_port( outport )}
to establish bar 2's linking port.
Process Q in interpreter A then called {\tt get\_link( "bar", 2, outport )},
which lead interpreter A to find interpreter B on host bar    
and return a copy of the outport passed by P in the 
{\tt set\_linking\_port( )} call.
A connection between Q and P has been established;
Q can now {\tt call outport( ... )} as it would any other output port and
P can receive messages
from the connected inport as it would any other input port.

Note that these calls can also be used to establish connections between
interpreters running on the same host.

\begin{figure}
\input dist_fig
\caption{A Distributed Hermes System}
\label{DistributedHermes}
\end{figure}
