Assignment 3 (due Sunday, 13 August, 8 am)

 

In this assignment, you will implement a distributed shared memory system.  You will use the distributed semaphore system, created in assignment 2, to effect synchronization.  This assignment can be done either individually or in groups of two. Assignments submitted with more than two group members will not be accepted.  You are free to use any group’s code for assignment 2 for distributed semaphore system.

 

What to do?

 

This assignment will also consist of two parts.  In the first part, you will build a SharedMemory class that will serve as an object repository.  In the second part, you will build the DistributedSharedMemory class that will be a peer-to-peer server facilitating distributed shared memory.  The idea is to provide access to objects created by a program running on one machine to other programs running on same or other machines.  The objects would be accessed by means of a global identifier called objectid, which for our case will be a value of type int.

 

Part I:

In this part, you will develop an object repository called SharedMemory.  The shared memory will consist of a large byte array.  The shared memory will provide three operations namely write, read and destroy on the objects.  These operations can be defined as follows,

1.      boolean write(int objectid, Serializable object):  This method will convert the object into a byte array called object segment and will store this object segment in the shared memory.

2.      Object read(int objectid):  This method will locate the object segment corresponding to the objectid  in the shared memory, convert it into an object and return it (returns null if object not found).

3.      void destroy(int objectid):  This method will de-allocate the space for the object in the object segment and also free any associations for the objectid.

 

This part of the assignment will consist of two major tasks.

1.      Maintaining the association between the objectids and the corresponding object segments.  In the write operation, whenever an object is presented and no association can be found for its objectid, a new association should be created.

2.      Managing space in the shared memory.  You can use any of the algorithms discussed in class for allocating space to variable size segments or you can invent your own algorithm to allocate space to object segments.  Remember that the goal is to minimize fragmentation, at the same time maintaining efficient allocation and de-allocation.  Also remember that, in the case of the write operation, the size of the object could be different from its earlier size.  So, you may have to de-allocate and reallocate space for an object sometimes.  The write operation will return false if space could not be allocated to the object.

 

Part II:

In this part, you will develop peer-to-peer servers for the distributed shared memory system.  This server will be a class called DistributedSharedMemory.  Each server will communicate with all of its peers during the course of its existence.  For the sake of this assignment, let us number the servers 1, 2, 3, etc.  Also let us maintain a file called “config.txt”, to specify for each server the ip-address of its host and the port at which it is listening.  Then the distributed shared memory object can be initialized using a constructor defined as DistributedSharedMemory(int serverid).  This constructor would then read the file “config.txt”, to find out the port numbers and ip-addresses of its peers and itself.  It would then open a datagram socket to listen to messages on the specified port.

Each distributed shared memory server will have a shared memory object (defined in part I).  It will also export the same interface as the shared memory object, i.e., it will have the following public methods.

1.      boolean write(int objectid, Serializable object)

2.      Object read(int objectid)

3.      void destroy(int objectid)

 

These operations can be consistently handled in several ways.  One way to handle it is to make the read operation local.  A copy is maintained in the local shared memory for every shared object.  The write operation would then involve a local write operation on the shared memory object and a broadcast of the object segment and objectid to all the peers.  Each peer would then do a local write operation upon receiving this message.  In another way, the write operation would be local and the read operation would involve querying the peer servers to find out the location of the object segment and fetch it.  In this case, care should be taken so that whenever there is a write operation, the older copies are invalidated.   Yet another way of doing the same would involve associating an owner server with each objectid.  Then every write or read operation would involve a request to this owner server.  You are free to use any (including your own) consistent way of handling write and read.

 

Handling write and read operations would also involve synchronization.  Since many programs could be simultaneously accessing the same objects concurrent writes and reads to the same object have to be taken care of.  Concurrent reads would not pose any problems and hence can be permitted.  However, when a write operation is going on, no other program should be able to read or write that object until the current write operation is complete.  The destroy operation should not be effected until any pending read or write operation is over.  We expect you to use the distributed semaphore system implemented in the assignment 2 to achieve synchronization.      

 

How to test your program?

In order to test your distributed shared memory system you can implement any suitable application, which will need a distributed shared memory to run.  Remember that in our implementation, the distributed shared memory servers are not stand-alone programs but individual object existing as a part of a larger program but having a different thread of control.

 

How to convert objects into bytes and vice versa?

 

In order to convert an object into a byte array, the object must be made to implement the Serializable interface.  Any object implementing a serializable interface can be converted into a byte array using a ByteArrayOutputStream object and an ObjectOutputStream object.  Similarly, a byte array can be converted into the object it represents using a ByteArrayInputStream object and an ObjectInputStream object.  For more details on how to do this, see online java tutorial (replace the file input and output streams with the byte array input and output streams).

 

 

What to submit?

           

You should submit the following things as a part of this assignment.

1.        The java programs used to implement the distributed shared memory system.

2.        A file called README.txt where you give a tutorial on how to compile and run your programs.  This file should also contain the names, netids and cornellids of all the individuals in the group.

3.        A file called LOGIC.txt, where you explain why you chose a particular algorithm to implement policies for handling segment space, read/write, and synchronization.

 

How will you be graded?

 

      The following will play a crucial role in your grades for this assignment.

1.        Correctness of the java programs written to implement the distributed shared memory.

2.        Choice of algorithms to implement various management policies (LOGIC.txt).

3.        Clarity of the java/C programs (comments!!!).

4.        Ease of using the README to test your programs and results.