From 82012ec4e3c441021795c66112a66e002d459e73 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Wed, 14 Oct 2009 16:21:48 -0700 Subject: * Clean up the SetThrottle() code and add a maxBurstRate parameter to allow more tweaking in the future --- OpenSim/Framework/ThrottleOutPacketType.cs | 11 +- .../Region/ClientStack/LindenUDP/LLUDPClient.cs | 188 ++++++++++----------- .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 1 - .../Region/ClientStack/LindenUDP/ThrottleRates.cs | 63 ++++++- 4 files changed, 161 insertions(+), 102 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/ThrottleOutPacketType.cs b/OpenSim/Framework/ThrottleOutPacketType.cs index eb42fea..e21ff32 100644 --- a/OpenSim/Framework/ThrottleOutPacketType.cs +++ b/OpenSim/Framework/ThrottleOutPacketType.cs @@ -41,13 +41,14 @@ namespace OpenSim.Framework Wind = 2, /// Cloud data Cloud = 3, + /// Any packets that do not fit into the other throttles + Task = 4, /// Texture assets - Texture = 4, + Texture = 5, /// Non-texture assets - Asset = 5, + Asset = 6, /// Avatar and primitive data - State = 6, - /// Any packets that do not fit into the other throttles - Task = 7, + /// This is a sub-category of Task + State = 7, } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index 39472cb..4eee6b6 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs @@ -31,6 +31,7 @@ using System.Net; using log4net; using OpenSim.Framework; using OpenMetaverse; +using OpenMetaverse.Packets; namespace OpenSim.Region.ClientStack.LindenUDP { @@ -60,13 +61,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public sealed class LLUDPClient { - private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - // FIXME: Make this a config setting + // TODO: Make this a config setting /// Percentage of the task throttle category that is allocated to avatar and prim /// state updates const float STATE_TASK_PERCENTAGE = 0.8f; + private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + /// The number of packet categories to throttle on. If a throttle category is added /// or removed, this number must also change const int THROTTLE_CATEGORY_COUNT = 8; @@ -129,21 +130,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP private int m_packetsSentReported; /// Throttle bucket for this agent's connection - private readonly TokenBucket throttle; + private readonly TokenBucket m_throttle; /// Throttle buckets for each packet category - private readonly TokenBucket[] throttleCategories; + private readonly TokenBucket[] m_throttleCategories; /// Throttle rate defaults and limits - private readonly ThrottleRates defaultThrottleRates; + private readonly ThrottleRates m_defaultThrottleRates; /// Outgoing queues for throttled packets - private readonly OpenSim.Framework.LocklessQueue[] packetOutboxes = new OpenSim.Framework.LocklessQueue[THROTTLE_CATEGORY_COUNT]; + private readonly OpenSim.Framework.LocklessQueue[] m_packetOutboxes = new OpenSim.Framework.LocklessQueue[THROTTLE_CATEGORY_COUNT]; /// A container that can hold one packet for each outbox, used to store /// dequeued packets that are being held for throttling - private readonly OutgoingPacket[] nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; + private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; /// Flags to prevent queue empty callbacks from stacking up on /// top of each other - private readonly bool[] onQueueEmptyRunning = new bool[THROTTLE_CATEGORY_COUNT]; + private readonly bool[] m_onQueueEmptyRunning = new bool[THROTTLE_CATEGORY_COUNT]; /// A reference to the LLUDPServer that is managing this client - private readonly LLUDPServer udpServer; + private readonly LLUDPServer m_udpServer; /// /// Default constructor @@ -157,27 +158,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Remote endpoint for this connection public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint) { - udpServer = server; AgentID = agentID; RemoteEndPoint = remoteEndPoint; CircuitCode = circuitCode; - defaultThrottleRates = rates; + m_udpServer = server; + m_defaultThrottleRates = rates; + m_throttle = new TokenBucket(parentThrottle, rates.TotalLimit, rates.Total); + m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) - packetOutboxes[i] = new OpenSim.Framework.LocklessQueue(); - - throttle = new TokenBucket(parentThrottle, rates.TotalLimit, rates.Total); - throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; - throttleCategories[(int)ThrottleOutPacketType.Resend] = new TokenBucket(throttle, rates.ResendLimit, rates.Resend); - throttleCategories[(int)ThrottleOutPacketType.Land] = new TokenBucket(throttle, rates.LandLimit, rates.Land); - throttleCategories[(int)ThrottleOutPacketType.Wind] = new TokenBucket(throttle, rates.WindLimit, rates.Wind); - throttleCategories[(int)ThrottleOutPacketType.Cloud] = new TokenBucket(throttle, rates.CloudLimit, rates.Cloud); - throttleCategories[(int)ThrottleOutPacketType.Texture] = new TokenBucket(throttle, rates.TextureLimit, rates.Texture); - throttleCategories[(int)ThrottleOutPacketType.Asset] = new TokenBucket(throttle, rates.AssetLimit, rates.Asset); - // State and Transaction are actually sub-categories of the LLUDP generic "Task" category - TokenBucket stateBucket = new TokenBucket(throttle, (int)((float)rates.TaskLimit * STATE_TASK_PERCENTAGE), (int)((float)rates.Task * STATE_TASK_PERCENTAGE)); - throttleCategories[(int)ThrottleOutPacketType.State] = stateBucket; - throttleCategories[(int)ThrottleOutPacketType.Task] = new TokenBucket(throttle, rates.TaskLimit - stateBucket.MaxBurst, rates.Task - stateBucket.DripRate); + { + ThrottleOutPacketType type = (ThrottleOutPacketType)i; + + m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue(); + m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type)); + } // Set the granularity variable used for retransmission calculations to // the measured resolution of Environment.TickCount @@ -199,8 +194,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP NeedAcks.Clear(); for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) { - packetOutboxes[i].Clear(); - nextPackets[i] = null; + m_packetOutboxes[i].Clear(); + m_nextPackets[i] = null; } OnPacketStats = null; OnQueueEmpty = null; @@ -219,13 +214,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP info.pendingAcks = new Dictionary(); info.needAck = new Dictionary(); - info.resendThrottle = throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate; - info.landThrottle = throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; - info.windThrottle = throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; - info.cloudThrottle = throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; - info.taskThrottle = throttleCategories[(int)ThrottleOutPacketType.State].DripRate + throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; - info.assetThrottle = throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; - info.textureThrottle = throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; + info.resendThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate; + info.landThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; + info.windThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; + info.cloudThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; + info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; + info.assetThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; + info.textureThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + info.taskThrottle + info.assetThrottle + info.textureThrottle; @@ -286,6 +281,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP adjData = throttleData; } + // 0.125f converts from bits to bytes int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; @@ -293,22 +289,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); + // State is a subcategory of task that we allocate a percentage to + int state = (int)((float)task * STATE_TASK_PERCENTAGE); + task -= state; - resend = (resend <= defaultThrottleRates.ResendLimit) ? resend : defaultThrottleRates.ResendLimit; - land = (land <= defaultThrottleRates.LandLimit) ? land : defaultThrottleRates.LandLimit; - wind = (wind <= defaultThrottleRates.WindLimit) ? wind : defaultThrottleRates.WindLimit; - cloud = (cloud <= defaultThrottleRates.CloudLimit) ? cloud : defaultThrottleRates.CloudLimit; - task = (task <= defaultThrottleRates.TaskLimit) ? task : defaultThrottleRates.TaskLimit; - texture = (texture <= defaultThrottleRates.TextureLimit) ? texture : defaultThrottleRates.TextureLimit; - asset = (asset <= defaultThrottleRates.AssetLimit) ? asset : defaultThrottleRates.AssetLimit; - - SetThrottle(ThrottleOutPacketType.Resend, resend); - SetThrottle(ThrottleOutPacketType.Land, land); - SetThrottle(ThrottleOutPacketType.Wind, wind); - SetThrottle(ThrottleOutPacketType.Cloud, cloud); - SetThrottle(ThrottleOutPacketType.Task, task); - SetThrottle(ThrottleOutPacketType.Texture, texture); - SetThrottle(ThrottleOutPacketType.Asset, asset); + int ceiling = Int32.MaxValue; + if (m_defaultThrottleRates.Total != 0) + { + ceiling = m_defaultThrottleRates.Total; + if (ceiling < Packet.MTU) ceiling = Packet.MTU; + } + + resend = Utils.Clamp(resend, Packet.MTU, ceiling); + land = Utils.Clamp(land, Packet.MTU, ceiling); + wind = Utils.Clamp(wind, Packet.MTU, ceiling); + cloud = Utils.Clamp(cloud, Packet.MTU, ceiling); + task = Utils.Clamp(task, Packet.MTU, ceiling); + texture = Utils.Clamp(texture, Packet.MTU, ceiling); + asset = Utils.Clamp(asset, Packet.MTU, ceiling); + state = Utils.Clamp(state, Packet.MTU, ceiling); + + int total = resend + land + wind + cloud + task + texture + asset + state; + int taskTotal = task + state; + + m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, Total={9}", + AgentID, resend, land, wind, cloud, task, texture, asset, state, total); + + SetThrottle(ThrottleOutPacketType.Resend, resend, resend); + SetThrottle(ThrottleOutPacketType.Land, land, land); + SetThrottle(ThrottleOutPacketType.Wind, wind, wind); + SetThrottle(ThrottleOutPacketType.Cloud, cloud, cloud); + SetThrottle(ThrottleOutPacketType.Task, task, taskTotal); + SetThrottle(ThrottleOutPacketType.Texture, texture, texture); + SetThrottle(ThrottleOutPacketType.Asset, asset, asset); + SetThrottle(ThrottleOutPacketType.State, state, taskTotal); } public byte[] GetThrottlesPacked() @@ -316,40 +330,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP byte[] data = new byte[7 * 4]; int i = 0; - Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate), 0, data, i, 4); i += 4; - Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4; - Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4; - Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4; - Buffer.BlockCopy(Utils.FloatToBytes((float)(throttleCategories[(int)ThrottleOutPacketType.Task].DripRate) + - throttleCategories[(int)ThrottleOutPacketType.State].DripRate), 0, data, i, 4); i += 4; - Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4; - Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)(m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate) + + m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4; return data; } - public void SetThrottle(ThrottleOutPacketType category, int rate) + public void SetThrottle(ThrottleOutPacketType category, int rate, int maxBurst) { - if (category == ThrottleOutPacketType.Task) - { - TokenBucket stateBucket = throttleCategories[(int)ThrottleOutPacketType.State]; - TokenBucket taskBucket = throttleCategories[(int)ThrottleOutPacketType.Task]; - - stateBucket.MaxBurst = (int)((float)rate * STATE_TASK_PERCENTAGE); - stateBucket.DripRate = (int)((float)rate * STATE_TASK_PERCENTAGE); - - taskBucket.MaxBurst = rate - stateBucket.MaxBurst; - taskBucket.DripRate = rate - stateBucket.DripRate; - } - else + int i = (int)category; + if (i >= 0 && i < m_throttleCategories.Length) { - int i = (int)category; - if (i >= 0 && i < throttleCategories.Length) - { - TokenBucket bucket = throttleCategories[(int)category]; - bucket.MaxBurst = rate; - bucket.DripRate = rate; - } + TokenBucket bucket = m_throttleCategories[(int)category]; + bucket.DripRate = rate; + bucket.MaxBurst = maxBurst; } } @@ -357,12 +357,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP { int category = (int)packet.Category; - if (category >= 0 && category < packetOutboxes.Length) + if (category >= 0 && category < m_packetOutboxes.Length) { - OpenSim.Framework.LocklessQueue queue = packetOutboxes[category]; - TokenBucket bucket = throttleCategories[category]; + OpenSim.Framework.LocklessQueue queue = m_packetOutboxes[category]; + TokenBucket bucket = m_throttleCategories[category]; - if (throttleCategories[category].RemoveTokens(packet.Buffer.DataLength)) + if (m_throttleCategories[category].RemoveTokens(packet.Buffer.DataLength)) { // Enough tokens were removed from the bucket, the packet will not be queued return false; @@ -397,19 +397,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) { - bucket = throttleCategories[i]; + bucket = m_throttleCategories[i]; - if (nextPackets[i] != null) + if (m_nextPackets[i] != null) { // This bucket was empty the last time we tried to send a packet, // leaving a dequeued packet still waiting to be sent out. Try to // send it again - OutgoingPacket nextPacket = nextPackets[i]; + OutgoingPacket nextPacket = m_nextPackets[i]; if (bucket.RemoveTokens(nextPacket.Buffer.DataLength)) { // Send the packet - udpServer.SendPacketFinal(nextPacket); - nextPackets[i] = null; + m_udpServer.SendPacketFinal(nextPacket); + m_nextPackets[i] = null; packetSent = true; } } @@ -417,7 +417,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // No dequeued packet waiting to be sent, try to pull one off // this queue - queue = packetOutboxes[i]; + queue = m_packetOutboxes[i]; if (queue.Dequeue(out packet)) { // A packet was pulled off the queue. See if we have @@ -425,13 +425,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (bucket.RemoveTokens(packet.Buffer.DataLength)) { // Send the packet - udpServer.SendPacketFinal(packet); + m_udpServer.SendPacketFinal(packet); packetSent = true; } else { // Save the dequeued packet for the next iteration - nextPackets[i] = packet; + m_nextPackets[i] = packet; } // If the queue is empty after this dequeue, fire the queue @@ -493,7 +493,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// for private void BeginFireQueueEmpty(int throttleIndex) { - if (!onQueueEmptyRunning[throttleIndex]) + if (!m_onQueueEmptyRunning[throttleIndex]) Util.FireAndForget(FireQueueEmpty, throttleIndex); } @@ -511,12 +511,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (callback != null) { - if (!onQueueEmptyRunning[i]) + if (!m_onQueueEmptyRunning[i]) { - onQueueEmptyRunning[i] = true; + m_onQueueEmptyRunning[i] = true; try { callback(type); } catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + type + ") threw an exception: " + e.Message, e); } - onQueueEmptyRunning[i] = false; + m_onQueueEmptyRunning[i] = false; } } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 09845d6..890f701 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -147,7 +147,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); } - // TODO: Config support for throttling the entire connection m_throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps); m_throttleRates = new ThrottleRates(configSource); } diff --git a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs index adad4c3..008d827 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs @@ -26,6 +26,7 @@ */ using System; +using OpenSim.Framework; using Nini.Config; namespace OpenSim.Region.ClientStack.LindenUDP @@ -45,12 +46,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP public int Wind; /// Drip rate for cloud packets public int Cloud; - /// Drip rate for task (state and transaction) packets + /// Drip rate for task packets public int Task; /// Drip rate for texture packets public int Texture; /// Drip rate for asset packets public int Asset; + /// Drip rate for state packets + public int State; /// Drip rate for the parent token bucket public int Total; @@ -68,6 +71,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public int TextureLimit; /// Maximum burst rate for asset packets public int AssetLimit; + /// Maximum burst rate for state packets + public int StateLimit; /// Burst rate for the parent token bucket public int TotalLimit; @@ -88,6 +93,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Task = throttleConfig.GetInt("task_default", 500); Texture = throttleConfig.GetInt("texture_default", 500); Asset = throttleConfig.GetInt("asset_default", 500); + State = throttleConfig.GetInt("state_default", 500); Total = throttleConfig.GetInt("client_throttle_max_bps", 0); @@ -95,13 +101,66 @@ namespace OpenSim.Region.ClientStack.LindenUDP LandLimit = throttleConfig.GetInt("land_limit", 29750); WindLimit = throttleConfig.GetInt("wind_limit", 18750); CloudLimit = throttleConfig.GetInt("cloud_limit", 18750); - TaskLimit = throttleConfig.GetInt("task_limit", 55750); + TaskLimit = throttleConfig.GetInt("task_limit", 18750); TextureLimit = throttleConfig.GetInt("texture_limit", 55750); AssetLimit = throttleConfig.GetInt("asset_limit", 27500); + State = throttleConfig.GetInt("state_limit", 37000); TotalLimit = throttleConfig.GetInt("client_throttle_max_bps", 0); } catch (Exception) { } } + + public int GetRate(ThrottleOutPacketType type) + { + switch (type) + { + case ThrottleOutPacketType.Resend: + return Resend; + case ThrottleOutPacketType.Land: + return Land; + case ThrottleOutPacketType.Wind: + return Wind; + case ThrottleOutPacketType.Cloud: + return Cloud; + case ThrottleOutPacketType.Task: + return Task; + case ThrottleOutPacketType.Texture: + return Texture; + case ThrottleOutPacketType.Asset: + return Asset; + case ThrottleOutPacketType.State: + return State; + case ThrottleOutPacketType.Unknown: + default: + return 0; + } + } + + public int GetLimit(ThrottleOutPacketType type) + { + switch (type) + { + case ThrottleOutPacketType.Resend: + return ResendLimit; + case ThrottleOutPacketType.Land: + return LandLimit; + case ThrottleOutPacketType.Wind: + return WindLimit; + case ThrottleOutPacketType.Cloud: + return CloudLimit; + case ThrottleOutPacketType.Task: + return TaskLimit; + case ThrottleOutPacketType.Texture: + return TextureLimit; + case ThrottleOutPacketType.Asset: + return AssetLimit; + case ThrottleOutPacketType.State: + return StateLimit; + case ThrottleOutPacketType.Unknown: + default: + return 0; + } + } } } -- cgit v1.1