aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs4
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs9
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs92
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs8
4 files changed, 95 insertions, 18 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 87b86eb..1108863 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -3585,6 +3585,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3585 /// </summary> 3585 /// </summary>
3586 private void ResendPrimUpdates(List<EntityUpdate> updates) 3586 private void ResendPrimUpdates(List<EntityUpdate> updates)
3587 { 3587 {
3588 // m_log.WarnFormat("[CLIENT] resending prim update {0}",updates[0].UpdateTime);
3589
3588 foreach (EntityUpdate update in updates) 3590 foreach (EntityUpdate update in updates)
3589 ResendPrimUpdate(update); 3591 ResendPrimUpdate(update);
3590 } 3592 }
@@ -4027,6 +4029,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4027 4029
4028 private void ResendPropertyUpdates(List<ObjectPropertyUpdate> updates) 4030 private void ResendPropertyUpdates(List<ObjectPropertyUpdate> updates)
4029 { 4031 {
4032 // m_log.WarnFormat("[CLIENT] resending object property {0}",updates[0].UpdateTime);
4033
4030 foreach (ObjectPropertyUpdate update in updates) 4034 foreach (ObjectPropertyUpdate update in updates)
4031 ResendPropertyUpdate(update); 4035 ResendPropertyUpdate(update);
4032 } 4036 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 7be8a0a..20bfec8 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -135,7 +135,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
135 private int m_nextOnQueueEmpty = 1; 135 private int m_nextOnQueueEmpty = 1;
136 136
137 /// <summary>Throttle bucket for this agent's connection</summary> 137 /// <summary>Throttle bucket for this agent's connection</summary>
138 private readonly TokenBucket m_throttleClient; 138 private readonly AdaptiveTokenBucket m_throttleClient;
139 public AdaptiveTokenBucket FlowThrottle
140 {
141 get { return m_throttleClient; }
142 }
143
139 /// <summary>Throttle bucket for this agent's connection</summary> 144 /// <summary>Throttle bucket for this agent's connection</summary>
140 private readonly TokenBucket m_throttleCategory; 145 private readonly TokenBucket m_throttleCategory;
141 /// <summary>Throttle buckets for each packet category</summary> 146 /// <summary>Throttle buckets for each packet category</summary>
@@ -176,7 +181,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
176 m_maxRTO = maxRTO; 181 m_maxRTO = maxRTO;
177 182
178 // Create a token bucket throttle for this client that has the scene token bucket as a parent 183 // Create a token bucket throttle for this client that has the scene token bucket as a parent
179 m_throttleClient = new TokenBucket(parentThrottle, rates.TotalLimit); 184 m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.TotalLimit);
180 // Create a token bucket throttle for the total categary with the client bucket as a throttle 185 // Create a token bucket throttle for the total categary with the client bucket as a throttle
181 m_throttleCategory = new TokenBucket(m_throttleClient, rates.TotalLimit); 186 m_throttleCategory = new TokenBucket(m_throttleClient, rates.TotalLimit);
182 // Create an array of token buckets for this clients different throttle categories 187 // Create an array of token buckets for this clients different throttle categories
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index 07b0a1d..4ee6d3a 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -48,31 +48,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
48 /// Number of ticks (ms) per quantum, drip rate and max burst 48 /// Number of ticks (ms) per quantum, drip rate and max burst
49 /// are defined over this interval. 49 /// are defined over this interval.
50 /// </summary> 50 /// </summary>
51 private const Int32 m_ticksPerQuantum = 1000; 51 protected const Int32 m_ticksPerQuantum = 1000;
52 52
53 /// <summary> 53 /// <summary>
54 /// This is the number of quantums worth of packets that can 54 /// This is the number of quantums worth of packets that can
55 /// be accommodated during a burst 55 /// be accommodated during a burst
56 /// </summary> 56 /// </summary>
57 private const Double m_quantumsPerBurst = 1.5; 57 protected const Double m_quantumsPerBurst = 1.5;
58 58
59 /// <summary> 59 /// <summary>
60 /// </summary> 60 /// </summary>
61 private const Int32 m_minimumDripRate = 1400; 61 protected const Int32 m_minimumDripRate = 1400;
62 62
63 /// <summary>Time of the last drip, in system ticks</summary> 63 /// <summary>Time of the last drip, in system ticks</summary>
64 private Int32 m_lastDrip; 64 protected Int32 m_lastDrip;
65 65
66 /// <summary> 66 /// <summary>
67 /// The number of bytes that can be sent at this moment. This is the 67 /// The number of bytes that can be sent at this moment. This is the
68 /// current number of tokens in the bucket 68 /// current number of tokens in the bucket
69 /// </summary> 69 /// </summary>
70 private Int64 m_tokenCount; 70 protected Int64 m_tokenCount;
71 71
72 /// <summary> 72 /// <summary>
73 /// Map of children buckets and their requested maximum burst rate 73 /// Map of children buckets and their requested maximum burst rate
74 /// </summary> 74 /// </summary>
75 private Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>(); 75 protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>();
76 76
77#region Properties 77#region Properties
78 78
@@ -81,7 +81,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
81 /// parent. The parent bucket will limit the aggregate bandwidth of all 81 /// parent. The parent bucket will limit the aggregate bandwidth of all
82 /// of its children buckets 82 /// of its children buckets
83 /// </summary> 83 /// </summary>
84 private TokenBucket m_parent; 84 protected TokenBucket m_parent;
85 public TokenBucket Parent 85 public TokenBucket Parent
86 { 86 {
87 get { return m_parent; } 87 get { return m_parent; }
@@ -93,7 +93,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
93 /// of tokens that can accumulate in the bucket at any one time. This 93 /// of tokens that can accumulate in the bucket at any one time. This
94 /// also sets the total request for leaf nodes 94 /// also sets the total request for leaf nodes
95 /// </summary> 95 /// </summary>
96 private Int64 m_burstRate; 96 protected Int64 m_burstRate;
97 public Int64 RequestedBurstRate 97 public Int64 RequestedBurstRate
98 { 98 {
99 get { return m_burstRate; } 99 get { return m_burstRate; }
@@ -118,8 +118,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
118 /// <remarks>Tokens are added to the bucket any time 118 /// <remarks>Tokens are added to the bucket any time
119 /// <seealso cref="RemoveTokens"/> is called, at the granularity of 119 /// <seealso cref="RemoveTokens"/> is called, at the granularity of
120 /// the system tick interval (typically around 15-22ms)</remarks> 120 /// the system tick interval (typically around 15-22ms)</remarks>
121 private Int64 m_dripRate; 121 protected Int64 m_dripRate;
122 public Int64 RequestedDripRate 122 public virtual Int64 RequestedDripRate
123 { 123 {
124 get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); } 124 get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); }
125 set { 125 set {
@@ -131,7 +131,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
131 } 131 }
132 } 132 }
133 133
134 public Int64 DripRate 134 public virtual Int64 DripRate
135 { 135 {
136 get { 136 get {
137 if (m_parent == null) 137 if (m_parent == null)
@@ -149,7 +149,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
149 /// The current total of the requested maximum burst rates of 149 /// The current total of the requested maximum burst rates of
150 /// this bucket's children buckets. 150 /// this bucket's children buckets.
151 /// </summary> 151 /// </summary>
152 private Int64 m_totalDripRequest; 152 protected Int64 m_totalDripRequest;
153 public Int64 TotalDripRequest 153 public Int64 TotalDripRequest
154 { 154 {
155 get { return m_totalDripRequest; } 155 get { return m_totalDripRequest; }
@@ -189,7 +189,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
189 /// hierarchy. However, if any of the parents is over-booked, then 189 /// hierarchy. However, if any of the parents is over-booked, then
190 /// the modifier will be less than 1. 190 /// the modifier will be less than 1.
191 /// </summary> 191 /// </summary>
192 private double DripRateModifier() 192 protected double DripRateModifier()
193 { 193 {
194 Int64 driprate = DripRate; 194 Int64 driprate = DripRate;
195 return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; 195 return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest;
@@ -197,7 +197,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
197 197
198 /// <summary> 198 /// <summary>
199 /// </summary> 199 /// </summary>
200 private double BurstRateModifier() 200 protected double BurstRateModifier()
201 { 201 {
202 // for now... burst rate is always m_quantumsPerBurst (constant) 202 // for now... burst rate is always m_quantumsPerBurst (constant)
203 // larger than drip rate so the ratio of burst requests is the 203 // larger than drip rate so the ratio of burst requests is the
@@ -268,7 +268,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
268 /// Deposit tokens into the bucket from a child bucket that did 268 /// Deposit tokens into the bucket from a child bucket that did
269 /// not use all of its available tokens 269 /// not use all of its available tokens
270 /// </summary> 270 /// </summary>
271 private void Deposit(Int64 count) 271 protected void Deposit(Int64 count)
272 { 272 {
273 m_tokenCount += count; 273 m_tokenCount += count;
274 274
@@ -285,7 +285,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
285 /// call to Drip 285 /// call to Drip
286 /// </summary> 286 /// </summary>
287 /// <returns>True if tokens were added to the bucket, otherwise false</returns> 287 /// <returns>True if tokens were added to the bucket, otherwise false</returns>
288 private void Drip() 288 protected void Drip()
289 { 289 {
290 // This should never happen... means we are a leaf node and were created 290 // This should never happen... means we are a leaf node and were created
291 // with no drip rate... 291 // with no drip rate...
@@ -310,4 +310,64 @@ namespace OpenSim.Region.ClientStack.LindenUDP
310 Deposit(deltaMS * DripRate / m_ticksPerQuantum); 310 Deposit(deltaMS * DripRate / m_ticksPerQuantum);
311 } 311 }
312 } 312 }
313
314 public class AdaptiveTokenBucket : TokenBucket
315 {
316 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
317
318 // <summary>
319 // The minimum rate for flow control.
320 // </summary>
321 protected const Int64 m_minimumFlow = m_minimumDripRate * 10;
322
323 // <summary>
324 // The maximum rate for flow control. Drip rate can never be
325 // greater than this.
326 // </summary>
327 protected Int64 m_maxDripRate = 0;
328 protected Int64 MaxDripRate
329 {
330 get { return (m_maxDripRate == 0 ? m_totalDripRequest : m_maxDripRate); }
331 set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value,m_minimumFlow)); }
332 }
333
334 // <summary>
335 //
336 // </summary>
337 public virtual Int64 AdjustedDripRate
338 {
339 get { return m_dripRate; }
340 set {
341 m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value,m_minimumFlow,MaxDripRate);
342 m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst);
343 if (m_parent != null)
344 m_parent.RegisterRequest(this,m_dripRate);
345 }
346 }
347
348 // <summary>
349 //
350 // </summary>
351 public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate) : base(parent,m_minimumFlow)
352 {
353 MaxDripRate = maxDripRate;
354 }
355
356 // <summary>
357 //
358 // </summary>
359 public void ExpirePackets(Int32 count)
360 {
361 // m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count);
362 AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count));
363 }
364
365 // <summary>
366 //
367 // </summary>
368 public void AcknowledgePackets(Int32 count)
369 {
370 AdjustedDripRate = AdjustedDripRate + count;
371 }
372 }
313} 373}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
index d195110..b170964 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
@@ -130,6 +130,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
130 // is actually sent out again 130 // is actually sent out again
131 packet.TickCount = 0; 131 packet.TickCount = 0;
132 132
133 // As with other network applications, assume that an expired packet is
134 // an indication of some network problem, slow transmission
135 packet.Client.FlowThrottle.ExpirePackets(1);
136
133 expiredPackets.Add(packet); 137 expiredPackets.Add(packet);
134 } 138 }
135 } 139 }
@@ -157,6 +161,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
157 { 161 {
158 m_packets.Remove(pendingRemove.SequenceNumber); 162 m_packets.Remove(pendingRemove.SequenceNumber);
159 163
164 // As with other network applications, assume that an acknowledged packet is an
165 // indication that the network can handle a little more load, speed up the transmission
166 ackedPacket.Client.FlowThrottle.AcknowledgePackets(ackedPacket.Buffer.DataLength);
167
160 // Update stats 168 // Update stats
161 Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); 169 Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
162 170