diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index 9dc9e0d7ac..d8ca343293 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -82,6 +82,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Any level above 0 will turn on logging. public int DebugDataOutLevel { get; set; } + /// + /// Controls whether information is logged about each outbound packet immediately before it is sent. For debug purposes. + /// + /// Any level above 0 will turn on logging. + public int ThrottleDebugLevel + { + get + { + return m_throttleDebugLevel; + } + + set + { + m_throttleDebugLevel = value; + m_throttleClient.DebugLevel = m_throttleDebugLevel; + m_throttleCategory.DebugLevel = m_throttleDebugLevel; + foreach (TokenBucket tb in m_throttleCategories) + tb.DebugLevel = m_throttleDebugLevel; + } + } + private int m_throttleDebugLevel; + /// Fired when updated networking stats are produced for this client public event PacketStats OnPacketStats; /// Fired when the queue for a packet category is empty. This event can be @@ -207,9 +229,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_maxRTO = maxRTO; // Create a token bucket throttle for this client that has the scene token bucket as a parent - m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled); + m_throttleClient + = new AdaptiveTokenBucket( + string.Format("adaptive throttle for {0} in {1}", AgentID, server.Scene.Name), + parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled); + // Create a token bucket throttle for the total category with the client bucket as a throttle - m_throttleCategory = new TokenBucket(m_throttleClient, 0); + m_throttleCategory + = new TokenBucket( + string.Format("total throttle for {0} in {1}", AgentID, server.Scene.Name), + m_throttleClient, 0); + // Create an array of token buckets for this clients different throttle categories m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; @@ -221,8 +251,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Initialize the packet outboxes, where packets sit while they are waiting for tokens m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue(); + // Initialize the token buckets that control the throttling for each category - m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type)); + m_throttleCategories[i] + = new TokenBucket( + string.Format("{0} throttle for {1} in {2}", type, AgentID, server.Scene.Name), + m_throttleCategory, rates.GetRate(type)); } // Default the retransmission timeout to one second @@ -371,8 +405,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP texture = (int)((1 - m_cannibalrate) * texture); //int total = resend + land + wind + cloud + task + texture + asset; - //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", - // AgentID, resend, land, wind, cloud, task, texture, asset, total); + + if (ThrottleDebugLevel > 0) + m_log.DebugFormat( + "[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}", + AgentID, m_udpServer.Scene.Name, resend, land, wind, cloud, task, texture, asset); // Update the token buckets with new throttle values TokenBucket bucket; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 0393a29b2a..e45de51aa6 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -434,7 +434,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP } #endregion BinaryStats - m_throttle = new TokenBucket(null, sceneThrottleBps); + // FIXME: Can't add info here because don't know scene yet. +// m_throttle +// = new TokenBucket( +// string.Format("server throttle bucket for {0}", Scene.Name), null, sceneThrottleBps); + + m_throttle = new TokenBucket("server throttle bucket", null, sceneThrottleBps); + ThrottleRates = new ThrottleRates(configSource); if (usePools) @@ -755,6 +761,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP "Return status of LLUDP packet processing.", HandleStatusCommand); + MainConsole.Instance.Commands.AddCommand( + "Debug", + false, + "debug lludp throttle log", + "debug lludp throttle log ", + "Change debug logging level for throttles.", + "If level >= 0 then throttle debug logging is performed.\n" + + "If level <= 0 then no throttle debug logging is performed.", + HandleThrottleCommand); + MainConsole.Instance.Commands.AddCommand( "Debug", false, @@ -795,6 +811,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP }); } + private void HandleThrottleCommand(string module, string[] args) + { + if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene) + return; + + if (args.Length != 7) + { + MainConsole.Instance.OutputFormat("Usage: debug lludp throttle log "); + return; + } + + int level; + if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out level)) + return; + + string firstName = args[5]; + string lastName = args[6]; + + Scene.ForEachScenePresence(sp => + { + if (sp.Firstname == firstName && sp.Lastname == lastName) + { + MainConsole.Instance.OutputFormat( + "Throttle log level for {0} ({1}) set to {2} in {3}", + sp.Name, sp.IsChildAgent ? "child" : "root", level, Scene.Name); + + ((LLClientView)sp.ControllingClient).UDPClient.ThrottleDebugLevel = level; + } + }); + } + private void HandlePacketCommand(string module, string[] args) { if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs index 0d4f54951e..658d9bbd3c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs @@ -43,8 +43,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static Int32 m_counter = 0; - -// private Int32 m_identifier; + + private LLUDPClient m_client; + + public string Identifier { get; private set; } + + public int DebugLevel { get; set; } /// /// Number of ticks (ms) per quantum, drip rate and max burst @@ -165,16 +169,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// Default constructor /// + /// Identifier for this token bucket /// Parent bucket if this is a child bucket, or /// null if this is a root bucket - /// Maximum size of the bucket in bytes, or - /// zero if this bucket has no maximum capacity /// Rate that the bucket fills, in bytes per /// second. If zero, the bucket always remains full - public TokenBucket(TokenBucket parent, Int64 dripRate) + public TokenBucket(string identifier, TokenBucket parent, Int64 dripRate) { -// m_identifier = m_counter++; - m_counter++; + Identifier = identifier; Parent = parent; RequestedDripRate = dripRate; @@ -301,7 +303,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // with no drip rate... if (DripRate == 0) { - m_log.WarnFormat("[TOKENBUCKET] something odd is happening and drip rate is 0"); + m_log.WarnFormat("[TOKENBUCKET] something odd is happening and drip rate is 0 for {0}", Identifier); return; } @@ -321,7 +323,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public class AdaptiveTokenBucket : TokenBucket { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// /// The minimum rate for flow control. Minimum drip rate is one @@ -360,13 +362,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP // // // - public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate, bool enabled) : base(parent,maxDripRate) + public AdaptiveTokenBucket(string identifier, TokenBucket parent, Int64 maxDripRate, bool enabled) + : base(identifier, parent, maxDripRate) { Enabled = enabled; if (Enabled) { - // m_log.DebugFormat("[TOKENBUCKET] Adaptive throttle enabled"); +// m_log.DebugFormat("[TOKENBUCKET]: Adaptive throttle enabled"); MaxDripRate = maxDripRate; AdjustedDripRate = m_minimumFlow; } @@ -377,9 +380,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP // public void ExpirePackets(Int32 count) { - // m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count); if (Enabled) + { + if (DebugLevel > 0) + m_log.WarnFormat( + "[ADAPTIVEBUCKET] drop {0} by {1} expired packets for {2}", + AdjustedDripRate, count, Identifier); + AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count)); + } } //