7. Creating  and  Launching  an Agent with Itinerary


     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.
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.

Split     and    SplitJoin    Patterns:

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.


7.2 Itinerary

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.
 


7.3 An Example of ItinAgent

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