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