aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs122
1 files changed, 97 insertions, 25 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs
index c427870..ff739c5 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs
@@ -39,7 +39,7 @@ using Timer=System.Timers.Timer;
39 39
40namespace OpenSim.Region.ClientStack.LindenUDP 40namespace OpenSim.Region.ClientStack.LindenUDP
41{ 41{
42 public class LLPacketQueue : IPullStatsProvider 42 public class LLPacketQueue : IPullStatsProvider, IDisposable
43 { 43 {
44 private static readonly ILog m_log 44 private static readonly ILog m_log
45 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -62,6 +62,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
62 private Queue<LLQueItem> TextureOutgoingPacketQueue; 62 private Queue<LLQueItem> TextureOutgoingPacketQueue;
63 private Queue<LLQueItem> AssetOutgoingPacketQueue; 63 private Queue<LLQueItem> AssetOutgoingPacketQueue;
64 64
65 private List<ThrottleOutPacketType> Empty = new List<ThrottleOutPacketType>();
66 // m_log.Info("[THROTTLE]: Entering Throttle");
65 // private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>(); 67 // private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>();
66 // private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>(); 68 // private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>();
67 69
@@ -85,26 +87,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
85 87
86 private Dictionary<uint,int> contents = new Dictionary<uint, int>(); 88 private Dictionary<uint,int> contents = new Dictionary<uint, int>();
87 89
88 /// <summary>
89 /// The number of packets in the OutgoingPacketQueue
90 ///
91 /// </summary>
92 internal int TextureOutgoingPacketQueueCount
93 {
94 get
95 {
96 if (TextureOutgoingPacketQueue == null)
97 return 0;
98 return TextureOutgoingPacketQueue.Count;
99 }
100 }
101
102 // private long LastThrottle; 90 // private long LastThrottle;
103 // private long ThrottleInterval; 91 // private long ThrottleInterval;
104 private Timer throttleTimer; 92 private Timer throttleTimer;
105 93
106 private UUID m_agentId; 94 private UUID m_agentId;
107 95
96 public event QueueEmpty OnQueueEmpty;
97
108 public LLPacketQueue(UUID agentId, ClientStackUserSettings userSettings) 98 public LLPacketQueue(UUID agentId, ClientStackUserSettings userSettings)
109 { 99 {
110 // While working on this, the BlockingQueue had me fooled for a bit. 100 // While working on this, the BlockingQueue had me fooled for a bit.
@@ -210,28 +200,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
210 switch (item.throttleType & ThrottleOutPacketType.TypeMask) 200 switch (item.throttleType & ThrottleOutPacketType.TypeMask)
211 { 201 {
212 case ThrottleOutPacketType.Resend: 202 case ThrottleOutPacketType.Resend:
213 ThrottleCheck(ref ResendThrottle, ref ResendOutgoingPacketQueue, item); 203 ThrottleCheck(ref ResendThrottle, ref ResendOutgoingPacketQueue, item, ThrottleOutPacketType.Resend);
214 break; 204 break;
215 case ThrottleOutPacketType.Texture: 205 case ThrottleOutPacketType.Texture:
216 ThrottleCheck(ref TextureThrottle, ref TextureOutgoingPacketQueue, item); 206 ThrottleCheck(ref TextureThrottle, ref TextureOutgoingPacketQueue, item, ThrottleOutPacketType.Texture);
217 break; 207 break;
218 case ThrottleOutPacketType.Task: 208 case ThrottleOutPacketType.Task:
219 if ((item.throttleType & ThrottleOutPacketType.LowPriority) != 0) 209 if ((item.throttleType & ThrottleOutPacketType.LowPriority) != 0)
220 ThrottleCheck(ref TaskThrottle, ref TaskLowpriorityPacketQueue, item); 210 ThrottleCheck(ref TaskThrottle, ref TaskLowpriorityPacketQueue, item, ThrottleOutPacketType.Task);
221 else 211 else
222 ThrottleCheck(ref TaskThrottle, ref TaskOutgoingPacketQueue, item); 212 ThrottleCheck(ref TaskThrottle, ref TaskOutgoingPacketQueue, item, ThrottleOutPacketType.Task);
223 break; 213 break;
224 case ThrottleOutPacketType.Land: 214 case ThrottleOutPacketType.Land:
225 ThrottleCheck(ref LandThrottle, ref LandOutgoingPacketQueue, item); 215 ThrottleCheck(ref LandThrottle, ref LandOutgoingPacketQueue, item, ThrottleOutPacketType.Land);
226 break; 216 break;
227 case ThrottleOutPacketType.Asset: 217 case ThrottleOutPacketType.Asset:
228 ThrottleCheck(ref AssetThrottle, ref AssetOutgoingPacketQueue, item); 218 ThrottleCheck(ref AssetThrottle, ref AssetOutgoingPacketQueue, item, ThrottleOutPacketType.Asset);
229 break; 219 break;
230 case ThrottleOutPacketType.Cloud: 220 case ThrottleOutPacketType.Cloud:
231 ThrottleCheck(ref CloudThrottle, ref CloudOutgoingPacketQueue, item); 221 ThrottleCheck(ref CloudThrottle, ref CloudOutgoingPacketQueue, item, ThrottleOutPacketType.Cloud);
232 break; 222 break;
233 case ThrottleOutPacketType.Wind: 223 case ThrottleOutPacketType.Wind:
234 ThrottleCheck(ref WindThrottle, ref WindOutgoingPacketQueue, item); 224 ThrottleCheck(ref WindThrottle, ref WindOutgoingPacketQueue, item, ThrottleOutPacketType.Wind);
235 break; 225 break;
236 226
237 default: 227 default:
@@ -293,30 +283,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP
293 if (LandOutgoingPacketQueue.Count > 0) 283 if (LandOutgoingPacketQueue.Count > 0)
294 { 284 {
295 SendQueue.Enqueue(LandOutgoingPacketQueue.Dequeue()); 285 SendQueue.Enqueue(LandOutgoingPacketQueue.Dequeue());
286 TriggerOnQueueEmpty(ThrottleOutPacketType.Land);
296 } 287 }
297 if (WindOutgoingPacketQueue.Count > 0) 288 if (WindOutgoingPacketQueue.Count > 0)
298 { 289 {
299 SendQueue.Enqueue(WindOutgoingPacketQueue.Dequeue()); 290 SendQueue.Enqueue(WindOutgoingPacketQueue.Dequeue());
291 TriggerOnQueueEmpty(ThrottleOutPacketType.Wind);
300 } 292 }
301 if (CloudOutgoingPacketQueue.Count > 0) 293 if (CloudOutgoingPacketQueue.Count > 0)
302 { 294 {
303 SendQueue.Enqueue(CloudOutgoingPacketQueue.Dequeue()); 295 SendQueue.Enqueue(CloudOutgoingPacketQueue.Dequeue());
296 TriggerOnQueueEmpty(ThrottleOutPacketType.Cloud);
304 } 297 }
298 bool tasksSent = false;
305 if (TaskOutgoingPacketQueue.Count > 0) 299 if (TaskOutgoingPacketQueue.Count > 0)
306 { 300 {
301 tasksSent = true;
307 SendQueue.PriorityEnqueue(TaskOutgoingPacketQueue.Dequeue()); 302 SendQueue.PriorityEnqueue(TaskOutgoingPacketQueue.Dequeue());
308 } 303 }
309 if (TaskLowpriorityPacketQueue.Count > 0) 304 if (TaskLowpriorityPacketQueue.Count > 0)
310 { 305 {
306 tasksSent = true;
311 SendQueue.Enqueue(TaskLowpriorityPacketQueue.Dequeue()); 307 SendQueue.Enqueue(TaskLowpriorityPacketQueue.Dequeue());
312 } 308 }
309 if (tasksSent)
310 {
311 TriggerOnQueueEmpty(ThrottleOutPacketType.Task);
312 }
313 if (TextureOutgoingPacketQueue.Count > 0) 313 if (TextureOutgoingPacketQueue.Count > 0)
314 { 314 {
315 SendQueue.Enqueue(TextureOutgoingPacketQueue.Dequeue()); 315 SendQueue.Enqueue(TextureOutgoingPacketQueue.Dequeue());
316 TriggerOnQueueEmpty(ThrottleOutPacketType.Texture);
316 } 317 }
317 if (AssetOutgoingPacketQueue.Count > 0) 318 if (AssetOutgoingPacketQueue.Count > 0)
318 { 319 {
319 SendQueue.Enqueue(AssetOutgoingPacketQueue.Dequeue()); 320 SendQueue.Enqueue(AssetOutgoingPacketQueue.Dequeue());
321 TriggerOnQueueEmpty(ThrottleOutPacketType.Asset);
320 } 322 }
321 } 323 }
322 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); 324 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets");
@@ -342,11 +344,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
342 344
343 public void Close() 345 public void Close()
344 { 346 {
347 Dispose();
348 }
349
350 public void Dispose()
351 {
345 Flush(); 352 Flush();
346 WipeClean(); // I'm sure there's a dirty joke in here somewhere. -AFrisby 353 WipeClean(); // I'm sure there's a dirty joke in here somewhere. -AFrisby
347 354
348 m_enabled = false; 355 m_enabled = false;
349 throttleTimer.Stop(); 356 throttleTimer.Stop();
357 throttleTimer.Close();
350 358
351 if (StatsManager.SimExtraStats != null) 359 if (StatsManager.SimExtraStats != null)
352 { 360 {
@@ -388,6 +396,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
388 396
389 int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once. 397 int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once.
390 int throttleLoops = 0; 398 int throttleLoops = 0;
399 List<ThrottleOutPacketType> e;
391 400
392 // We're going to dequeue all of the saved up packets until 401 // We're going to dequeue all of the saved up packets until
393 // we've hit the throttle limit or there's no more packets to send 402 // we've hit the throttle limit or there's no more packets to send
@@ -399,7 +408,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
399 bool qchanged = true; 408 bool qchanged = true;
400 409
401 ResetCounters(); 410 ResetCounters();
402 // m_log.Info("[THROTTLE]: Entering Throttle"); 411
403 while (TotalThrottle.UnderLimit() && qchanged && throttleLoops <= MaxThrottleLoops) 412 while (TotalThrottle.UnderLimit() && qchanged && throttleLoops <= MaxThrottleLoops)
404 { 413 {
405 qchanged = false; // We will break out of the loop if no work was accomplished 414 qchanged = false; // We will break out of the loop if no work was accomplished
@@ -425,6 +434,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
425 TotalThrottle.AddBytes(qpack.Length); 434 TotalThrottle.AddBytes(qpack.Length);
426 LandThrottle.AddBytes(qpack.Length); 435 LandThrottle.AddBytes(qpack.Length);
427 qchanged = true; 436 qchanged = true;
437
438 if (LandOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Land))
439 Empty.Add(ThrottleOutPacketType.Land);
428 } 440 }
429 441
430 if ((WindOutgoingPacketQueue.Count > 0) && WindThrottle.UnderLimit()) 442 if ((WindOutgoingPacketQueue.Count > 0) && WindThrottle.UnderLimit())
@@ -435,6 +447,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
435 TotalThrottle.AddBytes(qpack.Length); 447 TotalThrottle.AddBytes(qpack.Length);
436 WindThrottle.AddBytes(qpack.Length); 448 WindThrottle.AddBytes(qpack.Length);
437 qchanged = true; 449 qchanged = true;
450
451 if (WindOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Wind))
452 Empty.Add(ThrottleOutPacketType.Wind);
438 } 453 }
439 454
440 if ((CloudOutgoingPacketQueue.Count > 0) && CloudThrottle.UnderLimit()) 455 if ((CloudOutgoingPacketQueue.Count > 0) && CloudThrottle.UnderLimit())
@@ -445,6 +460,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
445 TotalThrottle.AddBytes(qpack.Length); 460 TotalThrottle.AddBytes(qpack.Length);
446 CloudThrottle.AddBytes(qpack.Length); 461 CloudThrottle.AddBytes(qpack.Length);
447 qchanged = true; 462 qchanged = true;
463
464 if (CloudOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Cloud))
465 Empty.Add(ThrottleOutPacketType.Cloud);
448 } 466 }
449 467
450 if ((TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0) && TaskThrottle.UnderLimit()) 468 if ((TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0) && TaskThrottle.UnderLimit())
@@ -464,6 +482,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
464 TotalThrottle.AddBytes(qpack.Length); 482 TotalThrottle.AddBytes(qpack.Length);
465 TaskThrottle.AddBytes(qpack.Length); 483 TaskThrottle.AddBytes(qpack.Length);
466 qchanged = true; 484 qchanged = true;
485
486 if (TaskOutgoingPacketQueue.Count == 0 && TaskLowpriorityPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Task))
487 Empty.Add(ThrottleOutPacketType.Task);
467 } 488 }
468 489
469 if ((TextureOutgoingPacketQueue.Count > 0) && TextureThrottle.UnderLimit()) 490 if ((TextureOutgoingPacketQueue.Count > 0) && TextureThrottle.UnderLimit())
@@ -474,6 +495,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
474 TotalThrottle.AddBytes(qpack.Length); 495 TotalThrottle.AddBytes(qpack.Length);
475 TextureThrottle.AddBytes(qpack.Length); 496 TextureThrottle.AddBytes(qpack.Length);
476 qchanged = true; 497 qchanged = true;
498
499 if (TextureOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Texture))
500 Empty.Add(ThrottleOutPacketType.Texture);
477 } 501 }
478 502
479 if ((AssetOutgoingPacketQueue.Count > 0) && AssetThrottle.UnderLimit()) 503 if ((AssetOutgoingPacketQueue.Count > 0) && AssetThrottle.UnderLimit())
@@ -484,12 +508,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
484 TotalThrottle.AddBytes(qpack.Length); 508 TotalThrottle.AddBytes(qpack.Length);
485 AssetThrottle.AddBytes(qpack.Length); 509 AssetThrottle.AddBytes(qpack.Length);
486 qchanged = true; 510 qchanged = true;
511
512 if (AssetOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Asset))
513 Empty.Add(ThrottleOutPacketType.Asset);
487 } 514 }
488 } 515 }
489 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); 516 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets");
517
518 e = new List<ThrottleOutPacketType>(Empty);
519 Empty.Clear();
520 }
521
522 foreach (ThrottleOutPacketType t in e)
523 {
524 if (GetQueueCount(t) == 0)
525 TriggerOnQueueEmpty(t);
490 } 526 }
491 } 527 }
492 528
529 private void TriggerOnQueueEmpty(ThrottleOutPacketType queue)
530 {
531 QueueEmpty handlerQueueEmpty = OnQueueEmpty;
532
533 if (handlerQueueEmpty == null)
534 return;
535
536 handlerQueueEmpty(queue);
537 }
538
493 private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e) 539 private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e)
494 { 540 {
495 // just to change the signature, and that ProcessThrottle 541 // just to change the signature, and that ProcessThrottle
@@ -497,7 +543,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
497 ProcessThrottle(); 543 ProcessThrottle();
498 } 544 }
499 545
500 private void ThrottleCheck(ref LLPacketThrottle throttle, ref Queue<LLQueItem> q, LLQueItem item) 546 private void ThrottleCheck(ref LLPacketThrottle throttle, ref Queue<LLQueItem> q, LLQueItem item, ThrottleOutPacketType itemType)
501 { 547 {
502 // The idea.. is if the packet throttle queues are empty 548 // The idea.. is if the packet throttle queues are empty
503 // and the client is under throttle for the type. Queue 549 // and the client is under throttle for the type. Queue
@@ -513,6 +559,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
513 throttle.AddBytes(item.Length); 559 throttle.AddBytes(item.Length);
514 TotalThrottle.AddBytes(item.Length); 560 TotalThrottle.AddBytes(item.Length);
515 SendQueue.Enqueue(item); 561 SendQueue.Enqueue(item);
562 lock (this)
563 {
564 if (!Empty.Contains(itemType))
565 Empty.Add(itemType);
566 }
516 } 567 }
517 catch (Exception e) 568 catch (Exception e)
518 { 569 {
@@ -698,5 +749,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
698 { 749 {
699 get { return throttleMultiplier; } 750 get { return throttleMultiplier; }
700 } 751 }
752
753 public int GetQueueCount(ThrottleOutPacketType queue)
754 {
755 switch (queue)
756 {
757 case ThrottleOutPacketType.Land:
758 return LandOutgoingPacketQueue.Count;
759 case ThrottleOutPacketType.Wind:
760 return WindOutgoingPacketQueue.Count;
761 case ThrottleOutPacketType.Cloud:
762 return CloudOutgoingPacketQueue.Count;
763 case ThrottleOutPacketType.Task:
764 return TaskOutgoingPacketQueue.Count;
765 case ThrottleOutPacketType.Texture:
766 return TextureOutgoingPacketQueue.Count;
767 case ThrottleOutPacketType.Asset:
768 return AssetOutgoingPacketQueue.Count;
769 }
770
771 return 0;
772 }
701 } 773 }
702} 774}