7.1
Programming with Migration
Patterns
7.2 Itinerary
7.3 An
Example of ItinAgent
7.4 An
Example of JointableAgent and SplitJoin Pattern
In this chapter we show how to construct
a simple itinerary based agent. This is the HelloWorld demo
program. Ajanta provides the ItinAgent
class
for building an itinerary-based agent. An itinerary is a
sequence of migration patters.
An Itinerary
y object allows the agent programmer to create a travel
plan for the agent and use a high
level abstraction for migration specification.
The base Agent class does not contain an itinerary.
The ItinAgent
class extends the Agent
class
and abstracts the agent's mobility into an Itinerary.
A ItinAgent contains
an itinerary object, which is a sequence of migration
patterns, which are described
below.
Our approach to building itinerary of an
agent programming is based on the separation of an agent's
migration control from its computation.
Complex travel plans can be programmed by composing them from
some commonly occurring migration
patterns. A Patternis
a description of an abstract migration path for
an agent.
An agent executes these patterns in the
given sequence. The
Itinerary provides to its
agent a method
named next to make a hop
to the next host on the itinerary. This next method is implemented
using the go
primitive of the server's AgentEnv
object.
7.1 Programming with Migration Patterns
By executing (or traversing) a pattern
an agent moves in the network. Pattern traversal l is determined
by the
abstract method next. It captures
the notion of the next hop in the migration path of the agent. Each
pattern
has its own semantics to determine
the next hop.
The basic migration pattern is an
ItinEntry,
which represent is single hop to a host to execute to a method.
This class is derived from the class
Pattern. An
ItinEntry object contains URN for a destination
server, and
the specification of the method to be
executed at the server. The method specification is given by: name of the
method, a vector of classes for
its parameter types, and a vector of objects containing the actual parameters.
This method specification is stored
as a MethodSpec
object. Its implementation of the next method actually
migrates to the specified host using the
go primitive. It specifies the URN of the destination server to migrate
to,
and the action to be performed at that
host.
The abstract class PatternCollection
represents an aggregation of patterns. The next
method can then be
given different semantics as described
below, to derive various patterns. There are several derived classes of
PatternCollection,
which define various different schemes for traversing the patterns contained
in the list.
Sequence:
The traversal of a Sequence pattern implies
traversal of all of the contained patterns in the given sequential
order.
Selection:
The Selection pattern selects
one pattern for traversal from the list. Its protected method
chooseNext
can be overridden by a derived
class to implement any desired policy of selecting one of the
patterns from
the list. This choice could depend on
the agent's state or the availability of hosts to be visited in the pattern.
This pattern is thus useful in selecting
alternate paths in case of failures.
Set:
The traversal of a Set pattern
implies traversal of all the contained patterns, but the order
of traversal
is immaterial, or is determined
dynamically by the user-defined chooseNext method. Hence, when
the next method is called
on this pattern, it chooses one amongst the list of patterns not
yet traversed.
This pattern can also be used to
make a travel plan more robust, since it can order paths based
on host
availability.
The Split pattern
results in the creation of child agents for parallel traversal of
the patterns contained in the
collection. One child agent is created
for each pattern in the collection. The execution of a Split pattern
only
controls creation and dispatch of agents,
and is used when child agents are not expected to report back to the
parent.
The SplitJoin
pattern is a specialization of Split in which a child agent
is required to synchronize with its
parent or some other object after it has
completed its task. Usually a child agent reports its results to
its
parent agent. On completing
its task a child agent colocates with the object with which it needs to
synchronize. It then invokes the
join method on it, which uses a Synchronizer object for synchronizing
the
child agents. In the default
case, the synchronizer is a simple counter implementing a barrier.
SplitJoin
is an abstract class, which can
be extended by the agent programmer to define a join policy. Two concrete
classes derived from it are SplitJoinAll
and SplitJoinAny.
The former waits for all child to return and
join, whereas the latter waits only
until any one of the child agents returns and execute its join method.
Ajanta system defines a class called JoinableAgent,
which is a subclass of the ItinAgent class. Typically, a
SplitJoin pattern
is executed by an agent of JoinableAgent class, which implements
the join method for its
child agents to call. Moreover,
an agent of this class always registers itself in its server's resource
registry
on arrival. This class defines
its arrive method as final. This method registers the agent
in its server's
resource registry on arrival.
Its child agent can thus get a reference to it when needed to report back
any results. To implement any application
specific actions on arrival, like getting a reference to the
server's calendar database, the JoinableAgent
provides a method named actionOnArrive.
The JoinableAgent class defines
two abstract methods:
actionBeforeJoin, and actionOnJoin.
These
methods must be suitably defined
by the application-defined class inheriting from SplitJoin.
The first
method is executed when a
child agent returns and ``joins" the parent. The synchronization protocol
executed by the agent results in
the execution of this method. An object reference to the joining
child
agent is passed as a parameter
to this method. This method is used to collect information
from a returning
agent. The second method is executed
by the parent agent when all of the specified child agents
have
joined and the desired synchronization
has occurred.
An itinerary is a sequence of pattern.
An ItinAgent is created with an Itinerary
object.
In its depart method
an ItinAgent calls the next
method of its itinerary object. The itinerary is vector of patterns
and an index
into this vector pointing to the current
pattern being traversed. The next method of the itinerary calls
the next
method of the current pattern, which then
in turn calls this method of its one of its contained patterns.
The next method of a pattern returns status
equal to DONE if the pattern has been completely traversed.
It returns FAILED status if this pattern's
traversal cannot be continued further due to some error condition.
The following HelloAgent class is defined by extending the ItinAgent class.
public class HelloAgent
extends ItinAgent
{
public HelloAgent(Credentials cred, Itinerary itin) {
super(cred, itin);
}
public void run( ) {
System.out.println ("Agent " + cred.name + " says Hello to " + host.getHostURN());
}
}
The following
code basically mirrors the example given in the previous chapter.
This code fragment
creates an itinerary-based
agent. The code for creating the credentials object for this agent
is the
same as in the previous
chapter. A HelloAgent object is created and launched
by a client using the
following code.
The agent is created to use a
Sequence itinerary. This
code initializes the Sequence
object from a file
called itinerary. It contains a sequence of ItinEntry
objects, each of which represents
hop to a server.
Itinerary itin = new Itinerary ();
Sequence s = new Sequence();
try{
BufferedReader itinfile = new BufferedReader (new FileReader("itinerary"));
String serverURN = itinfile.readLine();
while (serverURN != null)
{
s.insert (new ItinEntry(new URN (serverURN), "run", null, null));
serverURN = itinfile.readLine();
}
}
catch (IOException e)
{
System.err.println ("IO Exception reading the itinerary" + e);
e.printStackTrace();
}
itin.insert (s);
// Insert this Sequence object as the first element of the itinerary
HelloAgent ha = new HelloAgent(agCred, i); // agCred is a
Credentials object
ha.signOwner();
// put owner's signature on the Credentials object
registerAgent(ha);
// register this agent with the name service
ha.start( host);
// start the agent to go to the first server on the itinerary
7.4 An Example of JointableAgent and SplitJoin Pattern
The following code shows the definition of a HelloAgent class derived from the JoinableAgent.
public class HelloAgent
extends JoinableAgent
{
public HelloAgent(Credentials cred, Itinerary itin){
super(cred, itin);
}
public void hello() {
System.out.println ("Agent " + cred.name + " says Hello to
+ host.getHostURN());
}
public void run() {
System.out.println( " HelloAgent starting ");
}
}
An agent of
of this class can be created and launched as shown by the following code
fragment.
Assume that the
Credentials object cred has been properly constructed, as detailed
in the previous
section. The following code creates an itinerary with one SplitJoinAll
pattern
containing an ItinEntry
for each server to be visited. These entries are created by reading
file called itinerary,
as in the previous example. An execution of this pattern would result in
the
creation of one
agent for each entry. This creator agent would wait for all these agents
to
return and execute
the join method. (Some of the exception handling code has
been removed just
for the sake of
this presentation.)
Itinerary itin = new Itinerary ();
SplitJoinAll s = new SplitJoinAll("ajanta.demo.helloJoin.HelloAgent");
ItinEntry entry = null;
try {
BufferedReader itinfile = new BufferedReader (new FileReader("itinerary"));
String serverURN = itinfile.readLine();
while (serverURN != null)
{
System.out.println("run : serverURN = " + serverURN );
entry = new ItinEntry(new URN (serverURN), "hello", null, null);
s.insert (new ItinEntry(new URN (serverURN), "hello", null, null));
serverURN = itinfile.readLine();
}
}
catch (IOException e)
{
System.err.println ("IO Exception reading the itinerary" + e);
e.printStackTrace();
}
itin.insert (s);
itin.insert ( entry);
HelloAgent ha = new HelloAgent(cred, i);
ha.signOwner();
MethodSpec action = new MethodSpec ( "run", null , null );
registerAgent(ha);
ha.start( host, myURN, action );
GO TO - Top of this page Previous Chapter Next Chapter Table of Contents of this Guide