From 44776fea723774f0674881d69855af9657398d18 Mon Sep 17 00:00:00 2001 From: James J Greensky Date: Wed, 30 Sep 2009 17:30:28 -0700 Subject: Fixing LLClientView memory leak Fixing LLClientView memory leak by disposing of all timers utilized in LLClientView as they contain references to the callback method. This required the use of the Terminate and Close infrastructure that was already in place but was not being utilized. --- OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs index 798c1e7..6dd0697 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs @@ -39,7 +39,7 @@ using Timer=System.Timers.Timer; namespace OpenSim.Region.ClientStack.LindenUDP { - public class LLPacketQueue : IPullStatsProvider + public class LLPacketQueue : IPullStatsProvider, IDisposable { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -342,11 +342,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void Close() { + Dispose(); + } + + public void Dispose() + { Flush(); WipeClean(); // I'm sure there's a dirty joke in here somewhere. -AFrisby m_enabled = false; throttleTimer.Stop(); + throttleTimer.Close(); if (StatsManager.SimExtraStats != null) { -- cgit v1.1 From 5e9da4daabc49250af9c0ec810b1290c74bad885 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 1 Oct 2009 21:08:17 +0100 Subject: Add OnQueueEmpty event to the packet layers. No user functinality yet --- .../Region/ClientStack/LindenUDP/LLPacketQueue.cs | 49 ++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs index 6dd0697..f08f1b6 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs @@ -105,6 +105,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP private UUID m_agentId; + public event QueueEmpty OnQueueEmpty; + public LLPacketQueue(UUID agentId, ClientStackUserSettings userSettings) { // While working on this, the BlockingQueue had me fooled for a bit. @@ -293,30 +295,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (LandOutgoingPacketQueue.Count > 0) { SendQueue.Enqueue(LandOutgoingPacketQueue.Dequeue()); + TriggerOnQueueEmpty(ThrottleOutPacketType.Land); } if (WindOutgoingPacketQueue.Count > 0) { SendQueue.Enqueue(WindOutgoingPacketQueue.Dequeue()); + TriggerOnQueueEmpty(ThrottleOutPacketType.Wind); } if (CloudOutgoingPacketQueue.Count > 0) { SendQueue.Enqueue(CloudOutgoingPacketQueue.Dequeue()); + TriggerOnQueueEmpty(ThrottleOutPacketType.Cloud); } + bool tasksSent = false; if (TaskOutgoingPacketQueue.Count > 0) { + tasksSent = true; SendQueue.PriorityEnqueue(TaskOutgoingPacketQueue.Dequeue()); } if (TaskLowpriorityPacketQueue.Count > 0) { + tasksSent = true; SendQueue.Enqueue(TaskLowpriorityPacketQueue.Dequeue()); } + if (tasksSent) + { + TriggerOnQueueEmpty(ThrottleOutPacketType.Task); + } if (TextureOutgoingPacketQueue.Count > 0) { SendQueue.Enqueue(TextureOutgoingPacketQueue.Dequeue()); + TriggerOnQueueEmpty(ThrottleOutPacketType.Texture); } if (AssetOutgoingPacketQueue.Count > 0) { SendQueue.Enqueue(AssetOutgoingPacketQueue.Dequeue()); + TriggerOnQueueEmpty(ThrottleOutPacketType.Asset); } } // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); @@ -405,6 +419,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP bool qchanged = true; ResetCounters(); + + List Empty = new List(); // m_log.Info("[THROTTLE]: Entering Throttle"); while (TotalThrottle.UnderLimit() && qchanged && throttleLoops <= MaxThrottleLoops) { @@ -431,6 +447,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP TotalThrottle.AddBytes(qpack.Length); LandThrottle.AddBytes(qpack.Length); qchanged = true; + + if (LandOutgoingPacketQueue.Count == 0) + Empty.Add(ThrottleOutPacketType.Land); } if ((WindOutgoingPacketQueue.Count > 0) && WindThrottle.UnderLimit()) @@ -441,6 +460,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP TotalThrottle.AddBytes(qpack.Length); WindThrottle.AddBytes(qpack.Length); qchanged = true; + + if (WindOutgoingPacketQueue.Count == 0) + Empty.Add(ThrottleOutPacketType.Wind); } if ((CloudOutgoingPacketQueue.Count > 0) && CloudThrottle.UnderLimit()) @@ -451,6 +473,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP TotalThrottle.AddBytes(qpack.Length); CloudThrottle.AddBytes(qpack.Length); qchanged = true; + + if (CloudOutgoingPacketQueue.Count == 0) + Empty.Add(ThrottleOutPacketType.Cloud); } if ((TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0) && TaskThrottle.UnderLimit()) @@ -470,6 +495,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP TotalThrottle.AddBytes(qpack.Length); TaskThrottle.AddBytes(qpack.Length); qchanged = true; + + if (TaskOutgoingPacketQueue.Count == 0 && TaskLowpriorityPacketQueue.Count == 0) + Empty.Add(ThrottleOutPacketType.Task); } if ((TextureOutgoingPacketQueue.Count > 0) && TextureThrottle.UnderLimit()) @@ -480,6 +508,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP TotalThrottle.AddBytes(qpack.Length); TextureThrottle.AddBytes(qpack.Length); qchanged = true; + + if (TextureOutgoingPacketQueue.Count == 0) + Empty.Add(ThrottleOutPacketType.Texture); } if ((AssetOutgoingPacketQueue.Count > 0) && AssetThrottle.UnderLimit()) @@ -490,12 +521,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP TotalThrottle.AddBytes(qpack.Length); AssetThrottle.AddBytes(qpack.Length); qchanged = true; + + if (AssetOutgoingPacketQueue.Count == 0) + Empty.Add(ThrottleOutPacketType.Asset); } } // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); + + foreach (ThrottleOutPacketType t in Empty) + { + TriggerOnQueueEmpty(t); + } } } + private void TriggerOnQueueEmpty(ThrottleOutPacketType queue) + { + QueueEmpty handlerQueueEmpty = OnQueueEmpty; + + if (handlerQueueEmpty == null) + return; + + handlerQueueEmpty(queue); + } + private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e) { // just to change the signature, and that ProcessThrottle -- cgit v1.1 From 54a912bb9cd5148abfa5eb68b0146ae3b04051a3 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 1 Oct 2009 22:35:57 +0100 Subject: Add a method to determine the count of packets in a throttle --- .../Region/ClientStack/LindenUDP/LLPacketQueue.cs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs index f08f1b6..d4d654f 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs @@ -753,5 +753,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP { get { return throttleMultiplier; } } + + public int GetQueueCount(ThrottleOutPacketType queue) + { + switch (queue) + { + case ThrottleOutPacketType.Land: + return LandOutgoingPacketQueue.Count; + case ThrottleOutPacketType.Wind: + return WindOutgoingPacketQueue.Count; + case ThrottleOutPacketType.Cloud: + return CloudOutgoingPacketQueue.Count; + case ThrottleOutPacketType.Task: + return TaskOutgoingPacketQueue.Count; + case ThrottleOutPacketType.Texture: + return TextureOutgoingPacketQueue.Count; + case ThrottleOutPacketType.Asset: + return AssetOutgoingPacketQueue.Count; + } + + return 0; + } } } -- cgit v1.1 From 18a744cac10c797b67236988a84ab6d13a5543b8 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 2 Oct 2009 04:04:14 +0100 Subject: Change texture sending to be driven by the queue empty event from the packet queue, rather than a timer --- .../Region/ClientStack/LindenUDP/LLPacketQueue.cs | 64 ++++++++++------------ 1 file changed, 30 insertions(+), 34 deletions(-) (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs index d4d654f..8484846 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs @@ -62,6 +62,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP private Queue TextureOutgoingPacketQueue; private Queue AssetOutgoingPacketQueue; + private List Empty = new List(); + // m_log.Info("[THROTTLE]: Entering Throttle"); // private Dictionary PendingAcks = new Dictionary(); // private Dictionary NeedAck = new Dictionary(); @@ -85,20 +87,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP private Dictionary contents = new Dictionary(); - /// - /// The number of packets in the OutgoingPacketQueue - /// - /// - internal int TextureOutgoingPacketQueueCount - { - get - { - if (TextureOutgoingPacketQueue == null) - return 0; - return TextureOutgoingPacketQueue.Count; - } - } - // private long LastThrottle; // private long ThrottleInterval; private Timer throttleTimer; @@ -212,28 +200,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP switch (item.throttleType & ThrottleOutPacketType.TypeMask) { case ThrottleOutPacketType.Resend: - ThrottleCheck(ref ResendThrottle, ref ResendOutgoingPacketQueue, item); + ThrottleCheck(ref ResendThrottle, ref ResendOutgoingPacketQueue, item, ThrottleOutPacketType.Resend); break; case ThrottleOutPacketType.Texture: - ThrottleCheck(ref TextureThrottle, ref TextureOutgoingPacketQueue, item); + ThrottleCheck(ref TextureThrottle, ref TextureOutgoingPacketQueue, item, ThrottleOutPacketType.Texture); break; case ThrottleOutPacketType.Task: if ((item.throttleType & ThrottleOutPacketType.LowPriority) != 0) - ThrottleCheck(ref TaskThrottle, ref TaskLowpriorityPacketQueue, item); + ThrottleCheck(ref TaskThrottle, ref TaskLowpriorityPacketQueue, item, ThrottleOutPacketType.Task); else - ThrottleCheck(ref TaskThrottle, ref TaskOutgoingPacketQueue, item); + ThrottleCheck(ref TaskThrottle, ref TaskOutgoingPacketQueue, item, ThrottleOutPacketType.Task); break; case ThrottleOutPacketType.Land: - ThrottleCheck(ref LandThrottle, ref LandOutgoingPacketQueue, item); + ThrottleCheck(ref LandThrottle, ref LandOutgoingPacketQueue, item, ThrottleOutPacketType.Land); break; case ThrottleOutPacketType.Asset: - ThrottleCheck(ref AssetThrottle, ref AssetOutgoingPacketQueue, item); + ThrottleCheck(ref AssetThrottle, ref AssetOutgoingPacketQueue, item, ThrottleOutPacketType.Asset); break; case ThrottleOutPacketType.Cloud: - ThrottleCheck(ref CloudThrottle, ref CloudOutgoingPacketQueue, item); + ThrottleCheck(ref CloudThrottle, ref CloudOutgoingPacketQueue, item, ThrottleOutPacketType.Cloud); break; case ThrottleOutPacketType.Wind: - ThrottleCheck(ref WindThrottle, ref WindOutgoingPacketQueue, item); + ThrottleCheck(ref WindThrottle, ref WindOutgoingPacketQueue, item, ThrottleOutPacketType.Wind); break; default: @@ -408,6 +396,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once. int throttleLoops = 0; + List e; // We're going to dequeue all of the saved up packets until // we've hit the throttle limit or there's no more packets to send @@ -420,8 +409,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP ResetCounters(); - List Empty = new List(); - // m_log.Info("[THROTTLE]: Entering Throttle"); while (TotalThrottle.UnderLimit() && qchanged && throttleLoops <= MaxThrottleLoops) { qchanged = false; // We will break out of the loop if no work was accomplished @@ -448,7 +435,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP LandThrottle.AddBytes(qpack.Length); qchanged = true; - if (LandOutgoingPacketQueue.Count == 0) + if (LandOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Land)) Empty.Add(ThrottleOutPacketType.Land); } @@ -461,7 +448,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP WindThrottle.AddBytes(qpack.Length); qchanged = true; - if (WindOutgoingPacketQueue.Count == 0) + if (WindOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Wind)) Empty.Add(ThrottleOutPacketType.Wind); } @@ -474,7 +461,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP CloudThrottle.AddBytes(qpack.Length); qchanged = true; - if (CloudOutgoingPacketQueue.Count == 0) + if (CloudOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Cloud)) Empty.Add(ThrottleOutPacketType.Cloud); } @@ -496,7 +483,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP TaskThrottle.AddBytes(qpack.Length); qchanged = true; - if (TaskOutgoingPacketQueue.Count == 0 && TaskLowpriorityPacketQueue.Count == 0) + if (TaskOutgoingPacketQueue.Count == 0 && TaskLowpriorityPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Task)) Empty.Add(ThrottleOutPacketType.Task); } @@ -509,7 +496,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP TextureThrottle.AddBytes(qpack.Length); qchanged = true; - if (TextureOutgoingPacketQueue.Count == 0) + if (TextureOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Texture)) Empty.Add(ThrottleOutPacketType.Texture); } @@ -522,16 +509,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP AssetThrottle.AddBytes(qpack.Length); qchanged = true; - if (AssetOutgoingPacketQueue.Count == 0) + if (AssetOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Asset)) Empty.Add(ThrottleOutPacketType.Asset); } } // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); - foreach (ThrottleOutPacketType t in Empty) - { + e = new List(Empty); + Empty.Clear(); + } + + foreach (ThrottleOutPacketType t in e) + { + if (GetQueueCount(t) == 0) TriggerOnQueueEmpty(t); - } } } @@ -552,7 +543,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP ProcessThrottle(); } - private void ThrottleCheck(ref LLPacketThrottle throttle, ref Queue q, LLQueItem item) + private void ThrottleCheck(ref LLPacketThrottle throttle, ref Queue q, LLQueItem item, ThrottleOutPacketType itemType) { // The idea.. is if the packet throttle queues are empty // and the client is under throttle for the type. Queue @@ -568,6 +559,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP throttle.AddBytes(item.Length); TotalThrottle.AddBytes(item.Length); SendQueue.Enqueue(item); + lock (this) + { + if (!Empty.Contains(itemType)) + Empty.Add(itemType); + } } catch (Exception e) { -- cgit v1.1 From 9b342d3e0d85e64e143b9fe1010e4e27135e24ec Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Fri, 2 Oct 2009 12:00:42 -0700 Subject: * Changed the flush logic to drop packets in non-transactional streams, and to not fire any "put more data in the queues" callbacks * Minor tweaks to code formatting to make the callback chain for packet queuing easier to follow --- .../Region/ClientStack/LindenUDP/LLPacketQueue.cs | 58 +++++----------------- 1 file changed, 13 insertions(+), 45 deletions(-) (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs index 8484846..0f1acb1 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs @@ -273,55 +273,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP { lock (this) { - while (PacketsWaiting()) + // These categories do not contain transactional packets so we can safely drop any pending data in them + LandOutgoingPacketQueue.Clear(); + WindOutgoingPacketQueue.Clear(); + CloudOutgoingPacketQueue.Clear(); + TextureOutgoingPacketQueue.Clear(); + AssetOutgoingPacketQueue.Clear(); + + // Now comes the fun part.. we dump all remaining resend and task packets into the send queue + while (ResendOutgoingPacketQueue.Count > 0 || TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0) { - //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up. if (ResendOutgoingPacketQueue.Count > 0) - { SendQueue.Enqueue(ResendOutgoingPacketQueue.Dequeue()); - } - if (LandOutgoingPacketQueue.Count > 0) - { - SendQueue.Enqueue(LandOutgoingPacketQueue.Dequeue()); - TriggerOnQueueEmpty(ThrottleOutPacketType.Land); - } - if (WindOutgoingPacketQueue.Count > 0) - { - SendQueue.Enqueue(WindOutgoingPacketQueue.Dequeue()); - TriggerOnQueueEmpty(ThrottleOutPacketType.Wind); - } - if (CloudOutgoingPacketQueue.Count > 0) - { - SendQueue.Enqueue(CloudOutgoingPacketQueue.Dequeue()); - TriggerOnQueueEmpty(ThrottleOutPacketType.Cloud); - } - bool tasksSent = false; + if (TaskOutgoingPacketQueue.Count > 0) - { - tasksSent = true; SendQueue.PriorityEnqueue(TaskOutgoingPacketQueue.Dequeue()); - } + if (TaskLowpriorityPacketQueue.Count > 0) - { - tasksSent = true; SendQueue.Enqueue(TaskLowpriorityPacketQueue.Dequeue()); - } - if (tasksSent) - { - TriggerOnQueueEmpty(ThrottleOutPacketType.Task); - } - if (TextureOutgoingPacketQueue.Count > 0) - { - SendQueue.Enqueue(TextureOutgoingPacketQueue.Dequeue()); - TriggerOnQueueEmpty(ThrottleOutPacketType.Texture); - } - if (AssetOutgoingPacketQueue.Count > 0) - { - SendQueue.Enqueue(AssetOutgoingPacketQueue.Dequeue()); - TriggerOnQueueEmpty(ThrottleOutPacketType.Asset); - } } - // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); } } @@ -530,10 +500,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP { QueueEmpty handlerQueueEmpty = OnQueueEmpty; - if (handlerQueueEmpty == null) - return; - - handlerQueueEmpty(queue); + if (handlerQueueEmpty != null) + handlerQueueEmpty(queue); } private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e) -- cgit v1.1