% (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. 
\subsection{Resource manager}
\label{resource}
When you initialize a Hermes process by calling its initialization
port, you often pass some output ports to give the
new process initial access rights.  In some applications
the set of access rights may be very large, and in some
cases it may be open-ended --- that is, new services
may be added and you may wish to give the child
access to them without extending the parent-child interface
and recompiling both parent and child.

We address this problem by supplying a resource manager process.
The resource manager process owns a repository holding a dynamically
varying collection of access rights.  We provide services to
insert and remove access rights, and to retrieve a particular
access right.  Instead of passing a child process
a fixed set of bindings to services, the parent process can pass
a binding to the resource manager.  The child process
later requests particular ports from the resource manager,
and these ports will be delivered if they are in the repository
at the time of the request and
if the resource manager determines
that the caller has authority to obtain the ports.  Our approach is based on the
resource repository example in the Hermes Tutorial.

Since these access rights will in general have different types,
they are passed between applications and the resource
manager as values of type {\tt common!polymorph}.  The
application will have to {\tt wrap} values before sending
them to the resource manager, and to {\tt unwrap}
them after retrieving them.

Every resource in the resource manager is stored together with
three pieces of information: (1) a resource name,
(2) an ``owner name'' --- naming the individual who
inserted the resource into the repository, and (3)
an access function.  The access function takes a resource
from the repository, a requestor name, and a parameter,
and either returns a resource (which may or may not
be the one from the repository), or returns an
{\tt AccessDenied} exception.
The interfaces to the resource manager are defined
in {\tt sysrmanager.d}.

To post a resource, choose or write an access function.
(We supply a ``trivial'' access function {\tt ac\_none},
which gives everybody a copy of the resource.)
Wrap the resource (it usually is an output port
but need not be), and call either {\tt post} or {\tt insert},
passing the name of the resource and your name.
The difference between {\tt post} and {\tt insert}
is that {\tt post} saves a {\em copy} of the resource
in the repository (and will therefore fail if the resource
is uncopyable), whereas {\tt insert} {\em moves} the
resource into the repository.

To get a resource, call {\tt get} passing your name,
the resource name, and an additional string parameter which
may be used by the access function. Depending on the
access program, the caller of {\tt get} may receive
(1) a copy of the resource originally posted, (2) a different
resource, such as a port into a ``filter'', or (3)
an {\tt AccessDenied} exception.

To delete a resource, call {\tt remove} or {\tt delete}
passing your name and the resource name.  You must
be the owner to delete or remove a resource.  If you
{\tt remove} a resource, it is returned to you, whereas if
you {\tt delete} a resource, it is discarded.

To create a resource manager, instantiate the process
{\tt rmanager}.  The initialization call takes no input
parameters, and returns a {\tt sysRManager} record
containing ports corresponding to the operations
{\tt post}, {\tt insert}, {\tt get}, {\tt remove}, and {\tt delete}.

To build a system in which no client of the resource manager can cheat by using
someone else's name, you will typically create a filter for each user which automatically
supplies the user name. 
Users will then access the resource manager via the filtered interface, which has
one fewer parameter on each call.  It is defined in
{\tt rmanager.d}.

To create a ``personal'' resource manager which
uses the {\tt rmanager} rather than the {\tt sysRManager}
interface, instantiate the process {\tt personalrm}.
The initialization takes a string parameter representing
a user name, and returns a {\tt RManager} record.
If you already have access to a {\tt sysRManager}, and
wish to create a filter for a particular user to access
that resource manager using the {\tt rmanager} interface,
instantiate the process {\tt userrm}.  The initialization
takes a {\tt sysRManager} record and a user name, and
returns a {\tt RManager} record.

Resource managers can be ``chained together''.  That is,
you may create a resource manager which not only searches
the repository on a {\tt get} request, but also
searches a list of backup resource managers in case
a resource is not found locally.  
This gives you the ability to perform a directed
search for a resource.  To create such a
``chaining'' resource manager, instantiate the
process {\tt chainedsysrm} passing an ordered
list of {\tt sysRManager} records as an initialization parameter.
The first element of such a list is the resource manager
to which {\tt post}, {\tt insert}, {\tt delete},
and {\tt remove} are sent.  A {\tt get} request is
sent to each successive resource manager as long
as the resource is not found by all previous resource managers.
The process {\tt chainedrm} is just like {\tt chainedsysrm}
except that the {\tt rmanager} rather than the {\tt sysRManager}
interface is used.  The initialization interface
is in the module {\tt chainedrm.d}.
