aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs106
1 files changed, 68 insertions, 38 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 0fa074d..01d7122 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -135,7 +135,9 @@ 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_throttle; 138 private readonly TokenBucket m_throttleClient;
139 /// <summary>Throttle bucket for this agent's connection</summary>
140 private readonly TokenBucket m_throttleCategory;
139 /// <summary>Throttle buckets for each packet category</summary> 141 /// <summary>Throttle buckets for each packet category</summary>
140 private readonly TokenBucket[] m_throttleCategories; 142 private readonly TokenBucket[] m_throttleCategories;
141 /// <summary>Outgoing queues for throttled packets</summary> 143 /// <summary>Outgoing queues for throttled packets</summary>
@@ -175,7 +177,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
175 m_maxRTO = maxRTO; 177 m_maxRTO = maxRTO;
176 178
177 // Create a token bucket throttle for this client that has the scene token bucket as a parent 179 // Create a token bucket throttle for this client that has the scene token bucket as a parent
178 m_throttle = new TokenBucket(parentThrottle, rates.TotalLimit, rates.Total); 180 m_throttleClient = new TokenBucket(parentThrottle, rates.TotalLimit);
181 // Create a token bucket throttle for the total categary with the client bucket as a throttle
182 m_throttleCategory = new TokenBucket(m_throttleClient, rates.TotalLimit);
179 // Create an array of token buckets for this clients different throttle categories 183 // Create an array of token buckets for this clients different throttle categories
180 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 184 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
181 185
@@ -186,7 +190,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
186 // Initialize the packet outboxes, where packets sit while they are waiting for tokens 190 // Initialize the packet outboxes, where packets sit while they are waiting for tokens
187 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); 191 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
188 // Initialize the token buckets that control the throttling for each category 192 // Initialize the token buckets that control the throttling for each category
189 m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type)); 193 m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetLimit(type));
190 } 194 }
191 195
192 // Default the retransmission timeout to three seconds 196 // Default the retransmission timeout to three seconds
@@ -207,6 +211,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
207 m_packetOutboxes[i].Clear(); 211 m_packetOutboxes[i].Clear();
208 m_nextPackets[i] = null; 212 m_nextPackets[i] = null;
209 } 213 }
214
215 // pull the throttle out of the scene throttle
216 m_throttleClient.Parent.UnregisterRequest(m_throttleClient);
210 OnPacketStats = null; 217 OnPacketStats = null;
211 OnQueueEmpty = null; 218 OnQueueEmpty = null;
212 } 219 }
@@ -217,6 +224,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
217 /// <returns>Information about the client connection</returns> 224 /// <returns>Information about the client connection</returns>
218 public ClientInfo GetClientInfo() 225 public ClientInfo GetClientInfo()
219 { 226 {
227///<mic>
228 TokenBucket tb;
229
230 tb = m_throttleClient.Parent;
231 m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest,"ROOT");
232
233 tb = m_throttleClient;
234 m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CLIENT");
235
236 tb = m_throttleCategory;
237 m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CATEGORY");
238
239 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
240 {
241 tb = m_throttleCategories[i];
242 m_log.WarnFormat("[TOKENS] {4} <{0}:{1}>: Actual={2},Requested={3}",AgentID,i,tb.DripRate,tb.RequestedDripRate," BUCKET");
243 }
244
245///</mic>
246
220 // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists 247 // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists
221 // of pending and needed ACKs for every client every time some method wants information about 248 // of pending and needed ACKs for every client every time some method wants information about
222 // this connection is a recipe for poor performance 249 // this connection is a recipe for poor performance
@@ -224,13 +251,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
224 info.pendingAcks = new Dictionary<uint, uint>(); 251 info.pendingAcks = new Dictionary<uint, uint>();
225 info.needAck = new Dictionary<uint, byte[]>(); 252 info.needAck = new Dictionary<uint, byte[]>();
226 253
227 info.resendThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate; 254 info.resendThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate;
228 info.landThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; 255 info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
229 info.windThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; 256 info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
230 info.cloudThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; 257 info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
231 info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; 258 // info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
232 info.assetThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; 259 info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
233 info.textureThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; 260 info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
261 info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
234 info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + 262 info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle +
235 info.taskThrottle + info.assetThrottle + info.textureThrottle; 263 info.taskThrottle + info.assetThrottle + info.textureThrottle;
236 264
@@ -318,8 +346,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
318 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 346 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
319 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); 347 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
320 // State is a subcategory of task that we allocate a percentage to 348 // State is a subcategory of task that we allocate a percentage to
321 int state = (int)((float)task * STATE_TASK_PERCENTAGE); 349 int state = 0;
322 task -= state; 350 // int state = (int)((float)task * STATE_TASK_PERCENTAGE);
351 // task -= state;
323 352
324 // Make sure none of the throttles are set below our packet MTU, 353 // Make sure none of the throttles are set below our packet MTU,
325 // otherwise a throttle could become permanently clogged 354 // otherwise a throttle could become permanently clogged
@@ -340,40 +369,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
340 // Update the token buckets with new throttle values 369 // Update the token buckets with new throttle values
341 TokenBucket bucket; 370 TokenBucket bucket;
342 371
343 bucket = m_throttle; 372 bucket = m_throttleCategory;
344 bucket.MaxBurst = total; 373 bucket.RequestedDripRate = total;
345 374
346 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; 375 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
347 bucket.DripRate = resend; 376 bucket.RequestedDripRate = resend;
348 bucket.MaxBurst = resend;
349 377
350 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land]; 378 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land];
351 bucket.DripRate = land; 379 bucket.RequestedDripRate = land;
352 bucket.MaxBurst = land;
353 380
354 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind]; 381 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind];
355 bucket.DripRate = wind; 382 bucket.RequestedDripRate = wind;
356 bucket.MaxBurst = wind;
357 383
358 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud]; 384 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud];
359 bucket.DripRate = cloud; 385 bucket.RequestedDripRate = cloud;
360 bucket.MaxBurst = cloud;
361 386
362 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset]; 387 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset];
363 bucket.DripRate = asset; 388 bucket.RequestedDripRate = asset;
364 bucket.MaxBurst = asset;
365 389
366 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task]; 390 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task];
367 bucket.DripRate = task + state; 391 bucket.RequestedDripRate = task;
368 bucket.MaxBurst = task + state;
369 392
370 bucket = m_throttleCategories[(int)ThrottleOutPacketType.State]; 393 bucket = m_throttleCategories[(int)ThrottleOutPacketType.State];
371 bucket.DripRate = state; 394 bucket.RequestedDripRate = state;
372 bucket.MaxBurst = state;
373 395
374 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture]; 396 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture];
375 bucket.DripRate = texture; 397 bucket.RequestedDripRate = texture;
376 bucket.MaxBurst = texture;
377 398
378 // Reset the packed throttles cached data 399 // Reset the packed throttles cached data
379 m_packedThrottles = null; 400 m_packedThrottles = null;
@@ -388,14 +409,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
388 data = new byte[7 * 4]; 409 data = new byte[7 * 4];
389 int i = 0; 410 int i = 0;
390 411
391 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate), 0, data, i, 4); i += 4; 412 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate), 0, data, i, 4); i += 4;
392 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4; 413 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate), 0, data, i, 4); i += 4;
393 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4; 414 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate), 0, data, i, 4); i += 4;
394 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4; 415 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate), 0, data, i, 4); i += 4;
395 Buffer.BlockCopy(Utils.FloatToBytes((float)(m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate) + 416 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate), 0, data, i, 4); i += 4;
396 m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate), 0, data, i, 4); i += 4; 417 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate), 0, data, i, 4); i += 4;
397 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4; 418 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate), 0, data, i, 4); i += 4;
398 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4;
399 419
400 m_packedThrottles = data; 420 m_packedThrottles = data;
401 } 421 }
@@ -428,6 +448,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
428 448
429 TokenBucket bucket = m_throttleCategories[category]; 449 TokenBucket bucket = m_throttleCategories[category];
430 450
451 // Don't send this packet if there is already a packet waiting in the queue
452 // even if we have the tokens to send it, tokens should go to the already
453 // queued packets
454 if (queue.Count > 0)
455 {
456 queue.Enqueue(packet);
457 return true;
458 }
459
460
431 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength)) 461 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength))
432 { 462 {
433 // Enough tokens were removed from the bucket, the packet will not be queued 463 // Enough tokens were removed from the bucket, the packet will not be queued