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.cs405
1 files changed, 179 insertions, 226 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
index 4616203..1daf091 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
@@ -43,150 +43,143 @@ namespace OpenSim.Region.ClientStack.LindenUDP
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 45
46 public string Identifier { get; private set; } 46 private static Int32 m_counter = 0;
47 47
48 public int DebugLevel { get; set; } 48// private Int32 m_identifier;
49 49
50 /// <summary> 50 protected const float m_timeScale = 1e-3f;
51 /// Number of ticks (ms) per quantum, drip rate and max burst
52 /// are defined over this interval.
53 /// </summary>
54 protected const Int32 m_ticksPerQuantum = 1000;
55 51
56 /// <summary> 52 /// <summary>
57 /// This is the number of quantums worth of packets that can 53 /// This is the number of m_minimumDripRate bytes
58 /// be accommodated during a burst 54 /// allowed in a burst
55 /// roughtly, with this settings, the maximum time system will take
56 /// to recheck a bucket in ms
57 ///
59 /// </summary> 58 /// </summary>
60 protected const Double m_quantumsPerBurst = 1.5; 59 protected const float m_quantumsPerBurst = 5;
61 60
62 /// <summary> 61 /// <summary>
63 /// </summary> 62 /// </summary>
64 protected const Int32 m_minimumDripRate = LLUDPServer.MTU; 63 protected const float m_minimumDripRate = 1500;
65 64
66 /// <summary>Time of the last drip, in system ticks</summary> 65 /// <summary>Time of the last drip</summary>
67 protected Int32 m_lastDrip; 66 protected double m_lastDrip;
68 67
69 /// <summary> 68 /// <summary>
70 /// The number of bytes that can be sent at this moment. This is the 69 /// The number of bytes that can be sent at this moment. This is the
71 /// current number of tokens in the bucket 70 /// current number of tokens in the bucket
72 /// </summary> 71 /// </summary>
73 protected Int64 m_tokenCount; 72 protected float m_tokenCount;
74 73
75 /// <summary> 74 /// <summary>
76 /// Map of children buckets and their requested maximum burst rate 75 /// Map of children buckets and their requested maximum burst rate
77 /// </summary> 76 /// </summary>
78 protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>(); 77
78 protected Dictionary<TokenBucket, float> m_children = new Dictionary<TokenBucket, float>();
79
80#region Properties
79 81
80 /// <summary> 82 /// <summary>
81 /// The parent bucket of this bucket, or null if this bucket has no 83 /// The parent bucket of this bucket, or null if this bucket has no
82 /// parent. The parent bucket will limit the aggregate bandwidth of all 84 /// parent. The parent bucket will limit the aggregate bandwidth of all
83 /// of its children buckets 85 /// of its children buckets
84 /// </summary> 86 /// </summary>
85 public TokenBucket Parent { get; protected set; } 87 protected TokenBucket m_parent;
86 88 public TokenBucket Parent
89 {
90 get { return m_parent; }
91 set { m_parent = value; }
92 }
87 /// <summary> 93 /// <summary>
88 /// Maximum burst rate in bytes per second. This is the maximum number 94 /// This is the maximum number
89 /// of tokens that can accumulate in the bucket at any one time. This 95 /// of tokens that can accumulate in the bucket at any one time. This
90 /// also sets the total request for leaf nodes 96 /// also sets the total request for leaf nodes
91 /// </summary> 97 /// </summary>
92 protected Int64 m_burstRate; 98 protected float m_burst;
93 public Int64 RequestedBurstRate 99
100 protected float m_maxDripRate = 0;
101 public virtual float MaxDripRate
94 { 102 {
95 get { return m_burstRate; } 103 get { return m_maxDripRate; }
96 set { m_burstRate = (value < 0 ? 0 : value); } 104 set { m_maxDripRate = value; }
97 } 105 }
98 106
99 public Int64 BurstRate 107 public float RequestedBurst
100 { 108 {
101 get { 109 get { return m_burst; }
102 double rate = RequestedBurstRate * BurstRateModifier(); 110 set {
103 if (rate < m_minimumDripRate * m_quantumsPerBurst) 111 float rate = (value < 0 ? 0 : value);
112 if (rate < 1.5f * m_minimumDripRate)
113 rate = 1.5f * m_minimumDripRate;
114 else if (rate > m_minimumDripRate * m_quantumsPerBurst)
104 rate = m_minimumDripRate * m_quantumsPerBurst; 115 rate = m_minimumDripRate * m_quantumsPerBurst;
105 116
106 return (Int64) rate; 117 m_burst = rate;
118 }
119 }
120
121 public float Burst
122 {
123 get {
124 float rate = RequestedBurst * BurstModifier();
125 if (rate < m_minimumDripRate)
126 rate = m_minimumDripRate;
127 return (float)rate;
107 } 128 }
108 } 129 }
109 130
110 /// <summary> 131 /// <summary>
111 /// The requested drip rate for this particular bucket. 132 /// The requested drip rate for this particular bucket.
112 /// </summary> 133 /// </summary>
113 /// <remarks> 134 /// <remarks>
114 /// 0 then TotalDripRequest is used instead. 135 /// 0 then TotalDripRequest is used instead.
115 /// Can never be above MaxDripRate. 136 /// Can never be above MaxDripRate.
116 /// Tokens are added to the bucket at any time 137 /// Tokens are added to the bucket at any time
117 /// <seealso cref="RemoveTokens"/> is called, at the granularity of 138 /// <seealso cref="RemoveTokens"/> is called, at the granularity of
118 /// the system tick interval (typically around 15-22ms) 139 /// the system tick interval (typically around 15-22ms)</remarks>
119 /// FIXME: It is extremely confusing to be able to set a RequestedDripRate of 0 and then receive a positive 140 protected float m_dripRate;
120 /// number on get if TotalDripRequest is set. This also stops us being able to retrieve the fact that
121 /// RequestedDripRate is set to 0. Really, this should always return m_dripRate and then we can get
122 /// (m_dripRate == 0 ? TotalDripRequest : m_dripRate) on some other properties.
123 /// </remarks>
124 public virtual Int64 RequestedDripRate
125 {
126 get { return (m_dripRate == 0 ? TotalDripRequest : m_dripRate); }
127 set
128 {
129 if (value <= 0)
130 m_dripRate = 0;
131 else if (MaxDripRate > 0 && value > MaxDripRate)
132 m_dripRate = MaxDripRate;
133 else
134 m_dripRate = value;
135 141
136 m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); 142 public float RequestedDripRate
143 {
144 get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); }
145 set {
146 m_dripRate = (value < 0 ? 0 : value);
147 m_totalDripRequest = m_dripRate;
137 148
138 if (Parent != null) 149 if (m_parent != null)
139 Parent.RegisterRequest(this, m_dripRate); 150 m_parent.RegisterRequest(this,m_dripRate);
140 } 151 }
141 } 152 }
142 153
143 /// <summary> 154 public float DripRate
144 /// Gets the drip rate.
145 /// </summary>
146 /// <value>
147 /// DripRate can never be above max drip rate or below min drip rate.
148 /// If we are a child bucket then the drip rate return is modifed by the total load on the capacity of the
149 /// parent bucket.
150 /// </value>
151 public virtual Int64 DripRate
152 { 155 {
153 get 156 get {
154 { 157 float rate = Math.Min(RequestedDripRate,TotalDripRequest);
155 double rate; 158 if (m_parent == null)
156 159 return rate;
157 // FIXME: This doesn't properly work if we have a parent and children and a requested drip rate set
158 // on ourselves which is not equal to the child drip rates.
159 if (Parent == null)
160 {
161 if (TotalDripRequest > 0)
162 rate = Math.Min(RequestedDripRate, TotalDripRequest);
163 else
164 rate = RequestedDripRate;
165 }
166 else
167 {
168 rate = (double)RequestedDripRate * Parent.DripRateModifier();
169 }
170 160
161 rate *= m_parent.DripRateModifier();
171 if (rate < m_minimumDripRate) 162 if (rate < m_minimumDripRate)
172 rate = m_minimumDripRate; 163 rate = m_minimumDripRate;
173 else if (MaxDripRate > 0 && rate > MaxDripRate)
174 rate = MaxDripRate;
175 164
176 return (Int64)rate; 165 return (float)rate;
177 } 166 }
178 } 167 }
179 protected Int64 m_dripRate;
180
181 // <summary>
182 // The maximum rate for flow control. Drip rate can never be greater than this.
183 // </summary>
184 public Int64 MaxDripRate { get; set; }
185 168
186 /// <summary> 169 /// <summary>
187 /// The current total of the requested maximum burst rates of children buckets. 170 /// The current total of the requested maximum burst rates of children buckets.
188 /// </summary> 171 /// </summary>
189 public Int64 TotalDripRequest { get; protected set; } 172 protected float m_totalDripRequest;
173 public float TotalDripRequest
174 {
175 get { return m_totalDripRequest; }
176 set { m_totalDripRequest = value; }
177 }
178
179#endregion Properties
180
181#region Constructor
182
190 183
191 /// <summary> 184 /// <summary>
192 /// Default constructor 185 /// Default constructor
@@ -194,20 +187,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
194 /// <param name="identifier">Identifier for this token bucket</param> 187 /// <param name="identifier">Identifier for this token bucket</param>
195 /// <param name="parent">Parent bucket if this is a child bucket, or 188 /// <param name="parent">Parent bucket if this is a child bucket, or
196 /// null if this is a root bucket</param> 189 /// null if this is a root bucket</param>
197 /// <param name="requestedDripRate"> 190 /// <param name="maxBurst">Maximum size of the bucket in bytes, or
198 /// Requested rate that the bucket fills, in bytes per 191 /// zero if this bucket has no maximum capacity</param>
199 /// second. If zero, the bucket always remains full. 192 /// <param name="dripRate">Rate that the bucket fills, in bytes per
200 /// </param> 193 /// second. If zero, the bucket always remains full</param>
201 public TokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate) 194 public TokenBucket(TokenBucket parent, float dripRate, float MaxBurst)
202 { 195 {
203 Identifier = identifier; 196 m_counter++;
204 197
205 Parent = parent; 198 Parent = parent;
206 RequestedDripRate = requestedDripRate; 199 RequestedDripRate = dripRate;
207 MaxDripRate = maxDripRate; 200 RequestedBurst = MaxBurst;
208 m_lastDrip = Util.EnvironmentTickCount(); 201 m_lastDrip = Util.GetTimeStampMS() + 100000.0; // skip first drip
209 } 202 }
210 203
204#endregion Constructor
205
211 /// <summary> 206 /// <summary>
212 /// Compute a modifier for the MaxBurst rate. This is 1.0, meaning 207 /// Compute a modifier for the MaxBurst rate. This is 1.0, meaning
213 /// no modification if the requested bandwidth is less than the 208 /// no modification if the requested bandwidth is less than the
@@ -215,22 +210,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
215 /// hierarchy. However, if any of the parents is over-booked, then 210 /// hierarchy. However, if any of the parents is over-booked, then
216 /// the modifier will be less than 1. 211 /// the modifier will be less than 1.
217 /// </summary> 212 /// </summary>
218 protected double DripRateModifier() 213 protected float DripRateModifier()
219 { 214 {
220 Int64 driprate = DripRate; 215 float driprate = DripRate;
221 double modifier = driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; 216 return driprate >= TotalDripRequest ? 1.0f : (driprate / TotalDripRequest);
222
223// if (DebugLevel > 0)
224// m_log.DebugFormat(
225// "[TOKEN BUCKET]: Returning drip modifier {0}/{1} = {2} from {3}",
226// driprate, TotalDripRequest, modifier, Identifier);
227
228 return modifier;
229 } 217 }
230 218
231 /// <summary> 219 /// <summary>
232 /// </summary> 220 /// </summary>
233 protected double BurstRateModifier() 221 protected float BurstModifier()
234 { 222 {
235 // for now... burst rate is always m_quantumsPerBurst (constant) 223 // for now... burst rate is always m_quantumsPerBurst (constant)
236 // larger than drip rate so the ratio of burst requests is the 224 // larger than drip rate so the ratio of burst requests is the
@@ -242,29 +230,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
242 /// Register drip rate requested by a child of this throttle. Pass the 230 /// Register drip rate requested by a child of this throttle. Pass the
243 /// changes up the hierarchy. 231 /// changes up the hierarchy.
244 /// </summary> 232 /// </summary>
245 public void RegisterRequest(TokenBucket child, Int64 request) 233 public void RegisterRequest(TokenBucket child, float request)
246 { 234 {
247 lock (m_children) 235 lock (m_children)
248 { 236 {
249 m_children[child] = request; 237 m_children[child] = request;
250 238
251 TotalDripRequest = 0; 239 m_totalDripRequest = 0;
252 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) 240 foreach (KeyValuePair<TokenBucket, float> cref in m_children)
253 TotalDripRequest += cref.Value; 241 m_totalDripRequest += cref.Value;
254 } 242 }
255
256 // Pass the new values up to the parent
257 if (Parent != null)
258 {
259 Int64 effectiveDripRate;
260
261 if (RequestedDripRate > 0)
262 effectiveDripRate = Math.Min(RequestedDripRate, TotalDripRequest);
263 else
264 effectiveDripRate = TotalDripRequest;
265 243
266 Parent.RegisterRequest(this, effectiveDripRate); 244 // Pass the new values up to the parent
267 } 245 if (m_parent != null)
246 m_parent.RegisterRequest(this, Math.Min(RequestedDripRate, TotalDripRequest));
268 } 247 }
269 248
270 /// <summary> 249 /// <summary>
@@ -277,23 +256,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
277 { 256 {
278 m_children.Remove(child); 257 m_children.Remove(child);
279 258
280 TotalDripRequest = 0; 259 m_totalDripRequest = 0;
281 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) 260 foreach (KeyValuePair<TokenBucket, float> cref in m_children)
282 TotalDripRequest += cref.Value; 261 m_totalDripRequest += cref.Value;
283 } 262 }
284 263
285 // Pass the new values up to the parent 264 // Pass the new values up to the parent
286 if (Parent != null) 265 if (Parent != null)
287 Parent.RegisterRequest(this,Math.Min(RequestedDripRate, TotalDripRequest)); 266 Parent.RegisterRequest(this,Math.Min(RequestedDripRate, TotalDripRequest));
288 } 267 }
289 268
290 /// <summary> 269 /// <summary>
291 /// Remove a given number of tokens from the bucket 270 /// Remove a given number of tokens from the bucket
292 /// </summary> 271 /// </summary>
293 /// <param name="amount">Number of tokens to remove from the bucket</param> 272 /// <param name="amount">Number of tokens to remove from the bucket</param>
294 /// <returns>True if the requested number of tokens were removed from 273 /// <returns>True if the requested number of tokens were removed from
295 /// the bucket, otherwise false</returns> 274 /// the bucket, otherwise false</returns>
296 public bool RemoveTokens(Int64 amount) 275 public bool RemoveTokens(int amount)
297 { 276 {
298 // Deposit tokens for this interval 277 // Deposit tokens for this interval
299 Drip(); 278 Drip();
@@ -310,24 +289,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
310 return false; 289 return false;
311 } 290 }
312 291
313 /// <summary> 292 public bool CheckTokens(int amount)
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 { 293 {
319 m_tokenCount += count; 294 return (m_tokenCount - amount >= 0);
295 }
320 296
321 // Deposit the overflow in the parent bucket, this is how we share 297 public int GetCatBytesCanSend(int timeMS)
322 // unused bandwidth 298 {
323 Int64 burstrate = BurstRate; 299// return (int)(m_tokenCount + timeMS * m_dripRate * 1e-3);
324 if (m_tokenCount > burstrate) 300 return (int)(timeMS * DripRate * 1e-3);
325 m_tokenCount = burstrate;
326 } 301 }
327 302
328 /// <summary> 303 /// <summary>
329 /// Add tokens to the bucket over time. The number of tokens added each 304 /// Add tokens to the bucket over time. The number of tokens added each
330 /// call depends on the length of time that has passed since the last 305 /// call depends on the length of time that has passed since the last
331 /// call to Drip 306 /// call to Drip
332 /// </summary> 307 /// </summary>
333 /// <returns>True if tokens were added to the bucket, otherwise false</returns> 308 /// <returns>True if tokens were added to the bucket, otherwise false</returns>
@@ -337,128 +312,106 @@ namespace OpenSim.Region.ClientStack.LindenUDP
337 // with no drip rate... 312 // with no drip rate...
338 if (DripRate == 0) 313 if (DripRate == 0)
339 { 314 {
340 m_log.WarnFormat("[TOKENBUCKET] something odd is happening and drip rate is 0 for {0}", Identifier); 315 m_log.WarnFormat("[TOKENBUCKET] something odd is happening and drip rate is 0 for {0}", m_counter);
341 return; 316 return;
342 } 317 }
343 318
344 // Determine the interval over which we are adding tokens, never add 319 double now = Util.GetTimeStampMS();
345 // more than a single quantum of tokens 320 double deltaMS = now - m_lastDrip;
346 Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum); 321 m_lastDrip = now;
347 m_lastDrip = Util.EnvironmentTickCount(); 322
348
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) 323 if (deltaMS <= 0)
352 return; 324 return;
353 325
354 Deposit(deltaMS * DripRate / m_ticksPerQuantum); 326 m_tokenCount += (float)deltaMS * DripRate * m_timeScale;
327
328 float burst = Burst;
329 if (m_tokenCount > burst)
330 m_tokenCount = burst;
355 } 331 }
356 } 332 }
357 333
358 public class AdaptiveTokenBucket : TokenBucket 334 public class AdaptiveTokenBucket : TokenBucket
359 { 335 {
360 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 336 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
361 337
362 public bool AdaptiveEnabled { get; set; } 338 public bool AdaptiveEnabled { get; set; }
363 339
364 /// <summary> 340 /// <summary>
365 /// Target drip rate for this bucket. 341 /// The minimum rate for flow control. Minimum drip rate is one
342 /// packet per second.
366 /// </summary> 343 /// </summary>
367 /// <remarks>Usually set by the client. If adaptive is enabled then throttles will increase until we reach this.</remarks> 344
368 public Int64 TargetDripRate 345 protected const float m_minimumFlow = 50000;
369 { 346
370 get { return m_targetDripRate; } 347 // <summary>
371 set 348 // The maximum rate for flow control. Drip rate can never be
349 // greater than this.
350 // </summary>
351
352 public override float MaxDripRate
353 {
354 get { return (m_maxDripRate == 0 ? m_totalDripRequest : m_maxDripRate); }
355 set
372 { 356 {
373 m_targetDripRate = Math.Max(value, m_minimumFlow); 357 m_maxDripRate = (value == 0 ? m_totalDripRequest : Math.Max(value, m_minimumFlow));
374 } 358 }
375 } 359 }
376 protected Int64 m_targetDripRate; 360
361 private bool m_enabled = false;
377 362
378 // <summary> 363 // <summary>
379 // Adjust drip rate in response to network conditions. 364 // Adjust drip rate in response to network conditions.
380 // </summary> 365 // </summary>
381 public virtual Int64 AdjustedDripRate 366 public float AdjustedDripRate
382 { 367 {
383 get { return m_dripRate; } 368 get { return m_dripRate; }
384 set 369 set
385 { 370 {
386 m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value, m_minimumFlow, TargetDripRate); 371 m_dripRate = OpenSim.Framework.Util.Clamp<float>(value, m_minimumFlow, MaxDripRate);
387 m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst);
388 372
389 if (Parent != null) 373 if (m_parent != null)
390 Parent.RegisterRequest(this, m_dripRate); 374 m_parent.RegisterRequest(this, m_dripRate);
391 } 375 }
392 } 376 }
393
394 /// <summary>
395 /// The minimum rate for adaptive flow control.
396 /// </summary>
397 protected Int64 m_minimumFlow = 32000;
398 377
399 /// <summary>
400 /// Constructor for the AdaptiveTokenBucket class
401 /// <param name="identifier">Unique identifier for the client</param>
402 /// <param name="parent">Parent bucket in the hierarchy</param>
403 /// <param name="requestedDripRate"></param>
404 /// <param name="maxDripRate">The ceiling rate for adaptation</param>
405 /// <param name="minDripRate">The floor rate for adaptation</param>
406 /// </summary>
407 public AdaptiveTokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate, Int64 minDripRate, bool enabled)
408 : base(identifier, parent, requestedDripRate, maxDripRate)
409 {
410 AdaptiveEnabled = enabled;
411 378
412 if (AdaptiveEnabled) 379 // <summary>
413 { 380 //
414// m_log.DebugFormat("[TOKENBUCKET]: Adaptive throttle enabled"); 381 // </summary>
415 m_minimumFlow = minDripRate; 382 public AdaptiveTokenBucket(TokenBucket parent, float maxDripRate, float maxBurst, bool enabled)
416 TargetDripRate = m_minimumFlow; 383 : base(parent, maxDripRate, maxBurst)
417 AdjustedDripRate = m_minimumFlow;
418 }
419 }
420
421 /// <summary>
422 /// Reliable packets sent to the client for which we never received an ack adjust the drip rate down.
423 /// <param name="packets">Number of packets that expired without successful delivery</param>
424 /// </summary>
425 public void ExpirePackets(Int32 packets)
426 { 384 {
427 if (AdaptiveEnabled) 385 m_enabled = enabled;
428 {
429 if (DebugLevel > 0)
430 m_log.WarnFormat(
431 "[ADAPTIVEBUCKET] drop {0} by {1} expired packets for {2}",
432 AdjustedDripRate, packets, Identifier);
433 386
434 // AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,packets)); 387 m_maxDripRate = (maxDripRate == 0 ? m_totalDripRequest : Math.Max(maxDripRate, m_minimumFlow));
435 388
436 // Compute the fallback solely on the rate allocated beyond the minimum, this 389 if (enabled)
437 // should smooth out the fallback to the minimum rate 390 m_dripRate = m_maxDripRate * .5f;
438 AdjustedDripRate = m_minimumFlow + (Int64) ((AdjustedDripRate - m_minimumFlow) / Math.Pow(2, packets)); 391 else
439 } 392 m_dripRate = m_maxDripRate;
393 if (m_parent != null)
394 m_parent.RegisterRequest(this, m_dripRate);
440 } 395 }
441 396
442 /// <summary> 397 /// <summary>
443 /// Reliable packets acked by the client adjust the drip rate up. 398 /// Reliable packets sent to the client for which we never received an ack adjust the drip rate down.
444 /// <param name="packets">Number of packets successfully acknowledged</param> 399 /// <param name="packets">Number of packets that expired without successful delivery</param>
445 /// </summary> 400 /// </summary>
446 public void AcknowledgePackets(Int32 packets) 401 public void ExpirePackets(Int32 count)
447 { 402 {
448 if (AdaptiveEnabled) 403 // m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count);
449 AdjustedDripRate = AdjustedDripRate + packets * LLUDPServer.MTU; 404 if (m_enabled)
405 AdjustedDripRate = (Int64)(AdjustedDripRate / Math.Pow(2, count));
450 } 406 }
451 407
452 /// <summary> 408 // <summary>
453 /// Adjust the minimum flow level for the adaptive throttle, this will drop adjusted 409 //
454 /// throttles back to the minimum levels 410 // </summary>
455 /// <param>minDripRate--the new minimum flow</param> 411 public void AcknowledgePackets(Int32 count)
456 /// </summary>
457 public void ResetMinimumAdaptiveFlow(Int64 minDripRate)
458 { 412 {
459 m_minimumFlow = minDripRate; 413 if (m_enabled)
460 TargetDripRate = m_minimumFlow; 414 AdjustedDripRate = AdjustedDripRate + count;
461 AdjustedDripRate = m_minimumFlow;
462 } 415 }
463 } 416 }
464} \ No newline at end of file 417}