From 30eea2618dcc0a43d1d4d764590100c19bd7c05d Mon Sep 17 00:00:00 2001
From: Justin Clarke Casey
Date: Fri, 22 Feb 2008 20:50:30 +0000
Subject: * Implement packet queue statistics * This will show the packets
 waiting in each queue for each client logged into a region server * These are
 displayed using 'show stats' on the region command line * This is in pursuit
 of a memory leak. * This will require a prebuild

---
 .../Framework/Statistics/SimExtraStatsReporter.cs  | 95 ++++++++++++++++++++--
 OpenSim/Region/ClientStack/ClientView.cs           |  2 +-
 OpenSim/Region/ClientStack/PacketQueue.cs          | 37 ++++++++-
 3 files changed, 124 insertions(+), 10 deletions(-)

(limited to 'OpenSim')

diff --git a/OpenSim/Framework/Statistics/SimExtraStatsReporter.cs b/OpenSim/Framework/Statistics/SimExtraStatsReporter.cs
index c8b8223..acf2ecb 100644
--- a/OpenSim/Framework/Statistics/SimExtraStatsReporter.cs
+++ b/OpenSim/Framework/Statistics/SimExtraStatsReporter.cs
@@ -26,12 +26,19 @@
 * 
 */
 
+using System;
+using System.Collections.Generic;
+using System.Text;
+
 using OpenSim.Framework;
+using OpenSim.Framework.Statistics.Interfaces;
+
+using libsecondlife;
 
 namespace OpenSim.Framework.Statistics
 {  
     public class SimExtraStatsReporter
-    {
+    {        
         private long assetsInCache;
         private long texturesInCache;        
         private long assetCacheMemoryUsage;
@@ -42,6 +49,12 @@ namespace OpenSim.Framework.Statistics
         public long AssetCacheMemoryUsage { get { return assetCacheMemoryUsage; } }
         public long TextureCacheMemoryUsage { get { return textureCacheMemoryUsage; } }
         
+        /// <summary>
+        /// Retain a dictionary of all packet queues stats reporters
+        /// </summary>
+        private IDictionary<LLUUID, PacketQueueStatsReporter> packetQueueStatsReporters
+            = new Dictionary<LLUUID, PacketQueueStatsReporter>();
+        
         public void AddAsset(AssetBase asset)
         {
             assetsInCache++;
@@ -56,19 +69,87 @@ namespace OpenSim.Framework.Statistics
                 texturesInCache++;
                 textureCacheMemoryUsage += image.Data.Length;
             }
-        }        
+        }  
+        
+        /// <summary>
+        /// Register as a packet queue stats provider
+        /// </summary>
+        /// <param name="uuid">An agent LLUUID</param>
+        /// <param name="provider"></param>
+        public void RegisterPacketQueueStatsProvider(LLUUID uuid, IPullStatsProvider provider)
+        {
+            lock (packetQueueStatsReporters)
+            {
+                packetQueueStatsReporters[uuid] = new PacketQueueStatsReporter(provider);
+            }
+        }
+        
+        /// <summary>
+        /// Deregister a packet queue stats provider
+        /// </summary>
+        /// <param name="uuid">An agent LLUUID</param>
+        public void DeregisterPacketQueueStatsProvider(LLUUID uuid)
+        {
+            lock (packetQueueStatsReporters)
+            {
+                packetQueueStatsReporters.Remove(uuid);
+            }
+        }
 
         /// <summary>
         /// Report back collected statistical information.
         /// </summary>
         /// <returns></returns>
         public string Report()
-        {            
-            return string.Format(
+        {    
+            StringBuilder sb = new StringBuilder(Environment.NewLine);
+            sb.Append("PACKET QUEUE STATISTICS");
+            sb.Append(Environment.NewLine);            
+            sb.Append(
+                string.Format(
 @"Asset   cache contains {0,6} assets   using {1,10:0.000}K
-Texture cache contains {2,6} textures using {3,10:0.000}K",
-                AssetsInCache, AssetCacheMemoryUsage / 1024.0, 
-                TexturesInCache, TextureCacheMemoryUsage / 1024.0);
+Texture cache contains {2,6} textures using {3,10:0.000}K" + Environment.NewLine,
+                    AssetsInCache, AssetCacheMemoryUsage / 1024.0, 
+                    TexturesInCache, TextureCacheMemoryUsage / 1024.0));
+
+            sb.Append(Environment.NewLine);
+            sb.Append("PACKET QUEUE STATISTICS");
+            sb.Append(Environment.NewLine);
+            sb.Append("Agent UUID                                ");
+            sb.Append("  Send     In       Out      Resend ");  
+            sb.Append("  Land     Wind     Cloud    Task     Texture  Asset");
+            sb.Append(Environment.NewLine);            
+                
+            foreach (LLUUID key in packetQueueStatsReporters.Keys)
+            {
+                sb.Append(string.Format("{0}: ", key));
+                sb.Append(packetQueueStatsReporters[key].Report());
+                sb.Append(Environment.NewLine);
+            }
+            
+            return sb.ToString();
         }        
     }
+
+    /// <summary>
+    /// Pull packet queue stats from packet queues and report
+    /// </summary>
+    public class PacketQueueStatsReporter
+    {
+        private IPullStatsProvider m_statsProvider;
+        
+        public PacketQueueStatsReporter(IPullStatsProvider provider)
+        {
+            m_statsProvider = provider;    
+        }
+        
+        /// <summary>
+        /// Report back collected statistical information.
+        /// </summary>
+        /// <returns></returns>        
+        public string Report()
+        {
+            return m_statsProvider.GetStats();
+        }
+    }
 }
diff --git a/OpenSim/Region/ClientStack/ClientView.cs b/OpenSim/Region/ClientStack/ClientView.cs
index 2cedc81..8bdbe89 100644
--- a/OpenSim/Region/ClientStack/ClientView.cs
+++ b/OpenSim/Region/ClientStack/ClientView.cs
@@ -317,7 +317,7 @@ namespace OpenSim.Region.ClientStack
             // in it to process.  It's an on-purpose threadlock though because 
             // without it, the clientloop will suck up all sim resources.
 
-            m_packetQueue = new PacketQueue();
+            m_packetQueue = new PacketQueue(agentId);
 
             RegisterLocalPacketHandlers();
 
diff --git a/OpenSim/Region/ClientStack/PacketQueue.cs b/OpenSim/Region/ClientStack/PacketQueue.cs
index 06ed32e..4673082 100644
--- a/OpenSim/Region/ClientStack/PacketQueue.cs
+++ b/OpenSim/Region/ClientStack/PacketQueue.cs
@@ -29,13 +29,16 @@ using System;
 using System.Collections.Generic;
 using System.Threading;
 using System.Timers;
+using libsecondlife;
 using libsecondlife.Packets;
 using OpenSim.Framework;
+using OpenSim.Framework.Statistics;
+using OpenSim.Framework.Statistics.Interfaces;
 using Timer=System.Timers.Timer;
 
 namespace OpenSim.Region.ClientStack
 {
-    public class PacketQueue
+    public class PacketQueue : IPullStatsProvider
     {
         //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
 
@@ -76,8 +79,10 @@ namespace OpenSim.Region.ClientStack
         // private long LastThrottle;
         // private long ThrottleInterval;
         private Timer throttleTimer;
+        
+        private LLUUID m_agentId;
 
-        public PacketQueue()
+        public PacketQueue(LLUUID agentId)
         {
             // While working on this, the BlockingQueue had me fooled for a bit.
             // The Blocking queue causes the thread to stop until there's something 
@@ -116,6 +121,13 @@ namespace OpenSim.Region.ClientStack
             // TIMERS needed for this
             // LastThrottle = DateTime.Now.Ticks;
             // ThrottleInterval = (long)(throttletimems/throttleTimeDivisor);
+            
+            m_agentId = agentId;
+            
+            if (StatsManager.SimExtraStats != null)            
+            {
+                StatsManager.SimExtraStats.RegisterPacketQueueStatsProvider(m_agentId, this);
+            }
         }
 
         /* STANDARD QUEUE MANIPULATION INTERFACES */
@@ -214,6 +226,11 @@ namespace OpenSim.Region.ClientStack
         {
             m_enabled = false;
             throttleTimer.Stop();
+            
+            if (StatsManager.SimExtraStats != null)            
+            {
+                StatsManager.SimExtraStats.DeregisterPacketQueueStatsProvider(m_agentId);
+            }            
         }
 
         private void ResetCounters()
@@ -483,5 +500,21 @@ namespace OpenSim.Region.ClientStack
             // effectively wiggling the slider causes things reset
             ResetCounters();
         }
+        
+        // See IPullStatsProvider
+        public string GetStats()
+        {
+            return string.Format("{0,7}  {1,7}  {2,7}  {3,7}  {4,7}  {5,7}  {6,7}  {7,7}  {8,7}  {9,7}",
+                                 SendQueue.Count(),
+                                 IncomingPacketQueue.Count,
+                                 OutgoingPacketQueue.Count,
+                                 ResendOutgoingPacketQueue.Count,
+                                 LandOutgoingPacketQueue.Count,
+                                 WindOutgoingPacketQueue.Count,
+                                 CloudOutgoingPacketQueue.Count,
+                                 TaskOutgoingPacketQueue.Count,
+                                 TextureOutgoingPacketQueue.Count,
+                                 AssetOutgoingPacketQueue.Count);                                     
+        }
     }
 }
-- 
cgit v1.1