aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs31
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs75
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs4
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs80
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs66
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs58
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;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using OpenSim.Framework;
33
32using log4net; 34using log4net;
33 35
34namespace OpenSim.Region.ClientStack.LindenUDP 36namespace 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}