back to API     back to index     prev     next  

Active Object Migration

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

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 :

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.

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.

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.

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.

Copyright © April 2004 INRIA All Rights Reserved.