diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs | 110 |
1 files changed, 79 insertions, 31 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index e52ac37..bd4e617 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs | |||
@@ -31,6 +31,7 @@ using System.Net; | |||
31 | using System.Threading; | 31 | using System.Threading; |
32 | using log4net; | 32 | using log4net; |
33 | using OpenSim.Framework; | 33 | using OpenSim.Framework; |
34 | using OpenSim.Framework.Monitoring; | ||
34 | using OpenMetaverse; | 35 | using OpenMetaverse; |
35 | using OpenMetaverse.Packets; | 36 | using OpenMetaverse.Packets; |
36 | 37 | ||
@@ -81,6 +82,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
81 | /// hooked to put more data on the empty queue</summary> | 82 | /// hooked to put more data on the empty queue</summary> |
82 | public event QueueEmpty OnQueueEmpty; | 83 | public event QueueEmpty OnQueueEmpty; |
83 | 84 | ||
85 | public event Func<ThrottleOutPacketTypeFlags, bool> HasUpdates; | ||
86 | |||
84 | /// <summary>AgentID for this client</summary> | 87 | /// <summary>AgentID for this client</summary> |
85 | public readonly UUID AgentID; | 88 | public readonly UUID AgentID; |
86 | /// <summary>The remote address of the connected client</summary> | 89 | /// <summary>The remote address of the connected client</summary> |
@@ -161,6 +164,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
161 | public bool m_deliverPackets = true; | 164 | public bool m_deliverPackets = true; |
162 | 165 | ||
163 | /// <summary> | 166 | /// <summary> |
167 | /// This is the percentage of the udp texture queue to add to the task queue since | ||
168 | /// textures are now generally handled through http. | ||
169 | /// </summary> | ||
170 | private double m_cannibalrate = 0.0; | ||
171 | |||
172 | private ClientInfo m_info = new ClientInfo(); | ||
173 | |||
174 | /// <summary> | ||
164 | /// Default constructor | 175 | /// Default constructor |
165 | /// </summary> | 176 | /// </summary> |
166 | /// <param name="server">Reference to the UDP server this client is connected to</param> | 177 | /// <param name="server">Reference to the UDP server this client is connected to</param> |
@@ -197,6 +208,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
197 | // Create an array of token buckets for this clients different throttle categories | 208 | // Create an array of token buckets for this clients different throttle categories |
198 | m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; | 209 | m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; |
199 | 210 | ||
211 | m_cannibalrate = rates.CannibalizeTextureRate; | ||
212 | |||
200 | for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) | 213 | for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) |
201 | { | 214 | { |
202 | ThrottleOutPacketType type = (ThrottleOutPacketType)i; | 215 | ThrottleOutPacketType type = (ThrottleOutPacketType)i; |
@@ -241,20 +254,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
241 | // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists | 254 | // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists |
242 | // of pending and needed ACKs for every client every time some method wants information about | 255 | // of pending and needed ACKs for every client every time some method wants information about |
243 | // this connection is a recipe for poor performance | 256 | // this connection is a recipe for poor performance |
244 | ClientInfo info = new ClientInfo(); | 257 | |
245 | info.pendingAcks = new Dictionary<uint, uint>(); | 258 | m_info.resendThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate; |
246 | info.needAck = new Dictionary<uint, byte[]>(); | 259 | m_info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; |
247 | 260 | m_info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; | |
248 | info.resendThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate; | 261 | m_info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; |
249 | info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; | 262 | m_info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; |
250 | info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; | 263 | m_info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; |
251 | info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; | 264 | m_info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; |
252 | info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; | 265 | m_info.totalThrottle = (int)m_throttleCategory.DripRate; |
253 | info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; | 266 | |
254 | info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; | 267 | return m_info; |
255 | info.totalThrottle = (int)m_throttleCategory.DripRate; | ||
256 | |||
257 | return info; | ||
258 | } | 268 | } |
259 | 269 | ||
260 | /// <summary> | 270 | /// <summary> |
@@ -348,6 +358,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
348 | texture = Math.Max(texture, LLUDPServer.MTU); | 358 | texture = Math.Max(texture, LLUDPServer.MTU); |
349 | asset = Math.Max(asset, LLUDPServer.MTU); | 359 | asset = Math.Max(asset, LLUDPServer.MTU); |
350 | 360 | ||
361 | // Since most textures are now delivered through http, make it possible | ||
362 | // to cannibalize some of the bw from the texture throttle to use for | ||
363 | // the task queue (e.g. object updates) | ||
364 | task = task + (int)(m_cannibalrate * texture); | ||
365 | texture = (int)((1 - m_cannibalrate) * texture); | ||
366 | |||
351 | //int total = resend + land + wind + cloud + task + texture + asset; | 367 | //int total = resend + land + wind + cloud + task + texture + asset; |
352 | //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", | 368 | //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", |
353 | // AgentID, resend, land, wind, cloud, task, texture, asset, total); | 369 | // AgentID, resend, land, wind, cloud, task, texture, asset, total); |
@@ -646,15 +662,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
646 | /// <param name="categories">Throttle categories to fire the callback for</param> | 662 | /// <param name="categories">Throttle categories to fire the callback for</param> |
647 | private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories) | 663 | private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories) |
648 | { | 664 | { |
649 | if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty) | 665 | // if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty) |
666 | if (!m_isQueueEmptyRunning && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty) | ||
650 | { | 667 | { |
668 | m_isQueueEmptyRunning = true; | ||
669 | |||
670 | int start = Environment.TickCount & Int32.MaxValue; | ||
671 | const int MIN_CALLBACK_MS = 30; | ||
672 | |||
673 | m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; | ||
674 | if (m_nextOnQueueEmpty == 0) | ||
675 | m_nextOnQueueEmpty = 1; | ||
676 | |||
651 | // Use a value of 0 to signal that FireQueueEmpty is running | 677 | // Use a value of 0 to signal that FireQueueEmpty is running |
652 | m_nextOnQueueEmpty = 0; | 678 | // m_nextOnQueueEmpty = 0; |
653 | // Asynchronously run the callback | 679 | |
654 | Util.FireAndForget(FireQueueEmpty, categories); | 680 | m_categories = categories; |
681 | |||
682 | if (HasUpdates(m_categories)) | ||
683 | { | ||
684 | // Asynchronously run the callback | ||
685 | Util.FireAndForget(FireQueueEmpty, categories); | ||
686 | } | ||
687 | else | ||
688 | { | ||
689 | m_isQueueEmptyRunning = false; | ||
690 | } | ||
655 | } | 691 | } |
656 | } | 692 | } |
657 | 693 | ||
694 | private bool m_isQueueEmptyRunning; | ||
695 | private ThrottleOutPacketTypeFlags m_categories = 0; | ||
696 | |||
658 | /// <summary> | 697 | /// <summary> |
659 | /// Fires the OnQueueEmpty callback and sets the minimum time that it | 698 | /// Fires the OnQueueEmpty callback and sets the minimum time that it |
660 | /// can be called again | 699 | /// can be called again |
@@ -664,22 +703,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
664 | /// signature</param> | 703 | /// signature</param> |
665 | private void FireQueueEmpty(object o) | 704 | private void FireQueueEmpty(object o) |
666 | { | 705 | { |
667 | const int MIN_CALLBACK_MS = 30; | 706 | // int start = Environment.TickCount & Int32.MaxValue; |
707 | // const int MIN_CALLBACK_MS = 30; | ||
668 | 708 | ||
669 | ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; | 709 | // if (m_udpServer.IsRunningOutbound) |
670 | QueueEmpty callback = OnQueueEmpty; | 710 | // { |
671 | 711 | ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; | |
672 | int start = Environment.TickCount & Int32.MaxValue; | 712 | QueueEmpty callback = OnQueueEmpty; |
673 | 713 | ||
674 | if (callback != null) | 714 | if (callback != null) |
675 | { | 715 | { |
676 | try { callback(categories); } | 716 | // if (m_udpServer.IsRunningOutbound) |
677 | catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); } | 717 | // { |
678 | } | 718 | try { callback(categories); } |
719 | catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); } | ||
720 | // } | ||
721 | } | ||
722 | // } | ||
723 | |||
724 | // m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; | ||
725 | // if (m_nextOnQueueEmpty == 0) | ||
726 | // m_nextOnQueueEmpty = 1; | ||
727 | |||
728 | // } | ||
679 | 729 | ||
680 | m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; | 730 | m_isQueueEmptyRunning = false; |
681 | if (m_nextOnQueueEmpty == 0) | ||
682 | m_nextOnQueueEmpty = 1; | ||
683 | } | 731 | } |
684 | internal void ForceThrottleSetting(int throttle, int setting) | 732 | internal void ForceThrottleSetting(int throttle, int setting) |
685 | { | 733 | { |