Chapter 16. Active Object Migration

16.1. Migration Primitive

The migration of an active object can be triggered by the active object itself, or by an external agent. In both cases a single primitive will eventually get called to perform the migration. It is the method migrateTo accessible from a migratable body (a body that inherits from MigratableBody).

In order to ease the use of the migration, we provide 2 sets of static methods on the ProActive class. The first set is aimed at the migration triggered from the active object that wants to migrate. The methods rely on the fact that the calling thread is the active thread of the active object:

  • migrateTo(Object o): migrate to the same location as an existing active object

  • migrateTo(String nodeURL): migrate to the location given by the URL of the node

  • migrateTo(Node node): migrate to the location of the given node

The second set is aimed at the migration triggered from another agent than the target active object. In this case the external agent must have a reference to the Body of the active object it wants to migrate.

  • migrateTo(Body body, Object o, boolean priority): migrate to the same location as an existing active object

  • migrateTo(Body body, String nodeURL, boolean priority): migrate to the location given by the URL of the node

  • migrateTo(Body body, Node node, boolean priority): migrate to the location of the given node

16.2. Using migration

Any active object has the ability to migrate. If it references some passive objects, they will also migrate to the new location. Since we rely on the serialization to send the object on the network, the active object must implement the serializable interface. To migrate, an active object must have a method which contains a call to the migration primitive. This call must be the last one in the method, i.e the method must return immediately after. Here is an example of a method in an active object:

   public void moveTo(String t) {
     try {
       ProActive.migrateTo(t);
     } catch (Exception e) {
       e.printStackTrace();
     }
   }

We don't provide any test to check if the call to migrateTo is the last one in the method, hence if this rule is not enforced, it can lead to unexpected behavior. Now to make this object move, you just have to call its moveTo() method.

16.3. Complete example

  import org.objectweb.proactive.ProActive;
  public class SimpleAgent implements Serializable {
    public SimpleAgent() {
    }
    public void moveTo(String t) {
      try {
        ProActive.migrateTo(t);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    public String whereAreYou() {
      try {
        return InetAddress.getLocalHost().getHostName();
      } catch (Exception e) {
        return 'Localhost lookup failed';
      }
    }
    public static void main (String[] args) {
      if (!(args.length>0)) {
        System.out.println('Usage: java migration.test.TestSimple hostname/NodeName ');
        System.exit(-1);
      }
      SimpleAgent t = null;
      try {
        // create the SimpleAgent in this JVM
        t = (SimpleAgent) ProActive.newActive('migration.test.SimpleAgent',null);
      } catch (Exception e) {
        e.printStackTrace();
      }
      // migrate the SimpleAgent to the location identified by the given node URL
      // we assume here that the node does already exist
      t.moveTo(args[0]);
      System.out.println('The Active Object is now on host ' + t.whereAreYou());
    }
  }

The class SimpleAgent implements Serializable so the objects created will be able to migrate. We need to provide an empty constructor to avoid side effects during the creation of active objects. This object has two methods, moveTo() which makes it migrate to the specified location, and whereAreYou() which returns the hostname of the new location of the agent.

In the main method, we first need to create an active object, which is done through the call to newActive(). Once this is done, we can call methods on it as on any object. We call its moveTo method which will make it migrate to the node specified as parameter and then we ask it what is its current location.

16.4. Dealing with non-serializable attributes

The migration of an active object uses the serialization. Unfortunately, not all the objects in the Java language are serializable. We are going to see a simple method to deal with such attributes in the case their value does not need to be saved. For more complex cases, the reader can have a look to the Java RMI specifications.

When a NotSerializable exception is thrown, the first step to solve the problem is to identify the variable responsible, i.e the one which is not serializable... In front of the declaration of this variable, put the keyword transient. This indicates that the value of this variable should not be serialized. After the first migration, this field will be set to null since it has not been saved. So we have to rebuild it upon arrival of the active object on its new location. This can easily be done by providing in the active object the standard method

 private void readObject(java.io.ObjectInputStream in) throws java.io.IOException,
 ClassNotFoundException; 

See the Serializable interface in the standard JavaDoc to learn more.

16.5. Mixed Location Migration

16.5.1. Principles

There are two way to communicate with an active object which has migrated :

  • Forwarders

    An active object upon leaving a site leaves behind a special object, a forwarder, which is in charge of forwarding incoming messages to the next destination. As time goes, a chain of forwarders builds between a caller and the mobile object. Any message sent to the latter will go through the chain to reach the agent. There is a virtual path between a caller and a mobile object.

  • Location Server

    Communicating with a mobile object can be done with an explicit reference towards the mobile entity, which requires a mean to get its current location is necessary.

    In that case there is a two steps communication: first there should be a search to obtain an up-to-date reference (localization), and then the actual communication. The simplest solution is to have a unique location server which maintains a database of the known position of the agents. When an object wants to communicate with an object which has migrated, it queries the serv er which sends back a new reference. If this is the correct one then the communication takes place, otherwise a new query is issued.

Both techniques have their drawbacks. Two problems arise when using a forwarding scheme, especially if the ambition is scalable mobile agents over WAN. First, the forwarders use resources on a site as long as they have not been garbage collected. Thus if a chain exists between to objects, it will remains even if there is no new communications going by. Second, the longer the chain is, the more likely it will be cut because of a hardware or software failure. As a consequence, while forwarders are more efficient under some conditions, they do not appear to be scalable, nor reliable.

The server on the other hand is a single point of failure and a potential bottleneck. If a server is to help communicating with a higher number of mobile agents, then it might not be able to serve requests quickly enough. Furthermore, in case of a crash, it is not possible to communicate with mobile objects until the server is back. It si possible to avoid most of these issues by having redundant servers with load balancing at the cost of increaing complexity.

Based on these observations and taking into account the variability of the environment, we propose a configurable communication protocol which offers the main benefits from both the forwarder and the server while avoiding their drawbacks. Configurable with discrete and continuous parameters, it can be tailored to the environment to offer both performance and reliability.

16.5.1.1. Time To Live Forwarder

We introduce time limited forwarders which remain alive only for a limited period. When their lifetime is over, they can just be removed. First of all, this brings an important advantage: scalability due to absence of the DGC and the systematic reclaim of forwarding resources. But of course, this first principle increases the risks of having the forwarding chain cut since this can now happen during the normal execution of the application without any failure. In such a situation, we will rely on a server which will be considered as an alternative solution. This increases the overall reliability.

16.5.1.2. Updating forwarder

It is possible to rely on the forwarder to maintain the location of the agent by having them update the server. When they reach the end of their lifetime, they can send to the server their outgoing reference which could be the adress of the agent or another forwarder. The Updating forwarder parameter can be true or false. If true, the main advantage is that it releases the agent from most of the updates. In order to increase reliability, it is possible to have the agent also update the server on a regular basis. This leads us to the third principle.

16.5.1.3. Time To Update Agent

Each mobile agent has a nominal Time To Update (TTU) after which it will inform the localization server of its new location. Clearly, there are two differents events that influence when a localization server of its current position :

  • the number of migrations it has performed since its last update,

  • the time it has spent on the current node without having updated the server.

This observation leads us to the fourth principle :

16.5.1.4. Dual TTU

The TTu is defined as the first occurence of two potential events since the last update:

  • maxMigrationNb : the number of migrations,

  • maxTimeOnSite : the time already spent on the current site.

16.5.1.5. Conclusion

If we consider that both the agent and the forwarders can send updates to the server, the server must be able to make the difference between messages from the forwarders and from the agent; those are always the most up to date. Also, since we don't have any constraint on the Time To Live (TTL) of the forwarders, it could be that a forwarder at the beginning of a chain dies after on at the end. If this happens and we are not careful when dealing with the requests, the server could erase a more up to date reference with an old one.

To summarize, the adaptable mechanism we propose to localize mobile objects, is parameterized by the following values :

  • TTL forwarder :

    - ttl : time (in milliseconds),

    - updatingForwarder : boolean,

  • TTU agents :

    - maxMigrationNb : integer,

    - maxTimeOnSite : time (in milliseconds).

16.5.2. How to configure

As a default, ProActive uses a strategy "Forwarders based". It means that the forwarders have a unlimited lifetime and the agent never updates the location server.

16.5.2.1. Properties

To configure your own strategy, you have to edit the file src/org/objectweb/proactive/core/config/ProActiveConfiguration.xml. The four properties are the following :

  • proactive.mixedlocation.ttl

    the TTL value in milliseconds. Use -1 to indicate that the forwarders have a unlimited lifetime.

  • proactive.mixedlocation.updatingForwarder

    true or false.

  • proactive.mixedlocation.maxMigrationNb

    indicates the number of migrations without updating the server. Use -1 to indicate that the agent never updates the server.

  • proactive.mixedlocation.maxTimeOnSite

    the max time spent on a site before updating the server. You can use -1 to indicate that there is no limited time to spend on a site.

16.5.2.2. Location Server

A location server is available in the package org.objectweb.proactive.core.body.migration.MixedLocationServer. It can be launched using scripts/unix/migration/LocationServer. You can indicate on which node it have to be running.

Limitation : there can be only one LocationServer for the migration.