aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs219
1 files changed, 178 insertions, 41 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
index 4616203..7a42d82 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
@@ -42,6 +42,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
42 public class TokenBucket 42 public class TokenBucket
43 { 43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45<<<<<<< HEAD
45 46
46 public string Identifier { get; private set; } 47 public string Identifier { get; private set; }
47 48
@@ -52,16 +53,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
52 /// are defined over this interval. 53 /// are defined over this interval.
53 /// </summary> 54 /// </summary>
54 protected const Int32 m_ticksPerQuantum = 1000; 55 protected const Int32 m_ticksPerQuantum = 1000;
56=======
57 private static Int32 m_counter = 0;
58
59// private Int32 m_identifier;
60
61 protected const float m_timeScale = 1e-3f;
62>>>>>>> avn/ubitvar
55 63
56 /// <summary> 64 /// <summary>
57 /// This is the number of quantums worth of packets that can 65 /// This is the number of m_minimumDripRate bytes
58 /// be accommodated during a burst 66 /// allowed in a burst
67 /// roughtly, with this settings, the maximum time system will take
68 /// to recheck a bucket in ms
69 ///
59 /// </summary> 70 /// </summary>
60 protected const Double m_quantumsPerBurst = 1.5; 71 protected const float m_quantumsPerBurst = 5;
61 72
62 /// <summary> 73 /// <summary>
63 /// </summary> 74 /// </summary>
75<<<<<<< HEAD
64 protected const Int32 m_minimumDripRate = LLUDPServer.MTU; 76 protected const Int32 m_minimumDripRate = LLUDPServer.MTU;
77=======
78 protected const float m_minimumDripRate = 1400;
79>>>>>>> avn/ubitvar
65 80
66 /// <summary>Time of the last drip, in system ticks</summary> 81 /// <summary>Time of the last drip, in system ticks</summary>
67 protected Int32 m_lastDrip; 82 protected Int32 m_lastDrip;
@@ -70,12 +85,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
70 /// The number of bytes that can be sent at this moment. This is the 85 /// The number of bytes that can be sent at this moment. This is the
71 /// current number of tokens in the bucket 86 /// current number of tokens in the bucket
72 /// </summary> 87 /// </summary>
73 protected Int64 m_tokenCount; 88 protected float m_tokenCount;
74 89
75 /// <summary> 90 /// <summary>
76 /// Map of children buckets and their requested maximum burst rate 91 /// Map of children buckets and their requested maximum burst rate
77 /// </summary> 92 /// </summary>
93<<<<<<< HEAD
78 protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>(); 94 protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>();
95=======
96 protected Dictionary<TokenBucket, float> m_children = new Dictionary<TokenBucket, float>();
97
98#region Properties
99>>>>>>> avn/ubitvar
79 100
80 /// <summary> 101 /// <summary>
81 /// The parent bucket of this bucket, or null if this bucket has no 102 /// The parent bucket of this bucket, or null if this bucket has no
@@ -85,25 +106,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
85 public TokenBucket Parent { get; protected set; } 106 public TokenBucket Parent { get; protected set; }
86 107
87 /// <summary> 108 /// <summary>
88 /// Maximum burst rate in bytes per second. This is the maximum number 109 /// This is the maximum number
89 /// of tokens that can accumulate in the bucket at any one time. This 110 /// of tokens that can accumulate in the bucket at any one time. This
90 /// also sets the total request for leaf nodes 111 /// also sets the total request for leaf nodes
91 /// </summary> 112 /// </summary>
92 protected Int64 m_burstRate; 113 protected float m_burst;
93 public Int64 RequestedBurstRate 114 public float RequestedBurst
94 { 115 {
95 get { return m_burstRate; } 116 get { return m_burst; }
96 set { m_burstRate = (value < 0 ? 0 : value); } 117 set {
118 float rate = (value < 0 ? 0 : value);
119 if (rate < m_minimumDripRate)
120 rate = m_minimumDripRate;
121 else if (rate > m_minimumDripRate * m_quantumsPerBurst)
122 rate = m_minimumDripRate * m_quantumsPerBurst;
123
124 m_burst = rate;
125 }
97 } 126 }
98 127
99 public Int64 BurstRate 128 public float Burst
100 { 129 {
101 get { 130 get {
102 double rate = RequestedBurstRate * BurstRateModifier(); 131 float rate = RequestedBurst * BurstModifier();
103 if (rate < m_minimumDripRate * m_quantumsPerBurst) 132 if (rate < m_minimumDripRate)
104 rate = m_minimumDripRate * m_quantumsPerBurst; 133 rate = m_minimumDripRate;
105 134 return (float)rate;
106 return (Int64) rate;
107 } 135 }
108 } 136 }
109 137
@@ -115,6 +143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
115 /// Can never be above MaxDripRate. 143 /// Can never be above MaxDripRate.
116 /// Tokens are added to the bucket at any time 144 /// Tokens are added to the bucket at any time
117 /// <seealso cref="RemoveTokens"/> is called, at the granularity of 145 /// <seealso cref="RemoveTokens"/> is called, at the granularity of
146<<<<<<< HEAD
118 /// the system tick interval (typically around 15-22ms) 147 /// the system tick interval (typically around 15-22ms)
119 /// FIXME: It is extremely confusing to be able to set a RequestedDripRate of 0 and then receive a positive 148 /// FIXME: It is extremely confusing to be able to set a RequestedDripRate of 0 and then receive a positive
120 /// number on get if TotalDripRequest is set. This also stops us being able to retrieve the fact that 149 /// number on get if TotalDripRequest is set. This also stops us being able to retrieve the fact that
@@ -168,12 +197,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
168 rate = (double)RequestedDripRate * Parent.DripRateModifier(); 197 rate = (double)RequestedDripRate * Parent.DripRateModifier();
169 } 198 }
170 199
200=======
201 /// the system tick interval (typically around 15-22ms)</remarks>
202 protected float m_dripRate;
203 public virtual float RequestedDripRate
204 {
205 get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); }
206 set {
207 m_dripRate = (value < 0 ? 0 : value);
208 m_totalDripRequest = m_dripRate;
209
210 if (m_parent != null)
211 m_parent.RegisterRequest(this,m_dripRate);
212 }
213 }
214
215 public virtual float DripRate
216 {
217 get {
218 float rate = Math.Min(RequestedDripRate,TotalDripRequest);
219 if (m_parent == null)
220 return rate;
221
222 rate *= m_parent.DripRateModifier();
223>>>>>>> avn/ubitvar
171 if (rate < m_minimumDripRate) 224 if (rate < m_minimumDripRate)
172 rate = m_minimumDripRate; 225 rate = m_minimumDripRate;
173 else if (MaxDripRate > 0 && rate > MaxDripRate) 226 else if (MaxDripRate > 0 && rate > MaxDripRate)
174 rate = MaxDripRate; 227 rate = MaxDripRate;
175 228
176 return (Int64)rate; 229 return (float)rate;
177 } 230 }
178 } 231 }
179 protected Int64 m_dripRate; 232 protected Int64 m_dripRate;
@@ -186,7 +239,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
186 /// <summary> 239 /// <summary>
187 /// The current total of the requested maximum burst rates of children buckets. 240 /// The current total of the requested maximum burst rates of children buckets.
188 /// </summary> 241 /// </summary>
242<<<<<<< HEAD
189 public Int64 TotalDripRequest { get; protected set; } 243 public Int64 TotalDripRequest { get; protected set; }
244=======
245 protected float m_totalDripRequest;
246 public float TotalDripRequest
247 {
248 get { return m_totalDripRequest; }
249 set { m_totalDripRequest = value; }
250 }
251
252#endregion Properties
253
254#region Constructor
255>>>>>>> avn/ubitvar
190 256
191 /// <summary> 257 /// <summary>
192 /// Default constructor 258 /// Default constructor
@@ -194,18 +260,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
194 /// <param name="identifier">Identifier for this token bucket</param> 260 /// <param name="identifier">Identifier for this token bucket</param>
195 /// <param name="parent">Parent bucket if this is a child bucket, or 261 /// <param name="parent">Parent bucket if this is a child bucket, or
196 /// null if this is a root bucket</param> 262 /// null if this is a root bucket</param>
263<<<<<<< HEAD
197 /// <param name="requestedDripRate"> 264 /// <param name="requestedDripRate">
198 /// Requested rate that the bucket fills, in bytes per 265 /// Requested rate that the bucket fills, in bytes per
199 /// second. If zero, the bucket always remains full. 266 /// second. If zero, the bucket always remains full.
200 /// </param> 267 /// </param>
201 public TokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate) 268 public TokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate)
269=======
270 /// <param name="maxBurst">Maximum size of the bucket in bytes, or
271 /// zero if this bucket has no maximum capacity</param>
272 /// <param name="dripRate">Rate that the bucket fills, in bytes per
273 /// second. If zero, the bucket always remains full</param>
274 public TokenBucket(TokenBucket parent, float dripRate, float MaxBurst)
275>>>>>>> avn/ubitvar
202 { 276 {
203 Identifier = identifier; 277 Identifier = identifier;
204 278
205 Parent = parent; 279 Parent = parent;
280<<<<<<< HEAD
206 RequestedDripRate = requestedDripRate; 281 RequestedDripRate = requestedDripRate;
207 MaxDripRate = maxDripRate; 282 MaxDripRate = maxDripRate;
208 m_lastDrip = Util.EnvironmentTickCount(); 283 m_lastDrip = Util.EnvironmentTickCount();
284=======
285 RequestedDripRate = dripRate;
286 RequestedBurst = MaxBurst;
287 // TotalDripRequest = dripRate; // this will be overwritten when a child node registers
288 // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst);
289 m_lastDrip = Util.EnvironmentTickCount() + 100000;
290>>>>>>> avn/ubitvar
209 } 291 }
210 292
211 /// <summary> 293 /// <summary>
@@ -215,8 +297,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
215 /// hierarchy. However, if any of the parents is over-booked, then 297 /// hierarchy. However, if any of the parents is over-booked, then
216 /// the modifier will be less than 1. 298 /// the modifier will be less than 1.
217 /// </summary> 299 /// </summary>
218 protected double DripRateModifier() 300 protected float DripRateModifier()
219 { 301 {
302<<<<<<< HEAD
220 Int64 driprate = DripRate; 303 Int64 driprate = DripRate;
221 double modifier = driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; 304 double modifier = driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest;
222 305
@@ -226,11 +309,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
226// driprate, TotalDripRequest, modifier, Identifier); 309// driprate, TotalDripRequest, modifier, Identifier);
227 310
228 return modifier; 311 return modifier;
312=======
313 float driprate = DripRate;
314 return driprate >= TotalDripRequest ? 1.0f : driprate / TotalDripRequest;
315>>>>>>> avn/ubitvar
229 } 316 }
230 317
231 /// <summary> 318 /// <summary>
232 /// </summary> 319 /// </summary>
233 protected double BurstRateModifier() 320 protected float BurstModifier()
234 { 321 {
235 // for now... burst rate is always m_quantumsPerBurst (constant) 322 // for now... burst rate is always m_quantumsPerBurst (constant)
236 // larger than drip rate so the ratio of burst requests is the 323 // larger than drip rate so the ratio of burst requests is the
@@ -242,15 +329,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
242 /// Register drip rate requested by a child of this throttle. Pass the 329 /// Register drip rate requested by a child of this throttle. Pass the
243 /// changes up the hierarchy. 330 /// changes up the hierarchy.
244 /// </summary> 331 /// </summary>
245 public void RegisterRequest(TokenBucket child, Int64 request) 332 public void RegisterRequest(TokenBucket child, float request)
246 { 333 {
247 lock (m_children) 334 lock (m_children)
248 { 335 {
249 m_children[child] = request; 336 m_children[child] = request;
250 337
338<<<<<<< HEAD
251 TotalDripRequest = 0; 339 TotalDripRequest = 0;
252 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) 340 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
253 TotalDripRequest += cref.Value; 341 TotalDripRequest += cref.Value;
342=======
343 m_totalDripRequest = 0;
344 foreach (KeyValuePair<TokenBucket, float> cref in m_children)
345 m_totalDripRequest += cref.Value;
346>>>>>>> avn/ubitvar
254 } 347 }
255 348
256 // Pass the new values up to the parent 349 // Pass the new values up to the parent
@@ -277,9 +370,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
277 { 370 {
278 m_children.Remove(child); 371 m_children.Remove(child);
279 372
373<<<<<<< HEAD
280 TotalDripRequest = 0; 374 TotalDripRequest = 0;
281 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) 375 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
282 TotalDripRequest += cref.Value; 376 TotalDripRequest += cref.Value;
377=======
378 m_totalDripRequest = 0;
379 foreach (KeyValuePair<TokenBucket, float> cref in m_children)
380 m_totalDripRequest += cref.Value;
381>>>>>>> avn/ubitvar
283 } 382 }
284 383
285 // Pass the new values up to the parent 384 // Pass the new values up to the parent
@@ -293,7 +392,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
293 /// <param name="amount">Number of tokens to remove from the bucket</param> 392 /// <param name="amount">Number of tokens to remove from the bucket</param>
294 /// <returns>True if the requested number of tokens were removed from 393 /// <returns>True if the requested number of tokens were removed from
295 /// the bucket, otherwise false</returns> 394 /// the bucket, otherwise false</returns>
296 public bool RemoveTokens(Int64 amount) 395 public bool RemoveTokens(int amount)
297 { 396 {
298 // Deposit tokens for this interval 397 // Deposit tokens for this interval
299 Drip(); 398 Drip();
@@ -310,19 +409,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
310 return false; 409 return false;
311 } 410 }
312 411
313 /// <summary> 412 public int GetCatBytesCanSend(int timeMS)
314 /// Deposit tokens into the bucket from a child bucket that did
315 /// not use all of its available tokens
316 /// </summary>
317 protected void Deposit(Int64 count)
318 { 413 {
319 m_tokenCount += count; 414// return (int)(m_tokenCount + timeMS * m_dripRate * 1e-3);
320 415 return (int)(timeMS * m_dripRate * 1e-3);
321 // Deposit the overflow in the parent bucket, this is how we share
322 // unused bandwidth
323 Int64 burstrate = BurstRate;
324 if (m_tokenCount > burstrate)
325 m_tokenCount = burstrate;
326 } 416 }
327 417
328 /// <summary> 418 /// <summary>
@@ -341,17 +431,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
341 return; 431 return;
342 } 432 }
343 433
344 // Determine the interval over which we are adding tokens, never add 434 Int32 now = Util.EnvironmentTickCount();
345 // more than a single quantum of tokens 435 Int32 deltaMS = now - m_lastDrip;
346 Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum); 436 m_lastDrip = now;
347 m_lastDrip = Util.EnvironmentTickCount();
348 437
349 // This can be 0 in the very unusual case that the timer wrapped
350 // It can be 0 if we try add tokens at a sub-tick rate
351 if (deltaMS <= 0) 438 if (deltaMS <= 0)
352 return; 439 return;
353 440
354 Deposit(deltaMS * DripRate / m_ticksPerQuantum); 441 m_tokenCount += deltaMS * DripRate * m_timeScale;
442
443 float burst = Burst;
444 if (m_tokenCount > burst)
445 m_tokenCount = burst;
355 } 446 }
356 } 447 }
357 448
@@ -362,6 +453,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
362 public bool AdaptiveEnabled { get; set; } 453 public bool AdaptiveEnabled { get; set; }
363 454
364 /// <summary> 455 /// <summary>
456<<<<<<< HEAD
365 /// Target drip rate for this bucket. 457 /// Target drip rate for this bucket.
366 /// </summary> 458 /// </summary>
367 /// <remarks>Usually set by the client. If adaptive is enabled then throttles will increase until we reach this.</remarks> 459 /// <remarks>Usually set by the client. If adaptive is enabled then throttles will increase until we reach this.</remarks>
@@ -371,6 +463,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
371 set 463 set
372 { 464 {
373 m_targetDripRate = Math.Max(value, m_minimumFlow); 465 m_targetDripRate = Math.Max(value, m_minimumFlow);
466=======
467 /// The minimum rate for flow control. Minimum drip rate is one
468 /// packet per second.
469 /// </summary>
470
471 protected const float m_minimumFlow = 50000;
472
473 // <summary>
474 // The maximum rate for flow control. Drip rate can never be
475 // greater than this.
476 // </summary>
477
478 protected float m_maxDripRate = 0;
479 public float MaxDripRate
480 {
481 get { return (m_maxDripRate == 0 ? m_totalDripRequest : m_maxDripRate); }
482 set
483 {
484 m_maxDripRate = (value == 0 ? m_totalDripRequest : Math.Max(value, m_minimumFlow));
485>>>>>>> avn/ubitvar
374 } 486 }
375 } 487 }
376 protected Int64 m_targetDripRate; 488 protected Int64 m_targetDripRate;
@@ -378,9 +490,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
378 // <summary> 490 // <summary>
379 // Adjust drip rate in response to network conditions. 491 // Adjust drip rate in response to network conditions.
380 // </summary> 492 // </summary>
381 public virtual Int64 AdjustedDripRate 493 public virtual float AdjustedDripRate
382 { 494 {
383 get { return m_dripRate; } 495 get { return m_dripRate; }
496<<<<<<< HEAD
384 set 497 set
385 { 498 {
386 m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value, m_minimumFlow, TargetDripRate); 499 m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value, m_minimumFlow, TargetDripRate);
@@ -388,6 +501,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
388 501
389 if (Parent != null) 502 if (Parent != null)
390 Parent.RegisterRequest(this, m_dripRate); 503 Parent.RegisterRequest(this, m_dripRate);
504=======
505 set {
506 m_dripRate = OpenSim.Framework.Util.Clamp<float>(value,m_minimumFlow,MaxDripRate);
507
508 if (m_parent != null)
509 m_parent.RegisterRequest(this,m_dripRate);
510>>>>>>> avn/ubitvar
391 } 511 }
392 } 512 }
393 513
@@ -396,6 +516,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
396 /// </summary> 516 /// </summary>
397 protected Int64 m_minimumFlow = 32000; 517 protected Int64 m_minimumFlow = 32000;
398 518
519<<<<<<< HEAD
399 /// <summary> 520 /// <summary>
400 /// Constructor for the AdaptiveTokenBucket class 521 /// Constructor for the AdaptiveTokenBucket class
401 /// <param name="identifier">Unique identifier for the client</param> 522 /// <param name="identifier">Unique identifier for the client</param>
@@ -416,6 +537,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
416 TargetDripRate = m_minimumFlow; 537 TargetDripRate = m_minimumFlow;
417 AdjustedDripRate = m_minimumFlow; 538 AdjustedDripRate = m_minimumFlow;
418 } 539 }
540=======
541 // <summary>
542 //
543 // </summary>
544 public AdaptiveTokenBucket(TokenBucket parent, float maxDripRate,float maxBurst, bool enabled)
545 : base(parent, maxDripRate,maxBurst)
546 {
547 m_enabled = enabled;
548
549 MaxDripRate = maxDripRate;
550
551 if (enabled)
552 AdjustedDripRate = m_maxDripRate * .5f;
553 else
554 AdjustedDripRate = m_maxDripRate;
555>>>>>>> avn/ubitvar
419 } 556 }
420 557
421 /// <summary> 558 /// <summary>
@@ -461,4 +598,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP
461 AdjustedDripRate = m_minimumFlow; 598 AdjustedDripRate = m_minimumFlow;
462 } 599 }
463 } 600 }
464} \ No newline at end of file 601}