Merge branch 'queuetest' into careminster-presence-refactor

This commit is contained in:
Melanie
2011-04-25 23:26:37 +01:00
11 changed files with 412 additions and 229 deletions

View File

@@ -394,6 +394,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } }
public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
/// <summary>
/// Entity update queues
/// </summary>
public PriorityQueue EntityUpdateQueue { get { return m_entityUpdates; } }
/// <summary>
/// First name of the agent/avatar represented by the client
/// </summary>
@@ -3625,7 +3630,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Remove the update packet from the list of packets waiting for acknowledgement
// because we are requeuing the list of updates. They will be resent in new packets
// with the most recent state and priority.
m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber, 0, true);
m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
// Count this as a resent packet since we are going to requeue all of the updates contained in it
Interlocked.Increment(ref m_udpClient.PacketsResent);
foreach (EntityUpdate update in updates)
ResendPrimUpdate(update);
}
@@ -4092,7 +4101,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Remove the update packet from the list of packets waiting for acknowledgement
// because we are requeuing the list of updates. They will be resent in new packets
// with the most recent state.
m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber, 0, true);
m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
// Count this as a resent packet since we are going to requeue all of the updates contained in it
Interlocked.Increment(ref m_udpClient.PacketsResent);
foreach (ObjectPropertyUpdate update in updates)
ResendPropertyUpdate(update);
}
@@ -11513,7 +11526,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <returns></returns>
public byte[] GetThrottlesPacked(float multiplier)
{
return m_udpClient.GetThrottlesPacked();
return m_udpClient.GetThrottlesPacked(multiplier);
}
/// <summary>

View File

@@ -182,9 +182,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_maxRTO = maxRTO;
// Create a token bucket throttle for this client that has the scene token bucket as a parent
m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.TotalLimit);
m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled);
// Create a token bucket throttle for the total categary with the client bucket as a throttle
m_throttleCategory = new TokenBucket(m_throttleClient, rates.TotalLimit);
m_throttleCategory = new TokenBucket(m_throttleClient, rates.Total);
// Create an array of token buckets for this clients different throttle categories
m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
@@ -195,7 +195,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Initialize the packet outboxes, where packets sit while they are waiting for tokens
m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
// Initialize the token buckets that control the throttling for each category
m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetLimit(type));
m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type));
}
// Default the retransmission timeout to three seconds
@@ -229,26 +229,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <returns>Information about the client connection</returns>
public ClientInfo GetClientInfo()
{
///<mic>
TokenBucket tb;
tb = m_throttleClient.Parent;
m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest,"ROOT");
tb = m_throttleClient;
m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CLIENT");
tb = m_throttleCategory;
m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CATEGORY");
for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
{
tb = m_throttleCategories[i];
m_log.WarnFormat("[TOKENS] {4} <{0}:{1}>: Actual={2},Requested={3}",AgentID,i,tb.DripRate,tb.RequestedDripRate," BUCKET");
}
///</mic>
// TODO: This data structure is wrong in so many ways. Locking and copying the entire lists
// of pending and needed ACKs for every client every time some method wants information about
// this connection is a recipe for poor performance
@@ -260,12 +240,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
// info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle +
info.taskThrottle + info.assetThrottle + info.textureThrottle;
info.totalThrottle = (int)m_throttleCategory.DripRate;
return info;
}
@@ -352,8 +330,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
// State is a subcategory of task that we allocate a percentage to
int state = 0;
// int state = (int)((float)task * STATE_TASK_PERCENTAGE);
// task -= state;
// Make sure none of the throttles are set below our packet MTU,
// otherwise a throttle could become permanently clogged
@@ -364,19 +340,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
task = Math.Max(task, LLUDPServer.MTU);
texture = Math.Max(texture, LLUDPServer.MTU);
asset = Math.Max(asset, LLUDPServer.MTU);
state = Math.Max(state, LLUDPServer.MTU);
int total = resend + land + wind + cloud + task + texture + asset + 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);
//int total = resend + land + wind + cloud + task + texture + asset;
//m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
// AgentID, resend, land, wind, cloud, task, texture, asset, total);
// Update the token buckets with new throttle values
TokenBucket bucket;
bucket = m_throttleCategory;
bucket.RequestedDripRate = total;
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
bucket.RequestedDripRate = resend;
@@ -405,22 +376,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_packedThrottles = null;
}
public byte[] GetThrottlesPacked()
public byte[] GetThrottlesPacked(float multiplier)
{
byte[] data = m_packedThrottles;
if (data == null)
{
float rate;
data = new byte[7 * 4];
int i = 0;
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate), 0, data, i, 4); i += 4;
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate), 0, data, i, 4); i += 4;
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate), 0, data, i, 4); i += 4;
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate), 0, data, i, 4); i += 4;
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate), 0, data, i, 4); i += 4;
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate), 0, data, i, 4); i += 4;
Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate), 0, data, i, 4); i += 4;
// multiply by 8 to convert bytes back to bits
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * 8 * multiplier;
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * 8 * multiplier;
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * 8 * multiplier;
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * 8 * multiplier;
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * 8 * multiplier;
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * 8 * multiplier;
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * 8 * multiplier;
Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
m_packedThrottles = data;
}

View File

@@ -672,7 +672,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (packet.Header.AppendedAcks && packet.Header.AckList != null)
{
for (int i = 0; i < packet.Header.AckList.Length; i++)
udpClient.NeedAcks.Remove(packet.Header.AckList[i], now, packet.Header.Resent);
udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
}
// Handle PacketAck packets
@@ -681,7 +681,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
PacketAckPacket ackPacket = (PacketAckPacket)packet;
for (int i = 0; i < ackPacket.Packets.Length; i++)
udpClient.NeedAcks.Remove(ackPacket.Packets[i].ID, now, packet.Header.Resent);
udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
// We don't need to do anything else with PacketAck packets
return;

View File

@@ -52,30 +52,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public int Texture;
/// <summary>Drip rate for asset packets</summary>
public int Asset;
/// <summary>Drip rate for state packets</summary>
public int State;
/// <summary>Drip rate for the parent token bucket</summary>
public int Total;
/// <summary>Maximum burst rate for resent packets</summary>
public int ResendLimit;
/// <summary>Maximum burst rate for land packets</summary>
public int LandLimit;
/// <summary>Maximum burst rate for wind packets</summary>
public int WindLimit;
/// <summary>Maximum burst rate for cloud packets</summary>
public int CloudLimit;
/// <summary>Maximum burst rate for task (state and transaction) packets</summary>
public int TaskLimit;
/// <summary>Maximum burst rate for texture packets</summary>
public int TextureLimit;
/// <summary>Maximum burst rate for asset packets</summary>
public int AssetLimit;
/// <summary>Maximum burst rate for state packets</summary>
public int StateLimit;
/// <summary>Burst rate for the parent token bucket</summary>
public int TotalLimit;
/// <summary>Flag used to enable adaptive throttles</summary>
public bool AdaptiveThrottlesEnabled;
/// <summary>
/// Default constructor
/// </summary>
@@ -86,26 +69,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"];
Resend = throttleConfig.GetInt("resend_default", 12500);
Land = throttleConfig.GetInt("land_default", 1000);
Wind = throttleConfig.GetInt("wind_default", 1000);
Cloud = throttleConfig.GetInt("cloud_default", 1000);
Task = throttleConfig.GetInt("task_default", 1000);
Texture = throttleConfig.GetInt("texture_default", 1000);
Asset = throttleConfig.GetInt("asset_default", 1000);
State = throttleConfig.GetInt("state_default", 1000);
ResendLimit = throttleConfig.GetInt("resend_limit", 18750);
LandLimit = throttleConfig.GetInt("land_limit", 29750);
WindLimit = throttleConfig.GetInt("wind_limit", 18750);
CloudLimit = throttleConfig.GetInt("cloud_limit", 18750);
TaskLimit = throttleConfig.GetInt("task_limit", 18750);
TextureLimit = throttleConfig.GetInt("texture_limit", 55750);
AssetLimit = throttleConfig.GetInt("asset_limit", 27500);
StateLimit = throttleConfig.GetInt("state_limit", 37000);
Resend = throttleConfig.GetInt("resend_default", 6625);
Land = throttleConfig.GetInt("land_default", 9125);
Wind = throttleConfig.GetInt("wind_default", 1750);
Cloud = throttleConfig.GetInt("cloud_default", 1750);
Task = throttleConfig.GetInt("task_default", 18500);
Texture = throttleConfig.GetInt("texture_default", 18500);
Asset = throttleConfig.GetInt("asset_default", 10500);
Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
TotalLimit = Total;
AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
}
catch (Exception) { }
}
@@ -128,34 +102,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
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;

View File

@@ -29,6 +29,8 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using OpenSim.Framework;
using log4net;
namespace OpenSim.Region.ClientStack.LindenUDP
@@ -177,7 +179,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
RequestedDripRate = dripRate;
// TotalDripRequest = dripRate; // this will be overwritten when a child node registers
// MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst);
m_lastDrip = Environment.TickCount & Int32.MaxValue;
m_lastDrip = Util.EnvironmentTickCount();
}
#endregion Constructor
@@ -211,12 +213,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// </summary>
public void RegisterRequest(TokenBucket child, Int64 request)
{
m_children[child] = request;
// m_totalDripRequest = m_children.Values.Sum();
lock (m_children)
{
m_children[child] = request;
// m_totalDripRequest = m_children.Values.Sum();
m_totalDripRequest = 0;
foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
m_totalDripRequest += cref.Value;
m_totalDripRequest = 0;
foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
m_totalDripRequest += cref.Value;
}
// Pass the new values up to the parent
if (m_parent != null)
@@ -229,12 +234,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// </summary>
public void UnregisterRequest(TokenBucket child)
{
m_children.Remove(child);
// m_totalDripRequest = m_children.Values.Sum();
lock (m_children)
{
m_children.Remove(child);
// m_totalDripRequest = m_children.Values.Sum();
m_totalDripRequest = 0;
foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
m_totalDripRequest += cref.Value;
m_totalDripRequest = 0;
foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
m_totalDripRequest += cref.Value;
}
// Pass the new values up to the parent
if (m_parent != null)
@@ -297,10 +306,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Determine the interval over which we are adding tokens, never add
// more than a single quantum of tokens
Int32 now = Environment.TickCount & Int32.MaxValue;
Int32 deltaMS = Math.Min(now - m_lastDrip, m_ticksPerQuantum);
m_lastDrip = now;
Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum);
m_lastDrip = Util.EnvironmentTickCount();
// This can be 0 in the very unusual case that the timer wrapped
// It can be 0 if we try add tokens at a sub-tick rate
@@ -315,10 +322,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// <summary>
// The minimum rate for flow control.
// </summary>
protected const Int64 m_minimumFlow = m_minimumDripRate * 10;
/// <summary>
/// The minimum rate for flow control. Minimum drip rate is one
/// packet per second. Open the throttle to 15 packets per second
/// or about 160kbps.
/// </summary>
protected const Int64 m_minimumFlow = m_minimumDripRate * 15;
// <summary>
// The maximum rate for flow control. Drip rate can never be
@@ -331,6 +340,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value,m_minimumFlow)); }
}
private bool m_enabled = false;
// <summary>
//
// </summary>
@@ -348,9 +359,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// <summary>
//
// </summary>
public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate) : base(parent,m_minimumFlow)
public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate, bool enabled) : base(parent,maxDripRate)
{
MaxDripRate = maxDripRate;
m_enabled = enabled;
if (m_enabled)
{
m_log.WarnFormat("[TOKENBUCKET] Adaptive throttle enabled");
MaxDripRate = maxDripRate;
AdjustedDripRate = m_minimumFlow;
}
}
// <summary>
@@ -359,7 +377,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void ExpirePackets(Int32 count)
{
// m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count);
AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count));
if (m_enabled)
AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count));
}
// <summary>
@@ -367,7 +386,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// </summary>
public void AcknowledgePackets(Int32 count)
{
AdjustedDripRate = AdjustedDripRate + count;
if (m_enabled)
AdjustedDripRate = AdjustedDripRate + count;
}
}
}

View File

@@ -65,7 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary>Holds packets that need to be added to the unacknowledged list</summary>
private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>();
/// <summary>Holds information about pending acknowledgements</summary>
private LocklessQueue<PendingAck> m_pendingRemoves = new LocklessQueue<PendingAck>();
private LocklessQueue<PendingAck> m_pendingAcknowledgements = new LocklessQueue<PendingAck>();
/// <summary>Holds information about pending removals</summary>
private LocklessQueue<uint> m_pendingRemoves = new LocklessQueue<uint>();
/// <summary>
/// Add an unacked packet to the collection
@@ -83,15 +85,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary>
/// Marks a packet as acknowledged
/// This method is used when an acknowledgement is received from the network for a previously
/// sent packet. Effects of removal this way are to update unacked byte count, adjust RTT
/// and increase throttle to the coresponding client.
/// </summary>
/// <param name="sequenceNumber">Sequence number of the packet to
/// acknowledge</param>
/// <param name="currentTime">Current value of Environment.TickCount</param>
/// <remarks>This does not immediately acknowledge the packet, it only
/// queues the ack so it can be handled in a thread-safe way later</remarks>
public void Remove(uint sequenceNumber, int currentTime, bool fromResend)
public void Acknowledge(uint sequenceNumber, int currentTime, bool fromResend)
{
m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend));
m_pendingAcknowledgements.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend));
}
/// <summary>
/// Marks a packet as no longer needing acknowledgement without a received acknowledgement.
/// This method is called when a packet expires and we no longer need an acknowledgement.
/// When some reliable packet types expire, they are handled in a way other than simply
/// resending them. The only effect of removal this way is to update unacked byte count.
/// </summary>
/// <param name="sequenceNumber">Sequence number of the packet to
/// acknowledge</param>
/// <remarks>The does not immediately remove the packet, it only queues the removal
/// so it can be handled in a thread safe way later</remarks>
public void Remove(uint sequenceNumber)
{
m_pendingRemoves.Enqueue(sequenceNumber);
}
/// <summary>
@@ -151,15 +171,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_packets[pendingAdd.SequenceNumber] = pendingAdd;
// Process all the pending removes, including updating statistics and round-trip times
PendingAck pendingRemove;
OutgoingPacket ackedPacket;
while (m_pendingRemoves.TryDequeue(out pendingRemove))
PendingAck pendingAcknowledgement;
while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement))
{
if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket))
OutgoingPacket ackedPacket;
if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket))
{
if (ackedPacket != null)
{
m_packets.Remove(pendingRemove.SequenceNumber);
m_packets.Remove(pendingAcknowledgement.SequenceNumber);
// As with other network applications, assume that an acknowledged packet is an
// indication that the network can handle a little more load, speed up the transmission
@@ -168,16 +188,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Update stats
Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
if (!pendingRemove.FromResend)
if (!pendingAcknowledgement.FromResend)
{
// Calculate the round-trip time for this packet and its ACK
int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount;
int rtt = pendingAcknowledgement.RemoveTime - ackedPacket.TickCount;
if (rtt > 0)
ackedPacket.Client.UpdateRoundTrip(rtt);
}
}
}
}
uint pendingRemove;
while(m_pendingRemoves.TryDequeue(out pendingRemove))
{
OutgoingPacket removedPacket;
if (m_packets.TryGetValue(pendingRemove, out removedPacket))
{
if (removedPacket != null)
{
m_packets.Remove(pendingRemove);
// Update stats
Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
}
}
}
}
}
}
}