From 52dd547863c0cdd22f53f0efcaef11ae096855a0 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 8 Oct 2010 11:31:52 +0200 Subject: [PATCH] Make SendKillObject send multiple localIDs in one packet. This avoids the halting visual behavior of large group deletes and eliminates the packet flood --- .../Client/MXP/ClientStack/MXPClientView.cs | 8 +++- .../VWoHTTP/ClientStack/VWHClientView.cs | 2 +- OpenSim/Framework/IClientAPI.cs | 2 +- .../ClientStack/LindenUDP/LLClientView.cs | 41 ++++++++++++------- .../Avatar/Attachments/AttachmentsModule.cs | 2 +- .../EntityTransfer/EntityTransferModule.cs | 2 +- .../Examples/SimpleModule/ComplexObject.cs | 5 ++- .../Examples/SimpleModule/MyNpcCharacter.cs | 2 +- .../Scenes/AsyncSceneObjectGroupDeleter.cs | 7 ++++ .../Framework/Scenes/Scene.Inventory.cs | 8 ++-- OpenSim/Region/Framework/Scenes/Scene.cs | 26 +++++++----- .../Scenes/SceneCommunicationService.cs | 4 -- .../Framework/Scenes/SceneObjectGroup.cs | 6 +-- .../Server/IRCClientView.cs | 2 +- .../ContentManagementSystem/CMModel.cs | 3 +- .../ContentManagementSystem/MetaEntity.cs | 4 +- .../OptionalModules/World/NPC/NPCAvatar.cs | 2 +- .../TreePopulator/TreePopulatorModule.cs | 4 +- OpenSim/Tests/Common/Mock/TestClient.cs | 2 +- 19 files changed, 79 insertions(+), 53 deletions(-) diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs index 87b99e03c9..df9d21b76e 100644 --- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs +++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs @@ -897,7 +897,13 @@ namespace OpenSim.Client.MXP.ClientStack // Need to translate to MXP somehow } - public void SendKillObject(ulong regionHandle, uint localID) + public void SendKillObject(ulong regionHandle, List localIDs) + { + foreach (uint localID in localIDs) + SendKillObject(regionHandle, localID); + } + + private void SendKillObject(ulong regionHandle, uint localID) { DisappearanceEventMessage de = new DisappearanceEventMessage(); de.ObjectIndex = localID; diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index 51c5c17022..26be5d9ed3 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs @@ -495,7 +495,7 @@ namespace OpenSim.Client.VWoHTTP.ClientStack throw new System.NotImplementedException(); } - public void SendKillObject(ulong regionHandle, uint localID) + public void SendKillObject(ulong regionHandle, List localID) { throw new System.NotImplementedException(); } diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 9025dda46b..51482a1183 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -979,7 +979,7 @@ namespace OpenSim.Framework /// /// /// - void SendKillObject(ulong regionHandle, uint localID); + void SendKillObject(ulong regionHandle, List localID); void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs); void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args); diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 2b1bd977df..fff43001ff 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -1516,35 +1516,46 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(pc, ThrottleOutPacketType.Unknown); } - public void SendKillObject(ulong regionHandle, uint localID) + public void SendKillObject(ulong regionHandle, List localIDs) { // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); // TODO: don't create new blocks if recycling an old packet - kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; - kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); - kill.ObjectData[0].ID = localID; + kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count]; + for (int i = 0 ; i < localIDs.Count ; i++ ) + { + kill.ObjectData[i] = new KillObjectPacket.ObjectDataBlock(); + kill.ObjectData[i].ID = localIDs[i]; + } kill.Header.Reliable = true; kill.Header.Zerocoded = true; - if (m_scene.GetScenePresence(localID) == null) + if (localIDs.Count == 1) { - lock (m_entityUpdates.SyncRoot) + if (m_scene.GetScenePresence(localIDs[0]) != null) { - m_killRecord.Add(localID); - - // The throttle queue used here must match that being used for updates. Otherwise, there is a - // chance that a kill packet put on a separate queue will be sent to the client before an existing - // update packet on another queue. Receiving updates after kills results in unowned and undeletable - // scene objects in a viewer until that viewer is relogged in. - OutPacket(kill, ThrottleOutPacketType.Task); + OutPacket(kill, ThrottleOutPacketType.State); + return; } + m_killRecord.Add(localIDs[0]); } else { - OutPacket(kill, ThrottleOutPacketType.State); + lock (m_entityUpdates.SyncRoot) + { + foreach (uint localID in localIDs) + m_killRecord.Add(localID); + } } + + // The throttle queue used here must match that being used for + // updates. Otherwise, there is a chance that a kill packet put + // on a separate queue will be sent to the client before an + // existing update packet on another queue. Receiving updates + // after kills results in unowned and undeletable + // scene objects in a viewer until that viewer is relogged in. + OutPacket(kill, ThrottleOutPacketType.Task); } /// @@ -10969,7 +10980,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // It's a ghost! tell the client to delete it from view. simClient.SendKillObject(Scene.RegionInfo.RegionHandle, - localId); + new List() { localId }); } else { diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 87c91004d8..6ff0ffc9bf 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -616,7 +616,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // if (so.IsSelected) { - m_scene.SendKillObject(so.RootPart.LocalId); + m_scene.SendKillObject(new List { so.RootPart.LocalId }); } so.IsSelected = false; // fudge.... diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index d5062088a6..2921b0d07a 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -529,7 +529,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected void KillEntity(Scene scene, uint localID) { - scene.SendKillObject(localID); + scene.SendKillObject(new List() { localID }); } protected virtual GridRegion GetFinalDestination(GridRegion region) diff --git a/OpenSim/Region/Examples/SimpleModule/ComplexObject.cs b/OpenSim/Region/Examples/SimpleModule/ComplexObject.cs index e951befdc5..7a0ce5121a 100644 --- a/OpenSim/Region/Examples/SimpleModule/ComplexObject.cs +++ b/OpenSim/Region/Examples/SimpleModule/ComplexObject.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; @@ -110,7 +111,7 @@ namespace OpenSim.Region.Examples.SimpleModule { m_parts.Remove(part.UUID); - remoteClient.SendKillObject(m_regionHandle, part.LocalId); + remoteClient.SendKillObject(m_regionHandle, new List() { part.LocalId} ); remoteClient.AddMoney(1); remoteClient.SendChatMessage("Poof!", 1, AbsolutePosition, "Party Party", UUID.Zero, (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); } @@ -121,7 +122,7 @@ namespace OpenSim.Region.Examples.SimpleModule { m_parts.Remove(m_rootPart.UUID); m_scene.DeleteSceneObject(this, false); - remoteClient.SendKillObject(m_regionHandle, m_rootPart.LocalId); + remoteClient.SendKillObject(m_regionHandle, new List() { m_rootPart.LocalId }); remoteClient.AddMoney(50); remoteClient.SendChatMessage("KABLAM!!!", 1, AbsolutePosition, "Groupie Groupie", UUID.Zero, (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); } diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 944ad94b83..db427b4ba3 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -429,7 +429,7 @@ namespace OpenSim.Region.Examples.SimpleModule } - public virtual void SendKillObject(ulong regionHandle, uint localID) + public virtual void SendKillObject(ulong regionHandle, List localID) { } diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs index 8feb0227fc..a8d24fd13f 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs @@ -104,8 +104,15 @@ namespace OpenSim.Region.Framework.Scenes // better than losing the object for now. if (permissionToDelete) { + List killIDs = new List(); + foreach (SceneObjectGroup g in objectGroups) + { + killIDs.Add(g.LocalId); g.DeleteGroupFromScene(false); + } + + m_scene.SendKillObject(killIDs); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 8b5316a696..6d7f98478d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1709,7 +1709,7 @@ namespace OpenSim.Region.Framework.Scenes if (part == null) { //Client still thinks the object exists, kill it - SendKillObject(localID); + deleteIDs.Add(localID); continue; } @@ -1717,7 +1717,7 @@ namespace OpenSim.Region.Framework.Scenes if (part.ParentGroup == null || part.ParentGroup.IsDeleted) { //Client still thinks the object exists, kill it - SendKillObject(localID); + deleteIDs.Add(localID); continue; } @@ -1727,8 +1727,8 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup grp = part.ParentGroup; - deleteIDs.Add(localID); deleteGroups.Add(grp); + deleteIDs.Add(grp.LocalId); if (remoteClient == null) { @@ -1811,6 +1811,8 @@ namespace OpenSim.Region.Framework.Scenes } } + SendKillObject(deleteIDs); + if (permissionToTake) { m_asyncSceneObjectDeleter.DeleteToInventory( diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 76e160d93e..48ae4cab07 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2188,6 +2188,8 @@ namespace OpenSim.Region.Framework.Scenes } group.DeleteGroupFromScene(silent); + if (!silent) + SendKillObject(new List() { group.LocalId }); // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); } @@ -3273,7 +3275,7 @@ namespace OpenSim.Region.Framework.Scenes delegate(IClientAPI client) { //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway - try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); } + try { client.SendKillObject(avatar.RegionHandle, new List() { avatar.LocalId}); } catch (NullReferenceException) { } }); @@ -3336,18 +3338,24 @@ namespace OpenSim.Region.Framework.Scenes #region Entities - public void SendKillObject(uint localID) + public void SendKillObject(List localIDs) { - SceneObjectPart part = GetSceneObjectPart(localID); - if (part != null) // It is a prim + List deleteIDs = new List(); + + foreach (uint localID in localIDs) { - if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid + SceneObjectPart part = GetSceneObjectPart(localID); + if (part != null) // It is a prim { - if (part.ParentGroup.RootPart != part) // Child part - return; + if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid + { + if (part.ParentGroup.RootPart != part) // Child part + continue; + } } + deleteIDs.Add(localID); } - ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); }); + ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); }); } #endregion @@ -3365,7 +3373,6 @@ namespace OpenSim.Region.Framework.Scenes //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; - m_sceneGridService.KiPrimitive += SendKillObject; m_sceneGridService.OnGetLandData += GetLandData; } @@ -3374,7 +3381,6 @@ namespace OpenSim.Region.Framework.Scenes /// public void UnRegisterRegionWithComms() { - m_sceneGridService.KiPrimitive -= SendKillObject; m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 1293d5d531..632646d130 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -44,8 +44,6 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; namespace OpenSim.Region.Framework.Scenes { - public delegate void KiPrimitiveDelegate(uint localID); - public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List regionlst); /// @@ -113,8 +111,6 @@ namespace OpenSim.Region.Framework.Scenes // private LogOffUser handlerLogOffUser = null; // private GetLandData handlerGetLandData = null; // OnGetLandData - public KiPrimitiveDelegate KiPrimitive; - public SceneCommunicationService() { } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 9a7d560937..c87079788d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1151,7 +1151,7 @@ namespace OpenSim.Region.Framework.Scenes // if (IsSelected) { - m_scene.SendKillObject(m_rootPart.LocalId); + m_scene.SendKillObject(new List { m_rootPart.LocalId }); } IsSelected = false; // fudge.... @@ -1415,11 +1415,7 @@ namespace OpenSim.Region.Framework.Scenes avatar.StandUp(); if (!silent) - { part.UpdateFlag = 0; - if (part == m_rootPart) - avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); - } }); } diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 4ab67aa883..72e5ebdb4e 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -947,7 +947,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } - public void SendKillObject(ulong regionHandle, uint localID) + public void SendKillObject(ulong regionHandle, List localID) { } diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs index 3a6996ef9b..84c7f292b9 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs @@ -259,9 +259,10 @@ namespace OpenSim.Region.OptionalModules.ContentManagement // I thought that the DeleteGroup() function would handle all of this, but it doesn't. I'm not sure WHAT it handles. ((SceneObjectGroup)scene.Entities[uuid]).DetachFromBackup(); scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor); - scene.SendKillObject(scene.Entities[uuid].LocalId); + scene.SendKillObject(new List() { scene.Entities[uuid].LocalId }); scene.SceneGraph.DeleteSceneObject(uuid, false); ((SceneObjectGroup)scene.Entities[uuid]).DeleteGroupFromScene(false); + scene.SendKillObject(new List() { ((SceneObjectGroup)scene.Entities[uuid]).LocalId }); } catch(Exception e) { diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs index c7b1ed79cc..cd60f4bcfc 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs @@ -175,7 +175,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement //This is important because we are not IN any database. //m_Entity.FakeDeleteGroup(); foreach (SceneObjectPart part in m_Entity.Parts) - client.SendKillObject(m_Entity.RegionHandle, part.LocalId); + client.SendKillObject(m_Entity.RegionHandle, new List() { part.LocalId }); } /// @@ -187,7 +187,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement { m_Entity.Scene.ForEachClient( delegate(IClientAPI controller) - { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } + { controller.SendKillObject(m_Entity.RegionHandle, new List() { part.LocalId }); } ); } } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 1653ecbb56..3cbe39185d 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -519,7 +519,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC } - public virtual void SendKillObject(ulong regionHandle, uint localID) + public virtual void SendKillObject(ulong regionHandle, List localID) { } diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs index 421da3664a..2563361b39 100644 --- a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs +++ b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs @@ -386,7 +386,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator m_scene.ForEachClient(delegate(IClientAPI controller) { controller.SendKillObject(m_scene.RegionInfo.RegionHandle, - selectedTree.LocalId); + new List() { selectedTree.LocalId }); }); } else @@ -727,7 +727,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator m_scene.ForEachClient(delegate(IClientAPI controller) { controller.SendKillObject(m_scene.RegionInfo.RegionHandle, - selectedTree.LocalId); + new List() { selectedTree.LocalId }); }); break; diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 1c860a7d42..63241467a0 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -487,7 +487,7 @@ namespace OpenSim.Tests.Common.Mock } - public virtual void SendKillObject(ulong regionHandle, uint localID) + public virtual void SendKillObject(ulong regionHandle, List localID) { }