In
this project, we will distribute the data tables among several RMs and
perform distributed transactions across them.
The WorkflowController (WC) will be a front-end
so that the eventual location (partitioning) of data on the RM's is not
exposed to the client. To do this, the WC will support the same interface as
the RM, and also the new function:
boolean reserveItinerary(int xid, String custName, List flightNumList,
String location, boolean needCar,
boolean needRoom);
This itinerary reservation is the sort of high-level operation associated
with a workflow controller. The parameters are: xid
(transaction id), custName (name of customer), flightNumList (a List such a Vector of String flight
numbers), location (the place where a room or car might be reserved), and needCar/needRoom (true if the
customer wants a car/room reservation).
The TransactionManager supports mainly the
following operations: start, commit, abort, enlist.
The transaction manager is present to coordinate the distributed transactions
taking place across the several RMs involved. The interface of the TM is to
be used as follows: whenever a request is made to an RM, it calls the TM's
enlist method to tell the TM that it is involved in a transaction. The TM
then keeps track of which RMs are involved in which transactions. The WC
forwards a start/commit/abort call by the client directly to the TM. All
other calls by the client are forwarded to the appropriate RM.
Since the TM and the RMs exist behind the WC interface, their interfaces
don't have functions directly accesible to the
client. On startup, the RMs will obtain a reference to the TM (through a RMI
"Naming.lookup"). The WC connects to both
TM and all the RMs on startup. After a RM enlists with a TM, the TM will also
have a reference to that RM.
Here's a list of suggested steps to tackle Project 2:
- Step 1. Setup:
- Download the tarball from here
- Install the tarball and compile as in Project 1. The code
structure is very similar to Project 1. Don't forget to change RMIREGPORT in the Makefile.
- To run the system,
start the components under the project/transaction directory in the
following order (you'll need to open a few shell windows, or run some
of the processes in the background):
make runregistry
&
make runtm &
make runrmflights &
make runrmrooms &
make runrmcars &
make runrmcustomers &
make runwc &
make runclient &
- Step 2. Integrate your RM
code from Project 1 into the ResourceManager.java here. You should be
able to reuse a lot of your code from Project 1. Then modify the WC to
forward all calls to one specific RM.
- Step 3. Run multiple RMs. Separate flights, cars, rooms and
customers/reservations data each into one RM. The TM will maintain a
list for each active transaction of, which RMs are involved. The WC will
decide which data requests / transactions go where. On a commit/abort
request (which is forwarded to the TM), the TM calls the appropriate
functions on all RMs involved in the transaction.
- Step 4. Implement two phase
commit. At this stage, code the basics of two phase commit without
worrying about failures. That is, don't worry yet about when things need
to be written to disk.
- Step 5. Now worry about what
happens on failure. In particular, handle cases where components die in
the middle of commit. For example, make sure that a RM can recover if it
died before knowing the outcome of the transaction.
At this point, you will have a fully functioning distributed travel
reservation application.
Testing Scripts
We
have provided a package to help you design and test
your code. It uses a similar structure as project 1. Follow the instructions
in the "README.txt" file to run the code.
How to Submit
Make
sure:
- You have not modified
WorkflowController.java or the LockManager
code.
- All your code is
confined to the project/transaction directory (and
possible subdirectories).
- Your server puts all
files in a directory called data. If the directory
does not already exist, your server creates it.
- You have setup your
java environment properly.
- In project/transaction, after a "make
clean", your server compiles without errors with "make server".
- You can compile
Client.java with "make client".
- You can start
components of the system with the commands given in the original Makefile distributed to you. For example
java -classpath .. -DrmiPort=1234 -DrmiName=RMFlights -Djava.security.policy=./security-policy
transaction.ResourceManagerImpl
starts the RM for flights, where 1234 is the port of the running rmiregistry.
- You create a file
named README. Use the same
requirements of the file as project 1.
Steps
to submit assuming an ICS Unix environment (similar commands should be run in
a different environment):
- On an ICS SUN machine,
cd to your project/transaction directory.
- Make sure you
"make clean" to get rid of all .class files.
- tar cvf - * | gzip > ../cs223-project2.tar.gz (for project 2) which
will tar all the files under the current directory (including
subdirectories) into a tar file, then compress it into a zipped file.
- Submit the zipped file
to EEE.
|
- Put all files that
your RM creates (database files, master pointer files, transaction
lists...) in a directory called "data" in the
project/transaction/ directory. This way one can simply do a "rm -rf data" to remove the entire database state.
When your RM starts up, it will 1)check if "data" directory
exists; if not, create one; 2) check if the relevant files are there; if
not, create an empty database; if yes, try to "recover" from
those files.
- Let's assume that we
do not expect more than one transaction to frequently be working on reversations for the same customer at the same time.
So, assuming you take our suggestion and merge the RESERVATIONS table
with the CUSTOMERS table, it will be acceptable if, instead of locking
individual reservation rows, you decide to lock the entire customer row.
However, again, it is never acceptable to do table-level locking.
- The "make runserver" command
attempts to start the rmiregistry at your
unique port number. However, if you already have a previous instance of
your rmiregistry running, you'll get a
"...Port already in use..." exception. This is not a problem
since the server (RM) should still work. Or, you can always use "ps -ef|grep $USER|grep rmiregistry" to find your
old rmiregistry and kill it. For Project 2,
this is no longer an issue because the registry is started explicitly
with "make runregistry".
|