diff --git a/OpenSim/Framework/ClientInfo.cs b/OpenSim/Framework/ClientInfo.cs index d68078e88b..98e4465cf8 100644 --- a/OpenSim/Framework/ClientInfo.cs +++ b/OpenSim/Framework/ClientInfo.cs @@ -54,6 +54,10 @@ namespace OpenSim.Framework public int assetThrottle; public int textureThrottle; public int totalThrottle; + + // Used by adaptive only + public int targetThrottle; + public int maxThrottle; public Dictionary SyncRequests = new Dictionary(); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index 6864d377da..c7686621bf 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -229,7 +229,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_throttleClient = new AdaptiveTokenBucket( string.Format("adaptive throttle for {0} in {1}", AgentID, server.Scene.Name), - parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled); + parentThrottle, 0, rates.Total, rates.AdaptiveThrottlesEnabled); // Create an array of token buckets for this clients different throttle categories m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; @@ -247,7 +247,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_throttleCategories[i] = new TokenBucket( string.Format("{0} throttle for {1} in {2}", type, AgentID, server.Scene.Name), - m_throttleClient, rates.GetRate(type)); + m_throttleClient, rates.GetRate(type), 0); } // Default the retransmission timeout to one second @@ -293,6 +293,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; m_info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; m_info.totalThrottle = (int)m_throttleClient.DripRate; + m_info.targetThrottle = (int)m_throttleClient.TargetDripRate; m_info.maxThrottle = (int)m_throttleClient.MaxDripRate; return m_info; @@ -441,28 +442,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP } // Update the token buckets with new throttle values - TokenBucket bucket; + if (m_throttleClient.AdaptiveEnabled) + { + long total = resend + land + wind + cloud + task + texture + asset; + m_throttleClient.TargetDripRate = total; + } + else + { + TokenBucket bucket; - bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; - bucket.RequestedDripRate = resend; + bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; + bucket.RequestedDripRate = resend; - bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land]; - bucket.RequestedDripRate = land; + bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land]; + bucket.RequestedDripRate = land; - bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind]; - bucket.RequestedDripRate = wind; + bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind]; + bucket.RequestedDripRate = wind; - bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud]; - bucket.RequestedDripRate = cloud; + bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud]; + bucket.RequestedDripRate = cloud; - bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset]; - bucket.RequestedDripRate = asset; + bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset]; + bucket.RequestedDripRate = asset; - bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task]; - bucket.RequestedDripRate = task; + bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task]; + bucket.RequestedDripRate = task; - bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture]; - bucket.RequestedDripRate = texture; + bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture]; + bucket.RequestedDripRate = texture; + } // Reset the packed throttles cached data m_packedThrottles = null; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 610067eca3..64548f25d2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -245,11 +245,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Bandwidth throttle for this UDP server public TokenBucket Throttle { get; private set; } - - /// - /// Gets the maximum total drip rate allowed to all clients. - /// - public long MaxTotalDripRate { get { return Throttle.RequestedDripRate; } } /// Per client throttle rates enforced by this server /// @@ -452,7 +447,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // = new TokenBucket( // string.Format("server throttle bucket for {0}", Scene.Name), null, sceneThrottleBps); - Throttle = new TokenBucket("server throttle bucket", null, sceneThrottleBps); + Throttle = new TokenBucket("server throttle bucket", null, sceneThrottleBps, sceneThrottleBps); ThrottleRates = new ThrottleRates(configSource); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs index 52247abd2f..325b04a4f0 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs @@ -182,7 +182,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP ConsoleDisplayList cdl = new ConsoleDisplayList(); cdl.AddRow("Adaptive throttles", m_udpServer.ThrottleRates.AdaptiveThrottlesEnabled); - long maxSceneDripRate = m_udpServer.MaxTotalDripRate; + long maxSceneDripRate = m_udpServer.Throttle.MaxDripRate; cdl.AddRow( "Max scene throttle", maxSceneDripRate != 0 ? string.Format("{0} kbps", maxSceneDripRate * 8 / 1000) : "unset"); @@ -360,7 +360,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP param, newValue, sp.Name, sp.IsChildAgent ? "child" : "root", m_udpServer.Scene.Name); LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; - udpClient.FlowThrottle.Enabled = newValue; + udpClient.FlowThrottle.AdaptiveEnabled = newValue; // udpClient.FlowThrottle.MaxDripRate = 0; // udpClient.FlowThrottle.AdjustedDripRate = 0; } @@ -426,7 +426,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; ConsoleDisplayList cdl = new ConsoleDisplayList(); - cdl.AddRow("Adaptive throttle", udpClient.FlowThrottle.Enabled); + cdl.AddRow("Adaptive throttle", udpClient.FlowThrottle.AdaptiveEnabled); cdl.AddRow("Max throttle", string.Format("{0} kbps", udpClient.FlowThrottle.RequestedDripRate * 8 / 1000)); m_console.Output(cdl.ToString()); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs index b80a485f4a..79919960ca 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs @@ -26,6 +26,7 @@ */ using System; +using Nini.Config; using NUnit.Framework; using OpenMetaverse.Packets; using OpenSim.Framework; @@ -67,7 +68,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456); LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; -// udpClient.ThrottleDebugLevel = 1; + + udpServer.Throttle.DebugLevel = 1; + udpClient.ThrottleDebugLevel = 1; int resendBytes = 1000; int landBytes = 2000; @@ -83,7 +86,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests ClientInfo ci = udpClient.GetClientInfo(); // We expect this to be lower because of the minimum bound set by MTU - float totalBytes = LLUDPServer.MTU + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes; + int totalBytes = LLUDPServer.MTU + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes; Assert.AreEqual(LLUDPServer.MTU, ci.resendThrottle); Assert.AreEqual(landBytes, ci.landThrottle); Assert.AreEqual(windBytes, ci.windThrottle); @@ -92,6 +95,66 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests Assert.AreEqual(textureBytes, ci.textureThrottle); Assert.AreEqual(assetBytes, ci.assetThrottle); Assert.AreEqual(totalBytes, ci.totalThrottle); + + Assert.AreEqual(0, ci.maxThrottle); + } + + [Test] + public void TestClientThrottleAdaptiveNoLimit() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + Scene scene = new SceneHelpers().SetupScene(); + + IniConfigSource ics = new IniConfigSource(); + IConfig config = ics.AddConfig("ClientStack.LindenUDP"); + config.Set("enable_adaptive_throttles", true); + TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene, ics); + + ScenePresence sp + = ClientStackHelpers.AddChildClient( + scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456); + + LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; + + udpServer.Throttle.DebugLevel = 1; + udpClient.ThrottleDebugLevel = 1; + + // Total is 28000 + int resendBytes = 10000; + int landBytes = 20000; + int windBytes = 30000; + int cloudBytes = 40000; + int taskBytes = 50000; + int textureBytes = 60000; + int assetBytes = 70000; + + SetThrottles( + udpClient, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); + + ClientInfo ci = udpClient.GetClientInfo(); + + // We expect individual throttle changes to currently have no effect under adaptive, since this is managed + // purely by that throttle. However, we expect the max to change. + // XXX: At the moment we check against defaults, but at some point there should be a better test to + // active see change over time. + ThrottleRates defaultRates = udpServer.ThrottleRates; + + // Current total is 66750 + int totalBytes = defaultRates.Resend + defaultRates.Land + defaultRates.Wind + defaultRates.Cloud + defaultRates.Task + defaultRates.Texture + defaultRates.Asset; + int totalMaxBytes = resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes; + + Assert.AreEqual(0, ci.maxThrottle); + Assert.AreEqual(totalMaxBytes, ci.targetThrottle); + Assert.AreEqual(defaultRates.Resend, ci.resendThrottle); + Assert.AreEqual(defaultRates.Land, ci.landThrottle); + Assert.AreEqual(defaultRates.Wind, ci.windThrottle); + Assert.AreEqual(defaultRates.Cloud, ci.cloudThrottle); + Assert.AreEqual(defaultRates.Task, ci.taskThrottle); + Assert.AreEqual(defaultRates.Texture, ci.textureThrottle); + Assert.AreEqual(defaultRates.Asset, ci.assetThrottle); + Assert.AreEqual(totalBytes, ci.totalThrottle); } /// @@ -238,6 +301,101 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests Assert.AreEqual(totalBytes, ci.totalThrottle); } + [Test] + public void TestClientThrottlePerClientAndRegionLimited() + { + TestHelpers.InMethod(); + //TestHelpers.EnableLogging(); + + int resendBytes = 4000; + int landBytes = 6000; + int windBytes = 8000; + int cloudBytes = 10000; + int taskBytes = 12000; + int textureBytes = 14000; + int assetBytes = 16000; + + // current total 70000 + int totalBytes = resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes; + + Scene scene = new SceneHelpers().SetupScene(); + TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene); + udpServer.ThrottleRates.Total = (int)(totalBytes * 1.1); + udpServer.Throttle.RequestedDripRate = (int)(totalBytes * 1.5); + + ScenePresence sp1 + = ClientStackHelpers.AddChildClient( + scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456); + + LLUDPClient udpClient1 = ((LLClientView)sp1.ControllingClient).UDPClient; + udpClient1.ThrottleDebugLevel = 1; + + SetThrottles( + udpClient1, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); + + { + ClientInfo ci = udpClient1.GetClientInfo(); + + // Console.WriteLine( + // "Resend={0}, Land={1}, Wind={2}, Cloud={3}, Task={4}, Texture={5}, Asset={6}, TOTAL = {7}", + // ci.resendThrottle, ci.landThrottle, ci.windThrottle, ci.cloudThrottle, ci.taskThrottle, ci.textureThrottle, ci.assetThrottle, ci.totalThrottle); + + Assert.AreEqual(resendBytes, ci.resendThrottle); + Assert.AreEqual(landBytes, ci.landThrottle); + Assert.AreEqual(windBytes, ci.windThrottle); + Assert.AreEqual(cloudBytes, ci.cloudThrottle); + Assert.AreEqual(taskBytes, ci.taskThrottle); + Assert.AreEqual(textureBytes, ci.textureThrottle); + Assert.AreEqual(assetBytes, ci.assetThrottle); + Assert.AreEqual(totalBytes, ci.totalThrottle); + } + + // Now add another client + ScenePresence sp2 + = ClientStackHelpers.AddChildClient( + scene, udpServer, TestHelpers.ParseTail(0x10), TestHelpers.ParseTail(0x20), 123457); + + LLUDPClient udpClient2 = ((LLClientView)sp2.ControllingClient).UDPClient; + udpClient2.ThrottleDebugLevel = 1; + + SetThrottles( + udpClient2, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); + + { + ClientInfo ci = udpClient1.GetClientInfo(); + +// Console.WriteLine( +// "Resend={0}, Land={1}, Wind={2}, Cloud={3}, Task={4}, Texture={5}, Asset={6}, TOTAL = {7}", +// ci.resendThrottle, ci.landThrottle, ci.windThrottle, ci.cloudThrottle, ci.taskThrottle, ci.textureThrottle, ci.assetThrottle, ci.totalThrottle); + + Assert.AreEqual(resendBytes * 0.75, ci.resendThrottle); + Assert.AreEqual(landBytes * 0.75, ci.landThrottle); + Assert.AreEqual(windBytes * 0.75, ci.windThrottle); + Assert.AreEqual(cloudBytes * 0.75, ci.cloudThrottle); + Assert.AreEqual(taskBytes * 0.75, ci.taskThrottle); + Assert.AreEqual(textureBytes * 0.75, ci.textureThrottle); + Assert.AreEqual(assetBytes * 0.75, ci.assetThrottle); + Assert.AreEqual(totalBytes * 0.75, ci.totalThrottle); + } + + { + ClientInfo ci = udpClient2.GetClientInfo(); + +// Console.WriteLine( +// "Resend={0}, Land={1}, Wind={2}, Cloud={3}, Task={4}, Texture={5}, Asset={6}, TOTAL = {7}", +// ci.resendThrottle, ci.landThrottle, ci.windThrottle, ci.cloudThrottle, ci.taskThrottle, ci.textureThrottle, ci.assetThrottle, ci.totalThrottle); + + Assert.AreEqual(resendBytes * 0.75, ci.resendThrottle); + Assert.AreEqual(landBytes * 0.75, ci.landThrottle); + Assert.AreEqual(windBytes * 0.75, ci.windThrottle); + Assert.AreEqual(cloudBytes * 0.75, ci.cloudThrottle); + Assert.AreEqual(taskBytes * 0.75, ci.taskThrottle); + Assert.AreEqual(textureBytes * 0.75, ci.textureThrottle); + Assert.AreEqual(assetBytes * 0.75, ci.assetThrottle); + Assert.AreEqual(totalBytes * 0.75, ci.totalThrottle); + } + } + private void SetThrottles( LLUDPClient udpClient, int resendBytes, int landBytes, int windBytes, int cloudBytes, int taskBytes, int textureBytes, int assetBytes) { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs index e5bae6ee6c..dd15cc7d4f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs @@ -72,6 +72,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"]; + // Current default total is 66750 Resend = throttleConfig.GetInt("resend_default", 6625); Land = throttleConfig.GetInt("land_default", 9125); Wind = throttleConfig.GetInt("wind_default", 1750); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs index d696265c56..e0633d338f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs @@ -113,36 +113,65 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// The speed limit of this bucket in bytes per second. This is the /// number of tokens that are added to the bucket per quantum /// - /// Tokens are added to the bucket any time + /// + /// RequestedDripRate can never be above MaxDripRate. + /// Tokens are added to the bucket any time /// is called, at the granularity of /// the system tick interval (typically around 15-22ms) protected Int64 m_dripRate; public virtual Int64 RequestedDripRate { get { return (m_dripRate == 0 ? TotalDripRequest : m_dripRate); } - set { - m_dripRate = (value < 0 ? 0 : value); - m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); + set + { + if (value <= 0) + m_dripRate = 0; + else if (MaxDripRate > 0 && value > MaxDripRate) + m_dripRate = MaxDripRate; + else + m_dripRate = value; + TotalDripRequest = m_dripRate; + m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); + if (Parent != null) - Parent.RegisterRequest(this,m_dripRate); + Parent.RegisterRequest(this, m_dripRate); } } + /// + /// Gets the drip rate. + /// + /// DripRate can never be above max. public virtual Int64 DripRate { - get { + get + { if (Parent == null) return Math.Min(RequestedDripRate, TotalDripRequest); double rate = (double)RequestedDripRate * Parent.DripRateModifier(); if (rate < m_minimumDripRate) rate = m_minimumDripRate; + else if (MaxDripRate > 0 && rate > MaxDripRate) + rate = MaxDripRate; return (Int64)rate; } } + // + // The maximum rate for flow control. Drip rate can never be greater than this. + // +// protected Int64 m_maxDripRate; +// public Int64 MaxDripRate +// { +// get { return m_maxDripRate; } +// //get { return (m_maxDripRate == 0 ? TotalDripRequest : m_maxDripRate); } +// set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value, m_minimumFlow)); } +// } + public Int64 MaxDripRate { get; set; } + /// /// The current total of the requested maximum burst rates of /// this bucket's children buckets. @@ -161,12 +190,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// null if this is a root bucket /// Rate that the bucket fills, in bytes per /// second. If zero, the bucket always remains full - public TokenBucket(string identifier, TokenBucket parent, Int64 dripRate) + public TokenBucket(string identifier, TokenBucket parent, Int64 dripRate, Int64 maxDripRate) { Identifier = identifier; Parent = parent; RequestedDripRate = dripRate; + MaxDripRate = maxDripRate; // TotalDripRequest = dripRate; // this will be overwritten when a child node registers // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst); m_lastDrip = Util.EnvironmentTickCount(); @@ -184,7 +214,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected double DripRateModifier() { Int64 driprate = DripRate; - return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; + double modifier = driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; + +// if (DebugLevel > 0) +// m_log.DebugFormat( +// "[TOKEN BUCKET]: Returning drip modifier {0}/{1} = {2} from {3}", +// driprate, TotalDripRequest, modifier, Identifier); + + return modifier; } /// @@ -215,7 +252,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Pass the new values up to the parent if (Parent != null) - Parent.RegisterRequest(this,Math.Min(RequestedDripRate, TotalDripRequest)); + { + Int64 effectiveDripRate; + + if (MaxDripRate > 0) + effectiveDripRate = Math.Min(MaxDripRate, TotalDripRequest); + else + effectiveDripRate = TotalDripRequest; + + //Parent.RegisterRequest(this, Math.Min(RequestedDripRate, TotalDripRequest)); + Parent.RegisterRequest(this, effectiveDripRate); + } } /// @@ -309,8 +356,35 @@ 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); + public bool AdaptiveEnabled { get; set; } + + /// + /// Target drip rate for this bucket. + /// + /// Usually set by the client. If adaptive is enabled then throttles will increase until we reach this. + public Int64 TargetDripRate + { + get { return m_targetDripRate; } + set { m_targetDripRate = Math.Max(0, value); } + } + protected Int64 m_targetDripRate; + + // + // Adjust drip rate in response to network conditions. + // + public virtual Int64 AdjustedDripRate + { + get { return m_dripRate; } + set { + m_dripRate = OpenSim.Framework.Util.Clamp(value, m_minimumFlow, TargetDripRate); + m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); + if (Parent != null) + Parent.RegisterRequest(this, m_dripRate); + } + } + /// /// The minimum rate for flow control. Minimum drip rate is one /// packet per second. Open the throttle to 15 packets per second @@ -318,52 +392,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// protected const Int64 m_minimumFlow = m_minimumDripRate * 15; - // - // The maximum rate for flow control. Drip rate can never be - // greater than this. - // - protected Int64 m_maxDripRate = 0; - public Int64 MaxDripRate + public AdaptiveTokenBucket(string identifier, TokenBucket parent, Int64 dripRate, Int64 maxDripRate, bool enabled) + : base(identifier, parent, dripRate, maxDripRate) { - get { return (m_maxDripRate == 0 ? TotalDripRequest : m_maxDripRate); } - set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value,m_minimumFlow)); } - } + AdaptiveEnabled = enabled; - public bool Enabled { get; set; } - - // - // - // - public virtual Int64 AdjustedDripRate - { - get { return m_dripRate; } - set { - m_dripRate = OpenSim.Framework.Util.Clamp(value,m_minimumFlow,MaxDripRate); - m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); - if (Parent != null) - Parent.RegisterRequest(this, m_dripRate); - } - } - - public AdaptiveTokenBucket(string identifier, TokenBucket parent, Int64 maxDripRate, bool enabled) - : base(identifier, parent, maxDripRate) - { - Enabled = enabled; - - if (Enabled) + if (AdaptiveEnabled) { // m_log.DebugFormat("[TOKENBUCKET]: Adaptive throttle enabled"); - MaxDripRate = maxDripRate; AdjustedDripRate = m_minimumFlow; } } // - // + // Reliable packets sent to the client for which we never received an ack adjust the drip rate down. // public void ExpirePackets(Int32 count) { - if (Enabled) + if (AdaptiveEnabled) { if (DebugLevel > 0) m_log.WarnFormat( @@ -375,12 +421,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP } // - // + // Reliable packets acked by the client adjust the drip rate up. // public void AcknowledgePackets(Int32 count) { - if (Enabled) + if (AdaptiveEnabled) AdjustedDripRate = AdjustedDripRate + count; } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs index d471062f92..cc6a1e8681 100644 --- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs @@ -487,8 +487,9 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding)); report.AppendFormat( - "{0,8} {1,7} {2,8} {3,7} {4,7} {5,7} {6,7} {7,9} {8,7}\n", + "{0,8} {1,8} {2,7} {3,8} {4,7} {5,7} {6,7} {7,7} {8,9} {9,7}\n", "Max", + "Target", "Total", "Resend", "Land", @@ -500,7 +501,8 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", ""); report.AppendFormat( - "{0,8} {1,7} {2,8} {3,7} {4,7} {5,7} {6,7} {7,9} {8,7}\n", + "{0,8} {1,8} {2,7} {3,8} {4,7} {5,7} {6,7} {7,7} {8,9} {9,7}\n", + "kb/s", "kb/s", "kb/s", "kb/s", @@ -542,8 +544,9 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding)); report.AppendFormat( - "{0,8} {1,7} {2,8} {3,7} {4,7} {5,7} {6,7} {7,9} {8,7}", - (ci.maxThrottle * 8) / 1000, + "{0,8} {1,8} {2,7} {3,8} {4,7} {5,7} {6,7} {7,7} {8,9} {9,7}\n", + ci.maxThrottle > 0 ? ((ci.maxThrottle * 8) / 1000).ToString() : "-", + llUdpClient.FlowThrottle.AdaptiveEnabled ? ((ci.targetThrottle * 8) / 1000).ToString() : "-", (ci.totalThrottle * 8) / 1000, (ci.resendThrottle * 8) / 1000, (ci.landThrottle * 8) / 1000, @@ -551,9 +554,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden (ci.cloudThrottle * 8) / 1000, (ci.taskThrottle * 8) / 1000, (ci.textureThrottle * 8) / 1000, - (ci.assetThrottle * 8) / 1000); - - report.AppendLine(); + (ci.assetThrottle * 8) / 1000); } }); }