Location where = (Location)params[1];
if(myLogger.isLoggable(Logger.CONFIG))
myLogger.log(Logger.CONFIG,"Moving agent " + agentID.getName() + " on container " + where.getName());
Agent a = myContainer.acquireLocalAgent(agentID);
if (a == null) {
myLogger.log(Logger.SEVERE,"Internal error: handleMove() called with a wrong name (" + agentID.getName() + ") !!!");
return;
}
int transferState = 0;
List messages = new ArrayList();
AgentMobilitySlice dest = null;
try {
// If the destination container is the same as this one, there is nothing to do
if (CaseInsensitiveString.equalsIgnoreCase(where.getName(), myContainer.here().getName())) {
return;
}
dest = (AgentMobilitySlice) getSlice(where.getName());
if (dest == null) {
myLogger.log(Logger.SEVERE,"Destination "+where.getName()+" does not exist or does not support mobility");
return;
}
if(myLogger.isLoggable(Logger.FINE)) {
myLogger.log(Logger.FINE,"Destination container for agent " + agentID + " found");
}
transferState = 1;
// Serialize the agent
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream encoder = new ObjectOutputStream(out);
encoder.writeObject(a);
byte[] bytes = out.toByteArray();
if(myLogger.isLoggable(Logger.FINE)) {
myLogger.log(Logger.FINE,"Agent " + agentID.getName() + " correctly serialized");
}
// Gets the container where the agent classes can be retrieved (possibly the agent arrived in this container from another container)
String classSiteName = (String)sites.get(a);
if (classSiteName == null) {
// The agent was born on this container
classSiteName = getLocalNode().getName();
}
// Create the agent on the destination container
try {
dest.createAgent(agentID, bytes, classSiteName, MIGRATION, CREATE_ONLY);
}
catch(IMTPException imtpe) {
// Try to get a newer slice and repeat...
dest = (AgentMobilitySlice)getFreshSlice(where.getName());
dest.createAgent(agentID, bytes, classSiteName, MIGRATION, CREATE_ONLY);
}
transferState = 2;
if(myLogger.isLoggable(Logger.FINE)) {
myLogger.log(Logger.FINE,"Agent " + agentID.getName() + " correctly created on destination container");
}
AgentMobilitySlice mainSlice = (AgentMobilitySlice)getSlice(MAIN_SLICE);
// Perform an atomic transaction for agent identity transfer
// From now on, messages for the moving agent will be routed to the
// destination container
boolean transferResult = false;
try {
transferResult = mainSlice.transferIdentity(agentID, (ContainerID) myContainer.here(), (ContainerID) where);
}
catch(IMTPException imtpe) {
// Try to get a newer slice and repeat...
mainSlice = (AgentMobilitySlice)getFreshSlice(MAIN_SLICE);
transferResult = mainSlice.transferIdentity(agentID, (ContainerID) myContainer.here(), (ContainerID) where);
}
transferState = 3;
if (transferResult == TRANSFER_COMMIT) {
if(myLogger.isLoggable(Logger.FINE)) {
myLogger.log(Logger.FINE,"Identity of agent " + agentID.getName() + " correctly transferred");
}
// Send received messages to the destination container. Note that
// there is no synchronization problem as the agent is locked in the LADT
myContainer.fillListFromMessageQueue(messages, a);
dest.handleTransferResult(agentID, transferResult, messages);
try {
// Cause the termination of the agent thread
a.changeStateTo(new LifeCycle(AP_GONE) {
public boolean alive() {
return false;
}
});
// Remove the gone agent from the LADT
myContainer.removeLocalAgent(a.getAID());
}
catch (Exception e) {
// Should never happen
e.printStackTrace();
}
sites.remove(a);
if(myLogger.isLoggable(Logger.FINE)) {
myLogger.log(Logger.FINE,"Agent " + agentID.getName() + " correctly gone");
}
}
else {
myLogger.log(Logger.WARNING,"Error transferring identity of agent " + agentID.getName());
a.restoreBufferedState();
dest.handleTransferResult(agentID, transferResult, messages);
myLogger.log(Logger.WARNING,"Migration of agent " + agentID.getName() + "aborted");
}
}
//#DOTNET_EXCLUDE_BEGIN
catch (IOException ioe) {
// Error in agent serialization
myLogger.log(Logger.SEVERE,"Error in agent serialization. Abort transfer. " + ioe);
}
catch (JADESecurityException ae) {
// Permission to move not owned
myLogger.log(Logger.SEVERE,"Permission to move not owned. Abort transfer. " + ae.getMessage());
}
catch(NotFoundException nfe) {
if(transferState == 0) {
myLogger.log(Logger.SEVERE,"Destination container does not exist. Abort transfer. " + nfe.getMessage());
}
else if(transferState == 2) {
myLogger.log(Logger.SEVERE,"Transferring agent does not seem to be part of the platform. Abort transfer. " + nfe.getMessage());
}
else if(transferState == 3) {
// PANIC !!!
myLogger.log(Logger.SEVERE,"Transferred agent not found on destination container. Can't roll back. " + nfe.getMessage());
}
}
catch(NameClashException nce) {
// This should not happen, because the agent is not changing its name but just its location...
nce.printStackTrace();
}
catch(IMTPException imtpe) {
// Unexpected remote error
if (transferState == 0) {
myLogger.log(Logger.SEVERE,"Can't retrieve destination container. Abort transfer. " + imtpe.getMessage());
}
else if (transferState == 1) {
myLogger.log(Logger.SEVERE,"Error creating agent on destination container. Abort transfer. " + imtpe.getMessage());
}
else if (transferState == 2) {
myLogger.log(Logger.SEVERE,"Error transferring agent identity. Abort transfer. " + imtpe.getMessage());
try {
dest.handleTransferResult(agentID, TRANSFER_ABORT, messages);
}
catch (Exception e) {
e.printStackTrace();
}
}
else if (transferState == 3) {
// PANIC !!!
myLogger.log(Logger.SEVERE,"Error activating transferred agent. Can't roll back!!!. " + imtpe.getMessage());
}
}
//#DOTNET_EXCLUDE_END
/*#DOTNET_INCLUDE_BEGIN
catch(System.Exception exc)
{
if(myLogger.isLoggable(Logger.SEVERE))
myLogger.log(Logger.SEVERE,"Error in agent serialization. Abort transfer. " + exc.get_Message());
}
#DOTNET_INCLUDE_END*/
finally {
if (transferState <= 2) {
// Something went wrong --> Roll back.
a.restoreBufferedState();
}
myContainer.releaseLocalAgent(agentID);
}
}