diff options
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs | 47 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 49 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs | 33 |
3 files changed, 111 insertions, 18 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index 9dc9e0d..d8ca343 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs | |||
@@ -82,6 +82,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
82 | /// <remarks>Any level above 0 will turn on logging.</remarks> | 82 | /// <remarks>Any level above 0 will turn on logging.</remarks> |
83 | public int DebugDataOutLevel { get; set; } | 83 | public int DebugDataOutLevel { get; set; } |
84 | 84 | ||
85 | /// <summary> | ||
86 | /// Controls whether information is logged about each outbound packet immediately before it is sent. For debug purposes. | ||
87 | /// </summary> | ||
88 | /// <remarks>Any level above 0 will turn on logging.</remarks> | ||
89 | public int ThrottleDebugLevel | ||
90 | { | ||
91 | get | ||
92 | { | ||
93 | return m_throttleDebugLevel; | ||
94 | } | ||
95 | |||
96 | set | ||
97 | { | ||
98 | m_throttleDebugLevel = value; | ||
99 | m_throttleClient.DebugLevel = m_throttleDebugLevel; | ||
100 | m_throttleCategory.DebugLevel = m_throttleDebugLevel; | ||
101 | foreach (TokenBucket tb in m_throttleCategories) | ||
102 | tb.DebugLevel = m_throttleDebugLevel; | ||
103 | } | ||
104 | } | ||
105 | private int m_throttleDebugLevel; | ||
106 | |||
85 | /// <summary>Fired when updated networking stats are produced for this client</summary> | 107 | /// <summary>Fired when updated networking stats are produced for this client</summary> |
86 | public event PacketStats OnPacketStats; | 108 | public event PacketStats OnPacketStats; |
87 | /// <summary>Fired when the queue for a packet category is empty. This event can be | 109 | /// <summary>Fired when the queue for a packet category is empty. This event can be |
@@ -207,9 +229,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
207 | m_maxRTO = maxRTO; | 229 | m_maxRTO = maxRTO; |
208 | 230 | ||
209 | // Create a token bucket throttle for this client that has the scene token bucket as a parent | 231 | // Create a token bucket throttle for this client that has the scene token bucket as a parent |
210 | m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled); | 232 | m_throttleClient |
233 | = new AdaptiveTokenBucket( | ||
234 | string.Format("adaptive throttle for {0} in {1}", AgentID, server.Scene.Name), | ||
235 | parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled); | ||
236 | |||
211 | // Create a token bucket throttle for the total category with the client bucket as a throttle | 237 | // Create a token bucket throttle for the total category with the client bucket as a throttle |
212 | m_throttleCategory = new TokenBucket(m_throttleClient, 0); | 238 | m_throttleCategory |
239 | = new TokenBucket( | ||
240 | string.Format("total throttle for {0} in {1}", AgentID, server.Scene.Name), | ||
241 | m_throttleClient, 0); | ||
242 | |||
213 | // Create an array of token buckets for this clients different throttle categories | 243 | // Create an array of token buckets for this clients different throttle categories |
214 | m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; | 244 | m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; |
215 | 245 | ||
@@ -221,8 +251,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
221 | 251 | ||
222 | // Initialize the packet outboxes, where packets sit while they are waiting for tokens | 252 | // Initialize the packet outboxes, where packets sit while they are waiting for tokens |
223 | m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); | 253 | m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); |
254 | |||
224 | // Initialize the token buckets that control the throttling for each category | 255 | // Initialize the token buckets that control the throttling for each category |
225 | m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type)); | 256 | m_throttleCategories[i] |
257 | = new TokenBucket( | ||
258 | string.Format("{0} throttle for {1} in {2}", type, AgentID, server.Scene.Name), | ||
259 | m_throttleCategory, rates.GetRate(type)); | ||
226 | } | 260 | } |
227 | 261 | ||
228 | // Default the retransmission timeout to one second | 262 | // Default the retransmission timeout to one second |
@@ -371,8 +405,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
371 | texture = (int)((1 - m_cannibalrate) * texture); | 405 | texture = (int)((1 - m_cannibalrate) * texture); |
372 | 406 | ||
373 | //int total = resend + land + wind + cloud + task + texture + asset; | 407 | //int total = resend + land + wind + cloud + task + texture + asset; |
374 | //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", | 408 | |
375 | // AgentID, resend, land, wind, cloud, task, texture, asset, total); | 409 | if (ThrottleDebugLevel > 0) |
410 | m_log.DebugFormat( | ||
411 | "[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}", | ||
412 | AgentID, m_udpServer.Scene.Name, resend, land, wind, cloud, task, texture, asset); | ||
376 | 413 | ||
377 | // Update the token buckets with new throttle values | 414 | // Update the token buckets with new throttle values |
378 | TokenBucket bucket; | 415 | TokenBucket bucket; |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 0393a29..e45de51 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -434,7 +434,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
434 | } | 434 | } |
435 | #endregion BinaryStats | 435 | #endregion BinaryStats |
436 | 436 | ||
437 | m_throttle = new TokenBucket(null, sceneThrottleBps); | 437 | // FIXME: Can't add info here because don't know scene yet. |
438 | // m_throttle | ||
439 | // = new TokenBucket( | ||
440 | // string.Format("server throttle bucket for {0}", Scene.Name), null, sceneThrottleBps); | ||
441 | |||
442 | m_throttle = new TokenBucket("server throttle bucket", null, sceneThrottleBps); | ||
443 | |||
438 | ThrottleRates = new ThrottleRates(configSource); | 444 | ThrottleRates = new ThrottleRates(configSource); |
439 | 445 | ||
440 | if (usePools) | 446 | if (usePools) |
@@ -758,6 +764,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
758 | MainConsole.Instance.Commands.AddCommand( | 764 | MainConsole.Instance.Commands.AddCommand( |
759 | "Debug", | 765 | "Debug", |
760 | false, | 766 | false, |
767 | "debug lludp throttle log", | ||
768 | "debug lludp throttle log <level> <avatar-first-name> <avatar-last-name>", | ||
769 | "Change debug logging level for throttles.", | ||
770 | "If level >= 0 then throttle debug logging is performed.\n" | ||
771 | + "If level <= 0 then no throttle debug logging is performed.", | ||
772 | HandleThrottleCommand); | ||
773 | |||
774 | MainConsole.Instance.Commands.AddCommand( | ||
775 | "Debug", | ||
776 | false, | ||
761 | "debug lludp toggle agentupdate", | 777 | "debug lludp toggle agentupdate", |
762 | "debug lludp toggle agentupdate", | 778 | "debug lludp toggle agentupdate", |
763 | "Toggle whether agentupdate packets are processed or simply discarded.", | 779 | "Toggle whether agentupdate packets are processed or simply discarded.", |
@@ -795,6 +811,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
795 | }); | 811 | }); |
796 | } | 812 | } |
797 | 813 | ||
814 | private void HandleThrottleCommand(string module, string[] args) | ||
815 | { | ||
816 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene) | ||
817 | return; | ||
818 | |||
819 | if (args.Length != 7) | ||
820 | { | ||
821 | MainConsole.Instance.OutputFormat("Usage: debug lludp throttle log <level> <avatar-first-name> <avatar-last-name>"); | ||
822 | return; | ||
823 | } | ||
824 | |||
825 | int level; | ||
826 | if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out level)) | ||
827 | return; | ||
828 | |||
829 | string firstName = args[5]; | ||
830 | string lastName = args[6]; | ||
831 | |||
832 | Scene.ForEachScenePresence(sp => | ||
833 | { | ||
834 | if (sp.Firstname == firstName && sp.Lastname == lastName) | ||
835 | { | ||
836 | MainConsole.Instance.OutputFormat( | ||
837 | "Throttle log level for {0} ({1}) set to {2} in {3}", | ||
838 | sp.Name, sp.IsChildAgent ? "child" : "root", level, Scene.Name); | ||
839 | |||
840 | ((LLClientView)sp.ControllingClient).UDPClient.ThrottleDebugLevel = level; | ||
841 | } | ||
842 | }); | ||
843 | } | ||
844 | |||
798 | private void HandlePacketCommand(string module, string[] args) | 845 | private void HandlePacketCommand(string module, string[] args) |
799 | { | 846 | { |
800 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene) | 847 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene) |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs index 0d4f549..658d9bb 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs | |||
@@ -43,8 +43,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
43 | { | 43 | { |
44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
45 | private static Int32 m_counter = 0; | 45 | private static Int32 m_counter = 0; |
46 | 46 | ||
47 | // private Int32 m_identifier; | 47 | private LLUDPClient m_client; |
48 | |||
49 | public string Identifier { get; private set; } | ||
50 | |||
51 | public int DebugLevel { get; set; } | ||
48 | 52 | ||
49 | /// <summary> | 53 | /// <summary> |
50 | /// Number of ticks (ms) per quantum, drip rate and max burst | 54 | /// Number of ticks (ms) per quantum, drip rate and max burst |
@@ -165,16 +169,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
165 | /// <summary> | 169 | /// <summary> |
166 | /// Default constructor | 170 | /// Default constructor |
167 | /// </summary> | 171 | /// </summary> |
172 | /// <param name="identifier">Identifier for this token bucket</param> | ||
168 | /// <param name="parent">Parent bucket if this is a child bucket, or | 173 | /// <param name="parent">Parent bucket if this is a child bucket, or |
169 | /// null if this is a root bucket</param> | 174 | /// null if this is a root bucket</param> |
170 | /// <param name="maxBurst">Maximum size of the bucket in bytes, or | ||
171 | /// zero if this bucket has no maximum capacity</param> | ||
172 | /// <param name="dripRate">Rate that the bucket fills, in bytes per | 175 | /// <param name="dripRate">Rate that the bucket fills, in bytes per |
173 | /// second. If zero, the bucket always remains full</param> | 176 | /// second. If zero, the bucket always remains full</param> |
174 | public TokenBucket(TokenBucket parent, Int64 dripRate) | 177 | public TokenBucket(string identifier, TokenBucket parent, Int64 dripRate) |
175 | { | 178 | { |
176 | // m_identifier = m_counter++; | 179 | Identifier = identifier; |
177 | m_counter++; | ||
178 | 180 | ||
179 | Parent = parent; | 181 | Parent = parent; |
180 | RequestedDripRate = dripRate; | 182 | RequestedDripRate = dripRate; |
@@ -301,7 +303,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
301 | // with no drip rate... | 303 | // with no drip rate... |
302 | if (DripRate == 0) | 304 | if (DripRate == 0) |
303 | { | 305 | { |
304 | m_log.WarnFormat("[TOKENBUCKET] something odd is happening and drip rate is 0"); | 306 | m_log.WarnFormat("[TOKENBUCKET] something odd is happening and drip rate is 0 for {0}", Identifier); |
305 | return; | 307 | return; |
306 | } | 308 | } |
307 | 309 | ||
@@ -321,7 +323,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
321 | 323 | ||
322 | public class AdaptiveTokenBucket : TokenBucket | 324 | public class AdaptiveTokenBucket : TokenBucket |
323 | { | 325 | { |
324 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 326 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
325 | 327 | ||
326 | /// <summary> | 328 | /// <summary> |
327 | /// The minimum rate for flow control. Minimum drip rate is one | 329 | /// The minimum rate for flow control. Minimum drip rate is one |
@@ -360,13 +362,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
360 | // <summary> | 362 | // <summary> |
361 | // | 363 | // |
362 | // </summary> | 364 | // </summary> |
363 | public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate, bool enabled) : base(parent,maxDripRate) | 365 | public AdaptiveTokenBucket(string identifier, TokenBucket parent, Int64 maxDripRate, bool enabled) |
366 | : base(identifier, parent, maxDripRate) | ||
364 | { | 367 | { |
365 | Enabled = enabled; | 368 | Enabled = enabled; |
366 | 369 | ||
367 | if (Enabled) | 370 | if (Enabled) |
368 | { | 371 | { |
369 | // m_log.DebugFormat("[TOKENBUCKET] Adaptive throttle enabled"); | 372 | // m_log.DebugFormat("[TOKENBUCKET]: Adaptive throttle enabled"); |
370 | MaxDripRate = maxDripRate; | 373 | MaxDripRate = maxDripRate; |
371 | AdjustedDripRate = m_minimumFlow; | 374 | AdjustedDripRate = m_minimumFlow; |
372 | } | 375 | } |
@@ -377,9 +380,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
377 | // </summary> | 380 | // </summary> |
378 | public void ExpirePackets(Int32 count) | 381 | public void ExpirePackets(Int32 count) |
379 | { | 382 | { |
380 | // m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count); | ||
381 | if (Enabled) | 383 | if (Enabled) |
384 | { | ||
385 | if (DebugLevel > 0) | ||
386 | m_log.WarnFormat( | ||
387 | "[ADAPTIVEBUCKET] drop {0} by {1} expired packets for {2}", | ||
388 | AdjustedDripRate, count, Identifier); | ||
389 | |||
382 | AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count)); | 390 | AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count)); |
391 | } | ||
383 | } | 392 | } |
384 | 393 | ||
385 | // <summary> | 394 | // <summary> |