Constructing a Mobile Agent
Created by: Tony White
Overview
This page deals with the construction of a mobile agent. It is intended
to provide sufficient information such that a reader, along with the mobile
code toolkit (MCT), can construct a class that, when instantiated, allows
a mobile agent to migrate from one mobile code daemon to another. This
is not a reference manual.
Text in red on this page relates to MCT
or Java code; e.g. mct.users.SuperNetlet or
onInit(java.util.Properties).
Table of Contents
The following sections are defined:
-
Where to start
-
Communicating between mobile agents
-
Event management
-
Migration
Where to start...
The MCT has been constructed with a large number of interfaces.
However, wading through all of them, and implementing them correctly, takes
quite some time. You are interested in getting that first mobile agent
moving through the network! In that case, two classes should be consulted:
mct.users.SuperNetlet
and mct.users.SuperVirtualManagedComponent.
In order to have your mobile code do something useful, it should minimally:
-
Extend the mct.users.SuperNetlet class.
This ensures that all interfaces appropriate to a Netlet are implemented.
The mobile agent designer only needs to override default behaviour.
-
Implement onInit(java.util.Properties) and
onStart().
The onInit(java.util.Properties) callback
allows a mobile agent to perform initialization activity prior to performing
its main tasks in onStart(). The java.util.Properties
argument provided to this method is derived from the Properties
field of the WinMCTRMIClient, if
the mobile agent has been injected manually, or from the netletdaemon.install.mobilecode.
statements of the properties file used to startup the mobile code daemon.
-
Implement onMessage()
in order that your mobile agent can be notified of messages when they arrive.
By default, onMessage() does nothing. For
example, the behaviour implemented might be to receive()
the message and then perform processing on it.
and optionally:
-
implement onRestore() if your agent needs
to perform actions after migration but before starting its primary activity
on the destination mobile code daemon. By default, onRestore()
calls onInit(java.util.Properties);
-
implement onMigrate() if your agent has to
perform some action before migration occurs;
-
implement onDestroy() if your agent needs
to tidy up its use of resources before being removed from the mobile code
daemon;
-
implement onStop() if your agent needs to
perform actions when its thread is about to be terminated. Note: thread
termination occurs as part of the destruction of an agent. Destruction
of an agent occurs when the thread associated with onStart()
terminates, an exception that is not handled by onStart()
occurs, or migration is successful.
-
implement onFailMigrate(java.net.InetAddress, int,
boolean) in order to handle situations when a migration fails or
is refused by the destination mobile code daemon.
[Return to Table Of Contents]
Communicating between mobile agents
Mobile agents generally need to coordinate their activities, and will do
so by passing messages between them. Inter-agent communication is supported
in a location-transparent way. Agents need only know the identifier
of the agent with which they wish to communicate; e.g. Barney[PUBLIC]@mct.examples.MyNetlet.
Location-transparent inter-agent communication is supported by the configuration
of a regional mediator. The mediator
is notified of changes in location of mobile agents in order that it can
advise the local communication
facilitator of where to send a message. Both the mediator
and communication facilitator
use mobile code directories
for the storage of mobile agent location information.
Synchronous and asynchronous communication between mobile agents is
supported. If communication activity is planned, the onMessage()
callback should be implemented within the mobile agent class.
If a mobile agent is to support inter-agent communication, the following
communication API, defined by the mct.users.MessagingAccess
interface, must be supported:
mct.mediator.Message receive()
This method obtains a message for the mobile agent, waiting
for one to arrive if one is not available. Note: there is no timeout on
the receive() method, and the agent will wait
forever for a message to arrive. Use receive(long)
if your agent should not wait forever.
mct.mediator.Message receive(long)
This method obtains a message for the mobile agent, waiting
for one to arrive for up to long msecs if one is not available. If zero
msecs is used, the mobile agent will wait forever for a message to arrive.
mct.mediator.Message[] receiveAll()
This method obtains all messages that are currently waiting
for the mobile agent, waiting for one to arrive if one is not available.
Note: there is no timeout on the receiveAll()
method, and the agent will wait forever for a message to arrive. Use receiveAll(long)
if your agent should not wait forever.
mct.mediator.Message[] receiveAll(long)
This method obtains all messages that are currently waiting
for the mobile agent, waiting for up to long msecs if one is not available.
If zero msecs is used, the mobile agent will wait forever for a message
to arrive.
boolean send(mct.mediator.Message)
This method sends a message to a mobile agent (the destination
is stored within the Message object). The
send is synchronous, the sending mobile agent waiting until the destination
mobile agent reads the message. The sending mobile agent will wait forever
for the destination agent to read the message; there is no timeout. The
boolean return value of this method indicates whether the Message
was successfully delivered.
boolean sendAsync(mct.mediator.Message)
This method sends a message to a mobile agent (the destination
is stored within the Message object). The
send is asynchronous, the sending mobile agent waiting until the message
has been delivered to the mailbox of the destination mobile agent. The
boolean return value of this method indicates whether the Message
was successfully delivered.
boolean hasMessages()
This method returns true if a mobile agent has messages waiting
for it, false otherwise.
mct.mediator.Message peek()
This method peeks at the mailbox, returning the first Message
object should one be present. The Message
object is not removed from the mailbox. If no message is present
in the mailbox, null is returned. This method does not wait for an message
activity on the mailbox; i.e. it is non-blocking.
[Return to Table Of Contents]
Event management
A local event management service is provided within
the MCT through an event multicast mechanism, similar to that provided
by the java.awt.AWTEventMulticaster.
In
later releases, region-wide event notification may be supported.
A
netlet must implement the mct.users.MCDInterface
interface in order to be able to access the mct.admin.MCTEventMulticaster.
Both the mct.users.SuperNetlet
and mct.users.SuperVirtualManagedComponent
provide this interface. The event multicaster is obtained using the getEventDispatcher()
method. If security is enabled, a check on whether the netlet is allowed
access to the event dispatcher is performed. Consult the security
section of the mobile code daemon's properties file for information
on how to set up a netlet trusted to access the event multicaster.
Two types of event notifications are supported:
-
hard coded interfaces, or internal interfaces
-
mct.users.CallbackEvent, mct.users.CallbackEventListener
-
mct.users.MCEvent, mct.users.MCEventListener
-
mct.users.MigratableEvent, mct.users.MigratableEventListener
-
user definable interfaces
-
mct.users.MCTGenericEvent, mct.users.MCTGenericEventListener
Internal events relate to the lifecycle of a netlet.
They capture the creation, destruction and migration of a mobile agent,
along with callback-related events such as starting, stopping, suspending
or resumption of a mobile agent's thread. The user definable events allow
application-specific event notifications to be constructed. These interfaces
do not use hard-coded callbacks, but use the reflective facilities provided
in Java 1.1.*. Please consult java documentation on the java.lang.reflect
package for more information on the reflective facilities provided in Java
1.1.*.
How to listen for netlet initialization, start, stop,
suspend and resume events:
A netlet must register with the event multicaster
for events of the class mct.users.CallbackEvent
and
must implement the interface mct.users.CallbackEventListener.
The following table gives a mapping of netlet event to listening mobile
code callback:
netlet initialization |
netletInitialized(mct.users.CallbackEvent) |
netlet resumed |
netletResumed(mct.users.CallbackEvent) |
netlet started |
netletStarted(mct.users.CallbackEvent) |
netlet stopped |
netletStopped(mct.users.CallbackEvent) |
netlet suspended |
netletSuspended(mct.users.CallbackEvent) |
Registration for notification of these events
is via: addCallbackEventListener(mct.users.CallbackEventListener)
Deregistering for notification of these events
is via: removeCallbackEventListener(mct.users.CallbackEventListener)
NOTE: deregistration for events occurs automatically
when a netlet is destroyed, or migrates.
How to listen for netlet creation or destruction
events:
A netlet must register with the event multicaster
for events of the class mct.users.MCEvent
and must implement the interface mct.users.MCEventListener.
The following table gives a mapping of netlet event to listening mobile
code callback:
netlet created |
addMobileCode(mct.users.MCEvent) |
netlet destroyed |
removeMobileCode(mct.users.MCEvent) |
Registration for notification of these events
is via: addMCEventListener(mct.users.MCEventListener)
Deregistering for notification of these events
is via: removeMCEventListener(mct.users.MCEventListener)
NOTE: deregistration for events occurs automatically
when a netlet is destroyed, or migrates.
How to listen for migration events:
A netlet must first register with the event multicaster
for events of the class mct.users.MigratableEvent
and
implement the interface mct.users.MigratableEventListener.
The
following table gives a mapping of netlet event to listening mobile code
callback:
netlet migration |
migrated(mct.users.MigratableEvent) |
Registration for notification of these events
is via: addMigratableEventListener(mct.users.MigratableEventListener)
Deregistering for notification of these events
is via: removeMigratableEventListener(mct.users.MigratableEventListener)
NOTE: deregistration for events occurs automatically
when a netlet is destroyed, or migrates.
How to listen for user-definable events:
This facility provides the most general mechanism
for local event agent-to-agent notification. A netlet must first register
with the event multicaster for events of the class mct.users.MCTGenericEvent.
Generic
events can be injected into the system using the mct.admin.MCTEventMulticaster
call
notify(mct.users.MCTGenericEvent).
Registration for notification of these events is via: addGenericEventListener(mct.users.MCTGenericEventListener).
Deregistering
for notification of these events is via: removeGenericEventListener(mct.users.MCTGenericEventListener).
NOTE: deregistration for events occurs automatically
when a netlet is destroyed, or migrates.
A mct.users.MCTGenericEventListener
object
allows the user to specify the object and method to be invoked when an
event of interest is injected into the system. An event is of interest
to a listener when the two events are equal; i.e. the method equal(mct.users.MCTGenericEvent)
returns true. Two contructors are provided:
MCTGenericEventListener(mct.users.MCTGenericEvent, java.lang.Object,
String, Class[])
mct.users.MCTGenericEvent |
The event of interest |
java.lang.Object |
The object to be notified when the event is of interest |
java.lang.String |
The name of the method to be invoked when event is of interest |
Class[] |
The types of the arguments associated with the above method name |
MCTGenericEventListener(mct.users.MCTGenericEvent, mct.users.Receiver)
mct.users.MCTGenericEvent |
The event of interest |
mct.users.Receiver |
The receiver to be invoked when an event of interest occurs. |
NOTE: while the mct.users.MCTGenericEvent is
not an abstract class, it is intended that subclasses of it provide a useful
implementation of the equals(mct.users.MCTGenericEvent)
method
as the implement provided merely tests the equality of the source attribute
with that of the source attribute of the argument.
[Return to Table Of Contents]
Migration
There are essentially two forms of migration for a mobile agent:
-
default
-
user specified
With default migration, the mobile agent uses the method migrate(MobileCodeObject,
boolean). The first argument is generally
this, and the
second, true.
Using these arguments, the calling mobile agent will be migrated to the
default destination as specified in the netletdaemon.migration.rmi.host.X
and netletdaemon.migration.rmi.name.X statements of the mobile
code daemon properties file. All of the examples in the demonstration
use this form of migration.
User specified migration involves the mobile agent using the method
migrate(MobileCodeObject, InetAddress, MCIdentifier).
The first argument is generally this,
the second is the IP address of the host to which the mobile agent wishes
to migrate and the third is the identifier of the mct.admin.RemoteMigrationFacilitator
installed on a mobile code daemon running there.
[Return to Table Of Contents]
Maintained by: Tony White