diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs | 106 |
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 |