diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs index d195110..793aefe 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs | |||
@@ -65,7 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
65 | /// <summary>Holds packets that need to be added to the unacknowledged list</summary> | 65 | /// <summary>Holds packets that need to be added to the unacknowledged list</summary> |
66 | private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>(); | 66 | private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>(); |
67 | /// <summary>Holds information about pending acknowledgements</summary> | 67 | /// <summary>Holds information about pending acknowledgements</summary> |
68 | private LocklessQueue<PendingAck> m_pendingRemoves = new LocklessQueue<PendingAck>(); | 68 | private LocklessQueue<PendingAck> m_pendingAcknowledgements = new LocklessQueue<PendingAck>(); |
69 | /// <summary>Holds information about pending removals</summary> | ||
70 | private LocklessQueue<uint> m_pendingRemoves = new LocklessQueue<uint>(); | ||
69 | 71 | ||
70 | /// <summary> | 72 | /// <summary> |
71 | /// Add an unacked packet to the collection | 73 | /// Add an unacked packet to the collection |
@@ -83,15 +85,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
83 | 85 | ||
84 | /// <summary> | 86 | /// <summary> |
85 | /// Marks a packet as acknowledged | 87 | /// Marks a packet as acknowledged |
88 | /// This method is used when an acknowledgement is received from the network for a previously | ||
89 | /// sent packet. Effects of removal this way are to update unacked byte count, adjust RTT | ||
90 | /// and increase throttle to the coresponding client. | ||
86 | /// </summary> | 91 | /// </summary> |
87 | /// <param name="sequenceNumber">Sequence number of the packet to | 92 | /// <param name="sequenceNumber">Sequence number of the packet to |
88 | /// acknowledge</param> | 93 | /// acknowledge</param> |
89 | /// <param name="currentTime">Current value of Environment.TickCount</param> | 94 | /// <param name="currentTime">Current value of Environment.TickCount</param> |
90 | /// <remarks>This does not immediately acknowledge the packet, it only | 95 | /// <remarks>This does not immediately acknowledge the packet, it only |
91 | /// queues the ack so it can be handled in a thread-safe way later</remarks> | 96 | /// queues the ack so it can be handled in a thread-safe way later</remarks> |
92 | public void Remove(uint sequenceNumber, int currentTime, bool fromResend) | 97 | public void Acknowledge(uint sequenceNumber, int currentTime, bool fromResend) |
93 | { | 98 | { |
94 | m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend)); | 99 | m_pendingAcknowledgements.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend)); |
100 | } | ||
101 | |||
102 | /// <summary> | ||
103 | /// Marks a packet as no longer needing acknowledgement without a received acknowledgement. | ||
104 | /// This method is called when a packet expires and we no longer need an acknowledgement. | ||
105 | /// When some reliable packet types expire, they are handled in a way other than simply | ||
106 | /// resending them. The only effect of removal this way is to update unacked byte count. | ||
107 | /// </summary> | ||
108 | /// <param name="sequenceNumber">Sequence number of the packet to | ||
109 | /// acknowledge</param> | ||
110 | /// <remarks>The does not immediately remove the packet, it only queues the removal | ||
111 | /// so it can be handled in a thread safe way later</remarks> | ||
112 | public void Remove(uint sequenceNumber) | ||
113 | { | ||
114 | m_pendingRemoves.Enqueue(sequenceNumber); | ||
95 | } | 115 | } |
96 | 116 | ||
97 | /// <summary> | 117 | /// <summary> |
@@ -130,6 +150,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
130 | // is actually sent out again | 150 | // is actually sent out again |
131 | packet.TickCount = 0; | 151 | packet.TickCount = 0; |
132 | 152 | ||
153 | // As with other network applications, assume that an expired packet is | ||
154 | // an indication of some network problem, slow transmission | ||
155 | packet.Client.FlowThrottle.ExpirePackets(1); | ||
156 | |||
133 | expiredPackets.Add(packet); | 157 | expiredPackets.Add(packet); |
134 | } | 158 | } |
135 | } | 159 | } |
@@ -147,29 +171,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
147 | m_packets[pendingAdd.SequenceNumber] = pendingAdd; | 171 | m_packets[pendingAdd.SequenceNumber] = pendingAdd; |
148 | 172 | ||
149 | // Process all the pending removes, including updating statistics and round-trip times | 173 | // Process all the pending removes, including updating statistics and round-trip times |
150 | PendingAck pendingRemove; | 174 | PendingAck pendingAcknowledgement; |
151 | OutgoingPacket ackedPacket; | 175 | while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement)) |
152 | while (m_pendingRemoves.TryDequeue(out pendingRemove)) | ||
153 | { | 176 | { |
154 | if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) | 177 | OutgoingPacket ackedPacket; |
178 | if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket)) | ||
155 | { | 179 | { |
156 | if (ackedPacket != null) | 180 | if (ackedPacket != null) |
157 | { | 181 | { |
158 | m_packets.Remove(pendingRemove.SequenceNumber); | 182 | m_packets.Remove(pendingAcknowledgement.SequenceNumber); |
183 | |||
184 | // As with other network applications, assume that an acknowledged packet is an | ||
185 | // indication that the network can handle a little more load, speed up the transmission | ||
186 | ackedPacket.Client.FlowThrottle.AcknowledgePackets(ackedPacket.Buffer.DataLength); | ||
159 | 187 | ||
160 | // Update stats | 188 | // Update stats |
161 | Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); | 189 | Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); |
162 | 190 | ||
163 | if (!pendingRemove.FromResend) | 191 | if (!pendingAcknowledgement.FromResend) |
164 | { | 192 | { |
165 | // Calculate the round-trip time for this packet and its ACK | 193 | // Calculate the round-trip time for this packet and its ACK |
166 | int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount; | 194 | int rtt = pendingAcknowledgement.RemoveTime - ackedPacket.TickCount; |
167 | if (rtt > 0) | 195 | if (rtt > 0) |
168 | ackedPacket.Client.UpdateRoundTrip(rtt); | 196 | ackedPacket.Client.UpdateRoundTrip(rtt); |
169 | } | 197 | } |
170 | } | 198 | } |
171 | } | 199 | } |
172 | } | 200 | } |
201 | |||
202 | uint pendingRemove; | ||
203 | while(m_pendingRemoves.TryDequeue(out pendingRemove)) | ||
204 | { | ||
205 | OutgoingPacket removedPacket; | ||
206 | if (m_packets.TryGetValue(pendingRemove, out removedPacket)) | ||
207 | { | ||
208 | if (removedPacket != null) | ||
209 | { | ||
210 | m_packets.Remove(pendingRemove); | ||
211 | |||
212 | // Update stats | ||
213 | Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength); | ||
214 | } | ||
215 | } | ||
216 | } | ||
173 | } | 217 | } |
174 | } | 218 | } |
175 | } \ No newline at end of file | 219 | } |