diff options
Diffstat (limited to 'OpenSim/Region/ClientStack')
6 files changed, 162 insertions, 152 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index cd438d6..910fb76 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |||
@@ -395,6 +395,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
395 | public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } | 395 | public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } |
396 | 396 | ||
397 | /// <summary> | 397 | /// <summary> |
398 | /// Entity update queues | ||
399 | /// </summary> | ||
400 | public PriorityQueue EntityUpdateQueue { get { return m_entityUpdates; } } | ||
401 | |||
402 | /// <summary> | ||
398 | /// First name of the agent/avatar represented by the client | 403 | /// First name of the agent/avatar represented by the client |
399 | /// </summary> | 404 | /// </summary> |
400 | public string FirstName { get { return m_firstName; } } | 405 | public string FirstName { get { return m_firstName; } } |
@@ -3625,7 +3630,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3625 | // Remove the update packet from the list of packets waiting for acknowledgement | 3630 | // Remove the update packet from the list of packets waiting for acknowledgement |
3626 | // because we are requeuing the list of updates. They will be resent in new packets | 3631 | // because we are requeuing the list of updates. They will be resent in new packets |
3627 | // with the most recent state and priority. | 3632 | // with the most recent state and priority. |
3628 | m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber, 0, true); | 3633 | m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); |
3634 | |||
3635 | // Count this as a resent packet since we are going to requeue all of the updates contained in it | ||
3636 | Interlocked.Increment(ref m_udpClient.PacketsResent); | ||
3637 | |||
3629 | foreach (EntityUpdate update in updates) | 3638 | foreach (EntityUpdate update in updates) |
3630 | ResendPrimUpdate(update); | 3639 | ResendPrimUpdate(update); |
3631 | } | 3640 | } |
@@ -4092,7 +4101,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4092 | // Remove the update packet from the list of packets waiting for acknowledgement | 4101 | // Remove the update packet from the list of packets waiting for acknowledgement |
4093 | // because we are requeuing the list of updates. They will be resent in new packets | 4102 | // because we are requeuing the list of updates. They will be resent in new packets |
4094 | // with the most recent state. | 4103 | // with the most recent state. |
4095 | m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber, 0, true); | 4104 | m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); |
4105 | |||
4106 | // Count this as a resent packet since we are going to requeue all of the updates contained in it | ||
4107 | Interlocked.Increment(ref m_udpClient.PacketsResent); | ||
4108 | |||
4096 | foreach (ObjectPropertyUpdate update in updates) | 4109 | foreach (ObjectPropertyUpdate update in updates) |
4097 | ResendPropertyUpdate(update); | 4110 | ResendPropertyUpdate(update); |
4098 | } | 4111 | } |
@@ -4897,7 +4910,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4897 | data.RelativePosition.ToBytes(objectData, 0); | 4910 | data.RelativePosition.ToBytes(objectData, 0); |
4898 | data.Velocity.ToBytes(objectData, 12); | 4911 | data.Velocity.ToBytes(objectData, 12); |
4899 | data.Acceleration.ToBytes(objectData, 24); | 4912 | data.Acceleration.ToBytes(objectData, 24); |
4900 | data.RotationOffset.ToBytes(objectData, 36); | 4913 | try |
4914 | { | ||
4915 | data.RotationOffset.ToBytes(objectData, 36); | ||
4916 | } | ||
4917 | catch (Exception e) | ||
4918 | { | ||
4919 | m_log.Warn("[LLClientView]: exception converting quaternion to bytes, using Quaternion.Identity. Exception: " + e.ToString()); | ||
4920 | OpenMetaverse.Quaternion.Identity.ToBytes(objectData, 36); | ||
4921 | } | ||
4901 | data.AngularVelocity.ToBytes(objectData, 48); | 4922 | data.AngularVelocity.ToBytes(objectData, 48); |
4902 | 4923 | ||
4903 | ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); | 4924 | ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); |
@@ -11513,7 +11534,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11513 | /// <returns></returns> | 11534 | /// <returns></returns> |
11514 | public byte[] GetThrottlesPacked(float multiplier) | 11535 | public byte[] GetThrottlesPacked(float multiplier) |
11515 | { | 11536 | { |
11516 | return m_udpClient.GetThrottlesPacked(); | 11537 | return m_udpClient.GetThrottlesPacked(multiplier); |
11517 | } | 11538 | } |
11518 | 11539 | ||
11519 | /// <summary> | 11540 | /// <summary> |
@@ -11706,7 +11727,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11706 | 11727 | ||
11707 | info.userEP = m_userEndPoint; | 11728 | info.userEP = m_userEndPoint; |
11708 | info.proxyEP = null; | 11729 | info.proxyEP = null; |
11709 | info.agentcircuit = new sAgentCircuitData(RequestClientInfo()); | 11730 | info.agentcircuit = RequestClientInfo(); |
11710 | 11731 | ||
11711 | return info; | 11732 | return info; |
11712 | } | 11733 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index e54d326..95a8e23 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs | |||
@@ -182,9 +182,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
182 | m_maxRTO = maxRTO; | 182 | m_maxRTO = maxRTO; |
183 | 183 | ||
184 | // Create a token bucket throttle for this client that has the scene token bucket as a parent | 184 | // Create a token bucket throttle for this client that has the scene token bucket as a parent |
185 | m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.TotalLimit); | 185 | m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled); |
186 | // Create a token bucket throttle for the total categary with the client bucket as a throttle | 186 | // Create a token bucket throttle for the total categary with the client bucket as a throttle |
187 | m_throttleCategory = new TokenBucket(m_throttleClient, rates.TotalLimit); | 187 | m_throttleCategory = new TokenBucket(m_throttleClient, 0); |
188 | // Create an array of token buckets for this clients different throttle categories | 188 | // Create an array of token buckets for this clients different throttle categories |
189 | m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; | 189 | m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; |
190 | 190 | ||
@@ -195,7 +195,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
195 | // Initialize the packet outboxes, where packets sit while they are waiting for tokens | 195 | // Initialize the packet outboxes, where packets sit while they are waiting for tokens |
196 | m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); | 196 | m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); |
197 | // Initialize the token buckets that control the throttling for each category | 197 | // Initialize the token buckets that control the throttling for each category |
198 | m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetLimit(type)); | 198 | m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type)); |
199 | } | 199 | } |
200 | 200 | ||
201 | // Default the retransmission timeout to three seconds | 201 | // Default the retransmission timeout to three seconds |
@@ -229,26 +229,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
229 | /// <returns>Information about the client connection</returns> | 229 | /// <returns>Information about the client connection</returns> |
230 | public ClientInfo GetClientInfo() | 230 | public ClientInfo GetClientInfo() |
231 | { | 231 | { |
232 | ///<mic> | ||
233 | TokenBucket tb; | ||
234 | |||
235 | tb = m_throttleClient.Parent; | ||
236 | m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest,"ROOT"); | ||
237 | |||
238 | tb = m_throttleClient; | ||
239 | m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CLIENT"); | ||
240 | |||
241 | tb = m_throttleCategory; | ||
242 | m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CATEGORY"); | ||
243 | |||
244 | for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) | ||
245 | { | ||
246 | tb = m_throttleCategories[i]; | ||
247 | m_log.WarnFormat("[TOKENS] {4} <{0}:{1}>: Actual={2},Requested={3}",AgentID,i,tb.DripRate,tb.RequestedDripRate," BUCKET"); | ||
248 | } | ||
249 | |||
250 | ///</mic> | ||
251 | |||
252 | // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists | 232 | // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists |
253 | // of pending and needed ACKs for every client every time some method wants information about | 233 | // of pending and needed ACKs for every client every time some method wants information about |
254 | // this connection is a recipe for poor performance | 234 | // this connection is a recipe for poor performance |
@@ -260,12 +240,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
260 | info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; | 240 | info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; |
261 | info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; | 241 | info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; |
262 | info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; | 242 | info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; |
263 | // info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; | ||
264 | info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; | 243 | info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; |
265 | info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; | 244 | info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; |
266 | info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; | 245 | info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; |
267 | info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + | 246 | info.totalThrottle = (int)m_throttleCategory.DripRate; |
268 | info.taskThrottle + info.assetThrottle + info.textureThrottle; | ||
269 | 247 | ||
270 | return info; | 248 | return info; |
271 | } | 249 | } |
@@ -352,8 +330,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
352 | int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); | 330 | int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); |
353 | // State is a subcategory of task that we allocate a percentage to | 331 | // State is a subcategory of task that we allocate a percentage to |
354 | int state = 0; | 332 | int state = 0; |
355 | // int state = (int)((float)task * STATE_TASK_PERCENTAGE); | ||
356 | // task -= state; | ||
357 | 333 | ||
358 | // Make sure none of the throttles are set below our packet MTU, | 334 | // Make sure none of the throttles are set below our packet MTU, |
359 | // otherwise a throttle could become permanently clogged | 335 | // otherwise a throttle could become permanently clogged |
@@ -364,19 +340,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
364 | task = Math.Max(task, LLUDPServer.MTU); | 340 | task = Math.Max(task, LLUDPServer.MTU); |
365 | texture = Math.Max(texture, LLUDPServer.MTU); | 341 | texture = Math.Max(texture, LLUDPServer.MTU); |
366 | asset = Math.Max(asset, LLUDPServer.MTU); | 342 | asset = Math.Max(asset, LLUDPServer.MTU); |
367 | state = Math.Max(state, LLUDPServer.MTU); | ||
368 | 343 | ||
369 | int total = resend + land + wind + cloud + task + texture + asset + state; | 344 | //int total = resend + land + wind + cloud + task + texture + asset; |
370 | 345 | //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", | |
371 | //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}", | 346 | // AgentID, resend, land, wind, cloud, task, texture, asset, total); |
372 | // AgentID, resend, land, wind, cloud, task, texture, asset, state, total); | ||
373 | 347 | ||
374 | // Update the token buckets with new throttle values | 348 | // Update the token buckets with new throttle values |
375 | TokenBucket bucket; | 349 | TokenBucket bucket; |
376 | 350 | ||
377 | bucket = m_throttleCategory; | ||
378 | bucket.RequestedDripRate = total; | ||
379 | |||
380 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; | 351 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; |
381 | bucket.RequestedDripRate = resend; | 352 | bucket.RequestedDripRate = resend; |
382 | 353 | ||
@@ -405,22 +376,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
405 | m_packedThrottles = null; | 376 | m_packedThrottles = null; |
406 | } | 377 | } |
407 | 378 | ||
408 | public byte[] GetThrottlesPacked() | 379 | public byte[] GetThrottlesPacked(float multiplier) |
409 | { | 380 | { |
410 | byte[] data = m_packedThrottles; | 381 | byte[] data = m_packedThrottles; |
411 | 382 | ||
412 | if (data == null) | 383 | if (data == null) |
413 | { | 384 | { |
385 | float rate; | ||
386 | |||
414 | data = new byte[7 * 4]; | 387 | data = new byte[7 * 4]; |
415 | int i = 0; | 388 | int i = 0; |
416 | 389 | ||
417 | Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate), 0, data, i, 4); i += 4; | 390 | // multiply by 8 to convert bytes back to bits |
418 | Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate), 0, data, i, 4); i += 4; | 391 | rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * 8 * multiplier; |
419 | Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate), 0, data, i, 4); i += 4; | 392 | Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; |
420 | Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate), 0, data, i, 4); i += 4; | 393 | |
421 | Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate), 0, data, i, 4); i += 4; | 394 | rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * 8 * multiplier; |
422 | Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate), 0, data, i, 4); i += 4; | 395 | Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; |
423 | Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate), 0, data, i, 4); i += 4; | 396 | |
397 | rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * 8 * multiplier; | ||
398 | Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||
399 | |||
400 | rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * 8 * multiplier; | ||
401 | Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||
402 | |||
403 | rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * 8 * multiplier; | ||
404 | Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||
405 | |||
406 | rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * 8 * multiplier; | ||
407 | Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||
408 | |||
409 | rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * 8 * multiplier; | ||
410 | Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||
424 | 411 | ||
425 | m_packedThrottles = data; | 412 | m_packedThrottles = data; |
426 | } | 413 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index a1a58e5..ab6674d 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | |||
@@ -672,7 +672,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
672 | if (packet.Header.AppendedAcks && packet.Header.AckList != null) | 672 | if (packet.Header.AppendedAcks && packet.Header.AckList != null) |
673 | { | 673 | { |
674 | for (int i = 0; i < packet.Header.AckList.Length; i++) | 674 | for (int i = 0; i < packet.Header.AckList.Length; i++) |
675 | udpClient.NeedAcks.Remove(packet.Header.AckList[i], now, packet.Header.Resent); | 675 | udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); |
676 | } | 676 | } |
677 | 677 | ||
678 | // Handle PacketAck packets | 678 | // Handle PacketAck packets |
@@ -681,7 +681,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
681 | PacketAckPacket ackPacket = (PacketAckPacket)packet; | 681 | PacketAckPacket ackPacket = (PacketAckPacket)packet; |
682 | 682 | ||
683 | for (int i = 0; i < ackPacket.Packets.Length; i++) | 683 | for (int i = 0; i < ackPacket.Packets.Length; i++) |
684 | udpClient.NeedAcks.Remove(ackPacket.Packets[i].ID, now, packet.Header.Resent); | 684 | udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); |
685 | 685 | ||
686 | // We don't need to do anything else with PacketAck packets | 686 | // We don't need to do anything else with PacketAck packets |
687 | return; | 687 | return; |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs index aaf6e26..c9aac0b 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs | |||
@@ -52,30 +52,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
52 | public int Texture; | 52 | public int Texture; |
53 | /// <summary>Drip rate for asset packets</summary> | 53 | /// <summary>Drip rate for asset packets</summary> |
54 | public int Asset; | 54 | public int Asset; |
55 | /// <summary>Drip rate for state packets</summary> | 55 | |
56 | public int State; | ||
57 | /// <summary>Drip rate for the parent token bucket</summary> | 56 | /// <summary>Drip rate for the parent token bucket</summary> |
58 | public int Total; | 57 | public int Total; |
59 | 58 | ||
60 | /// <summary>Maximum burst rate for resent packets</summary> | 59 | /// <summary>Flag used to enable adaptive throttles</summary> |
61 | public int ResendLimit; | 60 | public bool AdaptiveThrottlesEnabled; |
62 | /// <summary>Maximum burst rate for land packets</summary> | 61 | |
63 | public int LandLimit; | ||
64 | /// <summary>Maximum burst rate for wind packets</summary> | ||
65 | public int WindLimit; | ||
66 | /// <summary>Maximum burst rate for cloud packets</summary> | ||
67 | public int CloudLimit; | ||
68 | /// <summary>Maximum burst rate for task (state and transaction) packets</summary> | ||
69 | public int TaskLimit; | ||
70 | /// <summary>Maximum burst rate for texture packets</summary> | ||
71 | public int TextureLimit; | ||
72 | /// <summary>Maximum burst rate for asset packets</summary> | ||
73 | public int AssetLimit; | ||
74 | /// <summary>Maximum burst rate for state packets</summary> | ||
75 | public int StateLimit; | ||
76 | /// <summary>Burst rate for the parent token bucket</summary> | ||
77 | public int TotalLimit; | ||
78 | |||
79 | /// <summary> | 62 | /// <summary> |
80 | /// Default constructor | 63 | /// Default constructor |
81 | /// </summary> | 64 | /// </summary> |
@@ -86,26 +69,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
86 | { | 69 | { |
87 | IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"]; | 70 | IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"]; |
88 | 71 | ||
89 | Resend = throttleConfig.GetInt("resend_default", 12500); | 72 | Resend = throttleConfig.GetInt("resend_default", 6625); |
90 | Land = throttleConfig.GetInt("land_default", 1000); | 73 | Land = throttleConfig.GetInt("land_default", 9125); |
91 | Wind = throttleConfig.GetInt("wind_default", 1000); | 74 | Wind = throttleConfig.GetInt("wind_default", 1750); |
92 | Cloud = throttleConfig.GetInt("cloud_default", 1000); | 75 | Cloud = throttleConfig.GetInt("cloud_default", 1750); |
93 | Task = throttleConfig.GetInt("task_default", 1000); | 76 | Task = throttleConfig.GetInt("task_default", 18500); |
94 | Texture = throttleConfig.GetInt("texture_default", 1000); | 77 | Texture = throttleConfig.GetInt("texture_default", 18500); |
95 | Asset = throttleConfig.GetInt("asset_default", 1000); | 78 | Asset = throttleConfig.GetInt("asset_default", 10500); |
96 | State = throttleConfig.GetInt("state_default", 1000); | ||
97 | |||
98 | ResendLimit = throttleConfig.GetInt("resend_limit", 18750); | ||
99 | LandLimit = throttleConfig.GetInt("land_limit", 29750); | ||
100 | WindLimit = throttleConfig.GetInt("wind_limit", 18750); | ||
101 | CloudLimit = throttleConfig.GetInt("cloud_limit", 18750); | ||
102 | TaskLimit = throttleConfig.GetInt("task_limit", 18750); | ||
103 | TextureLimit = throttleConfig.GetInt("texture_limit", 55750); | ||
104 | AssetLimit = throttleConfig.GetInt("asset_limit", 27500); | ||
105 | StateLimit = throttleConfig.GetInt("state_limit", 37000); | ||
106 | 79 | ||
107 | Total = throttleConfig.GetInt("client_throttle_max_bps", 0); | 80 | Total = throttleConfig.GetInt("client_throttle_max_bps", 0); |
108 | TotalLimit = Total; | 81 | |
82 | AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); | ||
109 | } | 83 | } |
110 | catch (Exception) { } | 84 | catch (Exception) { } |
111 | } | 85 | } |
@@ -128,34 +102,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
128 | return Texture; | 102 | return Texture; |
129 | case ThrottleOutPacketType.Asset: | 103 | case ThrottleOutPacketType.Asset: |
130 | return Asset; | 104 | return Asset; |
131 | case ThrottleOutPacketType.State: | ||
132 | return State; | ||
133 | case ThrottleOutPacketType.Unknown: | ||
134 | default: | ||
135 | return 0; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | public int GetLimit(ThrottleOutPacketType type) | ||
140 | { | ||
141 | switch (type) | ||
142 | { | ||
143 | case ThrottleOutPacketType.Resend: | ||
144 | return ResendLimit; | ||
145 | case ThrottleOutPacketType.Land: | ||
146 | return LandLimit; | ||
147 | case ThrottleOutPacketType.Wind: | ||
148 | return WindLimit; | ||
149 | case ThrottleOutPacketType.Cloud: | ||
150 | return CloudLimit; | ||
151 | case ThrottleOutPacketType.Task: | ||
152 | return TaskLimit; | ||
153 | case ThrottleOutPacketType.Texture: | ||
154 | return TextureLimit; | ||
155 | case ThrottleOutPacketType.Asset: | ||
156 | return AssetLimit; | ||
157 | case ThrottleOutPacketType.State: | ||
158 | return StateLimit; | ||
159 | case ThrottleOutPacketType.Unknown: | 105 | case ThrottleOutPacketType.Unknown: |
160 | default: | 106 | default: |
161 | return 0; | 107 | return 0; |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs index 4ee6d3a..29fd1a4 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs | |||
@@ -29,6 +29,8 @@ using System; | |||
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using OpenSim.Framework; | ||
33 | |||
32 | using log4net; | 34 | using log4net; |
33 | 35 | ||
34 | namespace OpenSim.Region.ClientStack.LindenUDP | 36 | namespace OpenSim.Region.ClientStack.LindenUDP |
@@ -177,7 +179,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
177 | RequestedDripRate = dripRate; | 179 | RequestedDripRate = dripRate; |
178 | // TotalDripRequest = dripRate; // this will be overwritten when a child node registers | 180 | // TotalDripRequest = dripRate; // this will be overwritten when a child node registers |
179 | // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst); | 181 | // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst); |
180 | m_lastDrip = Environment.TickCount & Int32.MaxValue; | 182 | m_lastDrip = Util.EnvironmentTickCount(); |
181 | } | 183 | } |
182 | 184 | ||
183 | #endregion Constructor | 185 | #endregion Constructor |
@@ -211,12 +213,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
211 | /// </summary> | 213 | /// </summary> |
212 | public void RegisterRequest(TokenBucket child, Int64 request) | 214 | public void RegisterRequest(TokenBucket child, Int64 request) |
213 | { | 215 | { |
214 | m_children[child] = request; | 216 | lock (m_children) |
215 | // m_totalDripRequest = m_children.Values.Sum(); | 217 | { |
218 | m_children[child] = request; | ||
219 | // m_totalDripRequest = m_children.Values.Sum(); | ||
216 | 220 | ||
217 | m_totalDripRequest = 0; | 221 | m_totalDripRequest = 0; |
218 | foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) | 222 | foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) |
219 | m_totalDripRequest += cref.Value; | 223 | m_totalDripRequest += cref.Value; |
224 | } | ||
220 | 225 | ||
221 | // Pass the new values up to the parent | 226 | // Pass the new values up to the parent |
222 | if (m_parent != null) | 227 | if (m_parent != null) |
@@ -229,12 +234,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
229 | /// </summary> | 234 | /// </summary> |
230 | public void UnregisterRequest(TokenBucket child) | 235 | public void UnregisterRequest(TokenBucket child) |
231 | { | 236 | { |
232 | m_children.Remove(child); | 237 | lock (m_children) |
233 | // m_totalDripRequest = m_children.Values.Sum(); | 238 | { |
239 | m_children.Remove(child); | ||
240 | // m_totalDripRequest = m_children.Values.Sum(); | ||
234 | 241 | ||
235 | m_totalDripRequest = 0; | 242 | m_totalDripRequest = 0; |
236 | foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) | 243 | foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) |
237 | m_totalDripRequest += cref.Value; | 244 | m_totalDripRequest += cref.Value; |
245 | } | ||
246 | |||
238 | 247 | ||
239 | // Pass the new values up to the parent | 248 | // Pass the new values up to the parent |
240 | if (m_parent != null) | 249 | if (m_parent != null) |
@@ -297,10 +306,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
297 | 306 | ||
298 | // Determine the interval over which we are adding tokens, never add | 307 | // Determine the interval over which we are adding tokens, never add |
299 | // more than a single quantum of tokens | 308 | // more than a single quantum of tokens |
300 | Int32 now = Environment.TickCount & Int32.MaxValue; | 309 | Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum); |
301 | Int32 deltaMS = Math.Min(now - m_lastDrip, m_ticksPerQuantum); | 310 | m_lastDrip = Util.EnvironmentTickCount(); |
302 | |||
303 | m_lastDrip = now; | ||
304 | 311 | ||
305 | // This can be 0 in the very unusual case that the timer wrapped | 312 | // This can be 0 in the very unusual case that the timer wrapped |
306 | // It can be 0 if we try add tokens at a sub-tick rate | 313 | // It can be 0 if we try add tokens at a sub-tick rate |
@@ -315,10 +322,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
315 | { | 322 | { |
316 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 323 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
317 | 324 | ||
318 | // <summary> | 325 | /// <summary> |
319 | // The minimum rate for flow control. | 326 | /// The minimum rate for flow control. Minimum drip rate is one |
320 | // </summary> | 327 | /// packet per second. Open the throttle to 15 packets per second |
321 | protected const Int64 m_minimumFlow = m_minimumDripRate * 10; | 328 | /// or about 160kbps. |
329 | /// </summary> | ||
330 | protected const Int64 m_minimumFlow = m_minimumDripRate * 15; | ||
322 | 331 | ||
323 | // <summary> | 332 | // <summary> |
324 | // The maximum rate for flow control. Drip rate can never be | 333 | // The maximum rate for flow control. Drip rate can never be |
@@ -331,6 +340,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
331 | set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value,m_minimumFlow)); } | 340 | set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value,m_minimumFlow)); } |
332 | } | 341 | } |
333 | 342 | ||
343 | private bool m_enabled = false; | ||
344 | |||
334 | // <summary> | 345 | // <summary> |
335 | // | 346 | // |
336 | // </summary> | 347 | // </summary> |
@@ -348,9 +359,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
348 | // <summary> | 359 | // <summary> |
349 | // | 360 | // |
350 | // </summary> | 361 | // </summary> |
351 | public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate) : base(parent,m_minimumFlow) | 362 | public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate, bool enabled) : base(parent,maxDripRate) |
352 | { | 363 | { |
353 | MaxDripRate = maxDripRate; | 364 | m_enabled = enabled; |
365 | |||
366 | if (m_enabled) | ||
367 | { | ||
368 | // m_log.DebugFormat("[TOKENBUCKET] Adaptive throttle enabled"); | ||
369 | MaxDripRate = maxDripRate; | ||
370 | AdjustedDripRate = m_minimumFlow; | ||
371 | } | ||
354 | } | 372 | } |
355 | 373 | ||
356 | // <summary> | 374 | // <summary> |
@@ -359,7 +377,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
359 | public void ExpirePackets(Int32 count) | 377 | public void ExpirePackets(Int32 count) |
360 | { | 378 | { |
361 | // m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count); | 379 | // m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count); |
362 | AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count)); | 380 | if (m_enabled) |
381 | AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count)); | ||
363 | } | 382 | } |
364 | 383 | ||
365 | // <summary> | 384 | // <summary> |
@@ -367,7 +386,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
367 | // </summary> | 386 | // </summary> |
368 | public void AcknowledgePackets(Int32 count) | 387 | public void AcknowledgePackets(Int32 count) |
369 | { | 388 | { |
370 | AdjustedDripRate = AdjustedDripRate + count; | 389 | if (m_enabled) |
390 | AdjustedDripRate = AdjustedDripRate + count; | ||
371 | } | 391 | } |
372 | } | 392 | } |
373 | } | 393 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs index b170964..793aefe 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs | |||
@@ -65,7 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
65 | /// <summary>Holds packets that need to be added to the unacknowledged list</summary> | 65 | /// <summary>Holds packets that need to be added to the unacknowledged list</summary> |
66 | private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>(); | 66 | private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>(); |
67 | /// <summary>Holds information about pending acknowledgements</summary> | 67 | /// <summary>Holds information about pending acknowledgements</summary> |
68 | private LocklessQueue<PendingAck> m_pendingRemoves = new LocklessQueue<PendingAck>(); | 68 | private LocklessQueue<PendingAck> m_pendingAcknowledgements = new LocklessQueue<PendingAck>(); |
69 | /// <summary>Holds information about pending removals</summary> | ||
70 | private LocklessQueue<uint> m_pendingRemoves = new LocklessQueue<uint>(); | ||
69 | 71 | ||
70 | /// <summary> | 72 | /// <summary> |
71 | /// Add an unacked packet to the collection | 73 | /// Add an unacked packet to the collection |
@@ -83,15 +85,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
83 | 85 | ||
84 | /// <summary> | 86 | /// <summary> |
85 | /// Marks a packet as acknowledged | 87 | /// Marks a packet as acknowledged |
88 | /// This method is used when an acknowledgement is received from the network for a previously | ||
89 | /// sent packet. Effects of removal this way are to update unacked byte count, adjust RTT | ||
90 | /// and increase throttle to the coresponding client. | ||
86 | /// </summary> | 91 | /// </summary> |
87 | /// <param name="sequenceNumber">Sequence number of the packet to | 92 | /// <param name="sequenceNumber">Sequence number of the packet to |
88 | /// acknowledge</param> | 93 | /// acknowledge</param> |
89 | /// <param name="currentTime">Current value of Environment.TickCount</param> | 94 | /// <param name="currentTime">Current value of Environment.TickCount</param> |
90 | /// <remarks>This does not immediately acknowledge the packet, it only | 95 | /// <remarks>This does not immediately acknowledge the packet, it only |
91 | /// queues the ack so it can be handled in a thread-safe way later</remarks> | 96 | /// queues the ack so it can be handled in a thread-safe way later</remarks> |
92 | public void Remove(uint sequenceNumber, int currentTime, bool fromResend) | 97 | public void Acknowledge(uint sequenceNumber, int currentTime, bool fromResend) |
93 | { | 98 | { |
94 | m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend)); | 99 | m_pendingAcknowledgements.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend)); |
100 | } | ||
101 | |||
102 | /// <summary> | ||
103 | /// Marks a packet as no longer needing acknowledgement without a received acknowledgement. | ||
104 | /// This method is called when a packet expires and we no longer need an acknowledgement. | ||
105 | /// When some reliable packet types expire, they are handled in a way other than simply | ||
106 | /// resending them. The only effect of removal this way is to update unacked byte count. | ||
107 | /// </summary> | ||
108 | /// <param name="sequenceNumber">Sequence number of the packet to | ||
109 | /// acknowledge</param> | ||
110 | /// <remarks>The does not immediately remove the packet, it only queues the removal | ||
111 | /// so it can be handled in a thread safe way later</remarks> | ||
112 | public void Remove(uint sequenceNumber) | ||
113 | { | ||
114 | m_pendingRemoves.Enqueue(sequenceNumber); | ||
95 | } | 115 | } |
96 | 116 | ||
97 | /// <summary> | 117 | /// <summary> |
@@ -151,15 +171,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
151 | m_packets[pendingAdd.SequenceNumber] = pendingAdd; | 171 | m_packets[pendingAdd.SequenceNumber] = pendingAdd; |
152 | 172 | ||
153 | // Process all the pending removes, including updating statistics and round-trip times | 173 | // Process all the pending removes, including updating statistics and round-trip times |
154 | PendingAck pendingRemove; | 174 | PendingAck pendingAcknowledgement; |
155 | OutgoingPacket ackedPacket; | 175 | while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement)) |
156 | while (m_pendingRemoves.TryDequeue(out pendingRemove)) | ||
157 | { | 176 | { |
158 | if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) | 177 | OutgoingPacket ackedPacket; |
178 | if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket)) | ||
159 | { | 179 | { |
160 | if (ackedPacket != null) | 180 | if (ackedPacket != null) |
161 | { | 181 | { |
162 | m_packets.Remove(pendingRemove.SequenceNumber); | 182 | m_packets.Remove(pendingAcknowledgement.SequenceNumber); |
163 | 183 | ||
164 | // As with other network applications, assume that an acknowledged packet is an | 184 | // As with other network applications, assume that an acknowledged packet is an |
165 | // indication that the network can handle a little more load, speed up the transmission | 185 | // indication that the network can handle a little more load, speed up the transmission |
@@ -168,16 +188,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
168 | // Update stats | 188 | // Update stats |
169 | Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); | 189 | Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); |
170 | 190 | ||
171 | if (!pendingRemove.FromResend) | 191 | if (!pendingAcknowledgement.FromResend) |
172 | { | 192 | { |
173 | // Calculate the round-trip time for this packet and its ACK | 193 | // Calculate the round-trip time for this packet and its ACK |
174 | int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount; | 194 | int rtt = pendingAcknowledgement.RemoveTime - ackedPacket.TickCount; |
175 | if (rtt > 0) | 195 | if (rtt > 0) |
176 | ackedPacket.Client.UpdateRoundTrip(rtt); | 196 | ackedPacket.Client.UpdateRoundTrip(rtt); |
177 | } | 197 | } |
178 | } | 198 | } |
179 | } | 199 | } |
180 | } | 200 | } |
201 | |||
202 | uint pendingRemove; | ||
203 | while(m_pendingRemoves.TryDequeue(out pendingRemove)) | ||
204 | { | ||
205 | OutgoingPacket removedPacket; | ||
206 | if (m_packets.TryGetValue(pendingRemove, out removedPacket)) | ||
207 | { | ||
208 | if (removedPacket != null) | ||
209 | { | ||
210 | m_packets.Remove(pendingRemove); | ||
211 | |||
212 | // Update stats | ||
213 | Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength); | ||
214 | } | ||
215 | } | ||
216 | } | ||
181 | } | 217 | } |
182 | } | 218 | } |
183 | } \ No newline at end of file | 219 | } |