% (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}

Section~\ref{low-level-distrib} described three C-Hermes functions
that could be used to provide interoperability among several Hermes
interpreters.  In this section we describe three corresponding Hermes
programs that make use of these facilities to provide an easy, flexible
mechanism for establishing interoperability.  The programs are
called {\tt startnet}, {\tt getlink}, and {\tt linkserver}.  Sources
for all can be found in the {\tt tools/distrib} directory.

Before describing these facilities it is necessary to come clean on
some information that was held back earlier in this User's Guide.

\subsection{The Truth About the {\tt Main} Interface, the {\tt Root}
Process, and the {\tt Cache}}

We said earlier that the {\tt root} process (the first process that's
spawned by the interpreter at startup) is responsible for running
whatever program is named on the command line, and that this program
must obey the {\tt main} interface.  This is not exactly correct.  In
truth, the {\tt root} process will run programs written to either of
two different interfaces.  {\tt Main} is one of them; the other is
{\tt sysMain}.  {\tt Main} and {\tt sysMain} differ primarily in that
the {\tt main} interface provides a filtered resource manager, while
{\tt sysMain} provides an unfiltered one.  The {\tt sysMain} interface
is thus suitable for programs like login shells that need to be able
to construct filtered resource managers.  The {\tt root} process knows
which interface to use by trial and error: after loading the named
program, it first tries to instantiate it as a {\tt main} process.  If
that results in an {\tt interfaceMismatch} exception, it tries again,
this time assuming {\tt sysMain}.  If that fails, {\tt root} gives up
and complains.

The {\tt cache} is really a {\tt sysMain} program, not a {\tt main}
program.  It operates by chaining the resource manager it gets on its
initialization call with a new resource manager that it creates.  The
cached versions of {\tt pathLoad}, etc. are posted to the new resource
manager, and it is the chained resource manager that is passed on to
the user program.  {\tt Cache}, like {\tt root}, is capable of running
both {\tt main} and {\tt sysMain} programs.  When it runs {\tt main}
programs, it uses the same code as {\tt root} to decide on the user
name for the filter, based on Unix environment variables.

Now here comes the tricky part: the {\tt root} process is capable of
running several commands on the same command line.  The individual
commands must be separated by semicolons, and the semicolons must be
separate ``words'' in the command line, i.e. they must be surrounded
by whitespace.\footnote{Be careful to quote the semicolons, e.g.
with backslashes, to prevent their being interpretered by your Unix
shell.} The commands are run in sequence, and a {\tt sysMain} program
is actually allowed to alter the resource manager that will be
provided to following commands.  This is achieved by making the {\tt
rm} component of the {\tt sysMain!sysMain} callmessage be non-constant
on the interface.  A {\tt sysMain} program is thus free to alter this
component of the callmessage before returning it.

The cache makes use of this facility.  Before returning its
callmessage, it replaces the incoming resource manager with the
chained resource manager that it created.  Thus the
commands {\tt hermes cache foo}, and {\tt hermes cache $\backslash$; foo}
should behave identically.

Note that the shell is a {\tt main} program and is only capable of
running {\tt main} programs.  The shell does not treat semicolons on
its command lines as command separators.
 
Now we can continue the discussion of the interoperability features.

\subsection{The {\tt StartNet} Program}

The {\tt startNet} program performs the {\tt "start network"} C-Hermes
function, initializing networking support and supplying an interpreter
number for the current interpreter.  {\tt StartNet} expects a single
command line argument, which should be an integer.  This is the number
it supplies as an interpreter number.  If the command line argument is
omitted, the default of 1 is used.


\subsection{The {\tt LinkServer} Program}

{\tt LinkServer} is a {\tt sysMain} program that allocates a port for
receiving linking calls from other interpreters, and performs the {\tt
"set linking port"} C-Hermes call to identify this port to the
interpreter.  It then spawns a process which accepts all future
requests made to this port.  Each request is returned carrying a copy
of the (unfiltered) resource manager that was provided to {\tt
linkServer} via the {\tt sysMain} interface.  The remote process that
made the linking request is thus able to retrieve any capabilities or
other resources that were posted to that resource manager.

\subsection{The {\tt GetLink} Program}

{\tt GetLink} is a {\tt sysMain} program that takes any number of
command line arguments.  Each argument should be of the form ``{\tt
{\em hostname}:{\em interp-no}}, where {\em hostname} and {\em
interp-no} identify a remote Hermes interpreter.  If the colon and
{\em interp-no} are omitted, the interpreter number defaults to 1.

{\tt GetLink} issues a {\tt "get link"} C-Hermes call in order to
establish interoperability with each of the identified remote
interpreters.  It calls each linking port and, assuming the remote
interpreters have run the {\tt linkServer} program, each remote
interpreter returns copy of its own local resource manager.  {\tt
GetLink} chains all these resource managers, together with the one it
received via its own initialization call on the {\tt sysMain}
interface, and replaces the resource manager from its initialization
call with the chained resource manager.  Subsequent programs invoked
from the same command line by {\tt root} will thus be able to retrieve
capabilities posted to the remote resource managers to which it has
linked.  

\subsubsection{An Example}

Here is the printer example that was described in
Section~\ref{low-level-distrib}, recast in terms of the programs shown
in this section.  Suppose that {\tt postPrinter} is a program that
simply posts a capability to a print spooler to what it believes is
its local resource manager.  And suppose that {\tt print} is a program
that retrieves a print spooler resource from what it believes is its
own local resource manager and then uses it to print a file.  We can
arrange for these two programs to run in separate machines and still
work without modification as follows:

\begin{enumerate}
\item On a machine called ``red,'' run the {\tt postPrinter} program
after running {\tt startNet} and {\tt linkServer} so other
interpreters can interoperate:

\begin{verbatim}
    hermes cache \; startnet 3 \; linkserver \; postprinter
\end{verbatim}

\item On a machine called ``blue,'' run the {\tt print} program after
first chaining onto red:3's resource manager:

\begin{verbatim}
    hermes cache \; startnet \; getlink red:3 \; print file.txt
\end{verbatim}

\end{enumerate}

Note that these facilities do not permit the construction of circular
resource manager chains; each {\tt getLink} operation can only chain
to resource managers that already exist.  It would be possible to
program arbitrary configurations using the C-Hermes functions
directly.
