From 26569a7cd02a03ea41e8febc69e659b670a9e031 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 1 Dec 2010 22:23:42 +0000 Subject: [PATCH 1/2] minor: add some method doc --- .../Region/ClientStack/LindenUDP/LLUDPClient.cs | 8 ++++++++ .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 14 ++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index c4db5da2da..5bf36e6f1d 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs @@ -399,6 +399,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP return data; } + /// + /// Queue an outgoing packet if appropriate. + /// + /// + /// + /// true if the packet has been queued, + /// false if the packet has not been queued and should be sent immediately. + /// public bool EnqueueOutgoing(OutgoingPacket packet) { int category = (int)packet.Category; diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index b5d8ec8dc5..ff4abf8997 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -312,6 +312,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + /// + /// Start the process of sending a packet to the client. + /// + /// + /// + /// + /// public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting) { // CoarseLocationUpdate packets cannot be split in an automated way @@ -339,6 +346,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + /// + /// Start the process of sending a packet to the client. + /// + /// + /// + /// + /// public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category) { int dataLength = data.Length; From 5246d98b8df3cc613a199851c3ac33ec753f522a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 2 Dec 2010 01:55:49 +0000 Subject: [PATCH 2/2] Stop LLUDPServer sending updates after object deletes by always queueing deletes If an LL 1.23.5 client (and possibly earlier and later) receives an object update after a kill object packet, it leaves the deleted prim in the scene until client relog This is possible in LLUDPServer if an object update packet is queued but a kill packet sent immediately. Beyond invasive tracking of kill sending, most expedient solution is to always queue kills, so that they always arrive after updates. In tests, this doesn't appear to affect performance. There is probably still an issue present where an update packet might not be acked and then resent after the kill packet. --- .../ClientStack/LindenUDP/LLClientView.cs | 32 +++++++++++-------- .../ClientStack/LindenUDP/LLUDPClient.cs | 7 ++-- .../ClientStack/LindenUDP/LLUDPServer.cs | 8 +++-- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 7851c4d5ad..f125822604 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3562,24 +3562,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP EntityUpdate update; while (updatesThisCall < maxUpdates && m_entityUpdates.TryDequeue(out update)) { - // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client - // will never receive an update after a prim kill. Even then, keeping the kill record may be a good - // safety measure. - // - // Receiving updates after kills results in undeleteable prims that persist until relog and - // currently occurs because prims can be deleted before all queued updates are sent. - if (m_killRecord.Contains(update.Entity.LocalId)) - { -// m_log.WarnFormat( -// "[CLIENT]: Preventing full update for prim with local id {0} after client for user {1} told it was deleted", -// update.Entity.LocalId, Name); - continue; - } - if (update.Entity is SceneObjectPart) { SceneObjectPart part = (SceneObjectPart)update.Entity; + // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client + // will never receive an update after a prim kill. Even then, keeping the kill record may be a good + // safety measure. + // + // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update + // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs + // updates and kills on different threads with different scheduling strategies, hence this protection. + // + // This doesn't appear to apply to child prims - a client will happily ignore these updates + // after the root prim has been deleted. + if (m_killRecord.Contains(part.LocalId)) + { + // m_log.WarnFormat( + // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted", + // part.LocalId, Name); + continue; + } + if (part.ParentGroup.IsAttachment && m_disableFacelights) { if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index 5bf36e6f1d..e02783ad4d 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs @@ -403,11 +403,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Queue an outgoing packet if appropriate. /// /// + /// Always queue the packet if at all possible. /// /// true if the packet has been queued, /// false if the packet has not been queued and should be sent immediately. /// - public bool EnqueueOutgoing(OutgoingPacket packet) + public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue) { int category = (int)packet.Category; @@ -416,14 +417,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP OpenSim.Framework.LocklessQueue queue = m_packetOutboxes[category]; TokenBucket bucket = m_throttleCategories[category]; - if (bucket.RemoveTokens(packet.Buffer.DataLength)) + if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength)) { // Enough tokens were removed from the bucket, the packet will not be queued return false; } else { - // Not enough tokens in the bucket, queue this packet + // Force queue specified or not enough tokens in the bucket, queue this packet queue.Enqueue(packet); return true; } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index ff4abf8997..e54cfc21ea 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -410,7 +410,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); - if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) + // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will + // continue to display the deleted object until relog. Therefore, we need to always queue a kill object + // packet so that it isn't sent before a queued update packet. + bool requestQueue = type == PacketType.KillObject; + if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue)) SendPacketFinal(outgoingPacket); #endregion Queue or Send @@ -503,7 +507,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP //Interlocked.Increment(ref Stats.ResentPackets); // Requeue or resend the packet - if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) + if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false)) SendPacketFinal(outgoingPacket); } }