diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index 31989e50ad..116b2c0cfe 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -248,6 +248,19 @@ namespace OpenSim.Framework.Monitoring
}
}
+ ///
+ /// Stat type.
+ ///
+ ///
+ /// A push stat is one which is continually updated and so it's value can simply by read.
+ /// A pull stat is one where reading the value triggers a collection method - the stat is not continually updated.
+ ///
+ public enum StatType
+ {
+ Push,
+ Pull
+ }
+
///
/// Verbosity of stat.
///
@@ -285,29 +298,65 @@ namespace OpenSim.Framework.Monitoring
///
public string Container { get; private set; }
+ public StatType StatType { get; private set; }
+
+ ///
+ /// Action used to update this stat when the value is requested if it's a pull type.
+ ///
+ public Action PullAction { get; private set; }
+
public StatVerbosity Verbosity { get; private set; }
public string ShortName { get; private set; }
public string Name { get; private set; }
public string Description { get; private set; }
public virtual string UnitName { get; private set; }
- public virtual double Value { get; set; }
+ public virtual double Value
+ {
+ get
+ {
+ // Asking for an update here means that the updater cannot access this value without infinite recursion.
+ // XXX: A slightly messy but simple solution may be to flick a flag so we can tell if this is being
+ // called by the pull action and just return the value.
+ if (StatType == StatType.Pull)
+ PullAction(this);
+
+ return m_value;
+ }
+
+ set
+ {
+ m_value = value;
+ }
+ }
+
+ private double m_value;
///
/// Constructor
///
/// Short name for the stat. Must not contain spaces. e.g. "LongFrames"
/// Human readable name for the stat. e.g. "Long frames"
+ /// Description of stat
///
/// Unit name for the stat. Should be preceeded by a space if the unit name isn't normally appeneded immediately to the value.
/// e.g. " frames"
///
/// Category under which this stat should appear, e.g. "scene". Do not capitalize.
/// Entity to which this stat relates. e.g. scene name if this is a per scene stat.
+ /// Push or pull
+ /// Pull stats need an action to update the stat on request. Push stats should set null here.
/// Verbosity of stat. Controls whether it will appear in short stat display or only full display.
- /// Description of stat
public Stat(
- string shortName, string name, string unitName, string category, string container, StatVerbosity verbosity, string description)
+ string shortName,
+ string name,
+ string description,
+ string unitName,
+ string category,
+ string container,
+ StatType type,
+ Action pullAction,
+ StatVerbosity verbosity)
{
if (StatsManager.SubCommands.Contains(category))
throw new Exception(
@@ -315,11 +364,18 @@ namespace OpenSim.Framework.Monitoring
ShortName = shortName;
Name = name;
+ Description = description;
UnitName = unitName;
Category = category;
Container = container;
+ StatType = type;
+
+ if (StatType == StatType.Push && pullAction != null)
+ throw new Exception("A push stat cannot have a pull action");
+ else
+ PullAction = pullAction;
+
Verbosity = verbosity;
- Description = description;
UniqueName = GenUniqueName(Container, Category, ShortName);
}
@@ -361,8 +417,15 @@ namespace OpenSim.Framework.Monitoring
}
public PercentageStat(
- string shortName, string name, string category, string container, StatVerbosity verbosity, string description)
- : base(shortName, name, "%", category, container, verbosity, description) {}
+ string shortName,
+ string name,
+ string description,
+ string category,
+ string container,
+ StatType type,
+ Action pullAction,
+ StatVerbosity verbosity)
+ : base(shortName, name, description, "%", category, container, type, pullAction, verbosity) {}
public override string ToConsoleString()
{
diff --git a/OpenSim/Framework/Pool.cs b/OpenSim/Framework/Pool.cs
index 1ca06c3065..5484f5c2d5 100644
--- a/OpenSim/Framework/Pool.cs
+++ b/OpenSim/Framework/Pool.cs
@@ -38,8 +38,23 @@ namespace OpenSim.Framework
///
public class Pool
{
+ ///
+ /// Number of objects in the pool.
+ ///
+ public int Count
+ {
+ get
+ {
+ lock (m_pool)
+ return m_pool.Count;
+ }
+ }
+
private Stack m_pool;
+ ///
+ /// Maximum pool size. Beyond this, any returned objects are not pooled.
+ ///
private int m_maxPoolSize;
private Func m_createFunction;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 419de66e7b..bcfd3920e9 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -278,7 +278,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
ThrottleRates = new ThrottleRates(configSource);
if (UsePools)
+ {
m_incomingPacketPool = new Pool(() => new IncomingPacket(), 500);
+
+ StatsManager.RegisterStat(
+ new Stat(
+ "IncomingPacketPoolCount",
+ "Objects within incoming packet pool",
+ "The number of objects currently stored within the incoming packet pool",
+ "",
+ "clientstack",
+ "packetpool",
+ StatType.Pull,
+ stat => stat.Value = m_incomingPacketPool.Count,
+ StatVerbosity.Debug));
+ }
}
public void Start()
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 6e6b3ef1b5..18abfd6a63 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -31,6 +31,7 @@ using System.Net.Sockets;
using System.Threading;
using log4net;
using OpenSim.Framework;
+using OpenSim.Framework.Monitoring;
namespace OpenMetaverse
{
@@ -107,9 +108,25 @@ namespace OpenMetaverse
public void StartInbound(int recvBufferSize, bool asyncPacketHandling)
{
if (UsePools)
+ {
m_pool = new Pool(() => new UDPPacketBuffer(), 500);
+
+ StatsManager.RegisterStat(
+ new Stat(
+ "UDPPacketBufferPoolCount",
+ "Objects within the UDPPacketBuffer pool",
+ "The number of objects currently stored within the UDPPacketBuffer pool",
+ "",
+ "clientstack",
+ "packetpool",
+ StatType.Pull,
+ stat => stat.Value = m_pool.Count,
+ StatVerbosity.Debug));
+ }
else
+ {
m_pool = null;
+ }
m_asyncPacketHandling = asyncPacketHandling;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
index 2a3d14f69f..9f22fb48ec 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
@@ -47,18 +47,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private PercentageStat m_packetsReusedStat = new PercentageStat(
"PacketsReused",
"Packets reused",
+ "Number of packets reused out of all requests to the packet pool",
"clientstack",
"packetpool",
- StatVerbosity.Debug,
- "Number of packets reused out of all requests to the packet pool");
+ StatType.Push,
+ null,
+ StatVerbosity.Debug);
private PercentageStat m_blocksReusedStat = new PercentageStat(
- "BlocksReused",
- "Blocks reused",
+ "PacketDataBlocksReused",
+ "Packet data blocks reused",
+ "Number of data blocks reused out of all requests to the packet pool",
"clientstack",
"packetpool",
- StatVerbosity.Debug,
- "Number of data blocks reused out of all requests to the packet pool");
+ StatType.Push,
+ null,
+ StatVerbosity.Debug);
///
/// Pool of packets available for reuse.
@@ -88,6 +92,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
StatsManager.RegisterStat(m_packetsReusedStat);
StatsManager.RegisterStat(m_blocksReusedStat);
+
+ StatsManager.RegisterStat(
+ new Stat(
+ "PacketsPoolCount",
+ "Objects within the packet pool",
+ "The number of objects currently stored within the packet pool",
+ "",
+ "clientstack",
+ "packetpool",
+ StatType.Pull,
+ stat => { lock (pool) { stat.Value = pool.Count; } },
+ StatVerbosity.Debug));
+
+ StatsManager.RegisterStat(
+ new Stat(
+ "PacketDataBlocksPoolCount",
+ "Objects within the packet data block pool",
+ "The number of objects currently stored within the packet data block pool",
+ "",
+ "clientstack",
+ "packetpool",
+ StatType.Pull,
+ stat => { lock (DataBlocks) { stat.Value = DataBlocks.Count; } },
+ StatVerbosity.Debug));
}
///
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 2addb5bab8..b9d615e804 100644
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -245,11 +245,13 @@ namespace OpenSim.Region.Framework.Scenes
= new Stat(
"SlowFrames",
"Slow Frames",
+ "Number of frames where frame time has been significantly longer than the desired frame time.",
" frames",
"scene",
m_scene.Name,
- StatVerbosity.Info,
- "Number of frames where frame time has been significantly longer than the desired frame time.");
+ StatType.Push,
+ null,
+ StatVerbosity.Info);
StatsManager.RegisterStat(SlowFramesStat);
}