|
![]() |
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 :
migrateTo(Object o)
: migrate to the same location as an existing active objectmigrateTo(String nodeURL)
: migrate to the location given by the URL of the nodemigrateTo(Node node)
: migrate to the location of the given nodeThe 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 objectmigrateTo(Body body, String nodeURL, boolean priority)
: migrate to the location given by the URL of the nodemigrateTo(Body body, Node node, boolean priority)
: migrate to the location of the given nodeAny 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.
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.
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.
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
See theprivate void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException;
Serializable
interface in the standard JavaDoc to learn more.