aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs50
1 files changed, 41 insertions, 9 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index e5b2594..b27d8d6 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -80,7 +80,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
80 /// <summary>Packets we have sent that need to be ACKed by the client</summary> 80 /// <summary>Packets we have sent that need to be ACKed by the client</summary>
81 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); 81 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
82 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary> 82 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
83 public readonly LocklessQueue<uint> PendingAcks = new LocklessQueue<uint>(); 83 public readonly OpenSim.Framework.LocklessQueue<uint> PendingAcks = new OpenSim.Framework.LocklessQueue<uint>();
84 84
85 /// <summary>Current packet sequence number</summary> 85 /// <summary>Current packet sequence number</summary>
86 public int CurrentSequence; 86 public int CurrentSequence;
@@ -127,13 +127,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
127 /// <summary>Throttle rate defaults and limits</summary> 127 /// <summary>Throttle rate defaults and limits</summary>
128 private readonly ThrottleRates defaultThrottleRates; 128 private readonly ThrottleRates defaultThrottleRates;
129 /// <summary>Outgoing queues for throttled packets</summary> 129 /// <summary>Outgoing queues for throttled packets</summary>
130 private readonly LocklessQueue<OutgoingPacket>[] packetOutboxes = new LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT]; 130 private readonly OpenSim.Framework.LocklessQueue<OutgoingPacket>[] packetOutboxes = new OpenSim.Framework.LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT];
131 /// <summary>A container that can hold one packet for each outbox, used to store 131 /// <summary>A container that can hold one packet for each outbox, used to store
132 /// dequeued packets that are being held for throttling</summary> 132 /// dequeued packets that are being held for throttling</summary>
133 private readonly OutgoingPacket[] nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; 133 private readonly OutgoingPacket[] nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT];
134 /// <summary>An optimization to store the length of dequeued packets being held 134 /// <summary>An optimization to store the length of dequeued packets being held
135 /// for throttling. This avoids expensive calls to Packet.Length</summary> 135 /// for throttling. This avoids expensive calls to Packet.Length</summary>
136 private readonly int[] nextPacketLengths = new int[THROTTLE_CATEGORY_COUNT]; 136 private readonly int[] nextPacketLengths = new int[THROTTLE_CATEGORY_COUNT];
137 /// <summary>Flags to prevent queue empty callbacks from repeatedly firing
138 /// before the callbacks have a chance to put packets in the queue</summary>
139 private readonly bool[] queueEmptySent = new bool[THROTTLE_CATEGORY_COUNT];
137 /// <summary>A reference to the LLUDPServer that is managing this client</summary> 140 /// <summary>A reference to the LLUDPServer that is managing this client</summary>
138 private readonly LLUDPServer udpServer; 141 private readonly LLUDPServer udpServer;
139 142
@@ -156,7 +159,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
156 defaultThrottleRates = rates; 159 defaultThrottleRates = rates;
157 160
158 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 161 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
159 packetOutboxes[i] = new LocklessQueue<OutgoingPacket>(); 162 packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
160 163
161 throttle = new TokenBucket(parentThrottle, 0, 0); 164 throttle = new TokenBucket(parentThrottle, 0, 0);
162 throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 165 throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
@@ -182,6 +185,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
182 public void Shutdown() 185 public void Shutdown()
183 { 186 {
184 IsConnected = false; 187 IsConnected = false;
188 NeedAcks.Clear();
189 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
190 {
191 packetOutboxes[i].Clear();
192 nextPackets[i] = null;
193 }
194 OnPacketStats = null;
195 OnQueueEmpty = null;
185 } 196 }
186 197
187 /// <summary> 198 /// <summary>
@@ -322,7 +333,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
322 333
323 if (category >= 0 && category < packetOutboxes.Length) 334 if (category >= 0 && category < packetOutboxes.Length)
324 { 335 {
325 LocklessQueue<OutgoingPacket> queue = packetOutboxes[category]; 336 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = packetOutboxes[category];
326 TokenBucket bucket = throttleCategories[category]; 337 TokenBucket bucket = throttleCategories[category];
327 338
328 if (throttleCategories[category].RemoveTokens(packet.Buffer.DataLength)) 339 if (throttleCategories[category].RemoveTokens(packet.Buffer.DataLength))
@@ -354,7 +365,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
354 public bool DequeueOutgoing() 365 public bool DequeueOutgoing()
355 { 366 {
356 OutgoingPacket packet; 367 OutgoingPacket packet;
357 LocklessQueue<OutgoingPacket> queue; 368 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
358 TokenBucket bucket; 369 TokenBucket bucket;
359 bool packetSent = false; 370 bool packetSent = false;
360 371
@@ -382,6 +393,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
382 queue = packetOutboxes[i]; 393 queue = packetOutboxes[i];
383 if (queue.Dequeue(out packet)) 394 if (queue.Dequeue(out packet))
384 { 395 {
396 // Reset the flag for firing this queue's OnQueueEmpty callback
397 // now that we have dequeued a packet
398 queueEmptySent[i] = false;
399
385 // A packet was pulled off the queue. See if we have 400 // A packet was pulled off the queue. See if we have
386 // enough tokens in the bucket to send it out 401 // enough tokens in the bucket to send it out
387 if (bucket.RemoveTokens(packet.Buffer.DataLength)) 402 if (bucket.RemoveTokens(packet.Buffer.DataLength))
@@ -397,13 +412,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
397 nextPackets[i] = packet; 412 nextPackets[i] = packet;
398 nextPacketLengths[i] = packet.Buffer.DataLength; 413 nextPacketLengths[i] = packet.Buffer.DataLength;
399 } 414 }
415
416 // If the queue is empty after this dequeue, fire the queue
417 // empty callback now so it has a chance to fill before we
418 // get back here
419 if (queue.Count == 0)
420 FireQueueEmpty(i);
400 } 421 }
401 else 422 else
402 { 423 {
403 // No packets in this queue. Fire the queue empty callback 424 // No packets in this queue. Fire the queue empty callback
404 QueueEmpty callback = OnQueueEmpty; 425 // if it has not been called recently
405 if (callback != null) 426 FireQueueEmpty(i);
406 callback((ThrottleOutPacketType)i);
407 } 427 }
408 } 428 }
409 } 429 }
@@ -432,8 +452,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
432 452
433 // Always round retransmission timeout up to two seconds 453 // Always round retransmission timeout up to two seconds
434 RTO = Math.Max(2000, (int)(SRTT + Math.Max(G, K * RTTVAR))); 454 RTO = Math.Max(2000, (int)(SRTT + Math.Max(G, K * RTTVAR)));
435 //Logger.Debug("Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " + 455 //m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " +
436 // RTTVAR + " based on new RTT of " + r + "ms"); 456 // RTTVAR + " based on new RTT of " + r + "ms");
437 } 457 }
458
459 private void FireQueueEmpty(int queueIndex)
460 {
461 if (!queueEmptySent[queueIndex])
462 {
463 queueEmptySent[queueIndex] = true;
464
465 QueueEmpty callback = OnQueueEmpty;
466 if (callback != null)
467 Util.FireAndForget(delegate(object o) { callback((ThrottleOutPacketType)(int)o); }, queueIndex);
468 }
469 }
438 } 470 }
439} 471}