From b5ab33b5e190e79789df3f44b24959fd229a8c6d Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Wed, 20 Apr 2011 23:08:51 -0700 Subject: bug fix. Now when an unacked update packet is handled through ResendPrimUpdates, it is removed from the UnackedPacketCollection. --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 34 +++++++++++++--------- .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 4 +-- .../Region/ClientStack/LindenUDP/OutgoingPacket.cs | 3 +- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 1108863..1e8bbb8 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3583,10 +3583,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// with any other updates that may be queued for the same entity. /// The original update time is used for the merged update. /// - private void ResendPrimUpdates(List updates) + private void ResendPrimUpdates(List updates, OutgoingPacket oPacket) { // m_log.WarnFormat("[CLIENT] resending prim update {0}",updates[0].UpdateTime); - + + // Remove the update packet from the list of packets waiting for acknowledgement + // because we are requeuing the list of updates. They will be resent in new packets + // with the most recent state and priority. + m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber, 0, true); foreach (EntityUpdate update in updates) ResendPrimUpdate(update); } @@ -3771,7 +3775,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP for (int i = 0; i < blocks.Count; i++) packet.ObjectData[i] = blocks[i]; // If any of the packets created from this call go unacknowledged, all of the updates will be resent - OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate() { ResendPrimUpdates(terseAgentUpdates.Value); }); + OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); }); } if (objectUpdateBlocks.IsValueCreated) @@ -3786,7 +3790,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP for (int i = 0; i < blocks.Count; i++) packet.ObjectData[i] = blocks[i]; // If any of the packets created from this call go unacknowledged, all of the updates will be resent - OutPacket(packet, ThrottleOutPacketType.Task, true, delegate() { ResendPrimUpdates(objectUpdates.Value); }); + OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); }); } if (compressedUpdateBlocks.IsValueCreated) @@ -3801,7 +3805,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP for (int i = 0; i < blocks.Count; i++) packet.ObjectData[i] = blocks[i]; // If any of the packets created from this call go unacknowledged, all of the updates will be resent - OutPacket(packet, ThrottleOutPacketType.Task, true, delegate() { ResendPrimUpdates(compressedUpdates.Value); }); + OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); }); } if (terseUpdateBlocks.IsValueCreated) @@ -3816,7 +3820,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP for (int i = 0; i < blocks.Count; i++) packet.ObjectData[i] = blocks[i]; // If any of the packets created from this call go unacknowledged, all of the updates will be resent - OutPacket(packet, ThrottleOutPacketType.Task, true, delegate() { ResendPrimUpdates(terseUpdates.Value); }); + OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); } } @@ -4027,10 +4031,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_entityProps.Enqueue(priority, update); } - private void ResendPropertyUpdates(List updates) + private void ResendPropertyUpdates(List updates, OutgoingPacket oPacket) { // m_log.WarnFormat("[CLIENT] resending object property {0}",updates[0].UpdateTime); + // Remove the update packet from the list of packets waiting for acknowledgement + // because we are requeuing the list of updates. They will be resent in new packets + // with the most recent state. + m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber, 0, true); foreach (ObjectPropertyUpdate update in updates) ResendPropertyUpdate(update); } @@ -4111,9 +4119,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Pass in the delegate so that if this packet needs to be resent, we send the current properties // of the object rather than the properties when the packet was created OutPacket(packet, ThrottleOutPacketType.Task, true, - delegate() + delegate(OutgoingPacket oPacket) { - ResendPropertyUpdates(updates); + ResendPropertyUpdates(updates, oPacket); }); // pbcnt += blocks.Count; @@ -4126,7 +4134,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (objectFamilyBlocks.IsValueCreated) { List blocks = objectFamilyBlocks.Value; - List updates = familyUpdates.Value; // one packet per object block... uggh... for (int i = 0; i < blocks.Count; i++) @@ -4139,11 +4146,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Pass in the delegate so that if this packet needs to be resent, we send the current properties // of the object rather than the properties when the packet was created - ObjectPropertyUpdate update = updates[i]; + List updates = new List(); + updates.Add(familyUpdates.Value[i]); OutPacket(packet, ThrottleOutPacketType.Task, true, - delegate() + delegate(OutgoingPacket oPacket) { - ResendPropertyUpdate(update); + ResendPropertyUpdates(updates, oPacket); }); // fpcnt++; diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 0848979..bd58ddc 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -413,7 +413,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); // If we were not provided a method for handling unacked, use the UDPServer default method - outgoingPacket.UnackedMethod = ((method == null) ? delegate() { ResendUnacked(outgoingPacket); } : method); + outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); // 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 @@ -494,7 +494,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Exponential backoff of the retransmission timeout udpClient.BackoffRTO(); for (int i = 0; i < expiredPackets.Count; ++i) - expiredPackets[i].UnackedMethod(); + expiredPackets[i].UnackedMethod(expiredPackets[i]); } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs index f4f024b..76c6c14 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs @@ -31,7 +31,8 @@ using OpenMetaverse; namespace OpenSim.Region.ClientStack.LindenUDP { - public delegate void UnackedPacketMethod(); + + public delegate void UnackedPacketMethod(OutgoingPacket oPacket); /// /// Holds a reference to the this packet is /// destined for, along with the serialized packet data, sequence number -- cgit v1.1