COP5615 Operating System Principles
Spring 2001
Project 3
Date Assigned: March 13, 2001
Date Due: March 27, 2001, 11:59pm
(FEEDS Date Due: April 3, 2001, 11:59pm)
Before getting started, please read this document thoroughly and carefully.
In this project we will be simulating our dining philospher
system, like we did in project 2. But this time we will use Java
Remote Method Invocation (RMI) instead of sockets. We
will use the same solution to the dining philosopher problem.
Hence we will be developing another distributed Client/Server
version of this solution, this time using a service-oriented
request/reply scheme. We will see how communication transparency
is achieved by RMI and how it is possible to develop elegant
distributed programs. Since we already implemented this solution
in previous projects, you will not need to write new code except
a few lines for RMI implementation.
What is RMI?
Remote Method Invocation can be considered as the Java counterpart of Remote Procedure Call (RPC). As in RPC, we make procedure calls (using Java terminology method invocations or calls) without even worrying about whether the method under conideration is a local or a remote one. Therefore our remote method calls will not be any different from local methods implemented and resides on the same machine. (see pg.113 of textbook if you need to review RPC)
As it can easily be guessed, using RMI we deal with objects distributed over several hosts on the Internet. The client objects are not actually different from regular clients which are created from ordinary classes as the ones we used for project 2. The interesting objects are at the server side and these objects (created using classes designed for this purpose) include methods that work on them not only for making local calls as in the conventional programming but also for remote calls over the Internet from remote hosts. The important point here is that these objects must make any methods publicly available if these method are subject to be invoked remotely. The way to achieve this is to develop interfaces and classes from which the objects are created. These publicly available remote methods are not actually any different from regular Java methods we use for conventional programming. What we need to do is to define an interface which includes signatures of those methods that is to be available to the remote processes over the network. The details for doing this is explained in the next section.
To implement and run a distributed system based on RMI, we
need nothing more than a JAVA SDK and Java Virtual Machines
running on all the hosts we want to
deploy our system. Hence we have all the tools and machines
needed in CISE network as part of the Internet.
RMI Implementation Details
RMI Registry
RMI registry is a Naming Service that acts like a broker. RMI servers registers their objects with the RMI registry to make them publicly avaliable. RMI clients look up the registry to locate an object they are interested in and then obtain a reference to that object in order to use its remote methods. Of course, servers register only their remote objects, which have remote methods. Details using the registry is given in the next section.
The Remote Interface
As it is mentioned above, remote methods that will be available to clients over the network, should be declared. This is accoplished by defining a remote interface. This interface must extend java.rmi.Remote class and must be defined as public to make it accessible to clients. The body of this interface definition consists of only the declaration of remote methods. The declaration is nothing more than the signatures of methods namely method name, parameters and return type. Each method declaration must also declare java.rmi.RemoteException as the throws part.
necessary Java packages: java.rmi.Remote
Implementation of Remote Interface
After defining the remote interface, we need to implement this interface. Implementing the interface means writing the actual code that will form the bodies of our remote methods. For this purpose we define a class from which we create our remote objects that will serve the clients. This class must extend RemoteObject provided by the java.rmi.server package. There is also a subclass UnicastRemoteObject which is also provided by the same package that provide sufficient basic functionality for our purpose. When we call its constructor, necessary steps are taken for us so that we will not need to deal with them.
An RMI server registers its remote objects by using bind() or rebind() method of Naming class.
necessary Java packages: java.rmi.*, java.rmi.server.*
RMI Clients
RMI clients are mostly ordinary Java programs. Only difference is that they use the remote interface. As we now know remote interface declares the remote methods to be used. In addition, the clients need to obtain a reference to the remote object, which includes the methods declared in remote interface.
The clients obtain this reference by using lookup() method of Naming class.
necessary Java packages: java.rmi.*
Security Considerations
As all other distributed system mechanisms and implementations security is an important concern for RMI. Java uses security managers for providing security. But security managers are not a default part of applications. Therefore we need to specify our own security requirements by implementing our own security managers. RMI provides the RMISecurityManager class to install a security manager for an RMI server.
Although some resources indicate that using the
RMISecurityManager is a must, actually it may cause problems when
an attempt is made to connect to the registry.
Basically a security manager is desirable if a server needs to
download remote class files from other servers. These remote
class files may include malicious code that may attempt to access
local resources without having necessary authorization.
RMISecurityManager checks whether any class file has such
behavior and prohibits unathorized access.
Therefore you do not need to install the security manager. But if you use the RMISecurityManager succesfully and explain the details in your report you will earn bonus points.
Project Implementation Details
In this project we will use our solution to dining philosoper problem. Therefore we will use the same code we have written for project 2. But we do not need the code for sockets (since RMI takes care of all communication necessary, for us) and threads (since RMI also takes care of threads for us by creating threads necessary at the server). But we still need to provide synchronization necessary for our solution. Therefore all the code we have written for this purpose will be useful and can be reused.
RMI registry
RMI registry can be started on a Unix machine by typing:
rmiregistry 3000 &
3000 is the port number we want the registry to listen for connections from RMI servers and clients. This port number is optional and if not specified, registry is started on default port 1099. A host that provides continuous RMI support should use this port number for convenience and standardization. But you will specify your own port number by starting your own RMI registry.
Note that "&" is to run the registry as a background process.
Start the registry by using the command above (use a different port number), check it with ps command, test your programs and terminate it using kill.
Compiling programs
You need to compile your remote interface definition file first since the server and client programs need it to properly compile and run.
Then compile your server and client pograms as usual.
After succesfully compiling all the source code, you need to create the stubs needed. The stubs are similar to the RPC stubs and used for the same purpose. To create the stubs you need to use rmic compiler as below. (Note that server stub is called the skeleton in RMI terminology and rmic is similar to rpcgen of RPC)
rmic <class-name>
the class-name above is the name of the class from which we create instances of remote objects. Clearly it is the server side class. Since you compile first your source code as explained above, the .class file will be available to the rmic compiler at this point.
The output of rmic is two class files one for client stub and the other for server skeleton. For example if the name of our class for remote objects is DPImpl then we should have DPImpl.java as our source file and DPImpl.class as the class file for our remote object. We type
rmic DPImpl
and the output of this command is two files:
DPImpl_Skel.class // server skeleton
DPImpl_Stub.class // client stub
Note that it is necessary to put all files into same
directory. In general, an RMI server needs both stub and skeleton
classes as well as remote object class. The client needs to
access the stub only. For convenience we will put all classes
into the same directory and run all our programs from that
directory.
Program Specification
Three programs (hence three main() methods) are needed for this system. First one is to start our clients. This program will read the configuration file config and start the clients on remote machines as we did in project 2 using rsh.
Second one is the client program that will act as the philosopher. This program will accept necessary parameters as in project 2.
Third one is our table (the server). This is the program that
will provide the class for the remote object. Hence, the remote
methods will be implemented in this program.
We will not start this server from any other program as explained
below.
Running the System
We need to follow the steps below to run the system:
1- start rmiregistry as a background process as explained above. Specify an arbitrary port number that is large enough to avoid collisions with the well-known port numbers.
2- start the server as a background process by typing
java DPImpl <port-number> &
Here port-number MUST be the same as the one you specified while starting the rmiregistry. We start the server manually because we can test our system as many times as we want by starting clients on remote machines by different parameters (i.e. by changing the config file). This is actually more realisitc since servers are supposed to run forever. Of course, we will terminate the server after testing the system by using kill.
Use ps to make sure the server is running.
Note that the name of the class file we run MUST be DPImpl. By convention RMI servers has the suffix Impl and clients have App.
3- Start clients remotely by running the program
java Start
This program will start the clients by providing necessary parameters including the port number the RMI registry is listening on. The host name of the server should also be passed as the local host we work on.
Check the output of the clients and repeat this step as many times as you want to test your system.
4- Terminate both the rmiregistry and the server by
killing the processes using kill.
Note on Registering and Looking up Remote Objects
As we now know, the server needs to register its remote object to the RMI registry to make its own remote methods publicy available to the clients. In turn, clients need to look up the RMI registry to obtain a reference to that object and then to call its remote methods.
You must use your CISE login name as the name of the service
for registering the remote object to the registry. Similarly the
clients must look up the object by giving your CISE login name.
The reason for this restriction is to prevent possible name
collisions by making the names unique, since we will use the same
RMI registry to test all of the projects.
Format of the configuration file config
# THIS IS EXACTLY THE SAME
config WE USED BUT THE PORT NUMBER IS NOW
# THE PORT THAT THE rmiregistry IS LISTENING.
# This is a comment line and should be ignored.
# First line is the port number, on which the RMI REGISTRY is
listening.
3000
#Second line is the number of actions for all the clients.
5
# Remaining lines specify the clients as follows
# HOST CLIENT-NAME
sun114-11
#
sun114-11
#
sun114-11
#
sun114-22
#
sun114-33
Output
The server and the clients will produce the exact same outputs of project 2. So, you do not need to write new code for output. Use your existing code as much as possible. If your output in project 2 does not conform to the specification, see project 2 description and correct your output.
Requirements
Tips
Submission
Local Students:
You MUST use the turnin command to submit your files. A typical submission is as follows:
turnin -c cop5615sp01 -p proj3 <files>
Note: Submissions in any means except turnin will NOT be accepted!
FEEDS Students:
turnin -c cop5615sp01 -p FEEDSproj3 <files>
FEEDS students can e-mail their projects for convenience but this is not preferred unless there is difficulty in remote login.
LOCAL STUDENTS: Do NOT use this! This is reserved ONLY for FEEDS students.
*** Please note that turnin accepts wildcards in file names
like *.java.
Resources
Tutorial on Java RMI
http://java.sun.com/docs/books/tutorial/rmi/index.html