parent
5976ac16b0
commit
4135b0c4dc
|
@ -31,13 +31,23 @@ namespace OpenSim.Framework
|
||||||
{
|
{
|
||||||
public enum ThrottleOutPacketType : int
|
public enum ThrottleOutPacketType : int
|
||||||
{
|
{
|
||||||
Unknown = -1, // Also doubles as 'do not throttle'
|
/// <summary>Unthrottled packets</summary>
|
||||||
|
Unknown = -1,
|
||||||
|
/// <summary>Packets that are being resent</summary>
|
||||||
Resend = 0,
|
Resend = 0,
|
||||||
|
/// <summary>Terrain data</summary>
|
||||||
Land = 1,
|
Land = 1,
|
||||||
|
/// <summary>Wind data</summary>
|
||||||
Wind = 2,
|
Wind = 2,
|
||||||
|
/// <summary>Cloud data</summary>
|
||||||
Cloud = 3,
|
Cloud = 3,
|
||||||
Task = 4,
|
/// <summary>Texture assets</summary>
|
||||||
Texture = 5,
|
Texture = 4,
|
||||||
Asset = 6,
|
/// <summary>Non-texture assets</summary>
|
||||||
|
Asset = 5,
|
||||||
|
/// <summary>Avatar and primitive data</summary>
|
||||||
|
State = 6,
|
||||||
|
/// <summary>Any packets that do not fit into the other throttles</summary>
|
||||||
|
Task = 7,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1223,7 +1223,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
kill.ObjectData[0].ID = localID;
|
kill.ObjectData[0].ID = localID;
|
||||||
kill.Header.Reliable = true;
|
kill.Header.Reliable = true;
|
||||||
kill.Header.Zerocoded = true;
|
kill.Header.Zerocoded = true;
|
||||||
OutPacket(kill, ThrottleOutPacketType.Task);
|
OutPacket(kill, ThrottleOutPacketType.State);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1817,7 +1817,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
sendXfer.XferID.ID = xferID;
|
sendXfer.XferID.ID = xferID;
|
||||||
sendXfer.XferID.Packet = packet;
|
sendXfer.XferID.Packet = packet;
|
||||||
sendXfer.DataPacket.Data = data;
|
sendXfer.DataPacket.Data = data;
|
||||||
OutPacket(sendXfer, ThrottleOutPacketType.Task);
|
OutPacket(sendXfer, ThrottleOutPacketType.Asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit,
|
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.AgentData.SessionID = SessionId;
|
||||||
packet.Header.Reliable = false;
|
packet.Header.Reliable = false;
|
||||||
packet.Header.Zerocoded = true;
|
packet.Header.Zerocoded = true;
|
||||||
OutPacket(packet, ThrottleOutPacketType.Task);
|
OutPacket(packet, ThrottleOutPacketType.State);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember,
|
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.IsTrial = false;
|
||||||
avp.Sender.ID = agentID;
|
avp.Sender.ID = agentID;
|
||||||
OutPacket(avp, ThrottleOutPacketType.Task);
|
OutPacket(avp, ThrottleOutPacketType.State);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
|
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.Reliable = false;
|
||||||
terse.Header.Zerocoded = true;
|
terse.Header.Zerocoded = true;
|
||||||
|
// FIXME: Move this to ThrottleOutPacketType.State when the real prioritization code is committed
|
||||||
OutPacket(terse, ThrottleOutPacketType.Task);
|
OutPacket(terse, ThrottleOutPacketType.Task);
|
||||||
|
|
||||||
if (m_avatarTerseUpdates.Count == 0)
|
if (m_avatarTerseUpdates.Count == 0)
|
||||||
|
@ -3506,7 +3507,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
|
|
||||||
outPacket.Header.Zerocoded = true;
|
outPacket.Header.Zerocoded = true;
|
||||||
OutPacket(outPacket, ThrottleOutPacketType.Task);
|
OutPacket(outPacket, ThrottleOutPacketType.State);
|
||||||
|
|
||||||
if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled)
|
if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled)
|
||||||
lock (m_primFullUpdateTimer)
|
lock (m_primFullUpdateTimer)
|
||||||
|
@ -3596,7 +3597,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
outPacket.Header.Reliable = false;
|
outPacket.Header.Reliable = false;
|
||||||
outPacket.Header.Zerocoded = true;
|
outPacket.Header.Zerocoded = true;
|
||||||
OutPacket(outPacket, ThrottleOutPacketType.Task);
|
OutPacket(outPacket, ThrottleOutPacketType.State);
|
||||||
|
|
||||||
if (m_primTerseUpdates.Count == 0)
|
if (m_primTerseUpdates.Count == 0)
|
||||||
lock (m_primTerseUpdateTimer)
|
lock (m_primTerseUpdateTimer)
|
||||||
|
|
|
@ -59,9 +59,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class LLUDPClient
|
public sealed class LLUDPClient
|
||||||
{
|
{
|
||||||
|
// FIXME: Make this a config setting
|
||||||
|
/// <summary>Percentage of the task throttle category that is allocated to avatar and prim
|
||||||
|
/// state updates</summary>
|
||||||
|
const float STATE_TASK_PERCENTAGE = 0.8f;
|
||||||
|
|
||||||
/// <summary>The number of packet categories to throttle on. If a throttle category is added
|
/// <summary>The number of packet categories to throttle on. If a throttle category is added
|
||||||
/// or removed, this number must also change</summary>
|
/// or removed, this number must also change</summary>
|
||||||
const int THROTTLE_CATEGORY_COUNT = 7;
|
const int THROTTLE_CATEGORY_COUNT = 8;
|
||||||
|
|
||||||
/// <summary>Fired when updated networking stats are produced for this client</summary>
|
/// <summary>Fired when updated networking stats are produced for this client</summary>
|
||||||
public event PacketStats OnPacketStats;
|
public event PacketStats OnPacketStats;
|
||||||
|
@ -134,9 +139,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <summary>An optimization to store the length of dequeued packets being held
|
/// <summary>An optimization to store the length of dequeued packets being held
|
||||||
/// for throttling. This avoids expensive calls to Packet.Length</summary>
|
/// for throttling. This avoids expensive calls to Packet.Length</summary>
|
||||||
private readonly int[] nextPacketLengths = new int[THROTTLE_CATEGORY_COUNT];
|
private readonly int[] nextPacketLengths = new int[THROTTLE_CATEGORY_COUNT];
|
||||||
/// <summary>Flags to prevent queue empty callbacks from repeatedly firing
|
|
||||||
/// before the callbacks have a chance to put packets in the queue</summary>
|
|
||||||
private readonly bool[] queueEmptySent = new bool[THROTTLE_CATEGORY_COUNT];
|
|
||||||
/// <summary>A reference to the LLUDPServer that is managing this client</summary>
|
/// <summary>A reference to the LLUDPServer that is managing this client</summary>
|
||||||
private readonly LLUDPServer udpServer;
|
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.Land] = new TokenBucket(throttle, rates.LandLimit, rates.Land);
|
||||||
throttleCategories[(int)ThrottleOutPacketType.Wind] = new TokenBucket(throttle, rates.WindLimit, rates.Wind);
|
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.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.Texture] = new TokenBucket(throttle, rates.TextureLimit, rates.Texture);
|
||||||
throttleCategories[(int)ThrottleOutPacketType.Asset] = new TokenBucket(throttle, rates.AssetLimit, rates.Asset);
|
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
|
// Set the granularity variable used for retransmission calculations to
|
||||||
// the measured resolution of Environment.TickCount
|
// the measured resolution of Environment.TickCount
|
||||||
|
@ -177,6 +182,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
// Default the retransmission timeout to three seconds
|
// Default the retransmission timeout to three seconds
|
||||||
RTO = 3000;
|
RTO = 3000;
|
||||||
|
|
||||||
|
// Initialize this to a sane value to prevent early disconnects
|
||||||
|
TickLastPacketReceived = Environment.TickCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -212,7 +220,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
info.landThrottle = throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
|
info.landThrottle = throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
|
||||||
info.windThrottle = throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
|
info.windThrottle = throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
|
||||||
info.cloudThrottle = throttleCategories[(int)ThrottleOutPacketType.Cloud].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.assetThrottle = throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
|
||||||
info.textureThrottle = throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
|
info.textureThrottle = throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
|
||||||
info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle +
|
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.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.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.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.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)throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4;
|
||||||
|
|
||||||
|
@ -317,6 +326,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetThrottle(ThrottleOutPacketType category, int rate)
|
public void SetThrottle(ThrottleOutPacketType category, int rate)
|
||||||
|
{
|
||||||
|
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;
|
int i = (int)category;
|
||||||
if (i >= 0 && i < throttleCategories.Length)
|
if (i >= 0 && i < throttleCategories.Length)
|
||||||
|
@ -326,6 +348,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
bucket.DripRate = rate;
|
bucket.DripRate = rate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool EnqueueOutgoing(OutgoingPacket packet)
|
public bool EnqueueOutgoing(OutgoingPacket packet)
|
||||||
{
|
{
|
||||||
|
@ -393,10 +416,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
queue = packetOutboxes[i];
|
queue = packetOutboxes[i];
|
||||||
if (queue.Dequeue(out packet))
|
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
|
// A packet was pulled off the queue. See if we have
|
||||||
// enough tokens in the bucket to send it out
|
// enough tokens in the bucket to send it out
|
||||||
if (bucket.RemoveTokens(packet.Buffer.DataLength))
|
if (bucket.RemoveTokens(packet.Buffer.DataLength))
|
||||||
|
@ -458,14 +477,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
private void FireQueueEmpty(int queueIndex)
|
private void FireQueueEmpty(int queueIndex)
|
||||||
{
|
{
|
||||||
if (!queueEmptySent[queueIndex])
|
|
||||||
{
|
|
||||||
queueEmptySent[queueIndex] = true;
|
|
||||||
|
|
||||||
QueueEmpty callback = OnQueueEmpty;
|
QueueEmpty callback = OnQueueEmpty;
|
||||||
if (callback != null)
|
if (callback != null)
|
||||||
Util.FireAndForget(delegate(object o) { callback((ThrottleOutPacketType)(int)o); }, queueIndex);
|
Util.FireAndForget(delegate(object o) { callback((ThrottleOutPacketType)(int)o); }, queueIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue