\documentstyle{article}
\title{\Large\sf RIDL\\ \small\sf Remote Invocation Description Language}
\author{Johan Ovlinger \\ \small Based on work by \\ Crista Lopes}

\setlength{\textwidth}{6.5 in}
\setlength{\oddsidemargin}{0.0 in}
\setlength{\evensidemargin}{0.0 in}
\setlength{\textheight}{9.0 in}
\setlength{\topmargin}{-0.5 in}


\begin{document}
\maketitle

\def\ridl{{\sf RIDL}}

\section{Intro}

\ridl\ is DemeterJ's aspect language for remote invocation. 
Basically, it is a wrapper around java's RMI.
This in itself is reason enough to use it; it allows the user to access remote objects and operations in a transparent manner. 
Furthermore, it allows the user to specify how arguments and results are to be passed; by copy (full or partial) or by reference. 

\ridl\ offers nothing that cannot be achieved using RMI, but the same can be said about assembly langauge. 
\ridl 's main selling point is that it separates out the remote aspect of an application to a separate specification; the behavioral part of the application is the same\footnote{Object instantiation is slightly different, but only a little bit. It's still better than RMI.} for both a remote or local application. 
RMI requires a significant reworking of the application when moving to a remote setting. 

\subsection{A small example}

I always find it easier to learn a new concept with a simple example to illustrate. 
So here, even before I've defined the terms necessary to describe it, is a small local application, written in the std DemeterJ behavior style. 

\begin{small}
\noindent
\begin{tabular}{ll}
\hline 
\multicolumn{2}{c}{\tt THE BEHAVIOR}  \\
\hline \\
\begin{minipage}{2.8in}
\begin{verbatim}
Counter {
 (@
  private IntHolder counter;
  @)
  public void reset(IntHolder i ) (@
    System.err.println("reset "+i.toString());
    counter = i;
  @)
  public IntHolder get_next() (@
    System.err.println("++"+counter.get_val());
    counter.set_val(counter.get_val()+1);
    return  new IntHolder(counter.get_val());
  @)
}
IntHolder { 
  public String toString() (@ 
   return "IntHolder "+get_val(); 
  @)
}
\end{verbatim}
\end{minipage}
&
\begin{minipage}{3in}
\begin{verbatim}
User {
  public static void main(String[] args) (@
    String host = "local" ;

    // ifndef RIDL
    Counter c1 = new Counter(); 
    // else
    /*
    host = args[0];
    int port    = Integer.parseInt(args[1]);
    Counter c1 = (Counter) Counter.remotenew(host,port);
    */
    // endif
    c1.reset(new IntHolder(10));
    for (int i =0;i<10;i++) {
      IntHolder i1 = c1.get_next();
      System.err.println(host1+" "+i1.get_val());
    }
  @)
}

\end{verbatim}
\end{minipage}
\end{tabular}

The application is a really simple one; a counter is created. 
It is incremented a number of times. Wow. 
The version shown is a simple vanilla java program. 
You can find the above code in {\tt demeterj/src/ridler/test}, if you don't want to type it in (actually, the code in that directory is slightly more complicated, as I used it to test \ridl's interaction with inheritance). 

Now our evil boss comes in and says that all design criteria have changed! 
Now the counter object should reside on another machine. 
All our work is for naught! 
Ha ha ha!

As the heroes of this little fable, we of course get the last laugh. 
Armed with our magical \ridl er capabilities, we quickly cobble up a \ridl\ description file, and make a few minor changes to the application (shown in the {\tt ifndef} comments), and our counter works on remote machines too.

\begin{tabular}{l|l}
\hline 
{\tt THE CD FILE } & {\tt THE RIDL FILE } \\
\hline \\

\begin{minipage}{3in}
\begin{verbatim}
*noparse*
User = .
*public* Counter = .
IntHolder = <val> int.
\end{verbatim}
\end{minipage}
 
&

\begin{minipage}{3in}
\begin{verbatim}
portal Counter { 
  public void reset(IntHolder i)
    i: copy ;
  public IntHolder get_next()
    return: gref;
}
portal IntHolder {
  public int get_val();
  public void set_val(int val);
}
\end{verbatim}
\end{minipage}
\end{tabular}
\end{small}


\subsection{Explanation}

The secret to our magical abilities is the \ridl er. 
It reads our specification and modifies the behavior and structural aspects (specified by {\tt *.beh} and {\tt *.cd} files, resp.).
Exactly how this is done not specified here. 
Crista Lopes's thesis covers these details. 

The program we wrote in response to the boss's requirements does the following: Like before, a {\tt User} object resides locally. 
It creates a remote instance of the {\tt Counter} on some other machine {\tt host}. 
This is now done using the remotenew functionality -- this requires that the remote machine is running a the RIDL\_RemoteInst service (see the instantiation section).

The ridl file specifies that we want to pass the argument to {\tt reset} by copy, but {\tt get\_next}\'s result by gref -- an RMI remote reference.

Because we've passed an {\tt IntHolder} by gref, we also need a portal for it, so that \ridl\ knows which methods to make remotely accessible. 
We don't need to specify a passing convention for its methods, as they only pass {\tt int}s, which can only be passed by copy. 

{\tt User} now resets the counter and gets the 10 next numbers, quite oblivious to the fact that the object is remote. 

Notice that unlike an RMI solution, we didn't need to change the code.  

\section{Reference manual}

Enough handholding. Here are the details.

\subsection{Gref or Copy}

An object can be either local or remote. 
\ridl\ deals with remote method invokation- or more accurately, invoking methods (and passing arguments and results) on remote objects.
Given a remote object to invoke methods on, we can either pass arguments to that method by copy or as a remote reference.

When something is passed by copy, a copy is made and reinstantiated on the remote machine. 
Java calls this serialization. 
\ridl\ allows the user to specify which part of the object needs to be copied (for some operations, perhaps we know that some part of the object will not be needed). 

A gref is a remote reference. 
Some objects require themselves to be unique (either they are too big to copy profusely, or they have semantic reasons to be unique). 
The main object resides on the remote machine, and only a proxy object exists locally. 
The proxy object forwards all method calls to the remote object. 


Grefs are fast to pass, but method invocation can be slow.
The tradeoff is that passing an object by copy can be slow, but once passed, invoking methods is fast. 

Primitive ({\tt int, boolean, short, ...}) values cannot be passed by gref. 

Interaction with classes that are external to the application is complicated; if the external class implements {\tt serializable}, it may be passed by full copy. 
If a class implements {\tt java.rmi.remote}, then it will be passed as a gref (but you have to pretend it is by copy), but any method calls on it that pass a non {\tt java.rmi.remote} class as an argument will fail. 
I recommend that the user stays away from {\tt java.rmi.remote} classes, as mixing two different disciplines of remote invokation is bound to cause trouble. 

\subsection{Portals}

A \ridl\ specification file is a sequence of portals.

A class needs a portal if it is to be passed as an argument to a remote object's method, or if it is to be a remote object itself. 
Only classes that are part of the application can have portals. 
F. ex, the class {\sf Integer} cannot be given a portal. 

\begin{verbatim}
Portal = "portal" ClassName [PortalBody]. }
PortalBody = "{" MethodList "}".
\end{verbatim}

In addition to just having a portal, a class can also have a portalbody. 
The portal body specifies which methods can be called on a remote (gref) object. 
The signature of each method that is to be callable needs to be listed in the portal body.

Optionally, we can specify how an argument or result is passed. 
The options are remote reference {\tt gref}, full copy {\tt copy}, or partial copy {\tt copy:} {\em traversal-name}. 
The traversal must be defined to accept a CopyVisitor as an argument. 
The object to be passed -- copy or original --is serialized using java.io.serializable.

Passing by gref, the object stays on the machine it currently resides on, and a pointer to it is passed. 
This is akin to java's {\tt RMI remote} objects.

The defaults are to pass by gref, except for primitive types, which must always be passed by copy.

\fbox{
\begin{minipage}{6in}
{\bf pitfall:}
Note that if we have an object that {\em is} a copy (full or partial) of some other object, we can pass it as a gref.
However, we cannot pass a gref object as a copy unless the traversal method's signature is included in the class's portal (and some similar methods on the CopyVisitor to return the result by copy).
We can never pass one by full copy. 

{\bf bug:} 
A method signature must be listed in the portal for the class where it is defined.
 If a method is inherited from a superclass, we must put the method spec on the portal for the class it is inherited from (which is perhaps not what we wanted- perhaps we don't want instances of the superclass to be remotable). 
Alternately we can create a method w/ that name and signature in this class, and have it delegate to super. 
Since the method now {\em is} defined locally, we can have a method portal. The bug is that this isn't done automatically (because it's a hassle to figure out where the method is defined).
Similar restrictions apply for abstract methods. 

{\bf bug:}
Calling non-remote methods on a remote objects will fail silently.
One unfortunate side-effect of weaving together many aspects is that it is almost impossible to statically destermine which methods will be visible on a given class. 
Thus, the \ridl er is unable to generate code to disable calling of non-remote methods (ie the methods on a class with a portal that do not have a method spec). 
\end{minipage}  
}

\subsection{Instatiation}

One of the more annoying aspects about using RMI is that object instatiation is very roundabout. 
To alleviate this, \ridl\ offers an object instantiation service. 

To use it, the \ridl\ remote instantiation server must be started on a remote machine.
{\em It needs to see in its {\tt CLASSPATH} all the classes it is to be able to instantiate}, and needs to be passed a port number to listen to. 
F.ex to start the naming server on port 1234, you could issue the command:

\mbox{{\tt > java RIDL\_Runtime.RIDL\_RemoteInst 1234}}

The class {\tt RIDL\_Runtime.RIDL\_RemoteInst} is included in {\tt rt.jar}. 

To then use this server (supposedly running on host {\tt ``bar''}) to instatitate an instance of class {\sf Foo}, one would say

\mbox{\tt Foo afoo = (Foo) Foo.remotenew("bar",1234); }

This was illustrated in the earlier example. {\tt afoo} is a gref (as it doesn't make sense to instantiate an object on a remote machine and return the result by copy), so {\sf Foo} needs to have a portal specification for this to work. 
Due to strange design decisions\footnote{Notably that methods cannot be overriden with a more precise return type, even though this is exactly what contravariance would suggest is possible.} in Java, we must cast the result to the proper type. 

\subsubsection{Naming}

\ridl\ also supports an RMI-like naming service (which is hinted at by the name {\tt RIDL\_Naming}). 
To create an object on a remote machine and bind it to the name {\tt ``erik''} ({\bf NB:} this operation returns void):

\mbox{\tt RIDL\_Runtime.RIDL\_Naming.remotenew("Foo","bar",1234,"erik"); }

We can now look up {\tt ``erik''} in that registry by saying:

\mbox{\tt Foo afoo = (Foo) RIDL\_Runtime.RIDL\_Naming.lookup("bar",1234,"erik"); }

\section{Turning it on}

\ridl\ is enabled by adding a {\tt RIDLFILES} entry to the project file of your application.
For example, if you have your portals in two files {\tt foo.ridl} and {\tt bar.ridl} you would add the line \mbox{\tt RIDLFILES = foo.ridl bar.ridl} to your project file.


\section{Troubleshooting}

\subsection{Solaris and Java2}

You're running into this error if at runtime your \ridl\ program complains about not being able to connect to localhost when you try to instantiate an object remotely. 

For some reason, sun's own programming language and sun's owwn operating system don't like each other. 
The problem is that RMI does stupid things when looking up the local hostname. 
The details aren't really relevant, but RMI sends the name of the local host along when invoking a method on a remote object. 
Solaris tells java that the current host is ``localhost'' with an IP of 127.0.0.1. 
While technically true, this isn't going to do much good on the remote host. 

This is a known bug with java (sun however thinks it's fixed...) {\tt http://developer.java.sun.com/developer/bugParade/bugs/4073539.html}. 

The RMI faq suggests that 

\begin{quote}
{\bf C.4 I am using the latest release of the JDK and I have a host that has multiple IP addresses. RMI is choosing the wrong IP address for its server hostname, how do I work around this problem? }

Set the java.rmi.server.hostname property to the correct IP address of the RMI
server machine. You can also specify that your server use a fully-qualified hostname obtained
from a name service by setting the property: 

    java.rmi.server.useLocalHostname=true
\end{quote}

so you would start your program (and also the remoteinst servers --  this is important) with the command line

{\tt java -Djava.rmi.server.useLocalHostname=true MainClass}

I haven't gotten that to work, but the following, even more brute force method does

{\tt java -Djava.rmi.server.hostname=foo.host.com MainClass}


\section{Links n stuff}

{\tt http://java.sun.com/people/linden/faq\_d.html\#Networking}\\
{\tt http://java.sun.com/products/jdk/1.2/docs/guide/rmi/faq.html}

\end{document}

