diff options
author | John Hurliman | 2009-10-14 11:43:31 -0700 |
---|---|---|
committer | John Hurliman | 2009-10-14 11:43:31 -0700 |
commit | 0d2e6463d714bce8a6a628bd647c625feeeae8f6 (patch) | |
tree | 1d4a805e65932c225a4c6a2b219b23840b3288a9 | |
parent | * Split Task category into Task and State (diff) | |
download | opensim-SC_OLD-0d2e6463d714bce8a6a628bd647c625feeeae8f6.zip opensim-SC_OLD-0d2e6463d714bce8a6a628bd647c625feeeae8f6.tar.gz opensim-SC_OLD-0d2e6463d714bce8a6a628bd647c625feeeae8f6.tar.bz2 opensim-SC_OLD-0d2e6463d714bce8a6a628bd647c625feeeae8f6.tar.xz |
* Minimized the number of times textures are pulled off the priority queue
* OnQueueEmpty is still called async, but will not be called for a given category if the previous callback for that category is still running. This is the most balanced behavior I could find, and seems to work well
* Added support for the old [ClientStack.LindenUDP] settings (including setting the receive buffer size) and added the new token bucket and global throttle settings
* Added the AssetLoaderEnabled config variable to optionally disable loading assets from XML every startup. This gives a dramatic improvement in startup times for those who don't need the functionality every startup
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs | 25 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 7 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs | 48 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs | 65 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 12 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs | 15 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs | 36 | ||||
-rw-r--r-- | OpenSim/Services/AssetService/AssetService.cs | 17 | ||||
-rw-r--r-- | bin/OpenSim.ini.example | 62 |
9 files changed, 189 insertions, 98 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs index 5877779..9ded390 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs | |||
@@ -72,14 +72,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
72 | m_imageManager = imageManager; | 72 | m_imageManager = imageManager; |
73 | } | 73 | } |
74 | 74 | ||
75 | public bool SendPackets(LLClientView client, int maxpack) | 75 | /// <summary> |
76 | /// Sends packets for this texture to a client until packetsToSend is | ||
77 | /// hit or the transfer completes | ||
78 | /// </summary> | ||
79 | /// <param name="client">Reference to the client that the packets are destined for</param> | ||
80 | /// <param name="packetsToSend">Maximum number of packets to send during this call</param> | ||
81 | /// <param name="packetsSent">Number of packets sent during this call</param> | ||
82 | /// <returns>True if the transfer completes at the current discard level, otherwise false</returns> | ||
83 | public bool SendPackets(LLClientView client, int packetsToSend, out int packetsSent) | ||
76 | { | 84 | { |
77 | if (client == null) | 85 | packetsSent = 0; |
78 | return false; | ||
79 | 86 | ||
80 | if (m_currentPacket <= m_stopPacket) | 87 | if (m_currentPacket <= m_stopPacket) |
81 | { | 88 | { |
82 | int count = 0; | ||
83 | bool sendMore = true; | 89 | bool sendMore = true; |
84 | 90 | ||
85 | if (!m_sentInfo || (m_currentPacket == 0)) | 91 | if (!m_sentInfo || (m_currentPacket == 0)) |
@@ -88,25 +94,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
88 | 94 | ||
89 | m_sentInfo = true; | 95 | m_sentInfo = true; |
90 | ++m_currentPacket; | 96 | ++m_currentPacket; |
91 | ++count; | 97 | ++packetsSent; |
92 | } | 98 | } |
93 | if (m_currentPacket < 2) | 99 | if (m_currentPacket < 2) |
94 | { | 100 | { |
95 | m_currentPacket = 2; | 101 | m_currentPacket = 2; |
96 | } | 102 | } |
97 | 103 | ||
98 | while (sendMore && count < maxpack && m_currentPacket <= m_stopPacket) | 104 | while (sendMore && packetsSent < packetsToSend && m_currentPacket <= m_stopPacket) |
99 | { | 105 | { |
100 | sendMore = SendPacket(client); | 106 | sendMore = SendPacket(client); |
101 | ++m_currentPacket; | 107 | ++m_currentPacket; |
102 | ++count; | 108 | ++packetsSent; |
103 | } | 109 | } |
104 | |||
105 | if (m_currentPacket > m_stopPacket) | ||
106 | return true; | ||
107 | } | 110 | } |
108 | 111 | ||
109 | return false; | 112 | return (m_currentPacket > m_stopPacket); |
110 | } | 113 | } |
111 | 114 | ||
112 | public void RunUpdate() | 115 | public void RunUpdate() |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 3b1a0bd..9afff5a 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |||
@@ -313,10 +313,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
313 | protected int m_primFullUpdatesPerPacket = 14; | 313 | protected int m_primFullUpdatesPerPacket = 14; |
314 | protected int m_primTerseUpdateRate = 10; | 314 | protected int m_primTerseUpdateRate = 10; |
315 | protected int m_primFullUpdateRate = 14; | 315 | protected int m_primFullUpdateRate = 14; |
316 | protected int m_textureSendLimit = 20; | ||
317 | protected int m_textureDataLimit = 10; | ||
318 | protected int m_avatarTerseUpdateRate = 50; | 316 | protected int m_avatarTerseUpdateRate = 50; |
319 | protected int m_avatarTerseUpdatesPerPacket = 5; | 317 | protected int m_avatarTerseUpdatesPerPacket = 5; |
318 | /// <summary>Number of texture packets to put on the queue each time the | ||
319 | /// OnQueueEmpty event is triggered for the texture category</summary> | ||
320 | protected int m_textureSendLimit = 20; | ||
320 | protected IAssetService m_assetService; | 321 | protected IAssetService m_assetService; |
321 | 322 | ||
322 | #endregion Class Members | 323 | #endregion Class Members |
@@ -3453,7 +3454,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3453 | void ProcessTextureRequests() | 3454 | void ProcessTextureRequests() |
3454 | { | 3455 | { |
3455 | if (m_imageManager != null) | 3456 | if (m_imageManager != null) |
3456 | m_imageManager.ProcessImageQueue(m_textureSendLimit, m_textureDataLimit); | 3457 | m_imageManager.ProcessImageQueue(m_textureSendLimit); |
3457 | } | 3458 | } |
3458 | 3459 | ||
3459 | void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) | 3460 | void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs index 8410ee9..9d36cff 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs | |||
@@ -162,32 +162,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
162 | } | 162 | } |
163 | } | 163 | } |
164 | 164 | ||
165 | public bool ProcessImageQueue(int count, int maxpack) | 165 | public bool ProcessImageQueue(int packetsToSend) |
166 | { | 166 | { |
167 | J2KImage imagereq; | ||
168 | int numCollected = 0; | ||
169 | |||
170 | m_lastloopprocessed = DateTime.Now.Ticks; | 167 | m_lastloopprocessed = DateTime.Now.Ticks; |
168 | int packetsSent = 0; | ||
171 | 169 | ||
172 | // This can happen during Close() | 170 | while (packetsSent < packetsToSend) |
173 | if (m_client == null) | ||
174 | return false; | ||
175 | |||
176 | while ((imagereq = GetHighestPriorityImage()) != null) | ||
177 | { | 171 | { |
178 | if (imagereq.IsDecoded == true) | 172 | J2KImage image = GetHighestPriorityImage(); |
173 | |||
174 | // If null was returned, the texture priority queue is currently empty | ||
175 | if (image == null) | ||
176 | return false; | ||
177 | |||
178 | if (image.IsDecoded) | ||
179 | { | 179 | { |
180 | ++numCollected; | 180 | int sent; |
181 | bool imageDone = image.SendPackets(m_client, packetsToSend - packetsSent, out sent); | ||
181 | 182 | ||
182 | if (imagereq.SendPackets(m_client, maxpack)) | 183 | packetsSent += sent; |
183 | { | ||
184 | // Send complete. Destroy any knowledge of this transfer | ||
185 | RemoveImageFromQueue(imagereq); | ||
186 | } | ||
187 | } | ||
188 | 184 | ||
189 | if (numCollected == count) | 185 | // If the send is complete, destroy any knowledge of this transfer |
190 | break; | 186 | if (imageDone) |
187 | RemoveImageFromQueue(image); | ||
188 | } | ||
189 | else | ||
190 | { | ||
191 | // TODO: This is a limitation of how LLImageManager is currently | ||
192 | // written. Undecoded textures should not be going into the priority | ||
193 | // queue, because a high priority undecoded texture will clog up the | ||
194 | // pipeline for a client | ||
195 | return true; | ||
196 | } | ||
191 | } | 197 | } |
192 | 198 | ||
193 | return m_priorityQueue.Count > 0; | 199 | return m_priorityQueue.Count > 0; |
@@ -199,10 +205,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
199 | public void Close() | 205 | public void Close() |
200 | { | 206 | { |
201 | m_shuttingdown = true; | 207 | m_shuttingdown = true; |
202 | m_priorityQueue = null; | ||
203 | m_j2kDecodeModule = null; | ||
204 | m_assetCache = null; | ||
205 | m_client = null; | ||
206 | } | 208 | } |
207 | 209 | ||
208 | #region Priority Queue Helpers | 210 | #region Priority Queue Helpers |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index e7707a9..39472cb 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs | |||
@@ -28,6 +28,7 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Net; | 30 | using System.Net; |
31 | using log4net; | ||
31 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
32 | using OpenMetaverse; | 33 | using OpenMetaverse; |
33 | 34 | ||
@@ -59,6 +60,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
59 | /// </summary> | 60 | /// </summary> |
60 | public sealed class LLUDPClient | 61 | public sealed class LLUDPClient |
61 | { | 62 | { |
63 | private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
64 | |||
62 | // FIXME: Make this a config setting | 65 | // FIXME: Make this a config setting |
63 | /// <summary>Percentage of the task throttle category that is allocated to avatar and prim | 66 | /// <summary>Percentage of the task throttle category that is allocated to avatar and prim |
64 | /// state updates</summary> | 67 | /// state updates</summary> |
@@ -136,9 +139,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
136 | /// <summary>A container that can hold one packet for each outbox, used to store | 139 | /// <summary>A container that can hold one packet for each outbox, used to store |
137 | /// dequeued packets that are being held for throttling</summary> | 140 | /// dequeued packets that are being held for throttling</summary> |
138 | private readonly OutgoingPacket[] nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; | 141 | private readonly OutgoingPacket[] nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; |
139 | /// <summary>An optimization to store the length of dequeued packets being held | 142 | /// <summary>Flags to prevent queue empty callbacks from stacking up on |
140 | /// for throttling. This avoids expensive calls to Packet.Length</summary> | 143 | /// top of each other</summary> |
141 | private readonly int[] nextPacketLengths = new int[THROTTLE_CATEGORY_COUNT]; | 144 | private readonly bool[] onQueueEmptyRunning = new bool[THROTTLE_CATEGORY_COUNT]; |
142 | /// <summary>A reference to the LLUDPServer that is managing this client</summary> | 145 | /// <summary>A reference to the LLUDPServer that is managing this client</summary> |
143 | private readonly LLUDPServer udpServer; | 146 | private readonly LLUDPServer udpServer; |
144 | 147 | ||
@@ -163,7 +166,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
163 | for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) | 166 | for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) |
164 | packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); | 167 | packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); |
165 | 168 | ||
166 | throttle = new TokenBucket(parentThrottle, 0, 0); | 169 | throttle = new TokenBucket(parentThrottle, rates.TotalLimit, rates.Total); |
167 | throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; | 170 | throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; |
168 | throttleCategories[(int)ThrottleOutPacketType.Resend] = new TokenBucket(throttle, rates.ResendLimit, rates.Resend); | 171 | throttleCategories[(int)ThrottleOutPacketType.Resend] = new TokenBucket(throttle, rates.ResendLimit, rates.Resend); |
169 | throttleCategories[(int)ThrottleOutPacketType.Land] = new TokenBucket(throttle, rates.LandLimit, rates.Land); | 172 | throttleCategories[(int)ThrottleOutPacketType.Land] = new TokenBucket(throttle, rates.LandLimit, rates.Land); |
@@ -401,10 +404,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
401 | // This bucket was empty the last time we tried to send a packet, | 404 | // This bucket was empty the last time we tried to send a packet, |
402 | // leaving a dequeued packet still waiting to be sent out. Try to | 405 | // leaving a dequeued packet still waiting to be sent out. Try to |
403 | // send it again | 406 | // send it again |
404 | if (bucket.RemoveTokens(nextPacketLengths[i])) | 407 | OutgoingPacket nextPacket = nextPackets[i]; |
408 | if (bucket.RemoveTokens(nextPacket.Buffer.DataLength)) | ||
405 | { | 409 | { |
406 | // Send the packet | 410 | // Send the packet |
407 | udpServer.SendPacketFinal(nextPackets[i]); | 411 | udpServer.SendPacketFinal(nextPacket); |
408 | nextPackets[i] = null; | 412 | nextPackets[i] = null; |
409 | packetSent = true; | 413 | packetSent = true; |
410 | } | 414 | } |
@@ -426,23 +430,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
426 | } | 430 | } |
427 | else | 431 | else |
428 | { | 432 | { |
429 | // Save the dequeued packet and the length calculation for | 433 | // Save the dequeued packet for the next iteration |
430 | // the next iteration | ||
431 | nextPackets[i] = packet; | 434 | nextPackets[i] = packet; |
432 | nextPacketLengths[i] = packet.Buffer.DataLength; | ||
433 | } | 435 | } |
434 | 436 | ||
435 | // If the queue is empty after this dequeue, fire the queue | 437 | // If the queue is empty after this dequeue, fire the queue |
436 | // empty callback now so it has a chance to fill before we | 438 | // empty callback now so it has a chance to fill before we |
437 | // get back here | 439 | // get back here |
438 | if (queue.Count == 0) | 440 | if (queue.Count == 0) |
439 | FireQueueEmpty(i); | 441 | BeginFireQueueEmpty(i); |
440 | } | 442 | } |
441 | else | 443 | else |
442 | { | 444 | { |
443 | // No packets in this queue. Fire the queue empty callback | 445 | // No packets in this queue. Fire the queue empty callback |
444 | // if it has not been called recently | 446 | // if it has not been called recently |
445 | FireQueueEmpty(i); | 447 | BeginFireQueueEmpty(i); |
446 | } | 448 | } |
447 | } | 449 | } |
448 | } | 450 | } |
@@ -450,6 +452,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
450 | return packetSent; | 452 | return packetSent; |
451 | } | 453 | } |
452 | 454 | ||
455 | /// <summary> | ||
456 | /// Called when an ACK packet is received and a round-trip time for a | ||
457 | /// packet is calculated. This is used to calculate the smoothed | ||
458 | /// round-trip time, round trip time variance, and finally the | ||
459 | /// retransmission timeout | ||
460 | /// </summary> | ||
461 | /// <param name="r">Round-trip time of a single packet and its | ||
462 | /// acknowledgement</param> | ||
453 | public void UpdateRoundTrip(float r) | 463 | public void UpdateRoundTrip(float r) |
454 | { | 464 | { |
455 | const float ALPHA = 0.125f; | 465 | const float ALPHA = 0.125f; |
@@ -475,11 +485,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
475 | // RTTVAR + " based on new RTT of " + r + "ms"); | 485 | // RTTVAR + " based on new RTT of " + r + "ms"); |
476 | } | 486 | } |
477 | 487 | ||
478 | private void FireQueueEmpty(int queueIndex) | 488 | /// <summary> |
489 | /// Does an early check to see if this queue empty callback is already | ||
490 | /// running, then asynchronously firing the event | ||
491 | /// </summary> | ||
492 | /// <param name="throttleIndex">Throttle category to fire the callback | ||
493 | /// for</param> | ||
494 | private void BeginFireQueueEmpty(int throttleIndex) | ||
479 | { | 495 | { |
496 | if (!onQueueEmptyRunning[throttleIndex]) | ||
497 | Util.FireAndForget(FireQueueEmpty, throttleIndex); | ||
498 | } | ||
499 | |||
500 | /// <summary> | ||
501 | /// Checks to see if this queue empty callback is already running, | ||
502 | /// then firing the event | ||
503 | /// </summary> | ||
504 | /// <param name="o">Throttle category to fire the callback for, stored | ||
505 | /// as an object to match the WaitCallback delegate signature</param> | ||
506 | private void FireQueueEmpty(object o) | ||
507 | { | ||
508 | int i = (int)o; | ||
509 | ThrottleOutPacketType type = (ThrottleOutPacketType)i; | ||
480 | QueueEmpty callback = OnQueueEmpty; | 510 | QueueEmpty callback = OnQueueEmpty; |
511 | |||
481 | if (callback != null) | 512 | if (callback != null) |
482 | Util.FireAndForget(delegate(object o) { callback((ThrottleOutPacketType)(int)o); }, queueIndex); | 513 | { |
514 | if (!onQueueEmptyRunning[i]) | ||
515 | { | ||
516 | onQueueEmptyRunning[i] = true; | ||
517 | try { callback(type); } | ||
518 | catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + type + ") threw an exception: " + e.Message, e); } | ||
519 | onQueueEmptyRunning[i] = false; | ||
520 | } | ||
521 | } | ||
483 | } | 522 | } |
484 | } | 523 | } |
485 | } | 524 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 57fee59..1cfde91 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | |||
@@ -109,6 +109,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
109 | private Location m_location; | 109 | private Location m_location; |
110 | /// <summary>The measured resolution of Environment.TickCount</summary> | 110 | /// <summary>The measured resolution of Environment.TickCount</summary> |
111 | private float m_tickCountResolution; | 111 | private float m_tickCountResolution; |
112 | /// <summary>The size of the receive buffer for the UDP socket. This value | ||
113 | /// is passed up to the operating system and used in the system networking | ||
114 | /// stack. Use zero to leave this value as the default</summary> | ||
115 | private int m_recvBufferSize; | ||
112 | 116 | ||
113 | /// <summary>The measured resolution of Environment.TickCount</summary> | 117 | /// <summary>The measured resolution of Environment.TickCount</summary> |
114 | public float TickCountResolution { get { return m_tickCountResolution; } } | 118 | public float TickCountResolution { get { return m_tickCountResolution; } } |
@@ -135,6 +139,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
135 | 139 | ||
136 | m_circuitManager = circuitManager; | 140 | m_circuitManager = circuitManager; |
137 | 141 | ||
142 | IConfig config = configSource.Configs["ClientStack.LindenUDP"]; | ||
143 | if (config != null) | ||
144 | { | ||
145 | m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0); | ||
146 | } | ||
147 | |||
138 | // TODO: Config support for throttling the entire connection | 148 | // TODO: Config support for throttling the entire connection |
139 | m_throttle = new TokenBucket(null, 0, 0); | 149 | m_throttle = new TokenBucket(null, 0, 0); |
140 | m_throttleRates = new ThrottleRates(configSource); | 150 | m_throttleRates = new ThrottleRates(configSource); |
@@ -145,7 +155,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
145 | if (m_scene == null) | 155 | if (m_scene == null) |
146 | throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); | 156 | throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); |
147 | 157 | ||
148 | base.Start(); | 158 | base.Start(m_recvBufferSize); |
149 | 159 | ||
150 | // Start the incoming packet processing thread | 160 | // Start the incoming packet processing thread |
151 | Thread incomingThread = new Thread(IncomingPacketHandler); | 161 | Thread incomingThread = new Thread(IncomingPacketHandler); |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs index fad2ea8..44a6ed6 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs | |||
@@ -73,6 +73,7 @@ namespace OpenMetaverse | |||
73 | /// </summary> | 73 | /// </summary> |
74 | /// <param name="bindAddress">Local IP address to bind the server to</param> | 74 | /// <param name="bindAddress">Local IP address to bind the server to</param> |
75 | /// <param name="port">Port to listening for incoming UDP packets on</param> | 75 | /// <param name="port">Port to listening for incoming UDP packets on</param> |
76 | /// | ||
76 | public OpenSimUDPBase(IPAddress bindAddress, int port) | 77 | public OpenSimUDPBase(IPAddress bindAddress, int port) |
77 | { | 78 | { |
78 | m_localBindAddress = bindAddress; | 79 | m_localBindAddress = bindAddress; |
@@ -82,25 +83,31 @@ namespace OpenMetaverse | |||
82 | /// <summary> | 83 | /// <summary> |
83 | /// Start the UDP server | 84 | /// Start the UDP server |
84 | /// </summary> | 85 | /// </summary> |
86 | /// <param name="recvBufferSize">The size of the receive buffer for | ||
87 | /// the UDP socket. This value is passed up to the operating system | ||
88 | /// and used in the system networking stack. Use zero to leave this | ||
89 | /// value as the default</param> | ||
85 | /// <remarks>This method will attempt to set the SIO_UDP_CONNRESET flag | 90 | /// <remarks>This method will attempt to set the SIO_UDP_CONNRESET flag |
86 | /// on the socket to get newer versions of Windows to behave in a sane | 91 | /// on the socket to get newer versions of Windows to behave in a sane |
87 | /// manner (not throwing an exception when the remote side resets the | 92 | /// manner (not throwing an exception when the remote side resets the |
88 | /// connection). This call is ignored on Mono where the flag is not | 93 | /// connection). This call is ignored on Mono where the flag is not |
89 | /// necessary</remarks> | 94 | /// necessary</remarks> |
90 | public void Start() | 95 | public void Start(int recvBufferSize) |
91 | { | 96 | { |
92 | if (m_shutdownFlag) | 97 | if (m_shutdownFlag) |
93 | { | 98 | { |
94 | const int SIO_UDP_CONNRESET = -1744830452; | 99 | const int SIO_UDP_CONNRESET = -1744830452; |
95 | 100 | ||
96 | IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); | 101 | IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); |
102 | |||
97 | m_udpSocket = new Socket( | 103 | m_udpSocket = new Socket( |
98 | AddressFamily.InterNetwork, | 104 | AddressFamily.InterNetwork, |
99 | SocketType.Dgram, | 105 | SocketType.Dgram, |
100 | ProtocolType.Udp); | 106 | ProtocolType.Udp); |
107 | |||
101 | try | 108 | try |
102 | { | 109 | { |
103 | // this udp socket flag is not supported under mono, | 110 | // This udp socket flag is not supported under mono, |
104 | // so we'll catch the exception and continue | 111 | // so we'll catch the exception and continue |
105 | m_udpSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null); | 112 | m_udpSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null); |
106 | m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag set"); | 113 | m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag set"); |
@@ -109,6 +116,10 @@ namespace OpenMetaverse | |||
109 | { | 116 | { |
110 | m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag not supported on this platform, ignoring"); | 117 | m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag not supported on this platform, ignoring"); |
111 | } | 118 | } |
119 | |||
120 | if (recvBufferSize != 0) | ||
121 | m_udpSocket.ReceiveBufferSize = recvBufferSize; | ||
122 | |||
112 | m_udpSocket.Bind(ipep); | 123 | m_udpSocket.Bind(ipep); |
113 | 124 | ||
114 | // we're not shutting down, we're starting up | 125 | // we're not shutting down, we're starting up |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs index 858a03c..adad4c3 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs | |||
@@ -51,6 +51,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
51 | public int Texture; | 51 | public int Texture; |
52 | /// <summary>Drip rate for asset packets</summary> | 52 | /// <summary>Drip rate for asset packets</summary> |
53 | public int Asset; | 53 | public int Asset; |
54 | /// <summary>Drip rate for the parent token bucket</summary> | ||
55 | public int Total; | ||
54 | 56 | ||
55 | /// <summary>Maximum burst rate for resent packets</summary> | 57 | /// <summary>Maximum burst rate for resent packets</summary> |
56 | public int ResendLimit; | 58 | public int ResendLimit; |
@@ -66,6 +68,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
66 | public int TextureLimit; | 68 | public int TextureLimit; |
67 | /// <summary>Maximum burst rate for asset packets</summary> | 69 | /// <summary>Maximum burst rate for asset packets</summary> |
68 | public int AssetLimit; | 70 | public int AssetLimit; |
71 | /// <summary>Burst rate for the parent token bucket</summary> | ||
72 | public int TotalLimit; | ||
69 | 73 | ||
70 | /// <summary> | 74 | /// <summary> |
71 | /// Default constructor | 75 | /// Default constructor |
@@ -77,21 +81,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
77 | { | 81 | { |
78 | IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"]; | 82 | IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"]; |
79 | 83 | ||
80 | Resend = throttleConfig.GetInt("ResendDefault", 12500); | 84 | Resend = throttleConfig.GetInt("resend_default", 12500); |
81 | Land = throttleConfig.GetInt("LandDefault", 500); | 85 | Land = throttleConfig.GetInt("land_default", 500); |
82 | Wind = throttleConfig.GetInt("WindDefault", 500); | 86 | Wind = throttleConfig.GetInt("wind_default", 500); |
83 | Cloud = throttleConfig.GetInt("CloudDefault", 500); | 87 | Cloud = throttleConfig.GetInt("cloud_default", 500); |
84 | Task = throttleConfig.GetInt("TaskDefault", 500); | 88 | Task = throttleConfig.GetInt("task_default", 500); |
85 | Texture = throttleConfig.GetInt("TextureDefault", 500); | 89 | Texture = throttleConfig.GetInt("texture_default", 500); |
86 | Asset = throttleConfig.GetInt("AssetDefault", 500); | 90 | Asset = throttleConfig.GetInt("asset_default", 500); |
87 | 91 | ||
88 | ResendLimit = throttleConfig.GetInt("ResendLimit", 18750); | 92 | Total = throttleConfig.GetInt("client_throttle_max_bps", 0); |
89 | LandLimit = throttleConfig.GetInt("LandLimit", 29750); | 93 | |
90 | WindLimit = throttleConfig.GetInt("WindLimit", 18750); | 94 | ResendLimit = throttleConfig.GetInt("resend_limit", 18750); |
91 | CloudLimit = throttleConfig.GetInt("CloudLimit", 18750); | 95 | LandLimit = throttleConfig.GetInt("land_limit", 29750); |
92 | TaskLimit = throttleConfig.GetInt("TaskLimit", 55750); | 96 | WindLimit = throttleConfig.GetInt("wind_limit", 18750); |
93 | TextureLimit = throttleConfig.GetInt("TextureLimit", 55750); | 97 | CloudLimit = throttleConfig.GetInt("cloud_limit", 18750); |
94 | AssetLimit = throttleConfig.GetInt("AssetLimit", 27500); | 98 | TaskLimit = throttleConfig.GetInt("task_limit", 55750); |
99 | TextureLimit = throttleConfig.GetInt("texture_limit", 55750); | ||
100 | AssetLimit = throttleConfig.GetInt("asset_limit", 27500); | ||
101 | |||
102 | TotalLimit = throttleConfig.GetInt("client_throttle_max_bps", 0); | ||
95 | } | 103 | } |
96 | catch (Exception) { } | 104 | catch (Exception) { } |
97 | } | 105 | } |
diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs index ebfd47a..df33db2 100644 --- a/OpenSim/Services/AssetService/AssetService.cs +++ b/OpenSim/Services/AssetService/AssetService.cs | |||
@@ -64,12 +64,17 @@ namespace OpenSim.Services.AssetService | |||
64 | string loaderArgs = assetConfig.GetString("AssetLoaderArgs", | 64 | string loaderArgs = assetConfig.GetString("AssetLoaderArgs", |
65 | String.Empty); | 65 | String.Empty); |
66 | 66 | ||
67 | m_log.InfoFormat("[ASSET]: Loading default asset set from {0}", loaderArgs); | 67 | bool assetLoaderEnabled = assetConfig.GetBoolean("AssetLoaderEnabled", true); |
68 | m_AssetLoader.ForEachDefaultXmlAsset(loaderArgs, | 68 | |
69 | delegate(AssetBase a) | 69 | if (assetLoaderEnabled) |
70 | { | 70 | { |
71 | Store(a); | 71 | m_log.InfoFormat("[ASSET]: Loading default asset set from {0}", loaderArgs); |
72 | }); | 72 | m_AssetLoader.ForEachDefaultXmlAsset(loaderArgs, |
73 | delegate(AssetBase a) | ||
74 | { | ||
75 | Store(a); | ||
76 | }); | ||
77 | } | ||
73 | 78 | ||
74 | m_log.Info("[ASSET CONNECTOR]: Local asset service enabled"); | 79 | m_log.Info("[ASSET CONNECTOR]: Local asset service enabled"); |
75 | } | 80 | } |
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 5cb51b2..0ab6257 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example | |||
@@ -341,25 +341,6 @@ | |||
341 | 341 | ||
342 | 342 | ||
343 | [ClientStack.LindenUDP] | 343 | [ClientStack.LindenUDP] |
344 | ; This is the multiplier applied to all client throttles for outgoing UDP network data | ||
345 | ; If it is set to 1, then we obey the throttle settings as given to us by the client. If it is set to 3, for example, then we | ||
346 | ; multiply that setting by 3 (e.g. if the client gives us a setting of 250 kilobits per second then we | ||
347 | ; will actually push down data at a maximum rate of 750 kilobits per second). | ||
348 | ; | ||
349 | ; In principle, setting a multiplier greater than 1 will allow data to be pushed down to a client much faster | ||
350 | ; than its UI allows the setting to go. This may be okay in some situations, such as standalone OpenSim | ||
351 | ; applications on a LAN. However, the greater the multipler, the higher the risk of packet drop, resulting | ||
352 | ; in symptoms such as missing terrain or objects. A much better solution is to change the client UI to allow | ||
353 | ; higher network bandwidth settings directly, though this isn't always possible. | ||
354 | ; | ||
355 | ; Currently this setting is 2 by default because we currently send much more texture data than is strictly | ||
356 | ; necessary. A setting of 1 could result in slow texture transfer. This will be fixed when the transfer | ||
357 | ; of textures at different levels of quality is improved. | ||
358 | ; | ||
359 | ; Pre r7113, this setting was not exposed but was effectively 8. You may want to try this if you encounter | ||
360 | ; unexpected difficulties | ||
361 | client_throttle_multiplier = 2; | ||
362 | |||
363 | ; the client socket receive buffer size determines how many | 344 | ; the client socket receive buffer size determines how many |
364 | ; incoming requests we can process; the default on .NET is 8192 | 345 | ; incoming requests we can process; the default on .NET is 8192 |
365 | ; which is about 2 4k-sized UDP datagrams. On mono this is | 346 | ; which is about 2 4k-sized UDP datagrams. On mono this is |
@@ -374,12 +355,39 @@ | |||
374 | ; by the system's settings for the maximum client receive buffer | 355 | ; by the system's settings for the maximum client receive buffer |
375 | ; size (on linux systems you can set that with "sysctl -w | 356 | ; size (on linux systems you can set that with "sysctl -w |
376 | ; net.core.rmem_max=X") | 357 | ; net.core.rmem_max=X") |
377 | ; | 358 | ;client_socket_rcvbuf_size = 8388608 |
378 | ; client_socket_rcvbuf_size = 8388608 | 359 | |
379 | 360 | ; Maximum outbound bits per second for a single scene. This can be used to | |
380 | ; Maximum bits per second to send to any single client. This will override the user's viewer preference settings. | 361 | ; throttle total outbound UDP traffic for a simulator. The default value is |
381 | 362 | ; 0, meaning no throttling at the scene level. The example given here is | |
382 | ; client_throttle_max_bps = 1500000 | 363 | ; 20 megabits |
364 | ;scene_throttle_max_bps = 20971520 | ||
365 | |||
366 | ; Maximum bits per second to send to any single client. This will override | ||
367 | ; the user's viewer preference settings. The default value is 0, meaning no | ||
368 | ; aggregate throttling on clients (only per-category throttling). The | ||
369 | ; example given here is 1.5 megabits | ||
370 | ;client_throttle_max_bps = 1572864 | ||
371 | |||
372 | ; Per-client bits per second rates for the various throttle categories. | ||
373 | ; These are default values that will be overriden by clients | ||
374 | ;resend_default = 12500 | ||
375 | ;land_default = 500 | ||
376 | ;wind_default = 500 | ||
377 | ;cloud_default = 50 | ||
378 | ;task_default = 500 | ||
379 | ;texture_default = 500 | ||
380 | ;asset_default = 500 | ||
381 | |||
382 | ; Per-client maximum burst rates in bits per second for the various throttle | ||
383 | ; categories. These are default values that will be overriden by clients | ||
384 | ;resend_limit = 18750 | ||
385 | ;land_limit = 29750 | ||
386 | ;wind_limit = 18750 | ||
387 | ;cloud_limit = 18750 | ||
388 | ;task_limit = 55750 | ||
389 | ;texture_limit = 55750 | ||
390 | ;asset_limit = 27500 | ||
383 | 391 | ||
384 | [Chat] | 392 | [Chat] |
385 | ; Controls whether the chat module is enabled. Default is true. | 393 | ; Controls whether the chat module is enabled. Default is true. |
@@ -1381,6 +1389,10 @@ | |||
1381 | [AssetService] | 1389 | [AssetService] |
1382 | DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll" | 1390 | DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll" |
1383 | AssetLoaderArgs = "assets/AssetSets.xml" | 1391 | AssetLoaderArgs = "assets/AssetSets.xml" |
1392 | |||
1393 | ; Disable this to prevent the default asset set from being inserted into the | ||
1394 | ; asset store each time the region starts | ||
1395 | AssetLoaderEnabled = true | ||
1384 | 1396 | ||
1385 | [GridService] | 1397 | [GridService] |
1386 | ;; default standalone, overridable in StandaloneCommon.ini | 1398 | ;; default standalone, overridable in StandaloneCommon.ini |