There are a whole lot of steps to writing a Java RMI program. It's easier than CORBA, but not to the same degree that Java Sockets are easier than C sockets.
package prog3;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface AllPairsInterface extends Remote {
String getHostName() throws RemoteException;
int[] getRow(int rowNumber) throws RemoteException;
void putRow(int rowNumber, int row[]) throws RemoteException;
}
You have to put everything in a package. I called mine prog3, and it
has to go in a directory named prog3, and you have to define CLASSPATH
to be the directory above prog3. Each method must throw
RemoteException.
package prog3;
import java.net.InetAddress;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
import java.rmi.server.UnicastRemoteObject;
public class AllPairsServer extends UnicastRemoteObject
implements AllPairsInterface {
private String machineName;
private int adjacency[][];
public AllPairsServer() throws RemoteException {
super();
}
public String getHostName() throws RemoteException {
return machineName;
}
public int[] getRow(int rowNumber) throws RemoteException {
return adjacency[rowNumber];
}
public synchronized void putRow(int rowNumber,
int row[]) throws RemoteException {
adjacency[rowNumber] = row;
}
public static void main(String args[]) {
String serverName;
// Create and install a security manager
if (System.getSecurityManager() == null) {
System.setSecurityManager(new RMISecurityManager());
}
try {
AllPairsServer server = new AllPairsServer();
// Bind this object instance to the name "HelloServer"
machineName = InetAddress.getLocalHost().getHostName();
serverName = "//" + machineName + ":" + portNumber + "/AllPairsServer";
Naming.rebind(serverName, server);
System.out.println("Server " + serverName + " bound in registry");
} catch (Exception e) {
System.out.println("Server initialization error: " + e.getMessage());
e.printStackTrace();
}
}
}
javac AllPairsInterface.java javac AllPairsServer.java rmic -d $HOME prog3.AllPairsServerFor no good reason, I set my CLASSPATH to be my home directory. My class files go in $HOME/prog3 (since prog3 is the package name). Note the rmic command requires the full package qualified name of the class, not the Java file.
unsetenv CLASSPATH
rmiregistry 4000&
setenv CLASSPATH /u/data03/ic0fram
java -Djava.rmi.server.codebase=file:///u/data03/ic0fram/ \
-Djava.rmi.server.hostname=$HOST \
prog3.AllPairsServer 4000
Of course, you need to adjust the CLASSPATH, portnum, and codebase parameters
for your own use. The books I've read all indicate using an http
codebase, but there aren't any http servers running on the SP2 nodes.
#!/bin/csh
unsetenv CLASSPATH
rmiregistry 4000&
setenv CLASSPATH /u/data03/ic0fram
java -Djava.rmi.server.codebase=file:///u/data03/ic0fram/ \
-Djava.rmi.server.hostname=$HOST \
prog3.AllPairsServer 4000
You can then use rsh to execute this on remote machines without
logging in to all of them.
rsh f01n09 /u/data03/ic0fram/remotestart
rsh f01n09 killallDo be good about this.
import java.io.*;
import java.rmi.Naming;
import prog3.AllPairsInterface;
class AllPairs {
private static int numberOfServers = 0;
private static int portNumber = 4000;
private static String machineNames[];
private static AllPairsInterface servers[];
public static void main(String args[]) {
String serverNames[] = new String[numberOfServers];
//----------
// connect to remote servers.
//----------
for (i = 0; i < numberOfServers; i++) {
serverNames[i] = "rmi://" + machineNames[i] + ":" + portNumber +
"/AllPairsServer";
System.out.println("Connecting to " + serverNames[i]);
try {
servers[i] = (AllPairsInterface)Naming.lookup(serverNames[i]);
System.out.println("Connected to " + servers[i].getHostName());
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
}
}
}
If you were asked this type of question on the final, you would only be required to write the monitor, not the threads or I/O.
| Error | Penalty |
|---|---|
| deadlock | 10 |
| fails to terminate (deadlock after 60 seconds) | 3 |
| neighbors eat simultaneously | 10 |
| one or more philsophers starve | 8 |
| no parallelism | 6 |
5 10 5 0 1 0 0 1 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 0 1 0
10 15 5 0 1 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 1 0
6 5 5 0 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 1 1 1 0
2 6
/ \ / \
0 1 3 5 7 - 9
\ / \ /
4 8
10 10 5
0 0 0 0 0 0 0 0 0 0
0 0 1 0 1 0 0 0 0 0
0 1 0 1 0 0 0 0 0 0
0 0 1 0 1 0 0 0 0 0
0 1 0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 0 1 0
0 0 0 0 0 1 0 1 0 0
0 0 0 0 0 0 1 0 1 1
0 0 0 0 0 1 0 1 0 0
0 0 0 0 0 0 0 1 0 0
6 5 10 0 1 1 0 1 0 1 0 1 1 0 1 1 1 0 1 1 0 0 1 1 0 1 0 1 0 1 1 0 1 0 1 0 0 1 0
These are some of the deductions I made
| Item | Deduction |
|---|---|
| compiler warnings | 2 |
| request forks one at a time | 5 |
| request forks over and over | 3 |
| modify shared variables in unsynchronized method | 5 |
| failed to define DIRTY, CLEAN or use an enum type | 2 |
| bad variable names | 1 |
| missing function/entity comments (the comments make it easy for me to find the methods) | 1 |