Make reset of EntityTransferStateMachine for an avatar transfer always happen despite unexpected exceptions.

This means that if such an exception does occur, the region does not need to be reset before that user can teleport from it again.
This is all Oren's code from his patch in http://opensimulator.org/mantis/view.php?id=6374 but I've chosen to split it in two.
0.7.4-extended
Justin Clark-Casey (justincc) 2013-02-22 21:59:00 +00:00
parent 2bde9e4f89
commit 772a0d785d
1 changed files with 81 additions and 42 deletions

View File

@ -177,13 +177,24 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (!sp.Scene.Permissions.CanTeleport(sp.UUID)) if (!sp.Scene.Permissions.CanTeleport(sp.UUID))
return; return;
// Reset animations; the viewer does that in teleports.
sp.Animator.ResetAnimations();
string destinationRegionName = "(not found)"; string destinationRegionName = "(not found)";
// Record that this agent is in transit so that we can prevent simultaneous requests and do later detection
// of whether the destination region completes the teleport.
if (!m_entityTransferStateMachine.SetInTransit(sp.UUID))
{
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2}@{3} - agent is already in transit.",
sp.Name, sp.UUID, position, regionHandle);
return;
}
try try
{ {
// Reset animations; the viewer does that in teleports.
sp.Animator.ResetAnimations();
if (regionHandle == sp.Scene.RegionInfo.RegionHandle) if (regionHandle == sp.Scene.RegionInfo.RegionHandle)
{ {
destinationRegionName = sp.Scene.RegionInfo.RegionName; destinationRegionName = sp.Scene.RegionInfo.RegionName;
@ -192,14 +203,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
} }
else // Another region possibly in another simulator else // Another region possibly in another simulator
{ {
GridRegion finalDestination; GridRegion finalDestination = null;
try
{
TeleportAgentToDifferentRegion( TeleportAgentToDifferentRegion(
sp, regionHandle, position, lookAt, teleportFlags, out finalDestination); sp, regionHandle, position, lookAt, teleportFlags, out finalDestination);
}
finally
{
if (finalDestination != null) if (finalDestination != null)
destinationRegionName = finalDestination.RegionName; destinationRegionName = finalDestination.RegionName;
} }
} }
}
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat( m_log.ErrorFormat(
@ -207,11 +223,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName, sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName,
e.Message, e.StackTrace); e.Message, e.StackTrace);
// Make sure that we clear the in-transit flag so that future teleport attempts don't always fail.
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
sp.ControllingClient.SendTeleportFailed("Internal error"); sp.ControllingClient.SendTeleportFailed("Internal error");
} }
finally
{
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
}
} }
/// <summary> /// <summary>
@ -227,15 +244,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
"[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}", "[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}",
sp.Name, position, sp.Scene.RegionInfo.RegionName); sp.Name, position, sp.Scene.RegionInfo.RegionName);
if (!m_entityTransferStateMachine.SetInTransit(sp.UUID))
{
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Ignoring within region teleport request of {0} {1} to {2} - agent is already in transit.",
sp.Name, sp.UUID, position);
return;
}
// Teleport within the same region // Teleport within the same region
if (IsOutsideRegion(sp.Scene, position) || position.Z < 0) if (IsOutsideRegion(sp.Scene, position) || position.Z < 0)
{ {
@ -280,7 +288,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
} }
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
} }
/// <summary> /// <summary>
@ -326,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// //
// This is it // This is it
// //
DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags); DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags);
// //
// //
// //
@ -374,6 +381,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
&& Math.Abs(sourceRegion.RegionLocY - destRegion.RegionCoordY) <= MaxTransferDistance; && Math.Abs(sourceRegion.RegionLocY - destRegion.RegionCoordY) <= MaxTransferDistance;
} }
/// <summary>
/// Wraps DoTeleportInternal() and manages the transfer state.
/// </summary>
public void DoTeleport( public void DoTeleport(
ScenePresence sp, GridRegion reg, GridRegion finalDestination, ScenePresence sp, GridRegion reg, GridRegion finalDestination,
Vector3 position, Vector3 lookAt, uint teleportFlags) Vector3 position, Vector3 lookAt, uint teleportFlags)
@ -389,11 +399,36 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return; return;
} }
try
{
DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[ENTITY TRANSFER MODULE]: Exception on teleport of {0} from {1}@{2} to {3}@{4}: {5}{6}",
sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, finalDestination.RegionName,
e.Message, e.StackTrace);
sp.ControllingClient.SendTeleportFailed("Internal error");
}
finally
{
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
}
}
/// <summary>
/// Teleports the agent to another region.
/// This method doesn't manage the transfer state; the caller must do that.
/// </summary>
private void DoTeleportInternal(
ScenePresence sp, GridRegion reg, GridRegion finalDestination,
Vector3 position, Vector3 lookAt, uint teleportFlags)
{
if (reg == null || finalDestination == null) if (reg == null || finalDestination == null)
{ {
sp.ControllingClient.SendTeleportFailed("Unable to locate destination"); sp.ControllingClient.SendTeleportFailed("Unable to locate destination");
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
return; return;
} }
@ -413,8 +448,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY, sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY,
MaxTransferDistance)); MaxTransferDistance));
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
return; return;
} }
@ -433,7 +466,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (endPoint.Address == null) if (endPoint.Address == null)
{ {
sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
return; return;
} }
@ -455,7 +487,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason)) finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason))
{ {
sp.ControllingClient.SendTeleportFailed(reason); sp.ControllingClient.SendTeleportFailed(reason);
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
m_log.DebugFormat( m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}", "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}",
@ -511,7 +542,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
{ {
sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason)); sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason));
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
m_log.DebugFormat( m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}", "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}",
@ -665,8 +695,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", // "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
// sp.UUID); // sp.UUID);
// } // }
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
} }
protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout) protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout)
@ -686,8 +714,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
Scene.SimulationService.CloseAgent(finalDestination, sp.UUID); Scene.SimulationService.CloseAgent(finalDestination, sp.UUID);
sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout); sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout);
m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
} }
protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout)
@ -1104,10 +1130,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (neighbourRegion == null) if (neighbourRegion == null)
return agent; return agent;
if (!m_entityTransferStateMachine.SetInTransit(agent.UUID))
{
m_log.ErrorFormat(
"[ENTITY TRANSFER MODULE]: Problem crossing user {0} to new region {1} from {2} - agent is already in transit",
agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName);
return agent;
}
bool transitWasReset = false;
try try
{ {
m_entityTransferStateMachine.SetInTransit(agent.UUID);
ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
m_log.DebugFormat( m_log.DebugFormat(
@ -1145,7 +1179,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
ReInstantiateScripts(agent); ReInstantiateScripts(agent);
agent.AddToPhysicalScene(isFlying); agent.AddToPhysicalScene(isFlying);
m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
return agent; return agent;
} }
@ -1193,6 +1226,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// FIXME: Possibly this should occur lower down after other commands to close other agents, // FIXME: Possibly this should occur lower down after other commands to close other agents,
// but not sure yet what the side effects would be. // but not sure yet what the side effects would be.
m_entityTransferStateMachine.ResetFromTransit(agent.UUID); m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
transitWasReset = true;
// now we have a child agent in this region. Request all interesting data about other (root) agents // now we have a child agent in this region. Request all interesting data about other (root) agents
agent.SendOtherAgentsAvatarDataToMe(); agent.SendOtherAgentsAvatarDataToMe();
@ -1232,6 +1266,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// TODO: Might be worth attempting other restoration here such as reinstantiation of scripts, etc. // TODO: Might be worth attempting other restoration here such as reinstantiation of scripts, etc.
} }
finally
{
if (!transitWasReset)
m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
}
return agent; return agent;
} }