aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs110
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;
31using System.Threading; 31using System.Threading;
32using log4net; 32using log4net;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Monitoring;
34using OpenMetaverse; 35using OpenMetaverse;
35using OpenMetaverse.Packets; 36using 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 {