diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs | 122 |
1 files changed, 84 insertions, 38 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs index d696265..e0633d3 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs | |||
@@ -113,36 +113,65 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
113 | /// The speed limit of this bucket in bytes per second. This is the | 113 | /// The speed limit of this bucket in bytes per second. This is the |
114 | /// number of tokens that are added to the bucket per quantum | 114 | /// number of tokens that are added to the bucket per quantum |
115 | /// </summary> | 115 | /// </summary> |
116 | /// <remarks>Tokens are added to the bucket any time | 116 | /// <remarks> |
117 | /// RequestedDripRate can never be above MaxDripRate. | ||
118 | /// Tokens are added to the bucket any time | ||
117 | /// <seealso cref="RemoveTokens"/> is called, at the granularity of | 119 | /// <seealso cref="RemoveTokens"/> is called, at the granularity of |
118 | /// the system tick interval (typically around 15-22ms)</remarks> | 120 | /// the system tick interval (typically around 15-22ms)</remarks> |
119 | protected Int64 m_dripRate; | 121 | protected Int64 m_dripRate; |
120 | public virtual Int64 RequestedDripRate | 122 | public virtual Int64 RequestedDripRate |
121 | { | 123 | { |
122 | get { return (m_dripRate == 0 ? TotalDripRequest : m_dripRate); } | 124 | get { return (m_dripRate == 0 ? TotalDripRequest : m_dripRate); } |
123 | set { | 125 | set |
124 | m_dripRate = (value < 0 ? 0 : value); | 126 | { |
125 | m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); | 127 | if (value <= 0) |
128 | m_dripRate = 0; | ||
129 | else if (MaxDripRate > 0 && value > MaxDripRate) | ||
130 | m_dripRate = MaxDripRate; | ||
131 | else | ||
132 | m_dripRate = value; | ||
133 | |||
126 | TotalDripRequest = m_dripRate; | 134 | TotalDripRequest = m_dripRate; |
135 | m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); | ||
136 | |||
127 | if (Parent != null) | 137 | if (Parent != null) |
128 | Parent.RegisterRequest(this,m_dripRate); | 138 | Parent.RegisterRequest(this, m_dripRate); |
129 | } | 139 | } |
130 | } | 140 | } |
131 | 141 | ||
142 | /// <summary> | ||
143 | /// Gets the drip rate. | ||
144 | /// </summary> | ||
145 | /// <value>DripRate can never be above max.</value> | ||
132 | public virtual Int64 DripRate | 146 | public virtual Int64 DripRate |
133 | { | 147 | { |
134 | get { | 148 | get |
149 | { | ||
135 | if (Parent == null) | 150 | if (Parent == null) |
136 | return Math.Min(RequestedDripRate, TotalDripRequest); | 151 | return Math.Min(RequestedDripRate, TotalDripRequest); |
137 | 152 | ||
138 | double rate = (double)RequestedDripRate * Parent.DripRateModifier(); | 153 | double rate = (double)RequestedDripRate * Parent.DripRateModifier(); |
139 | if (rate < m_minimumDripRate) | 154 | if (rate < m_minimumDripRate) |
140 | rate = m_minimumDripRate; | 155 | rate = m_minimumDripRate; |
156 | else if (MaxDripRate > 0 && rate > MaxDripRate) | ||
157 | rate = MaxDripRate; | ||
141 | 158 | ||
142 | return (Int64)rate; | 159 | return (Int64)rate; |
143 | } | 160 | } |
144 | } | 161 | } |
145 | 162 | ||
163 | // <summary> | ||
164 | // The maximum rate for flow control. Drip rate can never be greater than this. | ||
165 | // </summary> | ||
166 | // protected Int64 m_maxDripRate; | ||
167 | // public Int64 MaxDripRate | ||
168 | // { | ||
169 | // get { return m_maxDripRate; } | ||
170 | // //get { return (m_maxDripRate == 0 ? TotalDripRequest : m_maxDripRate); } | ||
171 | // set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value, m_minimumFlow)); } | ||
172 | // } | ||
173 | public Int64 MaxDripRate { get; set; } | ||
174 | |||
146 | /// <summary> | 175 | /// <summary> |
147 | /// The current total of the requested maximum burst rates of | 176 | /// The current total of the requested maximum burst rates of |
148 | /// this bucket's children buckets. | 177 | /// this bucket's children buckets. |
@@ -161,12 +190,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
161 | /// null if this is a root bucket</param> | 190 | /// null if this is a root bucket</param> |
162 | /// <param name="dripRate">Rate that the bucket fills, in bytes per | 191 | /// <param name="dripRate">Rate that the bucket fills, in bytes per |
163 | /// second. If zero, the bucket always remains full</param> | 192 | /// second. If zero, the bucket always remains full</param> |
164 | public TokenBucket(string identifier, TokenBucket parent, Int64 dripRate) | 193 | public TokenBucket(string identifier, TokenBucket parent, Int64 dripRate, Int64 maxDripRate) |
165 | { | 194 | { |
166 | Identifier = identifier; | 195 | Identifier = identifier; |
167 | 196 | ||
168 | Parent = parent; | 197 | Parent = parent; |
169 | RequestedDripRate = dripRate; | 198 | RequestedDripRate = dripRate; |
199 | MaxDripRate = maxDripRate; | ||
170 | // TotalDripRequest = dripRate; // this will be overwritten when a child node registers | 200 | // TotalDripRequest = dripRate; // this will be overwritten when a child node registers |
171 | // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst); | 201 | // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst); |
172 | m_lastDrip = Util.EnvironmentTickCount(); | 202 | m_lastDrip = Util.EnvironmentTickCount(); |
@@ -184,7 +214,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
184 | protected double DripRateModifier() | 214 | protected double DripRateModifier() |
185 | { | 215 | { |
186 | Int64 driprate = DripRate; | 216 | Int64 driprate = DripRate; |
187 | return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; | 217 | double modifier = driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; |
218 | |||
219 | // if (DebugLevel > 0) | ||
220 | // m_log.DebugFormat( | ||
221 | // "[TOKEN BUCKET]: Returning drip modifier {0}/{1} = {2} from {3}", | ||
222 | // driprate, TotalDripRequest, modifier, Identifier); | ||
223 | |||
224 | return modifier; | ||
188 | } | 225 | } |
189 | 226 | ||
190 | /// <summary> | 227 | /// <summary> |
@@ -215,7 +252,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
215 | 252 | ||
216 | // Pass the new values up to the parent | 253 | // Pass the new values up to the parent |
217 | if (Parent != null) | 254 | if (Parent != null) |
218 | Parent.RegisterRequest(this,Math.Min(RequestedDripRate, TotalDripRequest)); | 255 | { |
256 | Int64 effectiveDripRate; | ||
257 | |||
258 | if (MaxDripRate > 0) | ||
259 | effectiveDripRate = Math.Min(MaxDripRate, TotalDripRequest); | ||
260 | else | ||
261 | effectiveDripRate = TotalDripRequest; | ||
262 | |||
263 | //Parent.RegisterRequest(this, Math.Min(RequestedDripRate, TotalDripRequest)); | ||
264 | Parent.RegisterRequest(this, effectiveDripRate); | ||
265 | } | ||
219 | } | 266 | } |
220 | 267 | ||
221 | /// <summary> | 268 | /// <summary> |
@@ -309,61 +356,60 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
309 | 356 | ||
310 | public class AdaptiveTokenBucket : TokenBucket | 357 | public class AdaptiveTokenBucket : TokenBucket |
311 | { | 358 | { |
312 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 359 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
360 | |||
361 | public bool AdaptiveEnabled { get; set; } | ||
313 | 362 | ||
314 | /// <summary> | 363 | /// <summary> |
315 | /// The minimum rate for flow control. Minimum drip rate is one | 364 | /// Target drip rate for this bucket. |
316 | /// packet per second. Open the throttle to 15 packets per second | ||
317 | /// or about 160kbps. | ||
318 | /// </summary> | 365 | /// </summary> |
319 | protected const Int64 m_minimumFlow = m_minimumDripRate * 15; | 366 | /// <remarks>Usually set by the client. If adaptive is enabled then throttles will increase until we reach this.</remarks> |
320 | 367 | public Int64 TargetDripRate | |
321 | // <summary> | 368 | { |
322 | // The maximum rate for flow control. Drip rate can never be | 369 | get { return m_targetDripRate; } |
323 | // greater than this. | 370 | set { m_targetDripRate = Math.Max(0, value); } |
324 | // </summary> | ||
325 | protected Int64 m_maxDripRate = 0; | ||
326 | public Int64 MaxDripRate | ||
327 | { | ||
328 | get { return (m_maxDripRate == 0 ? TotalDripRequest : m_maxDripRate); } | ||
329 | set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value,m_minimumFlow)); } | ||
330 | } | 371 | } |
372 | protected Int64 m_targetDripRate; | ||
331 | 373 | ||
332 | public bool Enabled { get; set; } | ||
333 | |||
334 | // <summary> | 374 | // <summary> |
335 | // | 375 | // Adjust drip rate in response to network conditions. |
336 | // </summary> | 376 | // </summary> |
337 | public virtual Int64 AdjustedDripRate | 377 | public virtual Int64 AdjustedDripRate |
338 | { | 378 | { |
339 | get { return m_dripRate; } | 379 | get { return m_dripRate; } |
340 | set { | 380 | set { |
341 | m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value,m_minimumFlow,MaxDripRate); | 381 | m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value, m_minimumFlow, TargetDripRate); |
342 | m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); | 382 | m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); |
343 | if (Parent != null) | 383 | if (Parent != null) |
344 | Parent.RegisterRequest(this, m_dripRate); | 384 | Parent.RegisterRequest(this, m_dripRate); |
345 | } | 385 | } |
346 | } | 386 | } |
387 | |||
388 | /// <summary> | ||
389 | /// The minimum rate for flow control. Minimum drip rate is one | ||
390 | /// packet per second. Open the throttle to 15 packets per second | ||
391 | /// or about 160kbps. | ||
392 | /// </summary> | ||
393 | protected const Int64 m_minimumFlow = m_minimumDripRate * 15; | ||
347 | 394 | ||
348 | public AdaptiveTokenBucket(string identifier, TokenBucket parent, Int64 maxDripRate, bool enabled) | 395 | public AdaptiveTokenBucket(string identifier, TokenBucket parent, Int64 dripRate, Int64 maxDripRate, bool enabled) |
349 | : base(identifier, parent, maxDripRate) | 396 | : base(identifier, parent, dripRate, maxDripRate) |
350 | { | 397 | { |
351 | Enabled = enabled; | 398 | AdaptiveEnabled = enabled; |
352 | 399 | ||
353 | if (Enabled) | 400 | if (AdaptiveEnabled) |
354 | { | 401 | { |
355 | // m_log.DebugFormat("[TOKENBUCKET]: Adaptive throttle enabled"); | 402 | // m_log.DebugFormat("[TOKENBUCKET]: Adaptive throttle enabled"); |
356 | MaxDripRate = maxDripRate; | ||
357 | AdjustedDripRate = m_minimumFlow; | 403 | AdjustedDripRate = m_minimumFlow; |
358 | } | 404 | } |
359 | } | 405 | } |
360 | 406 | ||
361 | // <summary> | 407 | // <summary> |
362 | // | 408 | // Reliable packets sent to the client for which we never received an ack adjust the drip rate down. |
363 | // </summary> | 409 | // </summary> |
364 | public void ExpirePackets(Int32 count) | 410 | public void ExpirePackets(Int32 count) |
365 | { | 411 | { |
366 | if (Enabled) | 412 | if (AdaptiveEnabled) |
367 | { | 413 | { |
368 | if (DebugLevel > 0) | 414 | if (DebugLevel > 0) |
369 | m_log.WarnFormat( | 415 | m_log.WarnFormat( |
@@ -375,12 +421,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
375 | } | 421 | } |
376 | 422 | ||
377 | // <summary> | 423 | // <summary> |
378 | // | 424 | // Reliable packets acked by the client adjust the drip rate up. |
379 | // </summary> | 425 | // </summary> |
380 | public void AcknowledgePackets(Int32 count) | 426 | public void AcknowledgePackets(Int32 count) |
381 | { | 427 | { |
382 | if (Enabled) | 428 | if (AdaptiveEnabled) |
383 | AdjustedDripRate = AdjustedDripRate + count; | 429 | AdjustedDripRate = AdjustedDripRate + count; |
384 | } | 430 | } |
385 | } | 431 | } |
386 | } | 432 | } \ No newline at end of file |