Lab 3 Details for MPCS 51050

Each lab will consist of a small problem and details of  how to proceed. You need to submit labs to the TAs for grading--see submission instructions below.  Generally, unless otherwise specified, you will have one week to complete each assigned lab.

See the syllabus for information on grading.  Turning in lab assignments is required.  Submit your assignments to the subversion repository according to the directions on the syllabus page.

All coding must be done in the Java Programming Language.

Lab 3   Due: 5:00 pm, Monday, April 15, 2024

Problem 1 (Message Queue): 

For this assignment you will implement a distributed message queue in your language of choice.  There are two kinds of messages that can be sent to the Queue:  a "QueryMsg" and a "ReplyMsg". A user should be able to add messages to the Queue or remove messages from the Queue (assume the queue is strictly FIFO).
What you need to implement:

1.  A class called MessageQueue that stores the messages it gets in a Vector (or similar class). The Vector class (already available in Java.util and the STL etc.) implements an array with dynamic size. The MessageQueue will need to implement methods to manipulate the queue (e.g. addMsg, popMsg, isEmpty etc.). 

2.  A base class called Message and subclasses : QueryMsg and ReplyMsg. 

There are several basic mechanisms for handling messages in queues.  One is to simply return the oldest message in the queue.  Say that two messages are sent to the queue (M1 and M2 in that order).  When a request is made to return a message from the queue (note that the request does not specify a particular message), a FIFO queue will always return the "first in", that is, M1.  The next request would return M2, and so on.

3.  You are to provide an ability to simply request from your message queue the "next" message from the queue.  The "next" message in a FIFO sense is the oldest message in the queue, in our example, M1.  One way to do this would be to implement a "getNextFIFOMessage()" method on your queue which would return M1, then M2, etc.  Whenever a message is retrieved from the queue, it is also removed from the queue.

Another basic mechanism for handling messages in queues is to be able to put a "request" on a queue, have a responder read that request (which will remove the request message from the queue), and then send a "reply" message to the queue, which is a reply to the specific message the responder retrieved from the queue.  Say for example we have a "translation" queue that takes in request messages that contain a word form of a number, such as the word "one" and we want a response message that converts that word "one" to its numeric representation, that is to say, we want a reply message sent to the queue that contains the number "1".  Let's also imagine that two additional messages have been put on the message queue as requests for translation, "two" and "three".

So how would we do that?  How would the responder communicate "this is a response to the request to transate the word "two" AND the numeric representation of the word "two" is "2"?  One way this is often solved (hint) is that the Message class contains both a "Header" that contains an identifier that uniquely identifies a particular message, and a "Body" (or "Payload") that contains the actual response message, ie, "2".  That way the client that requests a translation for the word "two" can indicate that this message ID is "12345" and the translator that returns the translated response "2" marks that response as message ID "12345".  In this way, I can request a translation for the word "five" and mark it as ID "67890" .

4.  Include the ability (implementation and test code) to respond to a particular QueryMsg with a particular ReplyMsg.  You may use our translate problem if you prefer, or create another scenario of your own choosing. In this case, there are two queue writers - one that adds QueryMsg's, and another that responds to a specific QueryMsg with a ReplyMsg. The QueryMsg requests should be retrieved in FIFO fashion (i.e. reply to the oldest query first).  This is the start of a "distributed" message queue that uses a simple interprocess communication mechanism so that one process can send a message to another process over the message queue.  So in our example, the QueryMsg would set the header ID and a responder client would retrieve that QueryMsg from the queue, translate the body of the message (the word "two") into its numeric representation, and send it back to the queue as a ReplyMsg.  You do not have to specifically implement our numerical translation problem for this lab.  If you have another scenario you prefer, you may use that one instead.  If you do choose to implement the numeric translator, you should only support translations of a few words, say "one" through "five".  Please keep it contained whatever scenario you choose.  You may assume that once you have replied to all the request messages on the queue, you are done.  You do not need to worry about retrieving a ReplyMsg from the queue.  You will need to worry about how a Responder will only receive QueryMsgs from the queue and not his own ReplyMsgs.  One approach is to add a type to the message header indicating whether the message is a REQUEST or REPLY.  But that is just one way to do it.

Test your program by using the message queue to send and receive a couple of messages. Include tests to reply to a query.

Submitting:
Submit your assignments to the subversion repository in the pre-existing folder named "labN" (where N is the homework number). Please include a README text file that contains any instructions for the TAs to assist with grading, and design notes are often the most useful thing you can provide. We do not usually need any info on how to compile your code unless your code layout is arcane.