|
|||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||
java.lang.Objectorg.iids.aos.agent.Agent
public abstract class Agent
AgentScape agent interface. Every Java agent in AgentScape is a subclass
of this Agent class, which wraps some of the AgentScape API calls
for simplicity (effectively hiding details such as handles).
Access to the full API is still possible using the getApi()
method. Note that methods in this API require an AgentHandle
as an extra argument. For the AgentHandle, any handle belonging
to the agent will generally do (except maybe for calls to
receiveMessages(java.util.List.
For its most basic needs, the agent does generally not need to access the full API. Exceptions to that are the calls from the API that are not wrapped in this class, such as AgentContainer access, specific calls to the lookup service, and for creating new agents.
Once the agent is done (meaning that either a call to
move(AgentScapeID) or kill()
succeeded, or the
agent run() method finished, the agent officially no longer exists,
though if the agent has spawned other
threads (if allowed by the security manager) these can continue to run,
which is a little difficult to protect. In future, a security manager should be
able to prevent most of these illegal access attempts.
In any case, the agent's handles are no no longer valid, so the agent cannot
call any methods of the AgentScape API.
Note that this class caches some information (like handles).
If new handles are created using the API (ignoring the wrapper
calls) then the information from calls such as getAgentHandles()
is probably no longer correct. Using the API for such calls does not
offer more functionality, and should be avoided.
All kinds of exceptions that can occur are wrapped inside an
AgentScapeException for simplicity. For advanced error checking
use Throwable.getCause().
| Field Summary | |
|---|---|
protected AgentLog |
log
|
| Constructor Summary | |
|---|---|
Agent()
|
|
| Method Summary | |
|---|---|
boolean |
agentRunning()
See if (according to AgentScape) the agent is still running. |
protected void |
cleanUp()
User definable cleanup of the agent before stopping. |
AgentHandle |
createAgentHandle()
Create new communication handle for this agent. |
void |
deregister(AgentHandle handle,
java.lang.String name)
|
long |
getAgentCPUtime()
|
java.util.List<AgentHandle> |
getAgentHandles()
Obtain list of all agent handles. |
AgentScapeApi |
getApi()
Obtain reference to AgentScape API, if needed. |
java.lang.String[] |
getArgs()
Get startup arguments for the agent. |
org.mortbay.jetty.servlet.Context |
getContext()
Return context in which servlets of this agents are executed. |
AgentScapeID |
getCurrentLocation()
Obtain location ID where the agent currently resides. |
java.util.List<AgentScapeID> |
getLocations()
List all available locations in this AgentScape world (lookup service). |
static java.util.List<AgentScapeID> |
getLocations(AgentScapeApi api)
|
AgentLog |
getLog()
Get access to the agent's private log. |
AgentHandle |
getOwnerHandle()
Obtain owner handle, which - by design - is associated with the owner (creator) of this agent. |
AgentHandle |
getPrimaryHandle()
Obtain primary handle, which the agent can use to send/receive messages from this agent's owner and/or other agents. |
javax.servlet.http.HttpServlet |
getServlet(java.lang.String name)
Get this agent's servlet by name. |
java.util.Set<java.lang.String> |
getServletNames()
Lists the servlet names this agent has published. |
java.lang.Object |
getToken()
Obtain token, so that access to the API is possible as well. |
void |
initAgent(AgentScapeApi _api,
AgentScapeID loc,
AgentHandle owner,
AgentHandle primary,
java.lang.String[] args)
Initialisation, set agentscape API to contact. |
void |
kill()
Kill the agent. |
java.util.Map<AgentHandle,AgentScapeID> |
lookup(java.lang.String name)
Lookup handles of agents that have registered the String name. |
static java.util.Map<AgentHandle,AgentScapeID> |
lookup(java.lang.String name,
AgentScapeApi api)
|
static java.util.Map<AgentHandle,java.lang.String> |
lookupPublished(AgentScapeApi api,
java.lang.String name)
|
java.util.Map<AgentHandle,java.lang.String> |
lookupPublished(java.lang.String name)
Lookup a value that was previously published under a certain name
with the method publish. |
void |
move(AgentScapeID location)
Move agent to remote location. |
void |
move(AgentScapeID location,
java.lang.String leaseID)
Move agent with custom lease negotiation. |
void |
publish(AgentHandle handle,
java.lang.String name,
java.lang.String value)
Publish a value under a certain name. |
void |
publishServlet(java.lang.String name,
javax.servlet.http.HttpServlet servlet)
Publish a servlet for this Agent. |
Envelope |
receiveMessage(boolean block)
Receive a message for this agent. |
Envelope |
receiveMessage(java.util.List<AgentHandle> handles,
boolean block)
Receive a message for this agent. |
java.util.List<Envelope> |
receiveMessages(boolean block)
Receive messages for this agent. |
java.util.List<Envelope> |
receiveMessages(java.util.List<AgentHandle> handles,
boolean block)
Receive messages for this agent. |
void |
register(AgentHandle handle,
java.lang.String name)
Experimental, some simple agent registration and lookup methods. |
java.util.List<Envelope> |
removeAgentHandle(AgentHandle ah,
boolean pickup)
Remove existing communication handle for this agent. |
abstract void |
run()
To be implemented by the agent. |
void |
sendMessage(Envelope env)
Send a message to remote agent handle(s). |
void |
sendMessages(java.util.List<Envelope> envelopes)
Send multiple messages to remote agent handle(s). |
void |
start()
Start running the agent. |
void |
stopRunning()
Notifies the agent that it can stop running. |
void |
waitForCompletion()
Wait for this agent to be killed. |
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Field Detail |
|---|
protected AgentLog log
| Constructor Detail |
|---|
public Agent()
| Method Detail |
|---|
public AgentLog getLog()
public void initAgent(AgentScapeApi _api,
AgentScapeID loc,
AgentHandle owner,
AgentHandle primary,
java.lang.String[] args)
throws AgentStartupException
Usually called by the java agent runner, to set starting variables and such, so that the agent can actually get access to AgentScape. This function can be called only for each agent the host the agent currently resides. This prevents others from being able to re-init this agent.
TODO: exception when multiple initialization occurs!?
_api - Instance of (maybe remote) API to interact with.loc - Current location of the agent.owner - Handle of agent owner, can be used as a target for messages directed
to the owner of the message, etc. This owner handle will not be part
of the result of the getAgentHandles() method, as this handle
is not really part of the agent itself. However, this is just a
wrapper method for the API, which does not distinguish all different
kinds of agent handles.primary - The 'primary' agent handle is (just as the owner handle) created on
agent creation time. It is passed to the agent owner, so that it at
least knows one handle it can send control messages to. It is best
for an agent to send messages from 'primary' to 'owner', and vice
versa fot the agent owner.args - Array of initial (String) arguments for the agent.
AgentStartupException - If the agent cannot be initialized.public java.lang.String[] getArgs()
Arguments can be supplied to the agent when starting it up,
for example, as arguments to AgentScapeApi.startAgent(org.iids.aos.systemservices.communicator.structs.AgentHandle, boolean, java.lang.String...).
public AgentScapeApi getApi()
Usually, an agent does not need access to the full API, it can
just use all the calls from the Agent superclass. The API
does offer some more advanced features, such as lookup server access
and read/write access to its agent container.
public java.lang.Object getToken()
NOTE: for future use only!
null (unimplemented).public AgentHandle getOwnerHandle()
There is one special owner handle associated with each agent owner (though the AgentScape middleware does not explicitly see them as different parties). The owner handle can be used by an owner to receive messages from a specific agent. These messages are used as a private communication mechanism between owner and agent. Because each agent has an owner handle, an agent can always contact its owner using this handle. Because AgentScape itself does not recognize the difference between the owner handle and any other agent handle, one should be a little careful when using the API for receiving messages.
Messages to the owner should preferably originate from the primary handle, which is the only one that the owner is guaranteed to know (it was assigned at agent creation time). Even though the agent owner can get a list of all handles at any point during the agent's lifetime, using the primary handle avoids confusion.
public AgentHandle getPrimaryHandle()
The primary handle is the handle where all messages from the owner
will probably arrive. This is a convention, this does not need to be
respected, though it will avoid some confusion if this model is used.
Agents can create other handles, if so desired with createAgentHandle().
public java.util.List<AgentHandle> getAgentHandles()
throws AgentScapeException
This list contains all the current handles of this agent. These handles
can be used in a call to
receiveMessage(List,boolean) or
receiveMessages(List,boolean). It does not include the owner
handle, as the agent should really not use that handle for receiving
messages.
AgentScapeException - A problem obtaining the agent handles.
public AgentHandle createAgentHandle()
throws AgentScapeException
Each agent can have multiple handles, each can be used for communication with other agents. If you desire anonimity, then it is best to use a separate handle for all the different parties your agent communicates with. An agent handle can never be resolved to the actual ID/name or another one of the agent handles by anyone else other than the middleware or the agent/owner itself.
AgentScapeException - If, for some reason, a new handle cannot be created.
public java.util.List<Envelope> removeAgentHandle(AgentHandle ah,
boolean pickup)
throws AgentScapeException
You cannot and should not remove the primary or owner handle.
Each agent can have multiple handles, each can be used for communication with other agents. If you desire anonimity, then it is best to use a separate handle for all the different parties your agent communicates with. An agent handle can never be resolved to the actual ID/name or another one of the agent handles by anyone else than the middleware or the agent/owner itself.
ah - AgentHandle to be removed from this agentpickup - if true, any undelivered envelopes to this handle will be
returned.
pickup is true.
AgentScapeException - If, for some reason, a the handle cannot be removed.createAgentHandle()public AgentScapeID getCurrentLocation()
public java.util.List<AgentScapeID> getLocations()
throws AgentScapeException
A simple wrapper around a lookup service request, that returns a list of all the location IDs that are known at this specific point in time.
AgentScapeException - If there is a problem accessing the AgentScape API.
public static java.util.List<AgentScapeID> getLocations(AgentScapeApi api)
throws AgentScapeException
AgentScapeException
public void sendMessage(Envelope env)
throws AgentScapeException
Agent information (such as sender/receiver) is present in the envelope. If all this information is correct, then the message will be delivered to the remote agent(s).
The sending agent can use any of its current existing handles (except for the owner-handle) as the source handle in the envelope.
The envelope can contain a list of target handles, in which case the envelope will be sent to all these handles (multi-cast).
The data in the envelope can be any serializable object.
To send a message to this agent's owner, use this agent's primary handle as source handle.
This method is MT-safe.
env - Envelope to send. Note that for this envelope, the source handle
Envelope.getFromHandle() must match a local handle.
AgentScapeException - If the message cannot be delivered.
public void sendMessages(java.util.List<Envelope> envelopes)
throws AgentScapeException
Agent information (such as sender/receiver) is present in the envelope. If all this information is correct, then the message will be delivered to the remote agent(s).
This method is MT-safe.
envelopes - Envelopes to send. Note that for each envelope env in this list,
the handle Envelope.getFromHandle() must match a local handle.
AgentScapeException - If the message cannot be delivered.
public Envelope receiveMessage(java.util.List<AgentHandle> handles,
boolean block)
throws AgentScapeException
An agent can have multiple handles. Use this method to receive messages
that were sent to any subset of these handles. This subset can be
specified in the parameter handles. Any existing handle of
this agent can be present in this list, except for the owner handle
(the one returned by getOwnerHandle().
This method is MT-safe. However, a message will only be delivered _once_ (i.e., to one thread only) even if multiple threads are trying to receive messages for that particular handle.
handles - A list of handles to receive from. If handles==null then data
is received from all currently existing handles of this agent
(except the owner handle).block - Block (true) while waiting for message to arrive or poll
(false) for messages. If blocking, this call will return
only if a message has been received for this handle, this agent handle
has been removed, or until the agent has been removed from the host.
null if
there was no pending message for this agent (and block was false.
AgentScapeException - If there was any problem receiving the message.
public Envelope receiveMessage(boolean block)
throws AgentScapeException
Shortcut for receiveMessage(null,block).
block - Block (true) while waiting for message to arrive or poll
(false) for messages.
null if
there was no pending message for this agent (and block was false.
AgentScapeException - If there was any problem receiving the message.
public java.util.List<Envelope> receiveMessages(java.util.List<AgentHandle> handles,
boolean block)
throws AgentScapeException
handles - A list of handles to receive from. If this is null then data
is received from all handles (except the owner handle) that are
associated with this agent.
This method is MT-safe. However, a message will only be delivered _once_ (i.e., to one thread only) even if multiple threads are trying to receive messages for that particular handle.
block - Block (true) while waiting for message to arrive or poll
(false) for messages.
null if
there was no pending message for this agent (and block was false.
AgentScapeException - If there was any problem receiving the messages.
public java.util.List<Envelope> receiveMessages(boolean block)
throws AgentScapeException
Shortcut for receiveMessages(null,block).
block - Block (if true) while waiting for message to arrive or poll
(if false) for messages.
null if
there was no pending message for this agent (and block was false.
AgentScapeException - If there was any problem receiving the messages.protected void cleanUp()
stopRunning(), which is
called by AgentScape whenever the agent moves or is (being) killed.
An Agent-developer can override this method to perform any cleanup
necessary before the agent is stopped permanently, such as
stopping any threads this agent has created or removing any
windows that have been put on the screen.
This method may not throw any Exceptions.
public final void stopRunning()
agentRunning() method
returns false (and thus, the method waitForCompletion()
also returns).
This function is implicitly called after the kill() method or
the move(org.iids.aos.systemservices.communicator.structs.AgentScapeID) method returns successfully. This method is called
by the agent server, the Agent itself should never call this method,
otherwise the kill() method does not work anymore (and you
would need to call AgentScapeApi.killAgent(org.iids.aos.systemservices.communicator.structs.AgentHandle) from the main APi.
Bottom line: don't call this method from the agent directly. If
you need to perform some clean-up before the agent stop, override
the cleanUp() method, which will be called by AgentScape
whenever stopRunning is executed.
agentRunning(),
waitForCompletion(),
kill(),
move(org.iids.aos.systemservices.communicator.structs.AgentScapeID),
cleanUp()
public final void kill()
throws AgentScapeException
Calls the agent server, and instructs it to kill this agent. The agent itself is now no longer running on this host (though not all of its threads may have terminated).
AgentScapeException - If the agent cannot be killed.
public void move(AgentScapeID location)
throws AgentScapeException
location, and the local agent can stop
running.
Currently there is no way for the middleware to make sure that
the agent is actually done. For now, the agent is trusted to take care
of stopping all threads (see cleanUp().
In future, the security manager could be used to
track down all of the threads that are currently running on behalf of
the agent (and only confirm migration once all threads have finished).
location - Destination location of the agent.
AgentScapeException - If there was an error and the migration request could not be completed.
public void move(AgentScapeID location,
java.lang.String leaseID)
throws AgentScapeException
location - Target locationleaseID - Pre-negotiated lease
AgentScapeException - If the migration failspublic final void start()
Probably called from the JavaAgentRunner, performs some initialisation
before calling run() and cleanup after the agent has finished.
As an agent programmer, you don't need to use this method.
public abstract void run()
Once this function finishes, the agent is done. This can be preceded
by a successful call to move(AgentScapeID)
if the agent should continue to
run on another location. If no successful move was done beforehand,
then the agent is removed from the location.
Note that it is assumed that, once an agent moved to another location, this method will finish soon afterwards. There is no protection against this (yet) however.
Any cleanup operations can be done by implementing cleanUp().
cleanup,
movepublic void waitForCompletion()
kill() method (the owner, the agent itself,
or maybe the agent server). It also returns whenever the run()
method finishes (after which kill() is also implicitly called.
This is useful if the agent has multiple threads, and some of them
need to wait until the agent completes. What it actually does is
wait for the method agentRunning() to return false,
so you can also check it yourself. For example, if you want to perform
some function for as long as the agent lives, you can just use
while (agentRunning()) { do_stuff(); }
agentRunningpublic boolean agentRunning()
true), otherwise the AgentScape middleware has
either killed or moved the agent, and its thread should stop.
waitForCompletion
public void register(AgentHandle handle,
java.lang.String name)
throws AgentScapeException
This can for now only be used to lookup and register agent names. Location names, agent addresses, etc cannot be handled by this method.
Also handles the automatic agent name re-registration during the course of the agent lifetime.
After the name is registered, it can be looked up up again. One can
also obtain the current location of the agent handle (or should this be
hidden?) using lookup(java.lang.String).
Note: a more generic version of this is publish.
handle - The handle which to register the name toname - The name to associate with this handle
AgentScapeException - If there is some problem in registering the handle/name.publish,
lookup
public void deregister(AgentHandle handle,
java.lang.String name)
throws AgentScapeException
AgentScapeException
public java.util.Map<AgentHandle,AgentScapeID> lookup(java.lang.String name)
throws AgentScapeException
name.
name - The name to query the lookup service for.
AgentHandle that registered
the String name, as well as the location on which the agent
resideded when it registered name.
AgentScapeException - Problem performing lookup of registered name.register
public static final java.util.Map<AgentHandle,AgentScapeID> lookup(java.lang.String name,
AgentScapeApi api)
throws AgentScapeException
AgentScapeExceptionlookup
public void publish(AgentHandle handle,
java.lang.String name,
java.lang.String value)
throws AgentScapeException
value under a certain name. Other agents
can retrieve the value with the method
lookupPublished.
handle - handle of the agent that publishes this informationname - name under which the value can be foundvalue - the value to be published
AgentScapeException - If there is some problem in registering the (name, value) pair.lookupPublished
public java.util.Map<AgentHandle,java.lang.String> lookupPublished(java.lang.String name)
throws AgentScapeException
name
with the method publish.
name - name under which the value was published
AgentScapeExceptionpublish
public static java.util.Map<AgentHandle,java.lang.String> lookupPublished(AgentScapeApi api,
java.lang.String name)
throws AgentScapeException
AgentScapeExceptionlookupPublishedpublic long getAgentCPUtime()
public org.mortbay.jetty.servlet.Context getContext()
public void publishServlet(java.lang.String name,
javax.servlet.http.HttpServlet servlet)
NOTE: servlets DO NOT migrate with agents! Servlets must be published again after a migration!
Special log servlet is always available for each agent. This servlet does not have to be published. The log is available for a *short while* after the agent has finished.
name - name of servletservlet - published servletpublic java.util.Set<java.lang.String> getServletNames()
public javax.servlet.http.HttpServlet getServlet(java.lang.String name)
name - name of the servlet
|
|||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||