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.