Overview
Hostserver Link.
Your job is to build a system architecture in which agents can migrate from
one host process to another, while maintaining their internal state. Users
interact via the web with the agents, one user to one agent. Users get data
in the form of labels and matching data (think, e.g., quiz questions and
answers), and can also submit labels and matching data. Agents belong to
a group. Agents share data with members of their group. Maintain a
NameServer that knows the location of all agents and HostServers, and
provides utility services.
Note: Substantial extra credit for DIA systems that share data with the systems of
other students! Make sure I know. Define your interface and protocol! (Hosting of the agents
of other students should not be attempted.)
(Note: Old agent program page This has much
useful information. In particular you might wish to run the Web animal game,
and look over the code, to get a feel for dynamically generated Web
pages. The LUNCH PROBLEM discussion is also relevant.)
Submission Files
Submit all files to COL BEFORE the due date. Submit early, submit
often. Names for the java programs are PRECISE, and MUST be used. We
will be using batch compile scripts.
- Agent Checklist
- NameServer.java
- HostServer.java
- Optional: DIAdb.java <-- possibly needed for single repository of data
- ServerLogs.txt
- DIADiscussion.doc or (DIADiscussion.txt or DIADiscussion.html) No other formats!
- (optional) Readme.txt <-- Special instructions
Basic Grading Procedure
- Read your checklist to see which features have been implemented
- We will run the GradeAgent Batch File ,
under windows, to see your program work and to...
- Start your NameServer
- Start your DIAdb if provided
- Start your first HostServer
- Start a second HostServer by passing a different port number than the default
- Connect to the first HostServer three times to create agents one to three
- Connect to the second HostServer three times to create agents four to six
- Check the NameServer to see if both HostServers and six agents are
registered. See if agents belong to groups.
- Enter, and retrieve, data for various agents in one group.
- Check to see if the data is shared for agents in that group.
- See if agents migrate
- Make a top-level query of yor agent to dump its state, and verify that
the state is consistent with its known history.
- If you have a more complicated procedure to compile and run your code,
then provide a file name, explicitly, rundia.bat that
will compile, run, start browsers, for us to see your code work.
- [Compile your NameServer.java, and HostServer.java code (and DIAdb.java
if used).]
- Read your ServerLogs.txt file (Composite of NameServer and HostServer
sample server logs).
- Read your program code. Read the COMMENTS in your program code.
- Read your DIADiscussion file. How did you solve the lunch problem?
...share data? ...migrate agents?
- Follow the checklist to verify all features in the code.
- Follow your instructions to run the special features of your assignment
What to do first -- recommendations
Note: Not all students will finish all aspects of this assignment. Get the
basics done first. Add features as you have time. WRITE UP the valid design
of those features that you have not completed in your DIADiscussion file.
- Start your DIADiscussion file early, and keep notes as you develop. Use
this file to
make your case that you understand the issues. Remember this
programming assignment is supplementary to the lectures.
- Write comments in your code as you go. This is pedagogical code;
comments count.
- Get the basic HostServers running to support agents. Hard-code in the
NameServer functions to start
- Establish simple user communication with your agents - no data posting
at first.
- Hard-code in your agent migration from one HostServer to another with
no zombies.
- If you are going to use zombies, then build them now.
- Build your NameServer to display dynamic HTML.
- Integrate your NameServer with your HostServer so that when agents are
created, they get humand names from, and are registered by, the NameServer
- Integrate migration so that the NameServer is updated.
- On paper, develop your model of group membership. Then implement it
with the NameServer and the HostServers.
- Build the user interface dynamic HTML so that your users can review,
and add, data.
- On paper, develop your model of sharing data. DO THIS FIRST
- Implement your model of sharing data.
Note that the sharing of data is done last, because it is hard and may be
time-consuming. You can get most of the credit even if you only discuss your
design (without implementation) for data-sharing in your DIADiscussion notes.
Nameserver
Maintain a nameserver that keeps
track of the current location, and group, of each agent. The nameserver has
the following specifications:
- Displays all agents and HostServers in the system, retrievable via the web, in a table.
- When a HostServer is created, notification is sent to the NameServer
with the HostServer's ip address and port.
- When an agent migrates, a notification is sent to the nameserver with
the agent's ID number, and new endpoint.
- When an agent changes groups, a notification is sent to the nameserver
with the agent's ID number, and new group.
- "Clicking on" the agent's displayed link from the nameserver places a
web client in direct communication with the agent.
- (Optional) "Clicking on" the agent's kill link sends a message to the
agent to kill itself.
- In a separate section of the nameserver page, provide hotlinks to all
of the active HostServers in your system.
- "Clicking on" the hotlink for a HostServer puts you in direct
communication with that HostServer.
- (Optional) you might wish to display other information about your
HostServers, such as how many agents they are hosting. (But keep it to one
line!)
- Keep a list of at least twenty one-time-use human names, such as Alice,
Bob, Carold, Dave, Frank, and so on. When a HostServer connects to register
a new agent, provide a unique human name for that agent. (Once used, remove
the name from the available list!)
- Server Loop. Your NameServer must provide some utility functions
through a server loop as follows:
- When an agent wants to migrate, it can connect to the NameServer and
find an available HostServer from the list registered. Assign a HostServer
randomly, including, possibly, the same HostServer.
- When a HostServer is creating an agent, it must assign the agent to a
group. Provide a service so that a HostService can request a human name, the
name and ID# of a group, and all the other current members. When this
information is requested you must pass back the current IP address and agent
communication port of all agents in the group so that the new agent will be
able to communicate with them.
- When a HostServer is creating an agent, notification is sent to the
NameServer with the agent's name, ID number, current user endpoint (ip
address and port number), current agent-communication port, and optionally
current agent administration port, and they are added to the nameserver
table. The NameServer provides a unique human name for the agent (see
above), determines a group affiliation (color / group number) and returns
this to the HostServer along with the agent-communication endpoints of all
other agents in the group so that the new agent will be able to communicate
autonomously with its group. It is fine to hard-code three different group
ID#s (use ascii string for ease of HTML?), into your NameServer.
Interface
We should be able to run your agent by using the following web interfaces:
- All programs use the ports specified.
- For our testing purposes your agent system should run on localhost. However, you
are strongly encouraged to run your agents on multiple machines at home. A
simple way to effect this is to pass the IP address of your NameServer as
a (second) argument that otherwise defaults to localhost.
- When starting a HostServer it must use the default HostServer port, but
must also accept as the first argument an
alternate port.
- Starting the NameServer means that is that it is ready to register
agents and HostServers, to update agent location and group information, to
provide human names for new agents, and to provide a random valid HostServer
IP address when an agent wants to migrate.
- Running your HostServer program automatically registers it with the
NameServer.
- When a user makes the default connection to some HostServer, this starts up an agent,
and, in turn the HostServer registers that agent with the NameServer. The
user is now in direct communication with the agent and is no longer
communicating with the HostServer.
- Clicking on the associated link from the NameServer puts a user in direct contact with
the listed HostServer or Agent, thereby re-establishing contact with the agent.
- If you do not implement zombies, then when an agent migrates, the user
will submit to a dead link, and will have to re-establish contact with an
agent through the NameServer.
- If you DO use zombies, (see Zombie
Example ) then when an agent migrates, on reconnection,
the user will get an intermediate page, possibly with all of their data
intact, which will now point to the new location of the agent.
Ports
NameServer:
- IP address: localhost (127.0.0.1) for grading, by default. Optional:
other at home. Pass as second argument to new HostServers
- User communication Port: 48050
- Service Port: 48060
HostServer:
- Default Port: 45050 or by passing as first argment (will use 45050-45060)
- IP address: localhost (127.0.0.1) for grading -- but modify at home as needed
-
Agent:
- User communication port: determined by current HostServer at hosting
time, but see Get next available port
- Agent communication port: determined by current HostServer at hosting
time
- Optional administration port: determined by current HostServer at
hosting time
Sharing data
You must provide the design scheme, and code, for your agents to share
data. This will likely be the most complex part of your program.
Some questions to ask might be:
- Is the data stored on each agent, with updates broadcast to all?
- Is the data stored in one location with agents making retrievals over
the network for each display request? If so, how is this managed? (If you need a separate
server to manage shared data, call it DIAdb.java.)
- Do you broadcast new data to all the agents every time there is an update
at one of the agents?
- If you implement a model of agent-death, what happens to the group's
data when the last agent in a group goes away?
The lunch problem
- A user should submit the label for the data before
entering the matching data itself. This will help avoid the problem that the
user enters a label AND the data, submits the update, and then we discover
that there is already a description for that label.
- However, because data is shared between agents in a group, we can have
the following problem: User Alice submits the label "UDP" and, after a check
is made to verify that the label "UDP" does not already exist in the
database (DB), she is prompted to enter the matching data (description) for
that concept. Meanwhile User Bob submits a request to update the DB for
"UDP" and is given his own update screen for that concept. User Alice
submits her matching data, which is indexed under "UDP". User Bob submits
his matching data for "UDP" which then writes on top of Alice's
submission. Alice goes back to read her data, sees Bob's matching data, and
gets upset. Where is her data that she just typed in?
- So we decide to use record locking. User Alice submits the label "UDP" and
she is prompted to enter the matching data (description) for that
concept. Meanwhile User Bob submits a request to update the DB for "UDP" and
is told that the database entry for "UDP" has been locked. Meanwhile Alice
decides to go out to lunch. Then, when she comes back she gets involved in
something else, then goes home, and leaves on vacation the next day. Bob
repeatedly tries to either retrieve the data for "UDP" or enter his own, but
is locked out for two weeks while Alice is on vacation. During this time,
Carol and Dave discover that they are locked out as well. This is the
classic lunch problem .
- In the case of this particular application, having a single record locked, or
losing a small amount of data, is not fatal to the application. But the
problem occurs in many kinds of update environments, and should be handled
both intentionally, and with grace, on your part in this pedagogical exercise.
- A number of devices might be used in your solution. (a) Is there a time-out
on the lock? Might you wish to lock the whole database? Are you willing to
take on the burden of integrating disparate data when two users submit in an
overlapping way?
- Where are the bottlenecks? How will your solution scale to, say,
100,000 agents, and 50,000 concepts? Where are the weakpoints of your
system? Can the failure of one node cause the whole system to go down?
HostServers
You are to maintain multiple hostservers. When a new hostserver is started
up, it registers itself with the nameserver. When agents want to migrate,
they connect to the NameServer to find an available HostServer. If you
implement the optional killing of HostServers, then you have to figure out
how to force agents to first migrate elsewhere, and how to deal with the
zombie problem if the HostServer has to go down immediately.
Migration
Agents must migrate autonomously. This means that you must handle the
problem of notifying the web client, at some later time when the client
reconnects, where the agent has gone. (And keep in mind that the agent may
migrate more than once before the user client or admin client reconnects.)
Keep in mind that when an agent migrates from one location to another (e.g.,
to a different HostServer) the code that implements the agent is
already there. Migration, in our case here, means shipping the state
of the agent (ID number, group, relationships, data, history, etc.) to be
instantiated into the agent code that is started up at the new location.
- The easiest way to do this, although not elegant, is to simply leave a
dead link. The user must then be educated enough to know that they have to
connect to the NameServer to find the current location of their agent. Using
this scheme, no notification that the agent has migrated is possible.
- A somewhat more elegant method is to use an
automatic redirection scheme that sends back dynamically-generated html
that points to the new (basic) endpoint of the agent. However, if we want to
keep things simple, this will only be a top-level communication with the
agent (that is, no action statement, no form data), and the user's currently
submitted data may be lost.
- A more elegant method is to leave behind a zombie thread, listening at
the old port, which redirects the browser to the new endpoint of the
agent. (see Zombie
Example. )
- A simple scheme, and very acceptable for our purposes here, is to send
back, from the zombie, dynamically reconstructed html that includes all of
the user's just-submitted attribute/value pairs (data), but replaces the
action-statement URL with that of the new location of the agent, and ask the
user to resubmit it. A simple banner saying something like "Your agent has
migrated, press the submit button to reconnect" with a collection of data
using hidden or displayed values would be fine. This way your user will not
lose data, or the state of their conversation with the agent.
- If you maintain an admin connection to your agent, the zombie will need
to wait for this connection too.
- The zombie does not need to wait for agent communications because
agents can be notified of the new location before the migration.
- Lastly, if you really wanted to make this elegant, you could combine
techniques: have the zombie parse the type of request from the browser and
forward all of the data submitted to the newly-migrated agent; send a
redirect screen to the browser to connect to the agent's new location;
return an acknowledgment of the data submission from the agent to the
browser.
- You will have to think through the sequence of events that have to take
place for migration to occur. Consider that some sequences will be more
problematic if there are lost communications, or a process fails in the
middle of the migration. In your comments, discuss your system's robustness,
or lack thereof, in the presence of different types of failures during
migration. (For example, the NameServer provides a new destination host
location, and also updates its tables. Does this all take place in one
request, or is the old table information maintained until after the migration is
complete, requiring at least two connections to the NameServer?)
- Implement automous migration by using a
Sleep Looper . The agent wakes up, and may or may not decide to migrate.
Server Logs
Your HostServers and NameServer must print out out console logs whenever
something interesting happens. Concatenate some representative logs together
and submit to COL as part of your assignment. Log statements might be, e.g.,
"NS: HostServer has just requested creation of agent Frank." or "HS: Agent
Frank has just migrated to port 3289 on host localhost."
User Communication
Here are the required user interactions with your agent:
- Cold connection to the agent: dump the agent's state (except for data):
group affiliation, other agents in the group, number of user requests for
getting data, and also for posting data, history of migrations, number (or
log) of autonomous communications from other agents. Provide links to move into
to get-data mode, or send-data mode.
- Get label for data (e.g. pose a quiz question). Labels should repeat
until all have been seen by the user.
- Get matching data (e.g., present the associated answser - include the label as well).
- Check a label for redundancy
- Submit matching data (after checking the label - include the label at
the top, and a data-input box below it).
Here are some sample user screens:
Here are some points to consider for user communication:
- Your agent will be getting different types of requests through the same
port, at least: (a) requests for a new label to be displayed (b) requests
for matching data to be displayed (c) requests for a label to be checked for
redundancy before entering matching data (d) requests to post a
label/content pair (send data), and (e) requests to reconnect to an agent
(i.e., from NameServer link referral ).
- Imagine that a client connects to request a label, and your agent sends
back a page saying "UDP". The user thinks about this label, forms her
opinion and then presses submit to get the "answer" to see if she was
right. How do you know to send back the matching data that says, e.g.,
"Cheap sending of datagrams without guarantee of arrival or ordering." ?
There are many ways of handling this problem. For example you might...
- Send the matching data along with the original label, but put it in a hidden
value. Then when the user submits the page asking for the matching data to
be displayed, they are actually sending the data they want in the
request This way, even if you have migrated, or the agent was
restarted, you always have the data at hand to be simply returned to them.
- Do an expensive string match on the original label (which is resent by
the user), and send back the matching data when you locate it. This way even
if you have migrated, or the agent has been restarted, you still know
exactly what to send back.
- Generate a random number and store a permanent copy of it as an ID in
the structure where you store your copy of label and the data. When the user
gets the label, they also get the ID number. Then, when the user presses
submit they send not the label, but the ID number. You then make this cheap
(possibly indexed) match against the ID number, retrieve the associated
matching data and send it back to the user.
- Simply wait for the user to send another request and when they do, as
long as it is for matching data, just send back the matching data that you
have already queued. This simple mechanism will work, as long as the client
browser and your agent stay in sync.
- (Note: Some of you may optionally implement an administration client for
agents. All of the migration issues for the user client also apply to the
aministration client.)
- This design requires the sending of a great deal dynamically-generated
HTML from the agents back to the users. Are you clear on how this is done?
(The essence of it: use print-stream functions to send primarily static HTML
strings from your program. Fill in a few slots with dynamically-generated strings.)
Communication Data:
These are recommended data formats that will allow you to share data with
the agent systems of other students. You are not bound to use them.
Agent Communication Header:
- Agent Identifier of agent that initiated the conversation
- Agent Identifier of second agent in the conversation
- string-integer Conversation Number
- string-integer Message number
- string-integer Formal Command Number
- String data
Agent identifier:
- 12 character ascii string representation of integer:
Agent ID (integer between one and 2 billion) (e.g., "134000206000")
- 1 character ascii space " "
Delimiter
- 20 character ascii string:
Name
- 1 character ascii space " "
Delimiter
- 7 character ascii string starting with "#" then using only 0123456789ABCDEF,
(e.g., "#12FBC7"):
Current Group ID / Group Color
Commands:
- Hello
- Ack
- Request-to-share-data
- Sending-data
- etc.
Data Format:
- String Label
- String Interior Delimiter "FXGZ"
- String Matching-data
- String End Delimiter "ZGXF"
- Note: this allows you to send as many label/data pairs as you like,
of variable length, in a single message: "UDP FXGZ Cheaper than TCP ZGXF
Execution Environment FXGZ Memory, open files, semaphores, etc. bound to
process ZGXF..."
Migration commands: up to you to define.
Bragging Rights
- Share data with other students!
- Allow the nameserver to send a "die" message to a hostserver. The HostServer
then sends messages to each of the agents to migrate to a different
HostServer, and when this is done, then it dies. (Note that if you are using
zombies, then the HostServer will have to wait until the last client and
admin client have connected, and the last zombie has died before going
away.)
- Agents can wake up and send a message to all other members of their
group (and the NameServer) to change the color of the group.
- Develop a model of negotiation. Allow agents to autonomously communicate with agents
outside of their group to trade data.
- Allow Agents to switch groups. Are agents allowed to take data with them?
- Might you have spy agents that return with data from the other group?
- Allow the NameServer to kill off agents. If the last agent in a group is
killed off, where is the data saved?
- What sort of model might you build where agents can belong to more than
one group?
Issues
- When an agent migrates, if you are not using zombies, do you reuse the port,
or place it in a permanently unavailable pool? If you decide to re-use
ports, which would scale, how do you keep a web client from mistakenly
reconnecting to a port that has now been reused, unbeknownst to the old client?
- How are you going to implement the "labels should not repeat until the
user has seen all the data" specification? Keep in mind that new data may be
appearing all the time - both from the user themselves, or from data
gathered by other agents.
- Watch for updates to this section!