From c68e7b66218a6f85fdca71be2740bf9a15e92f37 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 31 May 2017 23:31:02 +0100 Subject: change child agents close control; disablesimulator is not a caps event message --- .../Linden/Caps/EventQueue/EventQueueGetModule.cs | 4 +- .../Linden/Caps/EventQueue/EventQueueHelper.cs | 4 +- .../EntityTransfer/EntityTransferModule.cs | 214 +++++++++------------ OpenSim/Region/Framework/Interfaces/IEventQueue.cs | 2 +- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 64 +++--- .../Tests/Common/Mock/TestEventQueueGetModule.cs | 4 +- 6 files changed, 128 insertions(+), 164 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 1feece1..7c9a1c4 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs @@ -500,13 +500,13 @@ namespace OpenSim.Region.ClientStack.Linden responsedata["http_protocol_version"] = "HTTP/1.0"; return responsedata; } - +/* this is not a event message public void DisableSimulator(ulong handle, UUID avatarID) { OSD item = EventQueueHelper.DisableSimulator(handle); Enqueue(item, avatarID); } - +*/ public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY) { if (DebugLevel > 0) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs index e1e88ae..461f776 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs @@ -90,7 +90,7 @@ namespace OpenSim.Region.ClientStack.Linden return BuildEvent("EnableSimulator", llsdBody); } - +/* public static OSD DisableSimulator(ulong handle) { //OSDMap llsdSimInfo = new OSDMap(1); @@ -105,7 +105,7 @@ namespace OpenSim.Region.ClientStack.Linden return BuildEvent("DisableSimulator", llsdBody); } - +*/ public static OSD CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, IPEndPoint newRegionExternalEndPoint, string capsURL, UUID agentID, UUID sessionID, diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index a1ada4c..bcf4322 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -843,6 +843,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.Name, Scene.Name, finalDestination.RegionName); string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + List<ulong> childRegionsToClose = sp.GetChildAgentsToClose(destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY); + foreach(ulong handler in childRegionsToClose) + { + agentCircuit.ChildrenCapSeeds.Remove(handler); + } // Let's create an agent there if one doesn't exist yet. // NOTE: logout will always be false for a non-HG teleport. @@ -1026,7 +1031,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } - /* // TODO: This may be 0.6. Check if still needed // For backwards compatibility @@ -1040,7 +1044,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); - sp.CloseChildAgents(logout, destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY); + if(logout) + sp.closeAllChildAgents(); + else + sp.CloseChildAgents(childRegionsToClose); // call HG hook AgentHasMovedAway(sp, logout); @@ -1066,9 +1073,6 @@ 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(2000); -// if (m_eqModule != null && !sp.DoNotCloseAfterTeleport) -// m_eqModule.DisableSimulator(sourceRegionHandle,sp.UUID); - Thread.Sleep(500); sp.Scene.CloseAgent(sp.UUID, false); } sp.IsInTransit = false; @@ -1078,7 +1082,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer IPEndPoint endPoint, uint teleportFlags, bool OutSideViewRange, EntityTransferContext ctx, out string reason) { ulong destinationHandle = finalDestination.RegionHandle; - AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); + + List<ulong> childRegionsToClose = sp.GetChildAgentsToClose(destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY); + foreach(ulong handler in childRegionsToClose) + { + agentCircuit.ChildrenCapSeeds.Remove(handler); + } string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);; @@ -1178,20 +1187,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}", sp.Name, finalDestination.RegionName, sp.Scene.Name); - Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); + Fail(sp, finalDestination, logout, agentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); sp.IsInTransit = false; return; } m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); - // Need to signal neighbours whether child agents may need closing irrespective of whether this - // one needed closing. We also need to close child agents as quickly as possible to avoid complicated - // race conditions with rapid agent releporting (e.g. from A1 to a non-neighbour B, back - // to a neighbour A2 then off to a non-neighbour C). Closing child agents any later requires complex - // distributed checks to avoid problems in rapid reteleporting scenarios and where child agents are - // abandoned without proper close by viewer but then re-used by an incoming connection. - sp.CloseChildAgents(logout, destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY); + if(logout) + sp.closeAllChildAgents(); + else + sp.CloseChildAgents(childRegionsToClose); sp.HasMovedAway(!(OutSideViewRange || logout)); @@ -1217,10 +1223,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // DECREASING THE WAIT TIME HERE WILL EITHER RESULT IN A VIEWER CRASH OR // IN THE AVIE BEING PLACED IN INFINITY FOR A COUPLE OF SECONDS. - Thread.Sleep(25000); -// if (m_eqModule != null && !sp.DoNotCloseAfterTeleport) -// m_eqModule.DisableSimulator(sourceRegionHandle,sp.UUID); -// Thread.Sleep(1000); + Thread.Sleep(15000); // OK, it got this agent. Let's close everything // If we shouldn't close the agent due to some other region renewing the connection @@ -1230,13 +1233,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.Scene.CloseAgent(sp.UUID, false); } -/* - else - { - // now we have a child agent in this region. - sp.Reset(); - } - */ sp.IsInTransit = false; } @@ -1641,54 +1637,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer icon.EndInvoke(iar); } - - - /// <summary> - /// This Closes child agents on neighbouring regions - /// Calls an asynchronous method to do so.. so it doesn't lag the sim. - /// </summary> - public ScenePresence CrossAgentToNewRegionAsync( - ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, - bool isFlying, EntityTransferContext ctx) - { - try - { - m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: new region={1} at <{2},{3}>. newpos={4}", - LogHeader, neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, pos); - - if (neighbourRegion == null) - { - m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: invalid destiny", LogHeader); - return agent; - } - - IPEndPoint endpoint = neighbourRegion.ExternalEndPoint; - if(endpoint == null) - { - m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: failed to resolve neighbour address {0} ",neighbourRegion.ExternalHostName); - return agent; - } - - m_entityTransferStateMachine.SetInTransit(agent.UUID); - agent.RemoveFromPhysicalScene(); - - if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying, ctx)) - { - m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader); - m_entityTransferStateMachine.ResetFromTransit(agent.UUID); - return agent; - } - - CrossAgentToNewRegionPost(agent, pos, neighbourRegion, endpoint, isFlying, ctx); - } - catch (Exception e) - { - m_log.Error(string.Format("{0}: CrossAgentToNewRegionAsync: failed with exception ", LogHeader), e); - } - - return agent; - } - public bool CrossAgentCreateFarChild(ScenePresence agent, GridRegion neighbourRegion, Vector3 pos, EntityTransferContext ctx) { ulong regionhandler = neighbourRegion.RegionHandle; @@ -1728,50 +1676,96 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer m_log.DebugFormat("CrossAgentCreateFarChild failed to resolve neighbour address {0}", neighbourRegion.ExternalHostName); return false; } - if (Scene.SimulationService.CreateAgent(source, neighbourRegion, agentCircuit, (int)TeleportFlags.Default, ctx, out reason)) + if (!Scene.SimulationService.CreateAgent(source, neighbourRegion, agentCircuit, (int)TeleportFlags.Default, ctx, out reason)) + { + agent.RemoveNeighbourRegion(regionhandler); + return false; + } + + string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + int newSizeX = neighbourRegion.RegionSizeX; + int newSizeY = neighbourRegion.RegionSizeY; + + if (m_eqModule != null) { - string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); - int newSizeX = neighbourRegion.RegionSizeX; - int newSizeY = neighbourRegion.RegionSizeY; + m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " + + "and EstablishAgentCommunication with seed cap {8}", LogHeader, + source.RegionName, agent.Name, + neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, newSizeX, newSizeY , capsPath); - if (m_eqModule != null) + m_eqModule.EnableSimulator(regionhandler, + endPoint, agent.UUID, newSizeX, newSizeY); + m_eqModule.EstablishAgentCommunication(agent.UUID, endPoint, capsPath, + regionhandler, newSizeX, newSizeY); + } + else + { + agent.ControllingClient.InformClientOfNeighbour(regionhandler, endPoint); + } + return true; + } + + /// <summary> + /// This Closes child agents on neighbouring regions + /// Calls an asynchronous method to do so.. so it doesn't lag the sim. + /// </summary> + public ScenePresence CrossAgentToNewRegionAsync( + ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, + bool isFlying, EntityTransferContext ctx) + { + try + { + m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: new region={1} at <{2},{3}>. newpos={4}", + LogHeader, neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, pos); + + if (neighbourRegion == null) { - m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " + - "and EstablishAgentCommunication with seed cap {8}", LogHeader, - source.RegionName, agent.Name, - neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, newSizeX, newSizeY , capsPath); - - m_eqModule.EnableSimulator(regionhandler, - endPoint, agent.UUID, newSizeX, newSizeY); - m_eqModule.EstablishAgentCommunication(agent.UUID, endPoint, capsPath, - regionhandler, newSizeX, newSizeY); + m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: invalid destiny", LogHeader); + return agent; } - else + + IPEndPoint endpoint = neighbourRegion.ExternalEndPoint; + if(endpoint == null) { - agent.ControllingClient.InformClientOfNeighbour(regionhandler, endPoint); + m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: failed to resolve neighbour address {0} ",neighbourRegion.ExternalHostName); + return agent; + } + + m_entityTransferStateMachine.SetInTransit(agent.UUID); + agent.RemoveFromPhysicalScene(); + + if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, endpoint, isFlying, ctx)) + { + m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader); + m_entityTransferStateMachine.ResetFromTransit(agent.UUID); } - return true; } - agent.RemoveNeighbourRegion(regionhandler); - return false; + catch (Exception e) + { + m_log.Error(string.Format("{0}: CrossAgentToNewRegionAsync: failed with exception ", LogHeader), e); + } + return agent; } - public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx) + public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, + IPEndPoint endpoint, bool isFlying, EntityTransferContext ctx) { int ts = Util.EnvironmentTickCount(); bool sucess = true; string reason = String.Empty; + List<ulong> childRegionsToClose = null; try { - AgentData cAgent = new AgentData(); agent.CopyTo(cAgent,true); -// agent.Appearance.WearableCacheItems = null; - cAgent.Position = pos; cAgent.ChildrenCapSeeds = agent.KnownRegions; + childRegionsToClose = agent.GetChildAgentsToClose(neighbourRegion.RegionHandle, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY); + foreach(ulong regh in childRegionsToClose) + cAgent.ChildrenCapSeeds.Remove(regh); + if (isFlying) cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; @@ -1806,7 +1800,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } m_log.DebugFormat("[CrossAgentIntoNewRegionMain] ok, time {0}ms",Util.EnvironmentTickCountSubtract(ts)); - } catch (Exception e) { @@ -1818,19 +1811,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return false; } - return true; - } - - public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, - IPEndPoint endpoint, bool isFlying, EntityTransferContext ctx) - { - string agentcaps; if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps)) { m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.", neighbourRegion.RegionHandle); - return; + return false; } // No turning back @@ -1865,7 +1851,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); - agent.CloseChildAgents(false, neighbourRegion.RegionHandle, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY); + if(childRegionsToClose != null) + agent.CloseChildAgents(childRegionsToClose); // this may need the attachments @@ -1877,20 +1864,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // but not sure yet what the side effects would be. m_entityTransferStateMachine.ResetFromTransit(agent.UUID); - // the user may change their profile information in other region, - // so the userinfo in UserProfileCache is not reliable any more, delete it - // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! -// if (agent.Scene.NeedSceneCacheClear(agent.UUID)) -// { -// m_log.DebugFormat( -// "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); -// } - - //m_log.Debug("AFTER CROSS"); - //Scene.DumpChildrenSeeds(UUID); - //DumpKnownRegions(); - - return; + return true; } private void CrossAgentToNewRegionCompleted(IAsyncResult iar) diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs index 7af56cb..7edd75a 100644 --- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs +++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs @@ -39,7 +39,7 @@ namespace OpenSim.Region.Framework.Interfaces bool Enqueue(OSD o, UUID avatarID); // These are required to decouple Scenes from EventQueueHelper - void DisableSimulator(ulong handle, UUID avatarID); +// void DisableSimulator(ulong handle, UUID avatarID); void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY); void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath, ulong regionHandle, int regionSizeX, int regionSizeY); diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 55ccb0a..f1e27a5 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1884,7 +1884,8 @@ namespace OpenSim.Region.Framework.Scenes { get { - return new List<ulong>(KnownRegions.Keys); + lock (m_knownChildRegions) + return new List<ulong>(m_knownChildRegions.Keys); } } @@ -4407,26 +4408,15 @@ namespace OpenSim.Region.Framework.Scenes } - /* useless. Either use MakeChild or delete the presence - public void Reset() - { - // m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); - - // Put the child agent back at the center - AbsolutePosition - = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70); - - Animator.ResetAnimations(); - } - */ /// <summary> /// Computes which child agents to close when the scene presence moves to another region. /// Removes those regions from m_knownRegions. /// </summary> - /// <param name="newRegionX">The new region's x on the map</param> - /// <param name="newRegionY">The new region's y on the map</param> + /// <param name="newRegionHandle">The new region's handle</param> + /// <param name="newRegionSizeX">The new region's size x</param> + /// <param name="newRegionSizeY">The new region's size y</param> /// <returns></returns> - public void CloseChildAgents(bool logout, ulong newRegionHandle, int newRegionSizeX, int newRegionSizeY) + public List<ulong> GetChildAgentsToClose(ulong newRegionHandle, int newRegionSizeX, int newRegionSizeY) { uint newRegionX, newRegionY; List<ulong> byebyeRegions = new List<ulong>(); @@ -4442,37 +4432,37 @@ namespace OpenSim.Region.Framework.Scenes foreach (ulong handle in knownRegions) { - // Don't close the agent on this region yet - if (handle != Scene.RegionInfo.RegionHandle) + if(newRegionY == 0) // HG + byebyeRegions.Add(handle); + else { - if (logout) - byebyeRegions.Add(handle); - else + Util.RegionHandleToRegionLoc(handle, out x, out y); + if (m_knownChildRegionsSizeInfo.TryGetValue(handle, out regInfo)) { - Util.RegionHandleToRegionLoc(handle, out x, out y); - if (m_knownChildRegionsSizeInfo.TryGetValue(handle, out regInfo)) +// if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY, + // for now need to close all but first order bc RegionViewDistance it the target value not ours + if (Util.IsOutsideView(255, x, newRegionX, y, newRegionY, + regInfo.sizeX, regInfo.sizeY, newRegionSizeX, newRegionSizeY)) { - if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY, - regInfo.sizeX, regInfo.sizeY, newRegionSizeX, newRegionSizeY)) - { - byebyeRegions.Add(handle); - } + byebyeRegions.Add(handle); } - else + } + else + { + if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY, + (int)Constants.RegionSize, (int)Constants.RegionSize, newRegionSizeX, newRegionSizeY)) { - if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY, - (int)Constants.RegionSize, (int)Constants.RegionSize, newRegionSizeX, newRegionSizeY)) - { - byebyeRegions.Add(handle); - // this should not be here -// if(eventQueue != null) -// eventQueue.DisableSimulator(handle,UUID); - } + byebyeRegions.Add(handle); } } } } + return byebyeRegions; + } + public void CloseChildAgents(List<ulong> byebyeRegions) + { + byebyeRegions.Remove(Scene.RegionInfo.RegionHandle); if (byebyeRegions.Count > 0) { m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); diff --git a/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs b/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs index 3e00d82..f2ce064 100644 --- a/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs +++ b/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs @@ -108,12 +108,12 @@ namespace OpenSim.Tests.Common AddEvent(avatarID, "Enqueue", o); return true; } - +/* public void DisableSimulator(ulong handle, UUID avatarID) { AddEvent(avatarID, "DisableSimulator", handle); } - +*/ public void EnableSimulator (ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY) { AddEvent(avatarID, "EnableSimulator", handle); -- cgit v1.1