aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2010-12-02 01:55:49 +0000
committerJustin Clark-Casey (justincc)2010-12-02 02:01:01 +0000
commit5246d98b8df3cc613a199851c3ac33ec753f522a (patch)
treed4ce71333504fef05419ba27cbfbeabcaad0f4c1 /OpenSim
parentminor: add some method doc (diff)
downloadopensim-SC-5246d98b8df3cc613a199851c3ac33ec753f522a.zip
opensim-SC-5246d98b8df3cc613a199851c3ac33ec753f522a.tar.gz
opensim-SC-5246d98b8df3cc613a199851c3ac33ec753f522a.tar.bz2
opensim-SC-5246d98b8df3cc613a199851c3ac33ec753f522a.tar.xz
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.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs32
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs7
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs8
3 files changed, 28 insertions, 19 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 7851c4d..f125822 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -3562,24 +3562,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3562 EntityUpdate update; 3562 EntityUpdate update;
3563 while (updatesThisCall < maxUpdates && m_entityUpdates.TryDequeue(out update)) 3563 while (updatesThisCall < maxUpdates && m_entityUpdates.TryDequeue(out update))
3564 { 3564 {
3565 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3566 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3567 // safety measure.
3568 //
3569 // Receiving updates after kills results in undeleteable prims that persist until relog and
3570 // currently occurs because prims can be deleted before all queued updates are sent.
3571 if (m_killRecord.Contains(update.Entity.LocalId))
3572 {
3573// m_log.WarnFormat(
3574// "[CLIENT]: Preventing full update for prim with local id {0} after client for user {1} told it was deleted",
3575// update.Entity.LocalId, Name);
3576 continue;
3577 }
3578
3579 if (update.Entity is SceneObjectPart) 3565 if (update.Entity is SceneObjectPart)
3580 { 3566 {
3581 SceneObjectPart part = (SceneObjectPart)update.Entity; 3567 SceneObjectPart part = (SceneObjectPart)update.Entity;
3582 3568
3569 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3570 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3571 // safety measure.
3572 //
3573 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3574 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3575 // updates and kills on different threads with different scheduling strategies, hence this protection.
3576 //
3577 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3578 // after the root prim has been deleted.
3579 if (m_killRecord.Contains(part.LocalId))
3580 {
3581 // m_log.WarnFormat(
3582 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted",
3583 // part.LocalId, Name);
3584 continue;
3585 }
3586
3583 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3587 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3584 { 3588 {
3585 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3589 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 5bf36e6..e02783a 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -403,11 +403,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
403 /// Queue an outgoing packet if appropriate. 403 /// Queue an outgoing packet if appropriate.
404 /// </summary> 404 /// </summary>
405 /// <param name="packet"></param> 405 /// <param name="packet"></param>
406 /// <param name="forceQueue">Always queue the packet if at all possible.</param>
406 /// <returns> 407 /// <returns>
407 /// true if the packet has been queued, 408 /// true if the packet has been queued,
408 /// false if the packet has not been queued and should be sent immediately. 409 /// false if the packet has not been queued and should be sent immediately.
409 /// </returns> 410 /// </returns>
410 public bool EnqueueOutgoing(OutgoingPacket packet) 411 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue)
411 { 412 {
412 int category = (int)packet.Category; 413 int category = (int)packet.Category;
413 414
@@ -416,14 +417,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
416 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 417 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
417 TokenBucket bucket = m_throttleCategories[category]; 418 TokenBucket bucket = m_throttleCategories[category];
418 419
419 if (bucket.RemoveTokens(packet.Buffer.DataLength)) 420 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength))
420 { 421 {
421 // Enough tokens were removed from the bucket, the packet will not be queued 422 // Enough tokens were removed from the bucket, the packet will not be queued
422 return false; 423 return false;
423 } 424 }
424 else 425 else
425 { 426 {
426 // Not enough tokens in the bucket, queue this packet 427 // Force queue specified or not enough tokens in the bucket, queue this packet
427 queue.Enqueue(packet); 428 queue.Enqueue(packet);
428 return true; 429 return true;
429 } 430 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index ff4abf8..e54cfc2 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -410,7 +410,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
410 410
411 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); 411 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);
412 412
413 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) 413 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will
414 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object
415 // packet so that it isn't sent before a queued update packet.
416 bool requestQueue = type == PacketType.KillObject;
417 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue))
414 SendPacketFinal(outgoingPacket); 418 SendPacketFinal(outgoingPacket);
415 419
416 #endregion Queue or Send 420 #endregion Queue or Send
@@ -503,7 +507,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
503 //Interlocked.Increment(ref Stats.ResentPackets); 507 //Interlocked.Increment(ref Stats.ResentPackets);
504 508
505 // Requeue or resend the packet 509 // Requeue or resend the packet
506 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) 510 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false))
507 SendPacketFinal(outgoingPacket); 511 SendPacketFinal(outgoingPacket);
508 } 512 }
509 } 513 }