CS223 Project 2
Due at the end of the quarter.

Description

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:
    1. Download the tarball from here
    2. 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.
    3. 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):

  1. On an ICS SUN machine, cd to your project/transaction directory.
  2. Make sure you "make clean" to get rid of all .class files.
  3. 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.
  4. Submit the zipped file to EEE.

Notes

  • 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".

Acknowledgements

This project is based on a similar course project developed by Anand Rajaraman at Stanford, which was based on a similar project developed by Phil Bernstein when he was teaching at the University of Washington.