Merge branch 'master' into careminster

avinationmerge
Melanie 2013-03-22 01:02:17 +00:00
commit d5e5c13f3b
2 changed files with 67 additions and 10 deletions

View File

@ -167,6 +167,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (!DisableInterRegionTeleportCancellation)
client.OnTeleportCancel += OnClientCancelTeleport;
client.OnConnectionClosed += OnConnectionClosed;
}
public virtual void Close() {}
@ -185,6 +187,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
#region Agent Teleports
private void OnConnectionClosed(IClientAPI client)
{
if (client.IsLoggingOut)
{
m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting);
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout",
client.Name, Scene.Name);
}
}
private void OnClientCancelTeleport(IClientAPI client)
{
m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Cancelling);
@ -603,6 +617,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return;
}
else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
{
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
sp.Name, finalDestination.RegionName, sp.Scene.Name);
return;
}
// Past this point we have to attempt clean up if the teleport fails, so update transfer state.
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
@ -662,12 +684,32 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
//sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
// We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to
// establish th econnection to the destination which makes it return true.
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
{
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent",
sp.Name, finalDestination.RegionName, sp.Scene.Name);
return;
}
// A common teleport failure occurs when we can send CreateAgent to the
// destination region but the viewer cannot establish the connection (e.g. due to network issues between
// the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then
// there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail().
if (!UpdateAgent(reg, finalDestination, agent, sp))
{
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
{
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
sp.Name, finalDestination.RegionName, sp.Scene.Name);
return;
}
m_log.WarnFormat(
"[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.",
sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
@ -682,7 +724,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
"[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
sp.Name, finalDestination.RegionName, sp.Scene.Name);
CleanupAbortedInterRegionTeleport(sp, finalDestination);
CleanupFailedInterRegionTeleport(sp, finalDestination);
return;
}
@ -711,6 +753,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// that the client contacted the destination before we close things here.
if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID))
{
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
{
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.",
sp.Name, finalDestination.RegionName, sp.Scene.Name);
return;
}
m_log.WarnFormat(
"[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.",
sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
@ -777,7 +828,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// <remarks>
/// <param name='sp'> </param>
/// <param name='finalDestination'></param>
protected virtual void CleanupAbortedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination)
protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination)
{
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
@ -799,7 +850,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param>
protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason)
{
CleanupAbortedInterRegionTeleport(sp, finalDestination);
CleanupFailedInterRegionTeleport(sp, finalDestination);
sp.ControllingClient.SendTeleportFailed(
string.Format(

View File

@ -51,11 +51,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// This is a state machine.
///
/// [Entry] => Preparing
/// Preparing => { Transferring || Cancelling || CleaningUp || [Exit] }
/// Transferring => { ReceivedAtDestination || Cancelling || CleaningUp }
/// Cancelling => CleaningUp
/// ReceivedAtDestination => CleaningUp
/// Preparing => { Transferring || Cancelling || CleaningUp || Aborting || [Exit] }
/// Transferring => { ReceivedAtDestination || Cancelling || CleaningUp || Aborting }
/// Cancelling => CleaningUp || Aborting
/// ReceivedAtDestination => CleaningUp || Aborting
/// CleaningUp => [Exit]
/// Aborting => [Exit]
///
/// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp
/// However, any state can transition to CleaningUp if the teleport has failed.
@ -66,7 +67,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
Transferring, // The agent is in the process of being transferred to a destination
ReceivedAtDestination, // The destination has notified us that the agent has been successfully received
CleaningUp, // The agent is being changed to child/removed after a transfer
Cancelling // The user has cancelled the teleport but we have yet to act upon this.
Cancelling, // The user has cancelled the teleport but we have yet to act upon this.
Aborting // The transfer is aborting. Unlike Cancelling, no compensating actions should be performed
}
/// <summary>
@ -134,7 +136,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// Illegal to try and update an agent that's not actually in transit.
if (!m_agentsInTransit.ContainsKey(id))
{
if (newState != AgentTransferState.Cancelling)
if (newState != AgentTransferState.Cancelling && newState != AgentTransferState.Aborting)
failureMessage = string.Format(
"Agent with ID {0} is not registered as in transit in {1}",
id, m_mod.Scene.RegionInfo.RegionName);
@ -145,7 +147,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{
oldState = m_agentsInTransit[id];
if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp)
if (newState == AgentTransferState.Aborting)
{
transitionOkay = true;
}
else if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp)
{
transitionOkay = true;
}