The Transport
interface separates the main part of the network
object runtime system from the parts that deal with low-level
communication. It is the interface that must be implemented
to extend the system to use new communication protocols. The
interface is reasonably narrow:
INTERFACEThe main ideas in the interface were described in Section 1.5, page 15. To summarize these briefly:Transport ; IMPORT NetObj, NetObjNotifier, StubLib, StubConn, Thread; TYPE T <: Public; Public = OBJECT METHODS fromEndpoint(e: Endpoint): Location; toEndpoint(): Endpoint; serviceCall(t: StubLib.Conn): (*reUse*) BOOLEAN RAISES {Thread.Alerted}; END; Location <: LocationP; LocationP = OBJECT METHODS new(): StubLib.Conn RAISES {NetObj.Error, Thread.Alerted}; free(c: StubLib.Conn; reUse: BOOLEAN); dead(st: NetObjNotifier.OwnerState); END; TYPE Endpoint = TEXT; REVEAL NetObj.Address = BRANDED REF ARRAY OF Endpoint; StubLib.Conn <: Conn; TYPE Conn = StubConn.Public BRANDED OBJECT loc: Location END; END Transport.
\begin{itemize}
\item A Transport.T
is an object that manages connections of some
particular class ({\it e.g.}, TCP).
\item A Transport.Location
is an object that creates connections of some
particular class to some particular address space.
\item A Transport.Endpoint
is a transport-specific name for an
address space ({\it e.g.}, an IP address plus a port number plus
a non-reusable process ID).
\item The fromEndpoint
method of a transport converts an endpoint into a
location, or into NIL
if the endpoint and transport are of different
classes.
\end{itemize}
\noindent
See Section 1.5 for an overall discussion of these concepts. Here
are specifications for the methods of a Transport.T
:
\begin{itemize}
\item The toEndpoint
method returns an endpoint for
the address space itself. The resulting endpoint should be
recognized by the fromEndpoint
method of transports of the same
class anywhere in the network. That is, if a program instance P
calls
tr1.toEndpoint()
, producing an endpoint ep
, then the call
tr.fromEndpoint(ep)
executed in any program instance either returns
NIL
(if tr
and tr1
are of different classes) or returns a location
that generates connections to P
.
\item Transports are required to provide the threads
that listen to the server
sides of connections. When a message arrives on the connection indicating
the beginning of a remote call, the threads are required to call the
serviceCall
method of their transport. The default value of this
method locates and calls the dispatcher procedure, as explained in
Section 1.5, page 18. Ordinarily a transport implementation will not need
to override this method. At the entry to tr.serviceCall(conn)
, conn.rd
is positioned at the start of the incoming message. The serviceCall
method processes the incoming remote invocation and sends the result
on conn.wr
. If it returns TRUE
, then the remote invocation was
processed without error and the transport can cache the connection. If
it returns FALSE
, a protocol error occurred during the call, and the
transport should destroy the connection.
\ttmindex{Transport.T}{serviceCall {\rm method}}
\end{itemize}
\noindent
And here are the specifications for the methods of a Transport.Location
:
\begin{itemize}
\item The new
method of a location returns a connection to the address
space for which it is a location. The call loc.new()
returns a
connection whose server side is that address space and whose client
side is the program instance making the call. By calling loc.new
,
the program acquires the obligation to pass the resulting connection to
loc.free
when it is finished with it.
\ttmindex{Transport.Location}{new {\rm method}}
\item The call loc.free(c, reUse)
frees the connection c
, which must
have been generated by loc.new()
. If reUse
is TRUE
, the client
asserts that the connection is in a suitable state for executing another
remote method call. In particular, c.wr
must be positioned at the
beginning of a message.
\ttmindex{Transport.Location}{free {\rm method}}
\item A transport is responsible for monitoring the liveness of program
instances for which it has locations or connections. The method of
monitoring depends on the transport. For example, the transport might
periodically ping the other program instance. A program is considered dead
if it exits, crashes, or if the underlying communication network cannot
reach it for an appreciable amount of time. Suppose that loc
is a
location that generates connections to some program instance P
.
If P
dies, the transport that provided loc
is responsible
for calling the method loc.dead(st)
. (The network object runtime
implements this method; the transport should not override it.)
The argument st
indicates whether the transport has detected
a permanent failure, or one that is potentially transient. In addition
to calling loc.dead
, the transport is responsible for alerting all
threads it has spawned to handle method invocations on behalf of P
.
\ttmindex{Transport.Location}{dead {\rm method}}
\index{liveness}
\end{itemize}
\noindent A transport is expected to manage the connections it creates. If creating connections is expensive, then the transport's locations should cache them. If maintaining idle connections is expensive, then the transport's locations should free them. Often connections are time-consuming to create, but then tie up scarce kernel resources when idle. Therefore transports typically cache idle connections for a limited amount of time.
The Transport
interface reveals the representation of NetObj.Address
: an
address is simply an array of endpoints for the program
instance designated by the address. The endpoints are generally of
different transport classes; they provide alternative ways of communicating
with the program instance. The modules of the network object
runtime that require this revelation are exactly the modules that
import the transport interface, so this is a convenient place to put it.
\ttindex{NetObj.Address}
The Transport
interface also reveals more information about the type
StubLib.Conn
. If t
is a StubLib.Conn
, then t.loc
is a Location
that generates connections to the program instance at the other end of t
.
The connections generated by t.loc
connect the same pair of program
instances that t
connects, but if t
is a handle on the server side
of the connection, then the connections generated by t.loc
will reverse
the direction of t
: their client side will be t
's server side, and
vice versa (so-called back connections). On the other hand, if t
is
a handle on the client side of the connection, then the connections
generated by t.loc
will be in the same direction as t
.
\ttindex{StubLib.Conn} A transport must ensure that the loc
field is defined in all connections returned by any of its locations.
\index{back connections}