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) if (!DisableInterRegionTeleportCancellation)
client.OnTeleportCancel += OnClientCancelTeleport; client.OnTeleportCancel += OnClientCancelTeleport;
client.OnConnectionClosed += OnConnectionClosed;
} }
public virtual void Close() {} public virtual void Close() {}
@ -185,6 +187,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
#region Agent Teleports #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) private void OnClientCancelTeleport(IClientAPI client)
{ {
m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Cancelling); m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Cancelling);
@ -603,6 +617,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return; 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. // Past this point we have to attempt clean up if the teleport fails, so update transfer state.
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
@ -662,12 +684,32 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
//sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); //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 // 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 // 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 // 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(). // 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 (!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( m_log.WarnFormat(
"[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", "[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); 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", "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
sp.Name, finalDestination.RegionName, sp.Scene.Name); sp.Name, finalDestination.RegionName, sp.Scene.Name);
CleanupAbortedInterRegionTeleport(sp, finalDestination); CleanupFailedInterRegionTeleport(sp, finalDestination);
return; return;
} }
@ -711,6 +753,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// that the client contacted the destination before we close things here. // that the client contacted the destination before we close things here.
if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID)) 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( 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.", "[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); sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
@ -777,7 +828,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// <remarks> /// <remarks>
/// <param name='sp'> </param> /// <param name='sp'> </param>
/// <param name='finalDestination'></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); 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> /// <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) protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason)
{ {
CleanupAbortedInterRegionTeleport(sp, finalDestination); CleanupFailedInterRegionTeleport(sp, finalDestination);
sp.ControllingClient.SendTeleportFailed( sp.ControllingClient.SendTeleportFailed(
string.Format( string.Format(

View File

@ -51,11 +51,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// This is a state machine. /// This is a state machine.
/// ///
/// [Entry] => Preparing /// [Entry] => Preparing
/// Preparing => { Transferring || Cancelling || CleaningUp || [Exit] } /// Preparing => { Transferring || Cancelling || CleaningUp || Aborting || [Exit] }
/// Transferring => { ReceivedAtDestination || Cancelling || CleaningUp } /// Transferring => { ReceivedAtDestination || Cancelling || CleaningUp || Aborting }
/// Cancelling => CleaningUp /// Cancelling => CleaningUp || Aborting
/// ReceivedAtDestination => CleaningUp /// ReceivedAtDestination => CleaningUp || Aborting
/// CleaningUp => [Exit] /// CleaningUp => [Exit]
/// Aborting => [Exit]
/// ///
/// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp /// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp
/// However, any state can transition to CleaningUp if the teleport has failed. /// 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 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 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 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> /// <summary>
@ -134,7 +136,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// Illegal to try and update an agent that's not actually in transit. // Illegal to try and update an agent that's not actually in transit.
if (!m_agentsInTransit.ContainsKey(id)) if (!m_agentsInTransit.ContainsKey(id))
{ {
if (newState != AgentTransferState.Cancelling) if (newState != AgentTransferState.Cancelling && newState != AgentTransferState.Aborting)
failureMessage = string.Format( failureMessage = string.Format(
"Agent with ID {0} is not registered as in transit in {1}", "Agent with ID {0} is not registered as in transit in {1}",
id, m_mod.Scene.RegionInfo.RegionName); id, m_mod.Scene.RegionInfo.RegionName);
@ -145,7 +147,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{ {
oldState = m_agentsInTransit[id]; 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; transitionOkay = true;
} }