Merge branch 'cpu-performance' of ssh://opensimulator.org/var/git/opensim into cpu-performance
commit
deace1f344
|
@ -287,7 +287,7 @@ namespace OpenSim.Framework
|
|||
public Vector3 AtAxis;
|
||||
public Vector3 LeftAxis;
|
||||
public Vector3 UpAxis;
|
||||
public bool ChangedGrid;
|
||||
public bool SenderWantsToWaitForRoot;
|
||||
|
||||
public float Far;
|
||||
public float Aspect;
|
||||
|
@ -356,8 +356,9 @@ namespace OpenSim.Framework
|
|||
args["left_axis"] = OSD.FromString(LeftAxis.ToString());
|
||||
args["up_axis"] = OSD.FromString(UpAxis.ToString());
|
||||
|
||||
|
||||
args["changed_grid"] = OSD.FromBoolean(ChangedGrid);
|
||||
//backwards compatibility
|
||||
args["changed_grid"] = OSD.FromBoolean(SenderWantsToWaitForRoot);
|
||||
args["wait_for_root"] = OSD.FromBoolean(SenderWantsToWaitForRoot);
|
||||
args["far"] = OSD.FromReal(Far);
|
||||
args["aspect"] = OSD.FromReal(Aspect);
|
||||
|
||||
|
@ -526,8 +527,8 @@ namespace OpenSim.Framework
|
|||
if (args["up_axis"] != null)
|
||||
Vector3.TryParse(args["up_axis"].AsString(), out AtAxis);
|
||||
|
||||
if (args["changed_grid"] != null)
|
||||
ChangedGrid = args["changed_grid"].AsBoolean();
|
||||
if (args.ContainsKey("wait_for_root") && args["wait_for_root"] != null)
|
||||
SenderWantsToWaitForRoot = args["wait_for_root"].AsBoolean();
|
||||
|
||||
if (args["far"] != null)
|
||||
Far = (float)(args["far"].AsReal());
|
||||
|
|
|
@ -1211,6 +1211,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
// UseCircuitCode handling
|
||||
if (packet.Type == PacketType.UseCircuitCode)
|
||||
{
|
||||
m_log.DebugFormat("[ZZZ]: In the dungeon: UseCircuitCode");
|
||||
// We need to copy the endpoint so that it doesn't get changed when another thread reuses the
|
||||
// buffer.
|
||||
object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
|
||||
|
@ -1219,6 +1220,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
return;
|
||||
}
|
||||
else if (packet.Type == PacketType.CompleteAgentMovement)
|
||||
{
|
||||
// Send ack straight away to let the viewer know that we got it.
|
||||
SendAckImmediate(endPoint, packet.Header.Sequence);
|
||||
|
||||
m_log.DebugFormat("[ZZZ]: In the dungeon: CompleteAgentMovement");
|
||||
// We need to copy the endpoint so that it doesn't get changed when another thread reuses the
|
||||
// buffer.
|
||||
object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
|
||||
|
||||
Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine which agent this packet came from
|
||||
IClientAPI client;
|
||||
|
@ -1557,6 +1572,56 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
}
|
||||
|
||||
private void HandleCompleteMovementIntoRegion(object o)
|
||||
{
|
||||
IPEndPoint endPoint = null;
|
||||
IClientAPI client = null;
|
||||
|
||||
try
|
||||
{
|
||||
object[] array = (object[])o;
|
||||
endPoint = (IPEndPoint)array[0];
|
||||
CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1];
|
||||
|
||||
// Determine which agent this packet came from
|
||||
int count = 10;
|
||||
while (!m_scene.TryGetClient(endPoint, out client) && count-- > 0)
|
||||
{
|
||||
m_log.Debug("[LLUDPSERVER]: Received a CompleteMovementIntoRegion in " + m_scene.RegionInfo.RegionName + " (not ready yet)");
|
||||
Thread.Sleep(200);
|
||||
}
|
||||
|
||||
if (client == null)
|
||||
return;
|
||||
|
||||
IncomingPacket incomingPacket1;
|
||||
|
||||
// Inbox insertion
|
||||
if (UsePools)
|
||||
{
|
||||
incomingPacket1 = m_incomingPacketPool.GetObject();
|
||||
incomingPacket1.Client = (LLClientView)client;
|
||||
incomingPacket1.Packet = packet;
|
||||
}
|
||||
else
|
||||
{
|
||||
incomingPacket1 = new IncomingPacket((LLClientView)client, packet);
|
||||
}
|
||||
|
||||
packetInbox.Enqueue(incomingPacket1);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[LLUDPSERVER]: CompleteMovementIntoRegion handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
|
||||
endPoint != null ? endPoint.ToString() : "n/a",
|
||||
client != null ? client.Name : "unknown",
|
||||
client != null ? client.AgentId.ToString() : "unknown",
|
||||
e.Message,
|
||||
e.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send an ack immediately to the given endpoint.
|
||||
/// </summary>
|
||||
|
@ -1949,6 +2014,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
Packet packet = incomingPacket.Packet;
|
||||
LLClientView client = incomingPacket.Client;
|
||||
|
||||
if (packet is CompleteAgentMovementPacket)
|
||||
m_log.DebugFormat("[ZZZ]: Received CompleteAgentMovementPacket");
|
||||
|
||||
if (client.IsActive)
|
||||
{
|
||||
m_currentIncomingClient = client;
|
||||
|
|
|
@ -684,8 +684,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
|
||||
}
|
||||
|
||||
//sp.ControllingClient.SendTeleportProgress(teleportFlags, "Contacting destination...");
|
||||
if (version.Equals("SIMULATION/0.2"))
|
||||
TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
|
||||
else
|
||||
TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
|
||||
|
||||
}
|
||||
|
||||
private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
|
||||
IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, string version, out string reason)
|
||||
{
|
||||
ulong destinationHandle = finalDestination.RegionHandle;
|
||||
AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
|
||||
|
||||
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Using TP V1");
|
||||
// Let's create an agent there if one doesn't exist yet.
|
||||
// NOTE: logout will always be false for a non-HG teleport.
|
||||
bool logout = false;
|
||||
|
@ -707,7 +719,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
m_interRegionTeleportCancels.Value++;
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
|
||||
"[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
|
||||
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||
|
||||
return;
|
||||
|
@ -726,13 +738,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
// Past this point we have to attempt clean up if the teleport fails, so update transfer state.
|
||||
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
|
||||
|
||||
#region old protocol
|
||||
// OK, it got this agent. Let's close some child agents
|
||||
sp.CloseChildAgents(newRegionX, newRegionY);
|
||||
|
||||
IClientIPEndpoint ipepClient;
|
||||
IClientIPEndpoint ipepClient;
|
||||
string capsPath = String.Empty;
|
||||
if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
|
||||
"[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
|
||||
finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
|
||||
|
||||
//sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
|
||||
|
@ -745,30 +759,30 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
#endregion
|
||||
capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
|
||||
|
||||
//if (m_eqModule != null)
|
||||
//{
|
||||
// // The EnableSimulator message makes the client establish a connection with the destination
|
||||
// // simulator by sending the initial UseCircuitCode UDP packet to the destination containing the
|
||||
// // correct circuit code.
|
||||
// m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID);
|
||||
if (m_eqModule != null)
|
||||
{
|
||||
// The EnableSimulator message makes the client establish a connection with the destination
|
||||
// simulator by sending the initial UseCircuitCode UDP packet to the destination containing the
|
||||
// correct circuit code.
|
||||
m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID);
|
||||
|
||||
// // XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination
|
||||
// // simulator to confirm that it has established communication with the viewer.
|
||||
// Thread.Sleep(200);
|
||||
// XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination
|
||||
// simulator to confirm that it has established communication with the viewer.
|
||||
Thread.Sleep(200);
|
||||
|
||||
// // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears
|
||||
// // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly
|
||||
// // only on TeleportFinish). This is untested for region teleport between different simulators
|
||||
// // though this probably also works.
|
||||
// m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// // XXX: This is a little misleading since we're information the client of its avatar destination,
|
||||
// // which may or may not be a neighbour region of the source region. This path is probably little
|
||||
// // used anyway (with EQ being the one used). But it is currently being used for test code.
|
||||
// sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
|
||||
//}
|
||||
// At least on LL 3.3.4 for teleports between different regions on the same simulator this appears
|
||||
// unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly
|
||||
// only on TeleportFinish). This is untested for region teleport between different simulators
|
||||
// though this probably also works.
|
||||
m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// XXX: This is a little misleading since we're information the client of its avatar destination,
|
||||
// which may or may not be a neighbour region of the source region. This path is probably little
|
||||
// used anyway (with EQ being the one used). But it is currently being used for test code.
|
||||
sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -776,15 +790,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
|
||||
}
|
||||
|
||||
#endregion old protocol
|
||||
|
||||
// Let's send a full update of the agent. This is a synchronous call.
|
||||
AgentData agent = new AgentData();
|
||||
sp.CopyTo(agent);
|
||||
agent.Position = position;
|
||||
//SetCallbackURL(agent, sp.Scene.RegionInfo);
|
||||
agent.Position = agentCircuit.startpos;
|
||||
SetCallbackURL(agent, sp.Scene.RegionInfo);
|
||||
|
||||
//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.
|
||||
|
@ -799,22 +810,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
return;
|
||||
}
|
||||
|
||||
// We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
|
||||
// where that neighbour simulator could otherwise request a child agent create on the source which then
|
||||
// closes our existing agent which is still signalled as root.
|
||||
sp.IsChildAgent = true;
|
||||
|
||||
// New protocol: send TP Finish directly, without prior ES or EAC. That's what happens in the Linden grid
|
||||
if (m_eqModule != null)
|
||||
{
|
||||
m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID);
|
||||
}
|
||||
else
|
||||
{
|
||||
sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
|
||||
teleportFlags, capsPath);
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -835,7 +830,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
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);
|
||||
|
||||
|
||||
Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
|
||||
return;
|
||||
}
|
||||
|
@ -845,7 +840,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
m_interRegionTeleportCancels.Value++;
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[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);
|
||||
|
||||
CleanupFailedInterRegionTeleport(sp, currentAgentCircuit.SessionID.ToString(), finalDestination);
|
||||
|
@ -857,30 +852,46 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
"[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
|
||||
capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
|
||||
|
||||
//// TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
|
||||
//// trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
|
||||
//// 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_interRegionTeleportAborts.Value++;
|
||||
// We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
|
||||
// where that neighbour simulator could otherwise request a child agent create on the source which then
|
||||
// closes our existing agent which is still signalled as root.
|
||||
sp.IsChildAgent = true;
|
||||
|
||||
// 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);
|
||||
// OK, send TPFinish to the client, so that it starts the process of contacting the destination region
|
||||
if (m_eqModule != null)
|
||||
{
|
||||
m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID);
|
||||
}
|
||||
else
|
||||
{
|
||||
sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
|
||||
teleportFlags, capsPath);
|
||||
}
|
||||
|
||||
// return;
|
||||
// }
|
||||
// TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
|
||||
// trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
|
||||
// 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_interRegionTeleportAborts.Value++;
|
||||
|
||||
// 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);
|
||||
|
||||
// Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Destination region did not signal teleport completion.");
|
||||
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;
|
||||
//}
|
||||
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);
|
||||
|
||||
Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Destination region did not signal teleport completion.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
|
||||
|
||||
|
@ -901,9 +912,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
// Now let's make it officially a child agent
|
||||
sp.MakeChildAgent();
|
||||
|
||||
// OK, it got this agent. Let's close some child agents
|
||||
sp.CloseChildAgents(newRegionX, newRegionY);
|
||||
|
||||
// Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
|
||||
|
||||
if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
|
||||
|
@ -914,7 +922,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
//
|
||||
// This sleep can be increased if necessary. However, whilst it's active,
|
||||
// an agent cannot teleport back to this region if it has teleported away.
|
||||
Thread.Sleep(15000);
|
||||
Thread.Sleep(2000);
|
||||
|
||||
sp.Scene.IncomingCloseAgent(sp.UUID, false);
|
||||
}
|
||||
|
@ -925,6 +933,126 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
}
|
||||
}
|
||||
|
||||
private void TransferAgent_V2(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
|
||||
IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, string version, out string reason)
|
||||
{
|
||||
ulong destinationHandle = finalDestination.RegionHandle;
|
||||
AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
|
||||
|
||||
// Let's create an agent there if one doesn't exist yet.
|
||||
// NOTE: logout will always be false for a non-HG teleport.
|
||||
bool logout = false;
|
||||
if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
|
||||
{
|
||||
m_interRegionTeleportFailures.Value++;
|
||||
|
||||
sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason));
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}",
|
||||
sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);
|
||||
|
||||
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);
|
||||
|
||||
IClientIPEndpoint ipepClient;
|
||||
string capsPath = String.Empty;
|
||||
if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}",
|
||||
finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
|
||||
|
||||
//sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
|
||||
#region IP Translation for NAT
|
||||
// Uses ipepClient above
|
||||
if (sp.ClientView.TryGet(out ipepClient))
|
||||
{
|
||||
endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
|
||||
}
|
||||
#endregion
|
||||
capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
|
||||
capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
|
||||
}
|
||||
|
||||
// We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
|
||||
// where that neighbour simulator could otherwise request a child agent create on the source which then
|
||||
// closes our existing agent which is still signalled as root.
|
||||
//sp.IsChildAgent = true;
|
||||
|
||||
// New protocol: send TP Finish directly, without prior ES or EAC. That's what happens in the Linden grid
|
||||
if (m_eqModule != null)
|
||||
m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID);
|
||||
else
|
||||
sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
|
||||
teleportFlags, capsPath);
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
|
||||
capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
|
||||
|
||||
// Let's send a full update of the agent.
|
||||
AgentData agent = new AgentData();
|
||||
sp.CopyTo(agent);
|
||||
agent.Position = agentCircuit.startpos;
|
||||
agent.SenderWantsToWaitForRoot = true;
|
||||
//SetCallbackURL(agent, sp.Scene.RegionInfo);
|
||||
|
||||
// Send the Update. If this returns true, we know the client has contacted the destination
|
||||
// via CompleteMovementIntoRegion, so we can let go.
|
||||
// If it returns false, something went wrong, and we need to abort.
|
||||
m_log.DebugFormat("[ZZZ]: Sending Update");
|
||||
if (!UpdateAgent(reg, finalDestination, agent, sp))
|
||||
{
|
||||
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
||||
{
|
||||
m_interRegionTeleportAborts.Value++;
|
||||
|
||||
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);
|
||||
|
||||
Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
|
||||
|
||||
// May need to logout or other cleanup
|
||||
AgentHasMovedAway(sp, logout);
|
||||
|
||||
// Well, this is it. The agent is over there.
|
||||
KillEntity(sp.Scene, sp.LocalId);
|
||||
|
||||
// Now let's make it officially a child agent
|
||||
sp.MakeChildAgent();
|
||||
|
||||
// OK, it got this agent. Let's close some child agents
|
||||
sp.CloseChildAgents(newRegionX, newRegionY);
|
||||
|
||||
// Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
|
||||
|
||||
if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
|
||||
sp.Scene.IncomingCloseAgent(sp.UUID, false);
|
||||
else
|
||||
// now we have a child agent in this region.
|
||||
sp.Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean up an inter-region teleport that did not complete, either because of simulator failure or cancellation.
|
||||
/// </summary>
|
||||
|
@ -936,13 +1064,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
/// <param name='finalDestination'></param>
|
||||
protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, string auth_token, GridRegion finalDestination)
|
||||
{
|
||||
m_log.DebugFormat("[ZZZ]: FAIL!");
|
||||
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
|
||||
|
||||
sp.IsChildAgent = false;
|
||||
ReInstantiateScripts(sp);
|
||||
|
||||
EnableChildAgents(sp);
|
||||
if (sp.IsChildAgent) // We had set it to child before attempted TP (V1)
|
||||
{
|
||||
sp.IsChildAgent = false;
|
||||
ReInstantiateScripts(sp);
|
||||
|
||||
EnableChildAgents(sp);
|
||||
}
|
||||
// Finally, kill the agent we just created at the destination.
|
||||
// XXX: Possibly this should be done asynchronously.
|
||||
Scene.SimulationService.CloseAgent(finalDestination, sp.UUID, auth_token);
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
|||
/// <summary>
|
||||
/// Version of this service
|
||||
/// </summary>
|
||||
private const string m_Version = "SIMULATION/0.1";
|
||||
private const string m_Version = "SIMULATION/0.2";
|
||||
|
||||
/// <summary>
|
||||
/// Map region ID to scene.
|
||||
|
|
|
@ -4206,6 +4206,20 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_log.WarnFormat("[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).", childAgentUpdate.UUID, cAgentData.SessionID);
|
||||
|
||||
childAgentUpdate.ChildAgentDataUpdate(cAgentData);
|
||||
|
||||
int ntimes = 20;
|
||||
if (cAgentData.SenderWantsToWaitForRoot)
|
||||
{
|
||||
while (childAgentUpdate.IsChildAgent && ntimes-- > 0)
|
||||
Thread.Sleep(500);
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits",
|
||||
childAgentUpdate.Name, childAgentUpdate.UUID, childAgentUpdate.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 20 - ntimes);
|
||||
|
||||
if (childAgentUpdate.IsChildAgent)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -4263,10 +4277,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_log.WarnFormat(
|
||||
"[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout",
|
||||
agentID, RegionInfo.RegionName);
|
||||
// else
|
||||
// m_log.DebugFormat(
|
||||
// "[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits",
|
||||
// sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 10 - ntimes);
|
||||
|
||||
return sp;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,9 @@ using System;
|
|||
using System.Xml;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Timers;
|
||||
using Timer = System.Timers.Timer;
|
||||
using OpenMetaverse;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
|
@ -1292,6 +1294,26 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
PhysicsActor.Size = new Vector3(0.45f, 0.6f, height);
|
||||
}
|
||||
|
||||
private bool WaitForUpdateAgent(IClientAPI client)
|
||||
{
|
||||
// Before UpdateAgent, m_originRegionID is UUID.Zero; after, it's non-Zero
|
||||
int count = 20;
|
||||
while (m_originRegionID.Equals(UUID.Zero) && count-- > 0)
|
||||
{
|
||||
m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.RegionInfo.RegionName);
|
||||
Thread.Sleep(200);
|
||||
}
|
||||
|
||||
if (m_originRegionID.Equals(UUID.Zero))
|
||||
{
|
||||
// Movement into region will fail
|
||||
m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived", client.Name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Complete Avatar's movement into the region.
|
||||
/// </summary>
|
||||
|
@ -1309,6 +1331,13 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
"[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
|
||||
client.Name, Scene.RegionInfo.RegionName, AbsolutePosition);
|
||||
|
||||
// Make sure it's not a login agent. We don't want to wait for updates during login
|
||||
if ((m_teleportFlags & TeleportFlags.ViaLogin) == 0)
|
||||
// Let's wait until UpdateAgent (called by departing region) is done
|
||||
if (!WaitForUpdateAgent(client))
|
||||
// The sending region never sent the UpdateAgent data, we have to refuse
|
||||
return;
|
||||
|
||||
Vector3 look = Velocity;
|
||||
|
||||
if ((look.X == 0) && (look.Y == 0) && (look.Z == 0))
|
||||
|
@ -1329,10 +1358,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
|
||||
MakeRootAgent(AbsolutePosition, flying);
|
||||
|
||||
// Tell the client that we're totally ready
|
||||
ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
|
||||
|
||||
// Remember in HandleUseCircuitCode, we delayed this to here
|
||||
// This will also send the initial data to clients when TP to a neighboring region.
|
||||
// Not ideal, but until we know we're TP-ing from a neighboring region, there's not much we can do
|
||||
if (m_teleportFlags > 0)
|
||||
SendInitialDataToMe();
|
||||
|
||||
|
|
Loading…
Reference in New Issue