From 4135b0c4dcd142fe43b4c1b020d41a72d9df63dd Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Tue, 13 Oct 2009 19:45:38 -0700 Subject: * Split Task category into Task and State * Crude prioritization hack --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 13 ++--- .../Region/ClientStack/LindenUDP/LLUDPClient.cs | 62 +++++++++++++--------- 2 files changed, 45 insertions(+), 30 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index ac558ff..3b1a0bd 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -1223,7 +1223,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP kill.ObjectData[0].ID = localID; kill.Header.Reliable = true; kill.Header.Zerocoded = true; - OutPacket(kill, ThrottleOutPacketType.Task); + OutPacket(kill, ThrottleOutPacketType.State); } /// @@ -1817,7 +1817,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP sendXfer.XferID.ID = xferID; sendXfer.XferID.Packet = packet; sendXfer.DataPacket.Data = data; - OutPacket(sendXfer, ThrottleOutPacketType.Task); + OutPacket(sendXfer, ThrottleOutPacketType.Asset); } public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, @@ -2099,7 +2099,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP packet.AgentData.SessionID = SessionId; packet.Header.Reliable = false; packet.Header.Zerocoded = true; - OutPacket(packet, ThrottleOutPacketType.Task); + OutPacket(packet, ThrottleOutPacketType.State); } public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, @@ -3122,7 +3122,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP avp.Sender.IsTrial = false; avp.Sender.ID = agentID; - OutPacket(avp, ThrottleOutPacketType.Task); + OutPacket(avp, ThrottleOutPacketType.State); } public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) @@ -3262,6 +3262,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP terse.Header.Reliable = false; terse.Header.Zerocoded = true; + // FIXME: Move this to ThrottleOutPacketType.State when the real prioritization code is committed OutPacket(terse, ThrottleOutPacketType.Task); if (m_avatarTerseUpdates.Count == 0) @@ -3506,7 +3507,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } outPacket.Header.Zerocoded = true; - OutPacket(outPacket, ThrottleOutPacketType.Task); + OutPacket(outPacket, ThrottleOutPacketType.State); if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) lock (m_primFullUpdateTimer) @@ -3596,7 +3597,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP outPacket.Header.Reliable = false; outPacket.Header.Zerocoded = true; - OutPacket(outPacket, ThrottleOutPacketType.Task); + OutPacket(outPacket, ThrottleOutPacketType.State); if (m_primTerseUpdates.Count == 0) lock (m_primTerseUpdateTimer) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index b27d8d6..e7707a9 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs @@ -59,9 +59,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public sealed class LLUDPClient { + // FIXME: 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; + /// 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 = 7; + const int THROTTLE_CATEGORY_COUNT = 8; /// Fired when updated networking stats are produced for this client public event PacketStats OnPacketStats; @@ -134,9 +139,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// An optimization to store the length of dequeued packets being held /// for throttling. This avoids expensive calls to Packet.Length private readonly int[] nextPacketLengths = new int[THROTTLE_CATEGORY_COUNT]; - /// Flags to prevent queue empty callbacks from repeatedly firing - /// before the callbacks have a chance to put packets in the queue - private readonly bool[] queueEmptySent = new bool[THROTTLE_CATEGORY_COUNT]; /// A reference to the LLUDPServer that is managing this client private readonly LLUDPServer udpServer; @@ -167,9 +169,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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.Task] = new TokenBucket(throttle, rates.TaskLimit, rates.Task); 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); // Set the granularity variable used for retransmission calculations to // the measured resolution of Environment.TickCount @@ -177,6 +182,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Default the retransmission timeout to three seconds RTO = 3000; + + // Initialize this to a sane value to prevent early disconnects + TickLastPacketReceived = Environment.TickCount; } /// @@ -212,7 +220,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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.Task].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.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + @@ -309,7 +317,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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), 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; @@ -318,12 +327,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SetThrottle(ThrottleOutPacketType category, int rate) { - int i = (int)category; - if (i >= 0 && i < throttleCategories.Length) + 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 { - TokenBucket bucket = throttleCategories[(int)category]; - bucket.MaxBurst = rate; - bucket.DripRate = rate; + int i = (int)category; + if (i >= 0 && i < throttleCategories.Length) + { + TokenBucket bucket = throttleCategories[(int)category]; + bucket.MaxBurst = rate; + bucket.DripRate = rate; + } } } @@ -393,10 +416,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP queue = packetOutboxes[i]; if (queue.Dequeue(out packet)) { - // Reset the flag for firing this queue's OnQueueEmpty callback - // now that we have dequeued a packet - queueEmptySent[i] = false; - // A packet was pulled off the queue. See if we have // enough tokens in the bucket to send it out if (bucket.RemoveTokens(packet.Buffer.DataLength)) @@ -458,14 +477,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP private void FireQueueEmpty(int queueIndex) { - if (!queueEmptySent[queueIndex]) - { - queueEmptySent[queueIndex] = true; - - QueueEmpty callback = OnQueueEmpty; - if (callback != null) - Util.FireAndForget(delegate(object o) { callback((ThrottleOutPacketType)(int)o); }, queueIndex); - } + QueueEmpty callback = OnQueueEmpty; + if (callback != null) + Util.FireAndForget(delegate(object o) { callback((ThrottleOutPacketType)(int)o); }, queueIndex); } } } -- cgit v1.1