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 as a tarball to the subversion repository according to the directions on the syllabus page.
You
may write these solutions in either
Java or C++...your choice.
Lab 3 Due: 5:00 pm, Tuesday, April 29, 2014
Problem 1 (Message Queue):
For
this assignment you will implement a message queue in your language of
choice. There are two kinds of messages that can be sent to the
Queue "QueryMsg" and "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 translate 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.
Problem 2
(Pipes & Filters Pattern):
You will implement a Pipes and Filter pattern for this assignment. A
Filter typically either feeds input to the Pipe or reads from the Pipe and
manipulates the data. In this case, there are two filters: the first one,
WriteFilter, simply sends data from the NHL file below into a pipe (which you
will also implement) and the second filter, CapsFilter, reads off the pipe and
converts the data to UPPER CASE and prints out the data.
What you need to implement:
1. A Pipe class which accepts input from a filter.
2. A Filter interface that is implemented by all filters.
Two particular filters, the WriteFilter and
CapsFilter as described above.
You will need to design the transport mechanism
you will use for delivering the data to and from the pipe (and there are no
restrictions as to how you do this).
A sample data file (top 30 NHL scorers) can be found here.
Submitting:
Submit your assignments in a folder called LAB3_MessageQueue or
LAB3_PipesAndFilter to the subversion repository. You will
only be graded on your material within a
reasonably labeled folder. Submit your assignments in a folder called LAB1 to the subversion
repository. Place all of your Lab 1 work into
one folder. You will only be graded on your material within a
reasonably labeled folder. Also, please include a README text file that
contains any instructions for the TAs to assist with grading, such as how to compile, run, or even understand
your code.