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.cs148
1 files changed, 94 insertions, 54 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs
index c427870..3eed2e0 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:
@@ -283,43 +273,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
283 { 273 {
284 lock (this) 274 lock (this)
285 { 275 {
286 while (PacketsWaiting()) 276 // These categories do not contain transactional packets so we can safely drop any pending data in them
277 LandOutgoingPacketQueue.Clear();
278 WindOutgoingPacketQueue.Clear();
279 CloudOutgoingPacketQueue.Clear();
280 TextureOutgoingPacketQueue.Clear();
281 AssetOutgoingPacketQueue.Clear();
282
283 // Now comes the fun part.. we dump all remaining resend and task packets into the send queue
284 while (ResendOutgoingPacketQueue.Count > 0 || TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0)
287 { 285 {
288 //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up.
289 if (ResendOutgoingPacketQueue.Count > 0) 286 if (ResendOutgoingPacketQueue.Count > 0)
290 {
291 SendQueue.Enqueue(ResendOutgoingPacketQueue.Dequeue()); 287 SendQueue.Enqueue(ResendOutgoingPacketQueue.Dequeue());
292 } 288
293 if (LandOutgoingPacketQueue.Count > 0)
294 {
295 SendQueue.Enqueue(LandOutgoingPacketQueue.Dequeue());
296 }
297 if (WindOutgoingPacketQueue.Count > 0)
298 {
299 SendQueue.Enqueue(WindOutgoingPacketQueue.Dequeue());
300 }
301 if (CloudOutgoingPacketQueue.Count > 0)
302 {
303 SendQueue.Enqueue(CloudOutgoingPacketQueue.Dequeue());
304 }
305 if (TaskOutgoingPacketQueue.Count > 0) 289 if (TaskOutgoingPacketQueue.Count > 0)
306 {
307 SendQueue.PriorityEnqueue(TaskOutgoingPacketQueue.Dequeue()); 290 SendQueue.PriorityEnqueue(TaskOutgoingPacketQueue.Dequeue());
308 } 291
309 if (TaskLowpriorityPacketQueue.Count > 0) 292 if (TaskLowpriorityPacketQueue.Count > 0)
310 {
311 SendQueue.Enqueue(TaskLowpriorityPacketQueue.Dequeue()); 293 SendQueue.Enqueue(TaskLowpriorityPacketQueue.Dequeue());
312 }
313 if (TextureOutgoingPacketQueue.Count > 0)
314 {
315 SendQueue.Enqueue(TextureOutgoingPacketQueue.Dequeue());
316 }
317 if (AssetOutgoingPacketQueue.Count > 0)
318 {
319 SendQueue.Enqueue(AssetOutgoingPacketQueue.Dequeue());
320 }
321 } 294 }
322 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets");
323 } 295 }
324 } 296 }
325 297
@@ -342,11 +314,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
342 314
343 public void Close() 315 public void Close()
344 { 316 {
317 Dispose();
318 }
319
320 public void Dispose()
321 {
345 Flush(); 322 Flush();
346 WipeClean(); // I'm sure there's a dirty joke in here somewhere. -AFrisby 323 WipeClean(); // I'm sure there's a dirty joke in here somewhere. -AFrisby
347 324
348 m_enabled = false; 325 m_enabled = false;
349 throttleTimer.Stop(); 326 throttleTimer.Stop();
327 throttleTimer.Close();
350 328
351 if (StatsManager.SimExtraStats != null) 329 if (StatsManager.SimExtraStats != null)
352 { 330 {
@@ -388,6 +366,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
388 366
389 int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once. 367 int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once.
390 int throttleLoops = 0; 368 int throttleLoops = 0;
369 List<ThrottleOutPacketType> e;
391 370
392 // We're going to dequeue all of the saved up packets until 371 // 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 372 // we've hit the throttle limit or there's no more packets to send
@@ -399,7 +378,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
399 bool qchanged = true; 378 bool qchanged = true;
400 379
401 ResetCounters(); 380 ResetCounters();
402 // m_log.Info("[THROTTLE]: Entering Throttle"); 381
403 while (TotalThrottle.UnderLimit() && qchanged && throttleLoops <= MaxThrottleLoops) 382 while (TotalThrottle.UnderLimit() && qchanged && throttleLoops <= MaxThrottleLoops)
404 { 383 {
405 qchanged = false; // We will break out of the loop if no work was accomplished 384 qchanged = false; // We will break out of the loop if no work was accomplished
@@ -425,6 +404,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
425 TotalThrottle.AddBytes(qpack.Length); 404 TotalThrottle.AddBytes(qpack.Length);
426 LandThrottle.AddBytes(qpack.Length); 405 LandThrottle.AddBytes(qpack.Length);
427 qchanged = true; 406 qchanged = true;
407
408 if (LandOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Land))
409 Empty.Add(ThrottleOutPacketType.Land);
428 } 410 }
429 411
430 if ((WindOutgoingPacketQueue.Count > 0) && WindThrottle.UnderLimit()) 412 if ((WindOutgoingPacketQueue.Count > 0) && WindThrottle.UnderLimit())
@@ -435,6 +417,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
435 TotalThrottle.AddBytes(qpack.Length); 417 TotalThrottle.AddBytes(qpack.Length);
436 WindThrottle.AddBytes(qpack.Length); 418 WindThrottle.AddBytes(qpack.Length);
437 qchanged = true; 419 qchanged = true;
420
421 if (WindOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Wind))
422 Empty.Add(ThrottleOutPacketType.Wind);
438 } 423 }
439 424
440 if ((CloudOutgoingPacketQueue.Count > 0) && CloudThrottle.UnderLimit()) 425 if ((CloudOutgoingPacketQueue.Count > 0) && CloudThrottle.UnderLimit())
@@ -445,6 +430,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
445 TotalThrottle.AddBytes(qpack.Length); 430 TotalThrottle.AddBytes(qpack.Length);
446 CloudThrottle.AddBytes(qpack.Length); 431 CloudThrottle.AddBytes(qpack.Length);
447 qchanged = true; 432 qchanged = true;
433
434 if (CloudOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Cloud))
435 Empty.Add(ThrottleOutPacketType.Cloud);
448 } 436 }
449 437
450 if ((TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0) && TaskThrottle.UnderLimit()) 438 if ((TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0) && TaskThrottle.UnderLimit())
@@ -464,6 +452,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
464 TotalThrottle.AddBytes(qpack.Length); 452 TotalThrottle.AddBytes(qpack.Length);
465 TaskThrottle.AddBytes(qpack.Length); 453 TaskThrottle.AddBytes(qpack.Length);
466 qchanged = true; 454 qchanged = true;
455
456 if (TaskOutgoingPacketQueue.Count == 0 && TaskLowpriorityPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Task))
457 Empty.Add(ThrottleOutPacketType.Task);
467 } 458 }
468 459
469 if ((TextureOutgoingPacketQueue.Count > 0) && TextureThrottle.UnderLimit()) 460 if ((TextureOutgoingPacketQueue.Count > 0) && TextureThrottle.UnderLimit())
@@ -474,6 +465,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
474 TotalThrottle.AddBytes(qpack.Length); 465 TotalThrottle.AddBytes(qpack.Length);
475 TextureThrottle.AddBytes(qpack.Length); 466 TextureThrottle.AddBytes(qpack.Length);
476 qchanged = true; 467 qchanged = true;
468
469 if (TextureOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Texture))
470 Empty.Add(ThrottleOutPacketType.Texture);
477 } 471 }
478 472
479 if ((AssetOutgoingPacketQueue.Count > 0) && AssetThrottle.UnderLimit()) 473 if ((AssetOutgoingPacketQueue.Count > 0) && AssetThrottle.UnderLimit())
@@ -484,10 +478,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
484 TotalThrottle.AddBytes(qpack.Length); 478 TotalThrottle.AddBytes(qpack.Length);
485 AssetThrottle.AddBytes(qpack.Length); 479 AssetThrottle.AddBytes(qpack.Length);
486 qchanged = true; 480 qchanged = true;
481
482 if (AssetOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Asset))
483 Empty.Add(ThrottleOutPacketType.Asset);
487 } 484 }
488 } 485 }
489 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); 486 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets");
487
488 e = new List<ThrottleOutPacketType>(Empty);
489 Empty.Clear();
490 } 490 }
491
492 foreach (ThrottleOutPacketType t in e)
493 {
494 if (GetQueueCount(t) == 0)
495 TriggerOnQueueEmpty(t);
496 }
497 }
498
499 private void TriggerOnQueueEmpty(ThrottleOutPacketType queue)
500 {
501 QueueEmpty handlerQueueEmpty = OnQueueEmpty;
502
503 if (handlerQueueEmpty != null)
504 handlerQueueEmpty(queue);
491 } 505 }
492 506
493 private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e) 507 private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e)
@@ -497,7 +511,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
497 ProcessThrottle(); 511 ProcessThrottle();
498 } 512 }
499 513
500 private void ThrottleCheck(ref LLPacketThrottle throttle, ref Queue<LLQueItem> q, LLQueItem item) 514 private void ThrottleCheck(ref LLPacketThrottle throttle, ref Queue<LLQueItem> q, LLQueItem item, ThrottleOutPacketType itemType)
501 { 515 {
502 // The idea.. is if the packet throttle queues are empty 516 // The idea.. is if the packet throttle queues are empty
503 // and the client is under throttle for the type. Queue 517 // and the client is under throttle for the type. Queue
@@ -513,6 +527,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
513 throttle.AddBytes(item.Length); 527 throttle.AddBytes(item.Length);
514 TotalThrottle.AddBytes(item.Length); 528 TotalThrottle.AddBytes(item.Length);
515 SendQueue.Enqueue(item); 529 SendQueue.Enqueue(item);
530 lock (this)
531 {
532 if (!Empty.Contains(itemType))
533 Empty.Add(itemType);
534 }
516 } 535 }
517 catch (Exception e) 536 catch (Exception e)
518 { 537 {
@@ -698,5 +717,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
698 { 717 {
699 get { return throttleMultiplier; } 718 get { return throttleMultiplier; }
700 } 719 }
720
721 public int GetQueueCount(ThrottleOutPacketType queue)
722 {
723 switch (queue)
724 {
725 case ThrottleOutPacketType.Land:
726 return LandOutgoingPacketQueue.Count;
727 case ThrottleOutPacketType.Wind:
728 return WindOutgoingPacketQueue.Count;
729 case ThrottleOutPacketType.Cloud:
730 return CloudOutgoingPacketQueue.Count;
731 case ThrottleOutPacketType.Task:
732 return TaskOutgoingPacketQueue.Count;
733 case ThrottleOutPacketType.Texture:
734 return TextureOutgoingPacketQueue.Count;
735 case ThrottleOutPacketType.Asset:
736 return AssetOutgoingPacketQueue.Count;
737 }
738
739 return 0;
740 }
701 } 741 }
702} 742}