diff --git a/OpenSim/Region/ClientStack/ClientView.cs b/OpenSim/Region/ClientStack/ClientView.cs index dfdc777476..ff1bac45d7 100644 --- a/OpenSim/Region/ClientStack/ClientView.cs +++ b/OpenSim/Region/ClientStack/ClientView.cs @@ -267,7 +267,7 @@ namespace OpenSim.Region.ClientStack // We can't reach into other scenes and close the connection // We need to do this over grid communications //m_scene.CloseAllAgents(CircuitCode); - + GC.Collect(); m_clientThread.Abort(); } diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index 36e98cfec8..4f44d3607b 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -1479,7 +1479,13 @@ namespace OpenSim.Region.Environment.Scenes m_sceneGridService.LogOffUser(agentID, RegionInfo.RegionID, RegionInfo.RegionHandle, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); - m_sceneGridService.SendCloseChildAgentConnections(avatar); + List childknownRegions = new List(); + List ckn = avatar.GetKnownRegionList(); + for (int i = 0; i < ckn.Count; i++) + { + childknownRegions.Add(ckn[i]); + } + m_sceneGridService.SendCloseChildAgentConnections(agentID, childknownRegions); } m_eventManager.TriggerClientClosed(agentID); @@ -1554,6 +1560,22 @@ namespace OpenSim.Region.Environment.Scenes //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); } + public void HandleRemoveKnownRegionsFromAvatar(LLUUID avatarID, List regionslst) + { + ScenePresence av = GetScenePresence(avatarID); + if (av != null) + { + lock (av) + { + + for (int i = 0; i < regionslst.Count; i++) + { + av.KnownChildRegions.Remove(regionslst[i]); + } + } + } + + } public override void CloseAllAgents(uint circuitcode) { @@ -1607,6 +1629,7 @@ namespace OpenSim.Region.Environment.Scenes m_sceneGridService.OnRegionUp += OtherRegionUp; m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; m_sceneGridService.OnExpectPrim += IncomingInterRegionPrimGroup; + m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; @@ -1620,6 +1643,7 @@ namespace OpenSim.Region.Environment.Scenes /// public void UnRegisterReginWithComms() { + m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; m_sceneGridService.OnExpectPrim -= IncomingInterRegionPrimGroup; m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; m_sceneGridService.OnRegionUp -= OtherRegionUp; diff --git a/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs index 4cf93ed167..e51438dcba 100644 --- a/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs @@ -38,6 +38,8 @@ namespace OpenSim.Region.Environment.Scenes { public delegate void KillObjectDelegate(uint localID); + public delegate void RemoveKnownRegionsFromAvatarList(LLUUID avatarID, List regionlst); + public class SceneCommunicationService //one instance per region { private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); @@ -54,6 +56,7 @@ namespace OpenSim.Region.Environment.Scenes public event PrimCrossing OnPrimCrossingIntoRegion; public event RegionUp OnRegionUp; public event ChildAgentUpdate OnChildAgentUpdate; + public event RemoveKnownRegionsFromAvatarList OnRemoveKnownRegionFromAvatar; @@ -393,23 +396,23 @@ namespace OpenSim.Region.Environment.Scenes d); } - public delegate void SendCloseChildAgentDelegate( ScenePresence presence); + public delegate void SendCloseChildAgentDelegate( LLUUID agentID, List regionlst); /// /// This Closes child agents on neighboring regions /// Calls an asynchronous method to do so.. so it doesn't lag the sim. /// - private void SendCloseChildAgentAsync(ScenePresence presence) + private void SendCloseChildAgentAsync(LLUUID agentID, List regionlst) { - foreach (ulong regionHandle in presence.KnownChildRegions) + foreach (ulong regionHandle in regionlst) { - bool regionAccepted = m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, presence.ControllingClient.AgentId); + bool regionAccepted = m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); if (regionAccepted) { m_log.Info("[INTERGRID]: Completed sending agent Close agent Request to neighbor"); - presence.RemoveNeighbourRegion(regionHandle); + } else { @@ -418,6 +421,13 @@ namespace OpenSim.Region.Environment.Scenes } } + // We remove the list of known regions from the agent's known region list through an event + // to scene, because, if an agent logged of, it's likely that there will be no scene presence + // by the time we get to this part of the method. + if (OnRemoveKnownRegionFromAvatar != null) + { + OnRemoveKnownRegionFromAvatar(agentID,regionlst); + } } private void SendCloseChildAgentCompleted(IAsyncResult iar) @@ -426,11 +436,11 @@ namespace OpenSim.Region.Environment.Scenes icon.EndInvoke(iar); } - public void SendCloseChildAgentConnections(ScenePresence presence) + public void SendCloseChildAgentConnections(LLUUID agentID, List regionslst) { // This assumes that we know what our neighbors are. SendCloseChildAgentDelegate d = SendCloseChildAgentAsync; - d.BeginInvoke(presence, + d.BeginInvoke(agentID, regionslst, SendCloseChildAgentCompleted, d); } @@ -522,7 +532,7 @@ namespace OpenSim.Region.Environment.Scenes uint oldRegionY = (((uint)(m_regionInfo.RegionHandle)) >> 8); if (Util.fast_distance2d((int)(newRegionX - oldRegionX), (int)(newRegionY - oldRegionY)) > 3) { - SendCloseChildAgentConnections(avatar); + SendCloseChildAgentConnections(avatar.UUID,avatar.GetKnownRegionList()); } } else diff --git a/OpenSim/Region/Environment/Scenes/ScenePresence.cs b/OpenSim/Region/Environment/Scenes/ScenePresence.cs index 17676237d2..4f68817a0f 100644 --- a/OpenSim/Region/Environment/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Environment/Scenes/ScenePresence.cs @@ -617,6 +617,11 @@ namespace OpenSim.Region.Environment.Scenes } } + public List GetKnownRegionList() + { + return m_knownChildRegions; + } + #endregion #region Event Handlers @@ -1767,7 +1772,25 @@ namespace OpenSim.Region.Environment.Scenes internal void Close() { + lock (m_knownPrimUUID) + { + m_knownPrimUUID.Clear(); + } + lock (m_knownChildRegions) + { + m_knownChildRegions.Clear(); + } + lock (m_updateTimes) + { + m_updateTimes.Clear(); + } + lock (m_partsUpdateQueue) + { + m_partsUpdateQueue.Clear(); + } + RemoveFromPhysicalScene(); + GC.Collect(); } } } diff --git a/OpenSim/Region/Environment/Types/UpdateQueue.cs b/OpenSim/Region/Environment/Types/UpdateQueue.cs index 0648476be2..90b7e73503 100644 --- a/OpenSim/Region/Environment/Types/UpdateQueue.cs +++ b/OpenSim/Region/Environment/Types/UpdateQueue.cs @@ -48,6 +48,17 @@ namespace OpenSim.Region.Environment.Types m_queue = new Queue(); m_ids = new List(); } + public void Clear() + { + lock (m_ids) + { + m_ids.Clear(); + } + lock (m_queue) + { + m_queue.Clear(); + } + } public void Enqueue(SceneObjectPart part) {