diff options
4 files changed, 121 insertions, 50 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index dce9469..38bbce0 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |||
@@ -3320,6 +3320,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3320 | // If we received an update about our own avatar, process the avatar update priority queue immediately | 3320 | // If we received an update about our own avatar, process the avatar update priority queue immediately |
3321 | if (data.AgentID == m_agentId) | 3321 | if (data.AgentID == m_agentId) |
3322 | ProcessAvatarTerseUpdates(); | 3322 | ProcessAvatarTerseUpdates(); |
3323 | else | ||
3324 | m_udpServer.SignalOutgoingPacketHandler(); | ||
3323 | } | 3325 | } |
3324 | 3326 | ||
3325 | private void ProcessAvatarTerseUpdates() | 3327 | private void ProcessAvatarTerseUpdates() |
@@ -3407,6 +3409,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3407 | 3409 | ||
3408 | lock (m_primFullUpdates.SyncRoot) | 3410 | lock (m_primFullUpdates.SyncRoot) |
3409 | m_primFullUpdates.Enqueue(data.priority, objectData, data.localID); | 3411 | m_primFullUpdates.Enqueue(data.priority, objectData, data.localID); |
3412 | |||
3413 | m_udpServer.SignalOutgoingPacketHandler(); | ||
3410 | } | 3414 | } |
3411 | 3415 | ||
3412 | void ProcessPrimFullUpdates() | 3416 | void ProcessPrimFullUpdates() |
@@ -3450,6 +3454,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3450 | 3454 | ||
3451 | lock (m_primTerseUpdates.SyncRoot) | 3455 | lock (m_primTerseUpdates.SyncRoot) |
3452 | m_primTerseUpdates.Enqueue(data.Priority, objectData, data.LocalID); | 3456 | m_primTerseUpdates.Enqueue(data.Priority, objectData, data.LocalID); |
3457 | |||
3458 | m_udpServer.SignalOutgoingPacketHandler(); | ||
3453 | } | 3459 | } |
3454 | 3460 | ||
3455 | void ProcessPrimTerseUpdates() | 3461 | void ProcessPrimTerseUpdates() |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index 134cfe5..b9d2c15 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs | |||
@@ -105,9 +105,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
105 | public int TickLastPacketReceived; | 105 | public int TickLastPacketReceived; |
106 | /// <summary>Environment.TickCount of the last time the outgoing packet handler executed for this client</summary> | 106 | /// <summary>Environment.TickCount of the last time the outgoing packet handler executed for this client</summary> |
107 | public int TickLastOutgoingPacketHandler; | 107 | public int TickLastOutgoingPacketHandler; |
108 | /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler executed for this client</summary> | ||
109 | public int ElapsedMSOutgoingPacketHandler; | ||
110 | /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed for this client</summary> | ||
111 | public int Elapsed100MSOutgoingPacketHandler; | ||
112 | /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed for this client</summary> | ||
113 | public int Elapsed500MSOutgoingPacketHandler; | ||
108 | 114 | ||
109 | /// <summary>Timer granularity. This is set to the measured resolution of Environment.TickCount</summary> | ||
110 | public readonly float G; | ||
111 | /// <summary>Smoothed round-trip time. A smoothed average of the round-trip time for sending a | 115 | /// <summary>Smoothed round-trip time. A smoothed average of the round-trip time for sending a |
112 | /// reliable packet to the client and receiving an ACK</summary> | 116 | /// reliable packet to the client and receiving an ACK</summary> |
113 | public float SRTT; | 117 | public float SRTT; |
@@ -182,15 +186,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
182 | m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type)); | 186 | m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type)); |
183 | } | 187 | } |
184 | 188 | ||
185 | // Set the granularity variable used for retransmission calculations to | ||
186 | // the measured resolution of Environment.TickCount | ||
187 | G = server.TickCountResolution; | ||
188 | |||
189 | // Default the retransmission timeout to three seconds | 189 | // Default the retransmission timeout to three seconds |
190 | RTO = 3000; | 190 | RTO = 3000; |
191 | 191 | ||
192 | // Initialize this to a sane value to prevent early disconnects | 192 | // Initialize this to a sane value to prevent early disconnects |
193 | TickLastPacketReceived = Environment.TickCount; | 193 | TickLastPacketReceived = Environment.TickCount & Int32.MaxValue; |
194 | ElapsedMSOutgoingPacketHandler = 0; | ||
195 | Elapsed100MSOutgoingPacketHandler = 0; | ||
196 | Elapsed500MSOutgoingPacketHandler = 0; | ||
194 | } | 197 | } |
195 | 198 | ||
196 | /// <summary> | 199 | /// <summary> |
@@ -391,6 +394,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
391 | { | 394 | { |
392 | // Not enough tokens in the bucket, queue this packet | 395 | // Not enough tokens in the bucket, queue this packet |
393 | queue.Enqueue(packet); | 396 | queue.Enqueue(packet); |
397 | m_udpServer.SignalOutgoingPacketHandler(); | ||
394 | return true; | 398 | return true; |
395 | } | 399 | } |
396 | } | 400 | } |
@@ -407,13 +411,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
407 | /// </summary> | 411 | /// </summary> |
408 | /// <remarks>This function is only called from a synchronous loop in the | 412 | /// <remarks>This function is only called from a synchronous loop in the |
409 | /// UDPServer so we don't need to bother making this thread safe</remarks> | 413 | /// UDPServer so we don't need to bother making this thread safe</remarks> |
410 | /// <returns>True if any packets were sent, otherwise false</returns> | 414 | /// <returns>The minimum amount of time before the next packet |
411 | public bool DequeueOutgoing() | 415 | /// can be sent to this client</returns> |
416 | public int DequeueOutgoing() | ||
412 | { | 417 | { |
413 | OutgoingPacket packet; | 418 | OutgoingPacket packet; |
414 | OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; | 419 | OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; |
415 | TokenBucket bucket; | 420 | TokenBucket bucket; |
416 | bool packetSent = false; | 421 | int dataLength; |
422 | int minTimeout = Int32.MaxValue; | ||
417 | 423 | ||
418 | //string queueDebugOutput = String.Empty; // Serious debug business | 424 | //string queueDebugOutput = String.Empty; // Serious debug business |
419 | 425 | ||
@@ -428,12 +434,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
428 | // leaving a dequeued packet still waiting to be sent out. Try to | 434 | // leaving a dequeued packet still waiting to be sent out. Try to |
429 | // send it again | 435 | // send it again |
430 | OutgoingPacket nextPacket = m_nextPackets[i]; | 436 | OutgoingPacket nextPacket = m_nextPackets[i]; |
431 | if (bucket.RemoveTokens(nextPacket.Buffer.DataLength)) | 437 | dataLength = nextPacket.Buffer.DataLength; |
438 | if (bucket.RemoveTokens(dataLength)) | ||
432 | { | 439 | { |
433 | // Send the packet | 440 | // Send the packet |
434 | m_udpServer.SendPacketFinal(nextPacket); | 441 | m_udpServer.SendPacketFinal(nextPacket); |
435 | m_nextPackets[i] = null; | 442 | m_nextPackets[i] = null; |
436 | packetSent = true; | 443 | minTimeout = 0; |
444 | } | ||
445 | else if (minTimeout != 0) | ||
446 | { | ||
447 | // Check the minimum amount of time we would have to wait before this packet can be sent out | ||
448 | minTimeout = Math.Min(minTimeout, ((dataLength - bucket.Content) / bucket.DripPerMS) + 1); | ||
437 | } | 449 | } |
438 | } | 450 | } |
439 | else | 451 | else |
@@ -445,16 +457,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
445 | { | 457 | { |
446 | // A packet was pulled off the queue. See if we have | 458 | // A packet was pulled off the queue. See if we have |
447 | // enough tokens in the bucket to send it out | 459 | // enough tokens in the bucket to send it out |
448 | if (bucket.RemoveTokens(packet.Buffer.DataLength)) | 460 | dataLength = packet.Buffer.DataLength; |
461 | if (bucket.RemoveTokens(dataLength)) | ||
449 | { | 462 | { |
450 | // Send the packet | 463 | // Send the packet |
451 | m_udpServer.SendPacketFinal(packet); | 464 | m_udpServer.SendPacketFinal(packet); |
452 | packetSent = true; | 465 | minTimeout = 0; |
453 | } | 466 | } |
454 | else | 467 | else |
455 | { | 468 | { |
456 | // Save the dequeued packet for the next iteration | 469 | // Save the dequeued packet for the next iteration |
457 | m_nextPackets[i] = packet; | 470 | m_nextPackets[i] = packet; |
471 | |||
472 | if (minTimeout != 0) | ||
473 | { | ||
474 | // Check the minimum amount of time we would have to wait before this packet can be sent out | ||
475 | minTimeout = Math.Min(minTimeout, ((dataLength - bucket.Content) / bucket.DripPerMS) + 1); | ||
476 | } | ||
458 | } | 477 | } |
459 | 478 | ||
460 | // If the queue is empty after this dequeue, fire the queue | 479 | // If the queue is empty after this dequeue, fire the queue |
@@ -473,7 +492,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
473 | } | 492 | } |
474 | 493 | ||
475 | //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business | 494 | //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business |
476 | return packetSent; | 495 | return minTimeout; |
477 | } | 496 | } |
478 | 497 | ||
479 | /// <summary> | 498 | /// <summary> |
@@ -504,7 +523,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
504 | } | 523 | } |
505 | 524 | ||
506 | // Always round retransmission timeout up to two seconds | 525 | // Always round retransmission timeout up to two seconds |
507 | RTO = Math.Max(2000, (int)(SRTT + Math.Max(G, K * RTTVAR))); | 526 | RTO = Math.Max(2000, (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR))); |
508 | //m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " + | 527 | //m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " + |
509 | // RTTVAR + " based on new RTT of " + r + "ms"); | 528 | // RTTVAR + " based on new RTT of " + r + "ms"); |
510 | } | 529 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 952d147..7d5c11e 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | |||
@@ -96,6 +96,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
96 | 96 | ||
97 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 97 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
98 | 98 | ||
99 | /// <summary>The measured resolution of Environment.TickCount</summary> | ||
100 | public readonly float TickCountResolution; | ||
101 | |||
99 | /// <summary>Handlers for incoming packets</summary> | 102 | /// <summary>Handlers for incoming packets</summary> |
100 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); | 103 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); |
101 | /// <summary>Incoming packets that are awaiting handling</summary> | 104 | /// <summary>Incoming packets that are awaiting handling</summary> |
@@ -112,20 +115,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
112 | private Scene m_scene; | 115 | private Scene m_scene; |
113 | /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> | 116 | /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> |
114 | private Location m_location; | 117 | private Location m_location; |
115 | /// <summary>The measured resolution of Environment.TickCount</summary> | ||
116 | private float m_tickCountResolution; | ||
117 | /// <summary>The size of the receive buffer for the UDP socket. This value | 118 | /// <summary>The size of the receive buffer for the UDP socket. This value |
118 | /// is passed up to the operating system and used in the system networking | 119 | /// is passed up to the operating system and used in the system networking |
119 | /// stack. Use zero to leave this value as the default</summary> | 120 | /// stack. Use zero to leave this value as the default</summary> |
120 | private int m_recvBufferSize; | 121 | private int m_recvBufferSize; |
121 | /// <summary>Flag to process packets asynchronously or synchronously</summary> | 122 | /// <summary>Flag to process packets asynchronously or synchronously</summary> |
122 | private bool m_asyncPacketHandling; | 123 | private bool m_asyncPacketHandling; |
123 | /// <summary>Track whether or not a packet was sent in the | 124 | /// <summary>Track the minimum amount of time needed to send the next packet in the |
124 | /// OutgoingPacketHandler loop so we know when to sleep</summary> | 125 | /// OutgoingPacketHandler loop so we know when to sleep</summary> |
125 | private bool m_packetSentLastLoop; | 126 | private int m_minTimeout = Int32.MaxValue; |
127 | /// <summary>EventWaitHandle to signify the outgoing packet handler thread that | ||
128 | /// there is more work to do</summary> | ||
129 | private EventWaitHandle m_outgoingWaitHandle; | ||
126 | 130 | ||
127 | /// <summary>The measured resolution of Environment.TickCount</summary> | ||
128 | public float TickCountResolution { get { return m_tickCountResolution; } } | ||
129 | public Socket Server { get { return null; } } | 131 | public Socket Server { get { return null; } } |
130 | 132 | ||
131 | public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) | 133 | public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) |
@@ -134,16 +136,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
134 | #region Environment.TickCount Measurement | 136 | #region Environment.TickCount Measurement |
135 | 137 | ||
136 | // Measure the resolution of Environment.TickCount | 138 | // Measure the resolution of Environment.TickCount |
137 | m_tickCountResolution = 0f; | 139 | TickCountResolution = 0f; |
138 | for (int i = 0; i < 5; i++) | 140 | for (int i = 0; i < 5; i++) |
139 | { | 141 | { |
140 | int start = Environment.TickCount; | 142 | int start = Environment.TickCount; |
141 | int now = start; | 143 | int now = start; |
142 | while (now == start) | 144 | while (now == start) |
143 | now = Environment.TickCount; | 145 | now = Environment.TickCount; |
144 | m_tickCountResolution += (float)(now - start) * 0.2f; | 146 | TickCountResolution += (float)(now - start) * 0.2f; |
145 | } | 147 | } |
146 | m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms"); | 148 | m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms"); |
149 | TickCountResolution = (float)Math.Ceiling(TickCountResolution); | ||
147 | 150 | ||
148 | #endregion Environment.TickCount Measurement | 151 | #endregion Environment.TickCount Measurement |
149 | 152 | ||
@@ -171,6 +174,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
171 | 174 | ||
172 | base.Start(m_recvBufferSize, m_asyncPacketHandling); | 175 | base.Start(m_recvBufferSize, m_asyncPacketHandling); |
173 | 176 | ||
177 | m_outgoingWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); | ||
178 | |||
174 | // Start the incoming packet processing thread | 179 | // Start the incoming packet processing thread |
175 | Thread incomingThread = new Thread(IncomingPacketHandler); | 180 | Thread incomingThread = new Thread(IncomingPacketHandler); |
176 | incomingThread.Name = "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")"; | 181 | incomingThread.Name = "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")"; |
@@ -185,6 +190,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
185 | { | 190 | { |
186 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); | 191 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); |
187 | base.Stop(); | 192 | base.Stop(); |
193 | |||
194 | m_outgoingWaitHandle.Close(); | ||
188 | } | 195 | } |
189 | 196 | ||
190 | public void AddScene(IScene scene) | 197 | public void AddScene(IScene scene) |
@@ -768,6 +775,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
768 | packetInbox.Clear(); | 775 | packetInbox.Clear(); |
769 | } | 776 | } |
770 | 777 | ||
778 | public bool SignalOutgoingPacketHandler() | ||
779 | { | ||
780 | return m_outgoingWaitHandle.Set(); | ||
781 | } | ||
782 | |||
771 | private void OutgoingPacketHandler() | 783 | private void OutgoingPacketHandler() |
772 | { | 784 | { |
773 | // Set this culture for the thread that outgoing packets are sent | 785 | // Set this culture for the thread that outgoing packets are sent |
@@ -778,14 +790,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
778 | { | 790 | { |
779 | try | 791 | try |
780 | { | 792 | { |
781 | m_packetSentLastLoop = false; | 793 | m_minTimeout = Int32.MaxValue; |
782 | 794 | ||
795 | // Handle outgoing packets, resends, acknowledgements, and pings for each | ||
796 | // client. m_minTimeout will be set to 0 if more packets are waiting in the | ||
797 | // queues with bandwidth to spare, or the number of milliseconds we need to | ||
798 | // wait before at least one packet can be sent to a client | ||
783 | m_scene.ClientManager.ForEachSync(ClientOutgoingPacketHandler); | 799 | m_scene.ClientManager.ForEachSync(ClientOutgoingPacketHandler); |
784 | 800 | ||
785 | // If no packets at all were sent, sleep to avoid chewing up CPU cycles | 801 | // Can't wait for a negative amount of time, and put a 100ms ceiling on our |
786 | // when there is nothing to do | 802 | // maximum wait time |
787 | if (!m_packetSentLastLoop) | 803 | m_minTimeout = Utils.Clamp(m_minTimeout, 0, 100); |
788 | Thread.Sleep(20); | 804 | |
805 | if (m_minTimeout > 0) | ||
806 | { | ||
807 | // Don't bother waiting for a shorter interval than our TickCountResolution | ||
808 | // since the token buckets wouldn't update anyways | ||
809 | m_minTimeout = Math.Max(m_minTimeout, (int)TickCountResolution); | ||
810 | |||
811 | // Wait for someone to signal that packets are ready to be sent, or for our | ||
812 | // sleep interval to expire | ||
813 | m_outgoingWaitHandle.WaitOne(m_minTimeout); | ||
814 | } | ||
789 | } | 815 | } |
790 | catch (Exception ex) | 816 | catch (Exception ex) |
791 | { | 817 | { |
@@ -802,32 +828,48 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
802 | { | 828 | { |
803 | LLUDPClient udpClient = ((LLClientView)client).UDPClient; | 829 | LLUDPClient udpClient = ((LLClientView)client).UDPClient; |
804 | 830 | ||
831 | // Update ElapsedMSOutgoingPacketHandler | ||
805 | int thisTick = Environment.TickCount & Int32.MaxValue; | 832 | int thisTick = Environment.TickCount & Int32.MaxValue; |
806 | int elapsedMS = thisTick - udpClient.TickLastOutgoingPacketHandler; | 833 | if (udpClient.TickLastOutgoingPacketHandler > thisTick) |
834 | udpClient.ElapsedMSOutgoingPacketHandler += ((Int32.MaxValue - udpClient.TickLastOutgoingPacketHandler) + thisTick); | ||
835 | else | ||
836 | udpClient.ElapsedMSOutgoingPacketHandler += (thisTick - udpClient.TickLastOutgoingPacketHandler); | ||
807 | 837 | ||
808 | if (udpClient.IsConnected) | 838 | if (udpClient.IsConnected) |
809 | { | 839 | { |
810 | // Check for pending outgoing resends every 100ms | 840 | // Check for pending outgoing resends every 100ms |
811 | if (elapsedMS >= 100) | 841 | if (udpClient.ElapsedMSOutgoingPacketHandler >= 100) |
812 | { | 842 | { |
813 | ResendUnacked(udpClient); | 843 | ResendUnacked(udpClient); |
844 | udpClient.ElapsedMSOutgoingPacketHandler -= 100; | ||
845 | udpClient.Elapsed100MSOutgoingPacketHandler += 1; | ||
846 | } | ||
814 | 847 | ||
815 | // Check for pending outgoing ACKs every 500ms | 848 | // Check for pending outgoing ACKs every 500ms |
816 | if (elapsedMS >= 500) | 849 | if (udpClient.Elapsed100MSOutgoingPacketHandler >= 5) |
817 | { | 850 | { |
818 | SendAcks(udpClient); | 851 | SendAcks(udpClient); |
819 | 852 | udpClient.Elapsed100MSOutgoingPacketHandler -= 5; | |
820 | // Send pings to clients every 5000ms | 853 | udpClient.Elapsed500MSOutgoingPacketHandler += 1; |
821 | if (elapsedMS >= 5000) | 854 | } |
822 | { | 855 | |
823 | SendPing(udpClient); | 856 | // Send pings to clients every 5000ms |
824 | } | 857 | if (udpClient.Elapsed500MSOutgoingPacketHandler >= 10) |
825 | } | 858 | { |
859 | SendPing(udpClient); | ||
860 | udpClient.Elapsed500MSOutgoingPacketHandler -= 10; | ||
826 | } | 861 | } |
827 | 862 | ||
828 | // Dequeue any outgoing packets that are within the throttle limits | 863 | // Dequeue any outgoing packets that are within the throttle limits |
829 | if (udpClient.DequeueOutgoing()) | 864 | // and get the minimum time we would have to sleep before this client |
830 | m_packetSentLastLoop = true; | 865 | // could send a packet out |
866 | int minTimeoutThisLoop = udpClient.DequeueOutgoing(); | ||
867 | |||
868 | // Although this is not thread safe, it is cheaper than locking and the | ||
869 | // worst that will happen is we sleep for slightly longer than the | ||
870 | // minimum necessary interval | ||
871 | if (minTimeoutThisLoop < m_minTimeout) | ||
872 | m_minTimeout = minTimeoutThisLoop; | ||
831 | } | 873 | } |
832 | 874 | ||
833 | udpClient.TickLastOutgoingPacketHandler = thisTick; | 875 | udpClient.TickLastOutgoingPacketHandler = thisTick; |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs index 0a64095..bdbd284 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs | |||
@@ -98,6 +98,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
98 | } | 98 | } |
99 | 99 | ||
100 | /// <summary> | 100 | /// <summary> |
101 | /// The speed limit of this bucket in bytes per millisecond | ||
102 | /// </summary> | ||
103 | public int DripPerMS | ||
104 | { | ||
105 | get { return tokensPerMS; } | ||
106 | } | ||
107 | |||
108 | /// <summary> | ||
101 | /// The number of bytes that can be sent at this moment. This is the | 109 | /// The number of bytes that can be sent at this moment. This is the |
102 | /// current number of tokens in the bucket | 110 | /// current number of tokens in the bucket |
103 | /// <remarks>If this bucket has a parent bucket that does not have | 111 | /// <remarks>If this bucket has a parent bucket that does not have |
@@ -106,11 +114,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
106 | /// </summary> | 114 | /// </summary> |
107 | public int Content | 115 | public int Content |
108 | { | 116 | { |
109 | get | 117 | get { return content; } |
110 | { | ||
111 | Drip(); | ||
112 | return content; | ||
113 | } | ||
114 | } | 118 | } |
115 | 119 | ||
116 | #endregion Properties | 120 | #endregion Properties |
@@ -182,7 +186,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
182 | /// call to Drip | 186 | /// call to Drip |
183 | /// </summary> | 187 | /// </summary> |
184 | /// <returns>True if tokens were added to the bucket, otherwise false</returns> | 188 | /// <returns>True if tokens were added to the bucket, otherwise false</returns> |
185 | private bool Drip() | 189 | public bool Drip() |
186 | { | 190 | { |
187 | if (tokensPerMS == 0) | 191 | if (tokensPerMS == 0) |
188 | { | 192 | { |