aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP
diff options
context:
space:
mode:
authorJohn Hurliman2009-10-14 16:21:48 -0700
committerJohn Hurliman2009-10-14 16:21:48 -0700
commit82012ec4e3c441021795c66112a66e002d459e73 (patch)
treee14187ec631f08cb56e0c5da3a28aa8cb727b378 /OpenSim/Region/ClientStack/LindenUDP
parent* Switched to a plain lock for the ClientManager collections and protected th... (diff)
downloadopensim-SC-82012ec4e3c441021795c66112a66e002d459e73.zip
opensim-SC-82012ec4e3c441021795c66112a66e002d459e73.tar.gz
opensim-SC-82012ec4e3c441021795c66112a66e002d459e73.tar.bz2
opensim-SC-82012ec4e3c441021795c66112a66e002d459e73.tar.xz
* Clean up the SetThrottle() code and add a maxBurstRate parameter to allow more tweaking in the future
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs188
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs1
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs63
3 files changed, 155 insertions, 97 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 39472cb..4eee6b6 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -31,6 +31,7 @@ using System.Net;
31using log4net; 31using log4net;
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.Packets;
34 35
35namespace OpenSim.Region.ClientStack.LindenUDP 36namespace OpenSim.Region.ClientStack.LindenUDP
36{ 37{
@@ -60,13 +61,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
60 /// </summary> 61 /// </summary>
61 public sealed class LLUDPClient 62 public sealed class LLUDPClient
62 { 63 {
63 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 64 // TODO: Make this a config setting
64
65 // FIXME: Make this a config setting
66 /// <summary>Percentage of the task throttle category that is allocated to avatar and prim 65 /// <summary>Percentage of the task throttle category that is allocated to avatar and prim
67 /// state updates</summary> 66 /// state updates</summary>
68 const float STATE_TASK_PERCENTAGE = 0.8f; 67 const float STATE_TASK_PERCENTAGE = 0.8f;
69 68
69 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
70
70 /// <summary>The number of packet categories to throttle on. If a throttle category is added 71 /// <summary>The number of packet categories to throttle on. If a throttle category is added
71 /// or removed, this number must also change</summary> 72 /// or removed, this number must also change</summary>
72 const int THROTTLE_CATEGORY_COUNT = 8; 73 const int THROTTLE_CATEGORY_COUNT = 8;
@@ -129,21 +130,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
129 private int m_packetsSentReported; 130 private int m_packetsSentReported;
130 131
131 /// <summary>Throttle bucket for this agent's connection</summary> 132 /// <summary>Throttle bucket for this agent's connection</summary>
132 private readonly TokenBucket throttle; 133 private readonly TokenBucket m_throttle;
133 /// <summary>Throttle buckets for each packet category</summary> 134 /// <summary>Throttle buckets for each packet category</summary>
134 private readonly TokenBucket[] throttleCategories; 135 private readonly TokenBucket[] m_throttleCategories;
135 /// <summary>Throttle rate defaults and limits</summary> 136 /// <summary>Throttle rate defaults and limits</summary>
136 private readonly ThrottleRates defaultThrottleRates; 137 private readonly ThrottleRates m_defaultThrottleRates;
137 /// <summary>Outgoing queues for throttled packets</summary> 138 /// <summary>Outgoing queues for throttled packets</summary>
138 private readonly OpenSim.Framework.LocklessQueue<OutgoingPacket>[] packetOutboxes = new OpenSim.Framework.LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT]; 139 private readonly OpenSim.Framework.LocklessQueue<OutgoingPacket>[] m_packetOutboxes = new OpenSim.Framework.LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT];
139 /// <summary>A container that can hold one packet for each outbox, used to store 140 /// <summary>A container that can hold one packet for each outbox, used to store
140 /// dequeued packets that are being held for throttling</summary> 141 /// dequeued packets that are being held for throttling</summary>
141 private readonly OutgoingPacket[] nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; 142 private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT];
142 /// <summary>Flags to prevent queue empty callbacks from stacking up on 143 /// <summary>Flags to prevent queue empty callbacks from stacking up on
143 /// top of each other</summary> 144 /// top of each other</summary>
144 private readonly bool[] onQueueEmptyRunning = new bool[THROTTLE_CATEGORY_COUNT]; 145 private readonly bool[] m_onQueueEmptyRunning = new bool[THROTTLE_CATEGORY_COUNT];
145 /// <summary>A reference to the LLUDPServer that is managing this client</summary> 146 /// <summary>A reference to the LLUDPServer that is managing this client</summary>
146 private readonly LLUDPServer udpServer; 147 private readonly LLUDPServer m_udpServer;
147 148
148 /// <summary> 149 /// <summary>
149 /// Default constructor 150 /// Default constructor
@@ -157,27 +158,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
157 /// <param name="remoteEndPoint">Remote endpoint for this connection</param> 158 /// <param name="remoteEndPoint">Remote endpoint for this connection</param>
158 public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint) 159 public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint)
159 { 160 {
160 udpServer = server;
161 AgentID = agentID; 161 AgentID = agentID;
162 RemoteEndPoint = remoteEndPoint; 162 RemoteEndPoint = remoteEndPoint;
163 CircuitCode = circuitCode; 163 CircuitCode = circuitCode;
164 defaultThrottleRates = rates; 164 m_udpServer = server;
165 m_defaultThrottleRates = rates;
166 m_throttle = new TokenBucket(parentThrottle, rates.TotalLimit, rates.Total);
167 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
165 168
166 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 169 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
167 packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); 170 {
168 171 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
169 throttle = new TokenBucket(parentThrottle, rates.TotalLimit, rates.Total); 172
170 throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 173 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
171 throttleCategories[(int)ThrottleOutPacketType.Resend] = new TokenBucket(throttle, rates.ResendLimit, rates.Resend); 174 m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type));
172 throttleCategories[(int)ThrottleOutPacketType.Land] = new TokenBucket(throttle, rates.LandLimit, rates.Land); 175 }
173 throttleCategories[(int)ThrottleOutPacketType.Wind] = new TokenBucket(throttle, rates.WindLimit, rates.Wind);
174 throttleCategories[(int)ThrottleOutPacketType.Cloud] = new TokenBucket(throttle, rates.CloudLimit, rates.Cloud);
175 throttleCategories[(int)ThrottleOutPacketType.Texture] = new TokenBucket(throttle, rates.TextureLimit, rates.Texture);
176 throttleCategories[(int)ThrottleOutPacketType.Asset] = new TokenBucket(throttle, rates.AssetLimit, rates.Asset);
177 // State and Transaction are actually sub-categories of the LLUDP generic "Task" category
178 TokenBucket stateBucket = new TokenBucket(throttle, (int)((float)rates.TaskLimit * STATE_TASK_PERCENTAGE), (int)((float)rates.Task * STATE_TASK_PERCENTAGE));
179 throttleCategories[(int)ThrottleOutPacketType.State] = stateBucket;
180 throttleCategories[(int)ThrottleOutPacketType.Task] = new TokenBucket(throttle, rates.TaskLimit - stateBucket.MaxBurst, rates.Task - stateBucket.DripRate);
181 176
182 // Set the granularity variable used for retransmission calculations to 177 // Set the granularity variable used for retransmission calculations to
183 // the measured resolution of Environment.TickCount 178 // the measured resolution of Environment.TickCount
@@ -199,8 +194,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
199 NeedAcks.Clear(); 194 NeedAcks.Clear();
200 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 195 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
201 { 196 {
202 packetOutboxes[i].Clear(); 197 m_packetOutboxes[i].Clear();
203 nextPackets[i] = null; 198 m_nextPackets[i] = null;
204 } 199 }
205 OnPacketStats = null; 200 OnPacketStats = null;
206 OnQueueEmpty = null; 201 OnQueueEmpty = null;
@@ -219,13 +214,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
219 info.pendingAcks = new Dictionary<uint, uint>(); 214 info.pendingAcks = new Dictionary<uint, uint>();
220 info.needAck = new Dictionary<uint, byte[]>(); 215 info.needAck = new Dictionary<uint, byte[]>();
221 216
222 info.resendThrottle = throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate; 217 info.resendThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate;
223 info.landThrottle = throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; 218 info.landThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
224 info.windThrottle = throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; 219 info.windThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
225 info.cloudThrottle = throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; 220 info.cloudThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
226 info.taskThrottle = throttleCategories[(int)ThrottleOutPacketType.State].DripRate + throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; 221 info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
227 info.assetThrottle = throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; 222 info.assetThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
228 info.textureThrottle = throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; 223 info.textureThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
229 info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + 224 info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle +
230 info.taskThrottle + info.assetThrottle + info.textureThrottle; 225 info.taskThrottle + info.assetThrottle + info.textureThrottle;
231 226
@@ -286,6 +281,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
286 adjData = throttleData; 281 adjData = throttleData;
287 } 282 }
288 283
284 // 0.125f converts from bits to bytes
289 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 285 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
290 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 286 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
291 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 287 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
@@ -293,22 +289,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
293 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 289 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
294 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 290 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
295 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); 291 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
292 // State is a subcategory of task that we allocate a percentage to
293 int state = (int)((float)task * STATE_TASK_PERCENTAGE);
294 task -= state;
296 295
297 resend = (resend <= defaultThrottleRates.ResendLimit) ? resend : defaultThrottleRates.ResendLimit; 296 int ceiling = Int32.MaxValue;
298 land = (land <= defaultThrottleRates.LandLimit) ? land : defaultThrottleRates.LandLimit; 297 if (m_defaultThrottleRates.Total != 0)
299 wind = (wind <= defaultThrottleRates.WindLimit) ? wind : defaultThrottleRates.WindLimit; 298 {
300 cloud = (cloud <= defaultThrottleRates.CloudLimit) ? cloud : defaultThrottleRates.CloudLimit; 299 ceiling = m_defaultThrottleRates.Total;
301 task = (task <= defaultThrottleRates.TaskLimit) ? task : defaultThrottleRates.TaskLimit; 300 if (ceiling < Packet.MTU) ceiling = Packet.MTU;
302 texture = (texture <= defaultThrottleRates.TextureLimit) ? texture : defaultThrottleRates.TextureLimit; 301 }
303 asset = (asset <= defaultThrottleRates.AssetLimit) ? asset : defaultThrottleRates.AssetLimit; 302
304 303 resend = Utils.Clamp(resend, Packet.MTU, ceiling);
305 SetThrottle(ThrottleOutPacketType.Resend, resend); 304 land = Utils.Clamp(land, Packet.MTU, ceiling);
306 SetThrottle(ThrottleOutPacketType.Land, land); 305 wind = Utils.Clamp(wind, Packet.MTU, ceiling);
307 SetThrottle(ThrottleOutPacketType.Wind, wind); 306 cloud = Utils.Clamp(cloud, Packet.MTU, ceiling);
308 SetThrottle(ThrottleOutPacketType.Cloud, cloud); 307 task = Utils.Clamp(task, Packet.MTU, ceiling);
309 SetThrottle(ThrottleOutPacketType.Task, task); 308 texture = Utils.Clamp(texture, Packet.MTU, ceiling);
310 SetThrottle(ThrottleOutPacketType.Texture, texture); 309 asset = Utils.Clamp(asset, Packet.MTU, ceiling);
311 SetThrottle(ThrottleOutPacketType.Asset, asset); 310 state = Utils.Clamp(state, Packet.MTU, ceiling);
311
312 int total = resend + land + wind + cloud + task + texture + asset + state;
313 int taskTotal = task + state;
314
315 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}",
316 AgentID, resend, land, wind, cloud, task, texture, asset, state, total);
317
318 SetThrottle(ThrottleOutPacketType.Resend, resend, resend);
319 SetThrottle(ThrottleOutPacketType.Land, land, land);
320 SetThrottle(ThrottleOutPacketType.Wind, wind, wind);
321 SetThrottle(ThrottleOutPacketType.Cloud, cloud, cloud);
322 SetThrottle(ThrottleOutPacketType.Task, task, taskTotal);
323 SetThrottle(ThrottleOutPacketType.Texture, texture, texture);
324 SetThrottle(ThrottleOutPacketType.Asset, asset, asset);
325 SetThrottle(ThrottleOutPacketType.State, state, taskTotal);
312 } 326 }
313 327
314 public byte[] GetThrottlesPacked() 328 public byte[] GetThrottlesPacked()
@@ -316,40 +330,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
316 byte[] data = new byte[7 * 4]; 330 byte[] data = new byte[7 * 4];
317 int i = 0; 331 int i = 0;
318 332
319 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate), 0, data, i, 4); i += 4; 333 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate), 0, data, i, 4); i += 4;
320 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4; 334 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4;
321 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4; 335 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4;
322 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4; 336 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4;
323 Buffer.BlockCopy(Utils.FloatToBytes((float)(throttleCategories[(int)ThrottleOutPacketType.Task].DripRate) + 337 Buffer.BlockCopy(Utils.FloatToBytes((float)(m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate) +
324 throttleCategories[(int)ThrottleOutPacketType.State].DripRate), 0, data, i, 4); i += 4; 338 m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate), 0, data, i, 4); i += 4;
325 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4; 339 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4;
326 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4; 340 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4;
327 341
328 return data; 342 return data;
329 } 343 }
330 344
331 public void SetThrottle(ThrottleOutPacketType category, int rate) 345 public void SetThrottle(ThrottleOutPacketType category, int rate, int maxBurst)
332 { 346 {
333 if (category == ThrottleOutPacketType.Task) 347 int i = (int)category;
334 { 348 if (i >= 0 && i < m_throttleCategories.Length)
335 TokenBucket stateBucket = throttleCategories[(int)ThrottleOutPacketType.State];
336 TokenBucket taskBucket = throttleCategories[(int)ThrottleOutPacketType.Task];
337
338 stateBucket.MaxBurst = (int)((float)rate * STATE_TASK_PERCENTAGE);
339 stateBucket.DripRate = (int)((float)rate * STATE_TASK_PERCENTAGE);
340
341 taskBucket.MaxBurst = rate - stateBucket.MaxBurst;
342 taskBucket.DripRate = rate - stateBucket.DripRate;
343 }
344 else
345 { 349 {
346 int i = (int)category; 350 TokenBucket bucket = m_throttleCategories[(int)category];
347 if (i >= 0 && i < throttleCategories.Length) 351 bucket.DripRate = rate;
348 { 352 bucket.MaxBurst = maxBurst;
349 TokenBucket bucket = throttleCategories[(int)category];
350 bucket.MaxBurst = rate;
351 bucket.DripRate = rate;
352 }
353 } 353 }
354 } 354 }
355 355
@@ -357,12 +357,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
357 { 357 {
358 int category = (int)packet.Category; 358 int category = (int)packet.Category;
359 359
360 if (category >= 0 && category < packetOutboxes.Length) 360 if (category >= 0 && category < m_packetOutboxes.Length)
361 { 361 {
362 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = packetOutboxes[category]; 362 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
363 TokenBucket bucket = throttleCategories[category]; 363 TokenBucket bucket = m_throttleCategories[category];
364 364
365 if (throttleCategories[category].RemoveTokens(packet.Buffer.DataLength)) 365 if (m_throttleCategories[category].RemoveTokens(packet.Buffer.DataLength))
366 { 366 {
367 // Enough tokens were removed from the bucket, the packet will not be queued 367 // Enough tokens were removed from the bucket, the packet will not be queued
368 return false; 368 return false;
@@ -397,19 +397,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
397 397
398 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 398 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
399 { 399 {
400 bucket = throttleCategories[i]; 400 bucket = m_throttleCategories[i];
401 401
402 if (nextPackets[i] != null) 402 if (m_nextPackets[i] != null)
403 { 403 {
404 // This bucket was empty the last time we tried to send a packet, 404 // This bucket was empty the last time we tried to send a packet,
405 // leaving a dequeued packet still waiting to be sent out. Try to 405 // leaving a dequeued packet still waiting to be sent out. Try to
406 // send it again 406 // send it again
407 OutgoingPacket nextPacket = nextPackets[i]; 407 OutgoingPacket nextPacket = m_nextPackets[i];
408 if (bucket.RemoveTokens(nextPacket.Buffer.DataLength)) 408 if (bucket.RemoveTokens(nextPacket.Buffer.DataLength))
409 { 409 {
410 // Send the packet 410 // Send the packet
411 udpServer.SendPacketFinal(nextPacket); 411 m_udpServer.SendPacketFinal(nextPacket);
412 nextPackets[i] = null; 412 m_nextPackets[i] = null;
413 packetSent = true; 413 packetSent = true;
414 } 414 }
415 } 415 }
@@ -417,7 +417,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
417 { 417 {
418 // No dequeued packet waiting to be sent, try to pull one off 418 // No dequeued packet waiting to be sent, try to pull one off
419 // this queue 419 // this queue
420 queue = packetOutboxes[i]; 420 queue = m_packetOutboxes[i];
421 if (queue.Dequeue(out packet)) 421 if (queue.Dequeue(out packet))
422 { 422 {
423 // A packet was pulled off the queue. See if we have 423 // A packet was pulled off the queue. See if we have
@@ -425,13 +425,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
425 if (bucket.RemoveTokens(packet.Buffer.DataLength)) 425 if (bucket.RemoveTokens(packet.Buffer.DataLength))
426 { 426 {
427 // Send the packet 427 // Send the packet
428 udpServer.SendPacketFinal(packet); 428 m_udpServer.SendPacketFinal(packet);
429 packetSent = true; 429 packetSent = true;
430 } 430 }
431 else 431 else
432 { 432 {
433 // Save the dequeued packet for the next iteration 433 // Save the dequeued packet for the next iteration
434 nextPackets[i] = packet; 434 m_nextPackets[i] = packet;
435 } 435 }
436 436
437 // If the queue is empty after this dequeue, fire the queue 437 // If the queue is empty after this dequeue, fire the queue
@@ -493,7 +493,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
493 /// for</param> 493 /// for</param>
494 private void BeginFireQueueEmpty(int throttleIndex) 494 private void BeginFireQueueEmpty(int throttleIndex)
495 { 495 {
496 if (!onQueueEmptyRunning[throttleIndex]) 496 if (!m_onQueueEmptyRunning[throttleIndex])
497 Util.FireAndForget(FireQueueEmpty, throttleIndex); 497 Util.FireAndForget(FireQueueEmpty, throttleIndex);
498 } 498 }
499 499
@@ -511,12 +511,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
511 511
512 if (callback != null) 512 if (callback != null)
513 { 513 {
514 if (!onQueueEmptyRunning[i]) 514 if (!m_onQueueEmptyRunning[i])
515 { 515 {
516 onQueueEmptyRunning[i] = true; 516 m_onQueueEmptyRunning[i] = true;
517 try { callback(type); } 517 try { callback(type); }
518 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + type + ") threw an exception: " + e.Message, e); } 518 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + type + ") threw an exception: " + e.Message, e); }
519 onQueueEmptyRunning[i] = false; 519 m_onQueueEmptyRunning[i] = false;
520 } 520 }
521 } 521 }
522 } 522 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 09845d6..890f701 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -147,7 +147,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
147 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); 147 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
148 } 148 }
149 149
150 // TODO: Config support for throttling the entire connection
151 m_throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps); 150 m_throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps);
152 m_throttleRates = new ThrottleRates(configSource); 151 m_throttleRates = new ThrottleRates(configSource);
153 } 152 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
index adad4c3..008d827 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using OpenSim.Framework;
29using Nini.Config; 30using Nini.Config;
30 31
31namespace OpenSim.Region.ClientStack.LindenUDP 32namespace OpenSim.Region.ClientStack.LindenUDP
@@ -45,12 +46,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
45 public int Wind; 46 public int Wind;
46 /// <summary>Drip rate for cloud packets</summary> 47 /// <summary>Drip rate for cloud packets</summary>
47 public int Cloud; 48 public int Cloud;
48 /// <summary>Drip rate for task (state and transaction) packets</summary> 49 /// <summary>Drip rate for task packets</summary>
49 public int Task; 50 public int Task;
50 /// <summary>Drip rate for texture packets</summary> 51 /// <summary>Drip rate for texture packets</summary>
51 public int Texture; 52 public int Texture;
52 /// <summary>Drip rate for asset packets</summary> 53 /// <summary>Drip rate for asset packets</summary>
53 public int Asset; 54 public int Asset;
55 /// <summary>Drip rate for state packets</summary>
56 public int State;
54 /// <summary>Drip rate for the parent token bucket</summary> 57 /// <summary>Drip rate for the parent token bucket</summary>
55 public int Total; 58 public int Total;
56 59
@@ -68,6 +71,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
68 public int TextureLimit; 71 public int TextureLimit;
69 /// <summary>Maximum burst rate for asset packets</summary> 72 /// <summary>Maximum burst rate for asset packets</summary>
70 public int AssetLimit; 73 public int AssetLimit;
74 /// <summary>Maximum burst rate for state packets</summary>
75 public int StateLimit;
71 /// <summary>Burst rate for the parent token bucket</summary> 76 /// <summary>Burst rate for the parent token bucket</summary>
72 public int TotalLimit; 77 public int TotalLimit;
73 78
@@ -88,6 +93,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
88 Task = throttleConfig.GetInt("task_default", 500); 93 Task = throttleConfig.GetInt("task_default", 500);
89 Texture = throttleConfig.GetInt("texture_default", 500); 94 Texture = throttleConfig.GetInt("texture_default", 500);
90 Asset = throttleConfig.GetInt("asset_default", 500); 95 Asset = throttleConfig.GetInt("asset_default", 500);
96 State = throttleConfig.GetInt("state_default", 500);
91 97
92 Total = throttleConfig.GetInt("client_throttle_max_bps", 0); 98 Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
93 99
@@ -95,13 +101,66 @@ namespace OpenSim.Region.ClientStack.LindenUDP
95 LandLimit = throttleConfig.GetInt("land_limit", 29750); 101 LandLimit = throttleConfig.GetInt("land_limit", 29750);
96 WindLimit = throttleConfig.GetInt("wind_limit", 18750); 102 WindLimit = throttleConfig.GetInt("wind_limit", 18750);
97 CloudLimit = throttleConfig.GetInt("cloud_limit", 18750); 103 CloudLimit = throttleConfig.GetInt("cloud_limit", 18750);
98 TaskLimit = throttleConfig.GetInt("task_limit", 55750); 104 TaskLimit = throttleConfig.GetInt("task_limit", 18750);
99 TextureLimit = throttleConfig.GetInt("texture_limit", 55750); 105 TextureLimit = throttleConfig.GetInt("texture_limit", 55750);
100 AssetLimit = throttleConfig.GetInt("asset_limit", 27500); 106 AssetLimit = throttleConfig.GetInt("asset_limit", 27500);
107 State = throttleConfig.GetInt("state_limit", 37000);
101 108
102 TotalLimit = throttleConfig.GetInt("client_throttle_max_bps", 0); 109 TotalLimit = throttleConfig.GetInt("client_throttle_max_bps", 0);
103 } 110 }
104 catch (Exception) { } 111 catch (Exception) { }
105 } 112 }
113
114 public int GetRate(ThrottleOutPacketType type)
115 {
116 switch (type)
117 {
118 case ThrottleOutPacketType.Resend:
119 return Resend;
120 case ThrottleOutPacketType.Land:
121 return Land;
122 case ThrottleOutPacketType.Wind:
123 return Wind;
124 case ThrottleOutPacketType.Cloud:
125 return Cloud;
126 case ThrottleOutPacketType.Task:
127 return Task;
128 case ThrottleOutPacketType.Texture:
129 return Texture;
130 case ThrottleOutPacketType.Asset:
131 return Asset;
132 case ThrottleOutPacketType.State:
133 return State;
134 case ThrottleOutPacketType.Unknown:
135 default:
136 return 0;
137 }
138 }
139
140 public int GetLimit(ThrottleOutPacketType type)
141 {
142 switch (type)
143 {
144 case ThrottleOutPacketType.Resend:
145 return ResendLimit;
146 case ThrottleOutPacketType.Land:
147 return LandLimit;
148 case ThrottleOutPacketType.Wind:
149 return WindLimit;
150 case ThrottleOutPacketType.Cloud:
151 return CloudLimit;
152 case ThrottleOutPacketType.Task:
153 return TaskLimit;
154 case ThrottleOutPacketType.Texture:
155 return TextureLimit;
156 case ThrottleOutPacketType.Asset:
157 return AssetLimit;
158 case ThrottleOutPacketType.State:
159 return StateLimit;
160 case ThrottleOutPacketType.Unknown:
161 default:
162 return 0;
163 }
164 }
106 } 165 }
107} 166}