Make SendKillObject send multiple localIDs in one packet. This avoids the

halting visual behavior of large group deletes and eliminates the packet flood
avinationmerge
Melanie 2010-10-08 11:31:52 +02:00
parent ba0afa53d3
commit 52dd547863
19 changed files with 79 additions and 53 deletions

View File

@ -897,7 +897,13 @@ namespace OpenSim.Client.MXP.ClientStack
// Need to translate to MXP somehow // Need to translate to MXP somehow
} }
public void SendKillObject(ulong regionHandle, uint localID) public void SendKillObject(ulong regionHandle, List<uint> localIDs)
{
foreach (uint localID in localIDs)
SendKillObject(regionHandle, localID);
}
private void SendKillObject(ulong regionHandle, uint localID)
{ {
DisappearanceEventMessage de = new DisappearanceEventMessage(); DisappearanceEventMessage de = new DisappearanceEventMessage();
de.ObjectIndex = localID; de.ObjectIndex = localID;

View File

@ -495,7 +495,7 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
public void SendKillObject(ulong regionHandle, uint localID) public void SendKillObject(ulong regionHandle, List<uint> localID)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }

View File

@ -979,7 +979,7 @@ namespace OpenSim.Framework
/// </summary> /// </summary>
/// <param name="regionHandle"></param> /// <param name="regionHandle"></param>
/// <param name="localID"></param> /// <param name="localID"></param>
void SendKillObject(ulong regionHandle, uint localID); void SendKillObject(ulong regionHandle, List<uint> localID);
void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs); void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs);
void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args); void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args);

View File

@ -1516,37 +1516,48 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OutPacket(pc, ThrottleOutPacketType.Unknown); OutPacket(pc, ThrottleOutPacketType.Unknown);
} }
public void SendKillObject(ulong regionHandle, uint localID) public void SendKillObject(ulong regionHandle, List<uint> localIDs)
{ {
// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle);
KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
// TODO: don't create new blocks if recycling an old packet // TODO: don't create new blocks if recycling an old packet
kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count];
kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); for (int i = 0 ; i < localIDs.Count ; i++ )
kill.ObjectData[0].ID = localID; {
kill.ObjectData[i] = new KillObjectPacket.ObjectDataBlock();
kill.ObjectData[i].ID = localIDs[i];
}
kill.Header.Reliable = true; kill.Header.Reliable = true;
kill.Header.Zerocoded = 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); OutPacket(kill, ThrottleOutPacketType.State);
return;
// 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);
} }
m_killRecord.Add(localIDs[0]);
} }
else 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);
}
/// <summary> /// <summary>
/// Send information about the items contained in a folder to the client. /// Send information about the items contained in a folder to the client.
/// ///
@ -10969,7 +10980,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
// It's a ghost! tell the client to delete it from view. // It's a ghost! tell the client to delete it from view.
simClient.SendKillObject(Scene.RegionInfo.RegionHandle, simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
localId); new List<uint>() { localId });
} }
else else
{ {

View File

@ -616,7 +616,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// //
if (so.IsSelected) if (so.IsSelected)
{ {
m_scene.SendKillObject(so.RootPart.LocalId); m_scene.SendKillObject(new List<uint> { so.RootPart.LocalId });
} }
so.IsSelected = false; // fudge.... so.IsSelected = false; // fudge....

View File

@ -529,7 +529,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
protected void KillEntity(Scene scene, uint localID) protected void KillEntity(Scene scene, uint localID)
{ {
scene.SendKillObject(localID); scene.SendKillObject(new List<uint>() { localID });
} }
protected virtual GridRegion GetFinalDestination(GridRegion region) protected virtual GridRegion GetFinalDestination(GridRegion region)

View File

@ -25,6 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System.Collections.Generic;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
@ -110,7 +111,7 @@ namespace OpenSim.Region.Examples.SimpleModule
{ {
m_parts.Remove(part.UUID); m_parts.Remove(part.UUID);
remoteClient.SendKillObject(m_regionHandle, part.LocalId); remoteClient.SendKillObject(m_regionHandle, new List<uint>() { part.LocalId} );
remoteClient.AddMoney(1); remoteClient.AddMoney(1);
remoteClient.SendChatMessage("Poof!", 1, AbsolutePosition, "Party Party", UUID.Zero, (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); 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_parts.Remove(m_rootPart.UUID);
m_scene.DeleteSceneObject(this, false); m_scene.DeleteSceneObject(this, false);
remoteClient.SendKillObject(m_regionHandle, m_rootPart.LocalId); remoteClient.SendKillObject(m_regionHandle, new List<uint>() { m_rootPart.LocalId });
remoteClient.AddMoney(50); remoteClient.AddMoney(50);
remoteClient.SendChatMessage("KABLAM!!!", 1, AbsolutePosition, "Groupie Groupie", UUID.Zero, (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); remoteClient.SendChatMessage("KABLAM!!!", 1, AbsolutePosition, "Groupie Groupie", UUID.Zero, (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully);
} }

View File

@ -429,7 +429,7 @@ namespace OpenSim.Region.Examples.SimpleModule
} }
public virtual void SendKillObject(ulong regionHandle, uint localID) public virtual void SendKillObject(ulong regionHandle, List<uint> localID)
{ {
} }

View File

@ -104,9 +104,16 @@ namespace OpenSim.Region.Framework.Scenes
// better than losing the object for now. // better than losing the object for now.
if (permissionToDelete) if (permissionToDelete)
{ {
List<uint> killIDs = new List<uint>();
foreach (SceneObjectGroup g in objectGroups) foreach (SceneObjectGroup g in objectGroups)
{
killIDs.Add(g.LocalId);
g.DeleteGroupFromScene(false); g.DeleteGroupFromScene(false);
} }
m_scene.SendKillObject(killIDs);
}
} }
private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e) private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e)

View File

@ -1709,7 +1709,7 @@ namespace OpenSim.Region.Framework.Scenes
if (part == null) if (part == null)
{ {
//Client still thinks the object exists, kill it //Client still thinks the object exists, kill it
SendKillObject(localID); deleteIDs.Add(localID);
continue; continue;
} }
@ -1717,7 +1717,7 @@ namespace OpenSim.Region.Framework.Scenes
if (part.ParentGroup == null || part.ParentGroup.IsDeleted) if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
{ {
//Client still thinks the object exists, kill it //Client still thinks the object exists, kill it
SendKillObject(localID); deleteIDs.Add(localID);
continue; continue;
} }
@ -1727,8 +1727,8 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectGroup grp = part.ParentGroup; SceneObjectGroup grp = part.ParentGroup;
deleteIDs.Add(localID);
deleteGroups.Add(grp); deleteGroups.Add(grp);
deleteIDs.Add(grp.LocalId);
if (remoteClient == null) if (remoteClient == null)
{ {
@ -1811,6 +1811,8 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
SendKillObject(deleteIDs);
if (permissionToTake) if (permissionToTake)
{ {
m_asyncSceneObjectDeleter.DeleteToInventory( m_asyncSceneObjectDeleter.DeleteToInventory(

View File

@ -2188,6 +2188,8 @@ namespace OpenSim.Region.Framework.Scenes
} }
group.DeleteGroupFromScene(silent); group.DeleteGroupFromScene(silent);
if (!silent)
SendKillObject(new List<uint>() { group.LocalId });
// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); // 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) delegate(IClientAPI client)
{ {
//We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway //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<uint>() { avatar.LocalId}); }
catch (NullReferenceException) { } catch (NullReferenceException) { }
}); });
@ -3336,7 +3338,11 @@ namespace OpenSim.Region.Framework.Scenes
#region Entities #region Entities
public void SendKillObject(uint localID) public void SendKillObject(List<uint> localIDs)
{
List<uint> deleteIDs = new List<uint>();
foreach (uint localID in localIDs)
{ {
SceneObjectPart part = GetSceneObjectPart(localID); SceneObjectPart part = GetSceneObjectPart(localID);
if (part != null) // It is a prim if (part != null) // It is a prim
@ -3344,10 +3350,12 @@ namespace OpenSim.Region.Framework.Scenes
if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid
{ {
if (part.ParentGroup.RootPart != part) // Child part if (part.ParentGroup.RootPart != part) // Child part
return; continue;
} }
} }
ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); }); deleteIDs.Add(localID);
}
ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); });
} }
#endregion #endregion
@ -3365,7 +3373,6 @@ namespace OpenSim.Region.Framework.Scenes
//m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
//m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
m_sceneGridService.KiPrimitive += SendKillObject;
m_sceneGridService.OnGetLandData += GetLandData; m_sceneGridService.OnGetLandData += GetLandData;
} }
@ -3374,7 +3381,6 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
public void UnRegisterRegionWithComms() public void UnRegisterRegionWithComms()
{ {
m_sceneGridService.KiPrimitive -= SendKillObject;
m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid;
//m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar;
//m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;

View File

@ -44,8 +44,6 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
namespace OpenSim.Region.Framework.Scenes namespace OpenSim.Region.Framework.Scenes
{ {
public delegate void KiPrimitiveDelegate(uint localID);
public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst); public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst);
/// <summary> /// <summary>
@ -113,8 +111,6 @@ namespace OpenSim.Region.Framework.Scenes
// private LogOffUser handlerLogOffUser = null; // private LogOffUser handlerLogOffUser = null;
// private GetLandData handlerGetLandData = null; // OnGetLandData // private GetLandData handlerGetLandData = null; // OnGetLandData
public KiPrimitiveDelegate KiPrimitive;
public SceneCommunicationService() public SceneCommunicationService()
{ {
} }

View File

@ -1151,7 +1151,7 @@ namespace OpenSim.Region.Framework.Scenes
// //
if (IsSelected) if (IsSelected)
{ {
m_scene.SendKillObject(m_rootPart.LocalId); m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
} }
IsSelected = false; // fudge.... IsSelected = false; // fudge....
@ -1415,11 +1415,7 @@ namespace OpenSim.Region.Framework.Scenes
avatar.StandUp(); avatar.StandUp();
if (!silent) if (!silent)
{
part.UpdateFlag = 0; part.UpdateFlag = 0;
if (part == m_rootPart)
avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
}
}); });
} }

View File

@ -947,7 +947,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
} }
public void SendKillObject(ulong regionHandle, uint localID) public void SendKillObject(ulong regionHandle, List<uint> localID)
{ {
} }

View File

@ -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. // 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(); ((SceneObjectGroup)scene.Entities[uuid]).DetachFromBackup();
scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor); scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor);
scene.SendKillObject(scene.Entities[uuid].LocalId); scene.SendKillObject(new List<uint>() { scene.Entities[uuid].LocalId });
scene.SceneGraph.DeleteSceneObject(uuid, false); scene.SceneGraph.DeleteSceneObject(uuid, false);
((SceneObjectGroup)scene.Entities[uuid]).DeleteGroupFromScene(false); ((SceneObjectGroup)scene.Entities[uuid]).DeleteGroupFromScene(false);
scene.SendKillObject(new List<uint>() { ((SceneObjectGroup)scene.Entities[uuid]).LocalId });
} }
catch(Exception e) catch(Exception e)
{ {

View File

@ -175,7 +175,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
//This is important because we are not IN any database. //This is important because we are not IN any database.
//m_Entity.FakeDeleteGroup(); //m_Entity.FakeDeleteGroup();
foreach (SceneObjectPart part in m_Entity.Parts) foreach (SceneObjectPart part in m_Entity.Parts)
client.SendKillObject(m_Entity.RegionHandle, part.LocalId); client.SendKillObject(m_Entity.RegionHandle, new List<uint>() { part.LocalId });
} }
/// <summary> /// <summary>
@ -187,7 +187,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
{ {
m_Entity.Scene.ForEachClient( m_Entity.Scene.ForEachClient(
delegate(IClientAPI controller) delegate(IClientAPI controller)
{ controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } { controller.SendKillObject(m_Entity.RegionHandle, new List<uint>() { part.LocalId }); }
); );
} }
} }

View File

@ -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<uint> localID)
{ {
} }

View File

@ -386,7 +386,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
m_scene.ForEachClient(delegate(IClientAPI controller) m_scene.ForEachClient(delegate(IClientAPI controller)
{ {
controller.SendKillObject(m_scene.RegionInfo.RegionHandle, controller.SendKillObject(m_scene.RegionInfo.RegionHandle,
selectedTree.LocalId); new List<uint>() { selectedTree.LocalId });
}); });
} }
else else
@ -727,7 +727,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
m_scene.ForEachClient(delegate(IClientAPI controller) m_scene.ForEachClient(delegate(IClientAPI controller)
{ {
controller.SendKillObject(m_scene.RegionInfo.RegionHandle, controller.SendKillObject(m_scene.RegionInfo.RegionHandle,
selectedTree.LocalId); new List<uint>() { selectedTree.LocalId });
}); });
break; break;

View File

@ -487,7 +487,7 @@ namespace OpenSim.Tests.Common.Mock
} }
public virtual void SendKillObject(ulong regionHandle, uint localID) public virtual void SendKillObject(ulong regionHandle, List<uint> localID)
{ {
} }